diff --git a/locale/ID.po b/locale/ID.po index 33767f674f904..21a16f4314b4d 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -4538,7 +4538,7 @@ msgstr "" #~ msgstr "Berjalan di mode aman(safe mode)! Auto-reload tidak aktif.\n" #~ msgid "Running in safe mode! Not running saved code.\n" -#~ msgstr "" +#~ msgstr "Berjalan di mode aman(safe mode)! Tidak menjalankan kode yang disimpan.\n" #~ "Berjalan di mode aman(safe mode)! tidak menjalankan kode yang tersimpan.\n" #~ msgid "'async for' or 'async with' outside async function" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index c04405b99fd44..a6e71b519c497 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -710,13 +710,7 @@ msgid "CircuitPython core code crashed hard. Whoops!\n" msgstr "" #: supervisor/shared/safe_mode.c -msgid "" -"CircuitPython is in safe mode because you pressed the reset button during " -"boot. Press again to exit safe mode.\n" -msgstr "" - -#: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" +msgid "CircuitPython was unable to allocate the heap." msgstr "" #: shared-module/bitbangio/SPI.c @@ -1634,10 +1628,6 @@ msgstr "" msgid "Not playing" msgstr "" -#: main.c -msgid "Not running saved code.\n" -msgstr "" - #: shared-bindings/_bleio/__init__.c msgid "Not settable" msgstr "" @@ -1950,7 +1940,7 @@ msgid "Row entry must be digitalio.DigitalInOut" msgstr "" #: main.c -msgid "Running in safe mode! " +msgid "Running in safe mode! Not running saved code.\n" msgstr "" #: shared-module/sdcardio/SDCard.c @@ -2071,13 +2061,13 @@ msgstr "" #: supervisor/shared/safe_mode.c msgid "" "The CircuitPython heap was corrupted because the stack was too small.\n" -"Please increase the stack size if you know how, or if not:" +"Increase the stack size if you know how. If not:" msgstr "" #: supervisor/shared/safe_mode.c msgid "" "The `microcontroller` module was used to boot into safe mode. Press reset to " -"exit safe mode.\n" +"exit safe mode." msgstr "" #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -2088,7 +2078,7 @@ msgstr "" msgid "" "The microcontroller's power dipped. Make sure your power supply provides\n" "enough power for the whole circuit and press reset (after ejecting " -"CIRCUITPY).\n" +"CIRCUITPY)." msgstr "" #: shared-module/audiomixer/MixerVoice.c @@ -2382,7 +2372,12 @@ msgid "Writes not supported on Characteristic" msgstr "" #: supervisor/shared/safe_mode.c -msgid "You are in safe mode: something unanticipated happened.\n" +msgid "You are in safe mode because:\n" +msgstr "" + +#: supervisor/shared/safe_mode.c +msgid "" +"You pressed the reset button during boot. Press again to exit safe mode." msgstr "" #: supervisor/shared/safe_mode.c diff --git a/locale/de_DE.po b/locale/de_DE.po index 3aaf33b57bfaf..641baa8e04974 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -732,8 +732,8 @@ msgstr "" "zu verlassen.\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPython war es nicht möglich heap-Speicher zu allozieren.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPython war es nicht möglich heap-Speicher zu allozieren." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." diff --git a/locale/en_GB.po b/locale/en_GB.po index 7fbac0439c8fb..ae8e3ff102ef9 100644 --- a/locale/en_GB.po +++ b/locale/en_GB.po @@ -729,8 +729,8 @@ msgstr "" "boot. Press again to exit safe mode.\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPython was unable to allocate the heap.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPython was unable to allocate the heap." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." diff --git a/locale/es.po b/locale/es.po index 096d413b074d1..7349726454a5c 100644 --- a/locale/es.po +++ b/locale/es.po @@ -738,8 +738,8 @@ msgstr "" "durante el arranque. Presione nuevamente para salir del modo seguro.\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPython no puedo encontrar el montículo.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPython no puedo encontrar el montículo." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." @@ -4777,7 +4777,7 @@ msgstr "zi debe ser una forma (n_section,2)" #~ msgstr "Ejecutando en modo seguro! La auto-recarga esta deshabilitada.\n" #~ msgid "Running in safe mode! Not running saved code.\n" -#~ msgstr "" +#~ msgstr "Ejecutando en modo seguro! No ejecutando el código almacenado.\n" #~ "Ejecutando en modo seguro! No se esta ejecutando el código guardado.\n" #~ msgid "__init__() should return None, not '%s'" diff --git a/locale/fr.po b/locale/fr.po index c422a12a51f9f..30be3b6cbee34 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -745,8 +745,8 @@ msgstr "" "mode sans échec.\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPython n'as pu faire l'allocation de la pile.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPython n'as pu faire l'allocation de la pile." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." diff --git a/locale/hi.po b/locale/hi.po index 369280fd9d485..566ed31686817 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -716,7 +716,7 @@ msgid "" msgstr "" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" +msgid "CircuitPython was unable to allocate the heap." msgstr "" #: shared-module/bitbangio/SPI.c diff --git a/locale/ja.po b/locale/ja.po index 5bb6460559af2..b1ce5591fdcbf 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -727,8 +727,8 @@ msgstr "" "度押すとセーフモードを終了します。\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPythonはヒープを確保できませんでした\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPythonはヒープを確保できませんでした" #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." @@ -1966,8 +1966,8 @@ msgid "Row entry must be digitalio.DigitalInOut" msgstr "Rowの各要素は digitalio.DigitalInOut でなければなりません" #: main.c -msgid "Running in safe mode! " -msgstr "セーフモードで実行中! " +msgid "Running in safe mode! Not running saved code.\n" +msgstr "セーフモードで実行中! 保存されたコードは実行していません。\n" #: shared-module/sdcardio/SDCard.c msgid "SD card CSD format not supported" diff --git a/locale/nl.po b/locale/nl.po index 475ba432bf5b8..ff030620eb6a3 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -725,8 +725,8 @@ msgstr "" "het opstarten. Druk nogmaals om veilige modus te verlaten\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPython kon het heap geheugen niet toewijzen.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPython kon het heap geheugen niet toewijzen." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." diff --git a/locale/pl.po b/locale/pl.po index c419e6aaaa1e2..0a8d30f604c20 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -725,8 +725,8 @@ msgstr "" "przycisk resetowania. Naciśnij ponownie, aby wyjść z trybu awaryjnego.\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPython nie mógł przydzielić sterty.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPython nie mógł przydzielić sterty." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." diff --git a/locale/pt_BR.po b/locale/pt_BR.po index dc95cee04751e..8e854609b7ada 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -743,8 +743,8 @@ msgstr "" "de segurança.\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "O CircuitPython não conseguiu alocar o heap.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "O CircuitPython não conseguiu alocar o heap." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." @@ -4818,7 +4818,7 @@ msgstr "zi deve estar na forma (n_section, 2)" #~ msgstr "Rodando em modo seguro! Atualização automática está desligada.\n" #~ msgid "Running in safe mode! Not running saved code.\n" -#~ msgstr "Rodando em modo seguro! Não está executando o código salvo.\n" +#~ msgstr "Rodando em modo seguro! O código salvo não está em execução.\n" #~ msgid "__init__() should return None, not '%s'" #~ msgstr "O __init__() deve retornar Nenhum, não '%s'" diff --git a/locale/sv.po b/locale/sv.po index 4d511c50cdf63..aaef6de777e8d 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -731,8 +731,8 @@ msgstr "" "under start. Tryck igen för att lämna säkert läge.\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPython kunde inte allokera heap.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPython kunde inte allokera heap." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 2978380792999..4a31b32cfa4c8 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -732,8 +732,8 @@ msgstr "" "chóng zhì ànniǔ. Zài àn yīcì tuìchū ānquán móshì.\n" #: supervisor/shared/safe_mode.c -msgid "CircuitPython was unable to allocate the heap.\n" -msgstr "CircuitPython wúfǎ fēnpèi duī.\n" +msgid "CircuitPython was unable to allocate the heap." +msgstr "CircuitPython wúfǎ fēnpèi duī." #: shared-module/bitbangio/SPI.c msgid "Clock pin init failed." diff --git a/main.c b/main.c index 48373b6834884..6904980ae95df 100755 --- a/main.c +++ b/main.c @@ -261,18 +261,20 @@ STATIC void print_code_py_status_message(safe_mode_t safe_mode) { serial_write_compressed(translate("Auto-reload is off.\n")); } if (safe_mode != NO_SAFE_MODE) { - serial_write_compressed(translate("Running in safe mode! ")); - serial_write_compressed(translate("Not running saved code.\n")); + serial_write_compressed(translate("Running in safe mode! Not running saved code.\n")); } } STATIC bool run_code_py(safe_mode_t safe_mode) { bool serial_connected_at_start = serial_connected(); + bool printed_safe_mode_message = false; #if CIRCUITPY_AUTORELOAD_DELAY_MS > 0 - serial_write("\n"); - print_code_py_status_message(safe_mode); - print_safe_mode_message(safe_mode); - serial_write("\n"); + if (serial_connected_at_start) { + serial_write("\r\n"); + print_code_py_status_message(safe_mode); + print_safe_mode_message(safe_mode); + printed_safe_mode_message = true; + } #endif pyexec_result_t result; @@ -383,8 +385,11 @@ STATIC bool run_code_py(safe_mode_t safe_mode) { print_code_py_status_message(safe_mode); } - print_safe_mode_message(safe_mode); - serial_write("\n"); + if (!printed_safe_mode_message) { + print_safe_mode_message(safe_mode); + printed_safe_mode_message = true; + } + serial_write("\r\n"); serial_write_compressed(translate("Press any key to enter the REPL. Use CTRL-D to reload.\n")); printed_press_any_key = true; } @@ -521,7 +526,6 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { usb_set_defaults(); #endif - // TODO(tannewt): Re-add support for flashing boot error output. if (ok_to_run) { bool found_boot = maybe_run_list(boot_py_filenames, NULL); (void) found_boot; diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index 060b17daf5979..8d0ff41768339 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -21,7 +21,7 @@ endif INTERNAL_LIBM = 1 # Number of USB endpoint pairs. -USB_NUM_EP = 8 +USB_NUM_ENDPOINT_PAIRS = 8 CIRCUITPY_ROTARYIO_SOFTENCODER = 1 diff --git a/ports/cxd56/mpconfigport.mk b/ports/cxd56/mpconfigport.mk index 5dbc71825df0c..edc8e6ddf5c1c 100644 --- a/ports/cxd56/mpconfigport.mk +++ b/ports/cxd56/mpconfigport.mk @@ -1,7 +1,7 @@ USB_HIGHSPEED = 1 # Number of USB endpoint pairs. -USB_NUM_EP = 6 +USB_NUM_ENDPOINT_PAIRS = 6 # Define an equivalent for MICROPY_LONGINT_IMPL, to pass to $(MPY-TOOL) in py/mkrules.mk # $(MPY-TOOL) needs to know what kind of longint to use (if any) to freeze long integers. diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk index 2671c3055801b..a8dded05deb37 100644 --- a/ports/esp32s2/mpconfigport.mk +++ b/ports/esp32s2/mpconfigport.mk @@ -27,11 +27,6 @@ CIRCUITPY_ROTARYIO = 1 CIRCUITPY_NVM = 1 CIRCUITPY_PS2IO ?= 1 CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 -# We don't have enough endpoints to include MIDI. -CIRCUITPY_USB_MIDI ?= 0 -CIRCUITPY_USB_HID ?= 1 -# We have borrowed the VENDOR nomenclature from tinyusb. VENDOR AKA WEBUSB -CIRCUITPY_USB_VENDOR ?= 0 CIRCUITPY_WIFI = 1 CIRCUITPY_WATCHDOG ?= 1 @@ -39,4 +34,14 @@ CIRCUITPY_ESPIDF = 1 CIRCUITPY_MODULE ?= none -USB_NUM_EP = 5 +# From the ESP32-S2 datasheet: +# +# Endpoint number 0 always present (bi-directional, consisting of EP0 IN and EP0 OUT) +# Six additional endpoints (endpoint numbers 1 to 6), configurable as IN or OUT +# Maximum of five IN endpoints concurrently active at any time (including EP0 IN) +# +# Due to the limited number of endpoints, some USB devices will be off by default. +# For instance MIDI is available, but the device is turned off. It can be turned on +# only if something else is turned off, such as HID. +USB_NUM_ENDPOINT_PAIRS = 7 +USB_NUM_IN_ENDPOINTS = 5 diff --git a/ports/litex/mpconfigport.mk b/ports/litex/mpconfigport.mk index d99b303f6d2c9..ce6ed08841682 100644 --- a/ports/litex/mpconfigport.mk +++ b/ports/litex/mpconfigport.mk @@ -7,7 +7,7 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz INTERNAL_LIBM = 1 # Number of USB endpoint pairs. -USB_NUM_EP = 16 +USB_NUM_ENDPOINT_PAIRS = 16 # Longints can be implemented as mpz, as longlong, or not LONGINT_IMPL = MPZ diff --git a/ports/mimxrt10xx/mpconfigport.mk b/ports/mimxrt10xx/mpconfigport.mk index 31b0dbfdac908..ac5e7fc8eda5f 100644 --- a/ports/mimxrt10xx/mpconfigport.mk +++ b/ports/mimxrt10xx/mpconfigport.mk @@ -17,7 +17,7 @@ INTERNAL_LIBM = 1 USB_HIGHSPEED = 1 # Number of USB endpoint pairs. -USB_NUM_EP = 8 +USB_NUM_ENDPOINT_PAIRS = 8 INTERNAL_FLASH_FILESYSTEM = 1 diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk index b00a051479e86..b355b8f652613 100644 --- a/ports/nrf/mpconfigport.mk +++ b/ports/nrf/mpconfigport.mk @@ -10,7 +10,7 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz INTERNAL_LIBM = 1 # Number of USB endpoint pairs. -USB_NUM_EP = 8 +USB_NUM_ENDPOINT_PAIRS = 8 # All nRF ports have longints. LONGINT_IMPL = MPZ diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index 75c5d227f00c9..8bc70ed638d60 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -49,6 +49,6 @@ CIRCUITPY_AUDIOMIXER = 1 INTERNAL_LIBM = 1 # Number of USB endpoint pairs. -USB_NUM_EP = 8 +USB_NUM_ENDPOINT_PAIRS = 8 INTERNAL_FLASH_FILESYSTEM = 1 diff --git a/ports/stm/boards/espruino_pico/mpconfigboard.mk b/ports/stm/boards/espruino_pico/mpconfigboard.mk index efbbaa22e2df3..bc415f07ec8f8 100644 --- a/ports/stm/boards/espruino_pico/mpconfigboard.mk +++ b/ports/stm/boards/espruino_pico/mpconfigboard.mk @@ -22,6 +22,8 @@ CIRCUITPY_AUDIOPWMIO = 0 CIRCUITPY_BUSDEVICE = 0 CIRCUITPY_BITMAPTOOLS = 0 CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_MIDI = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_ULAB = 0 CIRCUITPY_VECTORIO = 0 diff --git a/ports/stm/boards/pyb_nano_v2/mpconfigboard.mk b/ports/stm/boards/pyb_nano_v2/mpconfigboard.mk index 5824e65a29f4d..99af948d7bb7e 100644 --- a/ports/stm/boards/pyb_nano_v2/mpconfigboard.mk +++ b/ports/stm/boards/pyb_nano_v2/mpconfigboard.mk @@ -16,3 +16,5 @@ LD_FILE = boards/STM32F411_fs.ld # Too big for the flash CIRCUITPY_AUDIOCORE = 0 CIRCUITPY_AUDIOPWMIO = 0 +CIRCUITPY_MIDI = 0 +CIRCUITPY_MSGPACK = 0 diff --git a/ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk b/ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk index 3180fbd0845e0..04c8cc2d4503a 100644 --- a/ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk +++ b/ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk @@ -15,3 +15,5 @@ LD_FILE = boards/STM32F411_fs.ld # Too big for the flash CIRCUITPY_AUDIOCORE = 0 CIRCUITPY_AUDIOPWMIO = 0 +CIRCUITPY_MIDI = 0 +CIRCUITPY_MSGPACK = 0 diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk index ae021426dfded..551d2661d4046 100644 --- a/ports/stm/mpconfigport.mk +++ b/ports/stm/mpconfigport.mk @@ -7,7 +7,7 @@ ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F405xx STM32F407xx)) CIRCUITPY_FRAMEBUFFERIO ?= 1 CIRCUITPY_SDIOIO ?= 1 # Number of USB endpoint pairs. - USB_NUM_EP = 4 + USB_NUM_ENDPOINT_PAIRS = 4 endif ifeq ($(MCU_SERIES),F4) @@ -24,10 +24,7 @@ ifeq ($(MCU_SERIES),F4) CIRCUITPY_NVM ?= 0 CIRCUITPY_ROTARYIO ?= 0 CIRCUITPY_RTC ?= 0 - CIRCUITPY_USB_MIDI ?= 0 - CIRCUITPY_USB_HID ?= 0 - - USB_NUM_EP = 4 + USB_NUM_ENDPOINT_PAIRS = 4 endif ifeq ($(MCU_SERIES),H7) @@ -44,10 +41,8 @@ ifeq ($(MCU_SERIES),H7) CIRCUITPY_PWMIO ?= 0 CIRCUITPY_ROTARYIO ?= 0 CIRCUITPY_RTC ?= 0 - CIRCUITPY_USB_HID ?= 0 - CIRCUITPY_USB_MIDI ?= 0 - USB_NUM_EP = 9 + USB_NUM_ENDPOINT_PAIRS = 9 endif ifeq ($(MCU_SERIES),F7) @@ -62,8 +57,6 @@ ifeq ($(MCU_SERIES),F7) CIRCUITPY_NVM ?= 0 CIRCUITPY_ROTARYIO ?= 0 CIRCUITPY_RTC ?= 0 - CIRCUITPY_USB_HID ?= 0 - CIRCUITPY_USB_MIDI ?= 0 - USB_NUM_EP = 6 + USB_NUM_ENDPOINT_PAIRS = 6 endif diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index c7b83dba2104b..eec52ca5fc894 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -338,8 +338,18 @@ CFLAGS += -DCIRCUITPY_UHEAP=$(CIRCUITPY_UHEAP) CIRCUITPY_USB ?= 1 CFLAGS += -DCIRCUITPY_USB=$(CIRCUITPY_USB) -# Compute this value once, so the shell command is not reinvoked many times. -USB_NUM_EP_8_OR_GREATER := $(shell expr $(USB_NUM_EP) '>=' 8) +# Compute these value once, so the shell command is not reinvoked many times. +USB_NUM_ENDPOINT_PAIRS_5_OR_GREATER := $(shell expr $(USB_NUM_ENDPOINT_PAIRS) '>=' 5) +USB_NUM_ENDPOINT_PAIRS_8_OR_GREATER := $(shell expr $(USB_NUM_ENDPOINT_PAIRS) '>=' 8) + +# Some chips may not support the same number of IN or OUT endpoints as pairs. +# For instance, the ESP32-S2 only supports 5 IN endpoints at once, even though +# it has 7 endpoint pairs. +USB_NUM_IN_ENDPOINTS ?= $(USB_NUM_ENDPOINT_PAIRS) +CFLAGS += -DUSB_NUM_IN_ENDPOINTS=$(USB_NUM_IN_ENDPOINTS) + +USB_NUM_OUT_ENDPOINTS ?= $(USB_NUM_ENDPOINT_PAIRS) +CFLAGS += -DUSB_NUM_OUT_ENDPOINTS=$(USB_NUM_OUT_ENDPOINTS) CIRCUITPY_USB_CDC ?= 1 CFLAGS += -DCIRCUITPY_USB_CDC=$(CIRCUITPY_USB_CDC) @@ -348,20 +358,21 @@ CFLAGS += -DCIRCUITPY_USB_CDC_CONSOLE_ENABLED_DEFAULT=$(CIRCUITPY_USB_CDC_CONSOL CIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT ?= 0 CFLAGS += -DCIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT=$(CIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT) +# HID is available by default, but is not turned on if there are fewer than 5 endpoints. CIRCUITPY_USB_HID ?= 1 CFLAGS += -DCIRCUITPY_USB_HID=$(CIRCUITPY_USB_HID) -CIRCUITPY_USB_HID_ENABLED_DEFAULT = $(CIRCUITPY_USB_HID) +CIRCUITPY_USB_HID_ENABLED_DEFAULT ?= $(USB_NUM_ENDPOINT_PAIRS_5_OR_GREATER) CFLAGS += -DCIRCUITPY_USB_HID_ENABLED_DEFAULT=$(CIRCUITPY_USB_HID_ENABLED_DEFAULT) -# MIDI is usually available if there are at least 8 endpoints. -CIRCUITPY_USB_MIDI ?= $(USB_NUM_EP_8_OR_GREATER) +# MIDI is available by default, but is not turned on if there are fewer than 8 endpoints. +CIRCUITPY_USB_MIDI ?= 1 CFLAGS += -DCIRCUITPY_USB_MIDI=$(CIRCUITPY_USB_MIDI) -CIRCUITPY_USB_MIDI_ENABLED_DEFAULT = $(CIRCUITPY_USB_MIDI) +CIRCUITPY_USB_MIDI_ENABLED_DEFAULT ?= $(USB_NUM_ENDPOINT_PAIRS_8_OR_GREATER) CFLAGS += -DCIRCUITPY_USB_MIDI_ENABLED_DEFAULT=$(CIRCUITPY_USB_MIDI_ENABLED_DEFAULT) CIRCUITPY_USB_MSC ?= 1 CFLAGS += -DCIRCUITPY_USB_MSC=$(CIRCUITPY_USB_MSC) -CIRCUITPY_USB_MSC_ENABLED_DEFAULT = $(CIRCUITPY_USB_MSC) +CIRCUITPY_USB_MSC_ENABLED_DEFAULT ?= $(CIRCUITPY_USB_MSC) CFLAGS += -DCIRCUITPY_USB_MSC_ENABLED_DEFAULT=$(CIRCUITPY_USB_MSC_ENABLED_DEFAULT) # Defaulting this to OFF initially because it has only been tested on a @@ -370,10 +381,10 @@ CFLAGS += -DCIRCUITPY_USB_MSC_ENABLED_DEFAULT=$(CIRCUITPY_USB_MSC_ENABLED_DEFAUL CIRCUITPY_USB_VENDOR ?= 0 CFLAGS += -DCIRCUITPY_USB_VENDOR=$(CIRCUITPY_USB_VENDOR) -ifndef USB_NUM_EP -$(error "USB_NUM_EP (number of USB endpoint pairs)must be defined") +ifndef USB_NUM_ENDPOINT_PAIRS +$(error "USB_NUM_ENDPOINT_PAIRS (number of USB endpoint pairs)must be defined") endif -CFLAGS += -DUSB_NUM_EP=$(USB_NUM_EP) +CFLAGS += -DUSB_NUM_ENDPOINT_PAIRS=$(USB_NUM_ENDPOINT_PAIRS) # For debugging. CIRCUITPY_USTACK ?= 0 diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 754b6866c879f..f19aaa4396468 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -176,7 +176,13 @@ MP_DEFINE_CONST_FUN_OBJ_0(storage_disable_usb_drive_obj, storage_disable_usb_dri //| """Enabled presenting ``CIRCUITPY`` as a USB mass storage device. //| By default, the device is enabled and ``CIRCUITPY`` is visible, //| so you do not normally need to call this function. -//| Can be called in ``boot.py``, before USB is connected.""" +//| Can be called in ``boot.py``, before USB is connected. +//| +//| If you enable too many devices at once, you will run out of USB endpoints. +//| The number of available endpoints varies by microcontroller. +//| CircuitPython will go into safe mode after running boot.py to inform you if +//| not enough endpoints are available. +//| """ //| ... //| STATIC mp_obj_t storage_enable_usb_drive(void) { diff --git a/shared-bindings/usb_cdc/__init__.c b/shared-bindings/usb_cdc/__init__.c index 557c06a3ec35b..f16373fa7324a 100644 --- a/shared-bindings/usb_cdc/__init__.c +++ b/shared-bindings/usb_cdc/__init__.c @@ -82,7 +82,13 @@ MP_DEFINE_CONST_FUN_OBJ_0(usb_cdc_disable_obj, usb_cdc_disable); //| :param console bool: Enable or disable the `console` USB serial device. //| True to enable; False to disable. Enabled by default. //| :param data bool: Enable or disable the `data` USB serial device. -//| True to enable; False to disable. *Disabled* by default.""" +//| True to enable; False to disable. *Disabled* by default. +//| +//| If you enable too many devices at once, you will run out of USB endpoints. +//| The number of available endpoints varies by microcontroller. +//| CircuitPython will go into safe mode after running boot.py to inform you if +//| not enough endpoints are available. +//| """ //| ... //| STATIC mp_obj_t usb_cdc_enable(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { diff --git a/shared-bindings/usb_hid/__init__.c b/shared-bindings/usb_hid/__init__.c index 8e85cc67f03c7..f5a7c1cf725d3 100644 --- a/shared-bindings/usb_hid/__init__.c +++ b/shared-bindings/usb_hid/__init__.c @@ -37,12 +37,21 @@ //| //| devices: Tuple[Device, ...] -//| """Tuple of all active HID device interfaces.""" +//| """Tuple of all active HID device interfaces. +//| The default set of devices is ``Device.KEYBOARD, Device.MOUSE, Device.CONSUMER_CONTROL``, +//| On boards where `usb_hid` is disabled by default, `devices` is an empty tuple. +//| """ //| //| def disable() -> None: //| """Do not present any USB HID devices to the host computer. -//| Can be called in ``boot.py``, before USB is connected.""" +//| Can be called in ``boot.py``, before USB is connected. +//| The HID composite device is normally enabled by default, +//| but on some boards with limited endpoints, including STM32F4, +//| it is disabled by default. You must turn off another USB device such +//| as `usb_cdc` or `storage` to free up endpoints for use by `usb_hid`. +//| """ +//| STATIC mp_obj_t usb_hid_disable(void) { if (!common_hal_usb_hid_disable()) { mp_raise_RuntimeError(translate("Cannot change USB devices now")); @@ -59,6 +68,11 @@ MP_DEFINE_CONST_FUN_OBJ_0(usb_hid_disable_obj, usb_hid_disable); //| If `devices` is empty, HID is disabled. The order of the ``Devices`` //| may matter to the host. For instance, for MacOS, put the mouse device //| before any Gamepad or Digitizer HID device or else it will not work. +//| +//| If you enable too many devices at once, you will run out of USB endpoints. +//| The number of available endpoints varies by microcontroller. +//| CircuitPython will go into safe mode after running boot.py to inform you if +//| not enough endpoints are available. //| """ //| ... //| diff --git a/shared-bindings/usb_midi/__init__.c b/shared-bindings/usb_midi/__init__.c index a3ed06dd8c71d..9c583fb78e556 100644 --- a/shared-bindings/usb_midi/__init__.c +++ b/shared-bindings/usb_midi/__init__.c @@ -45,7 +45,8 @@ //| def disable() -> None: //| """Disable presenting a USB MIDI device to the host. -//| The device is normally enabled by default. +//| The device is normally enabled by default, but on some boards with limited endpoints +//| including ESP32-S2 and certain STM boards, it is disabled by default. //| Can be called in ``boot.py``, before USB is connected.""" //| ... //| @@ -60,7 +61,13 @@ MP_DEFINE_CONST_FUN_OBJ_0(usb_midi_disable_obj, usb_midi_disable); //| def enable() -> None: //| """Enable presenting a USB MIDI device to the host. //| The device is enabled by default, so you do not normally need to call this function. -//| Can be called in ``boot.py``, before USB is connected.""" +//| Can be called in ``boot.py``, before USB is connected. +//| +//| If you enable too many devices at once, you will run out of USB endpoints. +//| The number of available endpoints varies by microcontroller. +//| CircuitPython will go into safe mode after running boot.py to inform you if +//| not enough endpoints are available. +//| """ //| ... //| STATIC mp_obj_t usb_midi_enable(void) { diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index b1d038a7d30de..cbe72c6f161a2 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -93,14 +93,18 @@ size_t storage_usb_descriptor_length(void) { static const char storage_interface_name[] = USB_INTERFACE_NAME " Mass Storage"; -size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t *current_interface_string) { +size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string) { memcpy(descriptor_buf, usb_msc_descriptor_template, sizeof(usb_msc_descriptor_template)); - descriptor_buf[MSC_INTERFACE_INDEX] = *current_interface; - (*current_interface)++; - - descriptor_buf[MSC_IN_ENDPOINT_INDEX] = 0x80 | (USB_MSC_EP_NUM_IN ? USB_MSC_EP_NUM_IN : *current_endpoint); - descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = USB_MSC_EP_NUM_OUT ? USB_MSC_EP_NUM_OUT : *current_endpoint; - (*current_endpoint)++; + descriptor_buf[MSC_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_counts->current_interface++; + + descriptor_buf[MSC_IN_ENDPOINT_INDEX] = + 0x80 | (USB_MSC_EP_NUM_IN ? USB_MSC_EP_NUM_IN : descriptor_counts->current_endpoint); + descriptor_counts->num_in_endpoints++; + descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = + USB_MSC_EP_NUM_OUT ? USB_MSC_EP_NUM_OUT : descriptor_counts->current_endpoint; + descriptor_counts->num_out_endpoints++; + descriptor_counts->current_endpoint++; usb_add_interface_string(*current_interface_string, storage_interface_name); descriptor_buf[MSC_INTERFACE_STRING_INDEX] = *current_interface_string; diff --git a/shared-module/storage/__init__.h b/shared-module/storage/__init__.h index addc8e3d05d77..a07e2c2e0e720 100644 --- a/shared-module/storage/__init__.h +++ b/shared-module/storage/__init__.h @@ -28,12 +28,13 @@ #define SHARED_MODULE_STORAGE___INIT___H #include "py/mpconfig.h" +#include "supervisor/usb.h" #if CIRCUITPY_USB bool storage_usb_enabled(void); void storage_usb_set_defaults(void); size_t storage_usb_descriptor_length(void); -size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t *current_interface_string); +size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string); #endif #endif // SHARED_MODULE_STORAGE___INIT___H diff --git a/shared-module/usb_cdc/__init__.c b/shared-module/usb_cdc/__init__.c index 446c65931e038..c5da1f41e0379 100644 --- a/shared-module/usb_cdc/__init__.c +++ b/shared-module/usb_cdc/__init__.c @@ -173,37 +173,39 @@ size_t usb_cdc_descriptor_length(void) { return sizeof(usb_cdc_descriptor_template); } -size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t *current_interface_string, bool console) { +size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string, bool console) { memcpy(descriptor_buf, usb_cdc_descriptor_template, sizeof(usb_cdc_descriptor_template)); // Store comm interface number. - descriptor_buf[CDC_FIRST_INTERFACE_INDEX] = *current_interface; - descriptor_buf[CDC_COMM_INTERFACE_INDEX] = *current_interface; - descriptor_buf[CDC_UNION_MASTER_INTERFACE_INDEX] = *current_interface; - (*current_interface)++; + descriptor_buf[CDC_FIRST_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_buf[CDC_COMM_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_buf[CDC_UNION_MASTER_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_counts->current_interface++; // Now store data interface number. - descriptor_buf[CDC_CALL_MANAGEMENT_DATA_INTERFACE_INDEX] = *current_interface; - descriptor_buf[CDC_UNION_SLAVE_INTERFACE_INDEX] = *current_interface; - descriptor_buf[CDC_DATA_INTERFACE_INDEX] = *current_interface; - (*current_interface)++; + descriptor_buf[CDC_CALL_MANAGEMENT_DATA_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_buf[CDC_UNION_SLAVE_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_buf[CDC_DATA_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_counts->current_interface++; descriptor_buf[CDC_CONTROL_IN_ENDPOINT_INDEX] = 0x80 | ( console - ? (USB_CDC_EP_NUM_NOTIFICATION ? USB_CDC_EP_NUM_NOTIFICATION : *current_endpoint) - : (USB_CDC2_EP_NUM_NOTIFICATION ? USB_CDC2_EP_NUM_NOTIFICATION : *current_endpoint)); - (*current_endpoint)++; - - descriptor_buf[CDC_DATA_OUT_ENDPOINT_INDEX] = - console - ? (USB_CDC_EP_NUM_DATA_OUT ? USB_CDC_EP_NUM_DATA_OUT : *current_endpoint) - : (USB_CDC2_EP_NUM_DATA_OUT ? USB_CDC2_EP_NUM_DATA_OUT : *current_endpoint); + ? (USB_CDC_EP_NUM_NOTIFICATION ? USB_CDC_EP_NUM_NOTIFICATION : descriptor_counts->current_endpoint) + : (USB_CDC2_EP_NUM_NOTIFICATION ? USB_CDC2_EP_NUM_NOTIFICATION : descriptor_counts->current_endpoint)); + descriptor_counts->num_in_endpoints++; + descriptor_counts->current_endpoint++; descriptor_buf[CDC_DATA_IN_ENDPOINT_INDEX] = 0x80 | ( console - ? (USB_CDC_EP_NUM_DATA_IN ? USB_CDC_EP_NUM_DATA_IN : *current_endpoint) - : (USB_CDC2_EP_NUM_DATA_IN ? USB_CDC2_EP_NUM_DATA_IN : *current_endpoint)); - (*current_endpoint)++; + ? (USB_CDC_EP_NUM_DATA_IN ? USB_CDC_EP_NUM_DATA_IN : descriptor_counts->current_endpoint) + : (USB_CDC2_EP_NUM_DATA_IN ? USB_CDC2_EP_NUM_DATA_IN : descriptor_counts->current_endpoint)); + descriptor_counts->num_in_endpoints++; + descriptor_buf[CDC_DATA_OUT_ENDPOINT_INDEX] = + console + ? (USB_CDC_EP_NUM_DATA_OUT ? USB_CDC_EP_NUM_DATA_OUT : descriptor_counts->current_endpoint) + : (USB_CDC2_EP_NUM_DATA_OUT ? USB_CDC2_EP_NUM_DATA_OUT : descriptor_counts->current_endpoint); + descriptor_counts->num_out_endpoints++; + descriptor_counts->current_endpoint++; usb_add_interface_string(*current_interface_string, console ? console_cdc_comm_interface_name : data_cdc_comm_interface_name); diff --git a/shared-module/usb_cdc/__init__.h b/shared-module/usb_cdc/__init__.h index ae39143017816..5195c964e25e8 100644 --- a/shared-module/usb_cdc/__init__.h +++ b/shared-module/usb_cdc/__init__.h @@ -29,6 +29,7 @@ #include "py/mpconfig.h" #include "py/objtuple.h" +#include "supervisor/usb.h" bool usb_cdc_console_enabled(void); bool usb_cdc_data_enabled(void); @@ -36,6 +37,6 @@ bool usb_cdc_data_enabled(void); void usb_cdc_set_defaults(void); size_t usb_cdc_descriptor_length(void); -size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t *current_interface_string, bool repl); +size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string, bool console); #endif /* SHARED_MODULE_USB_CDC___INIT___H */ diff --git a/shared-module/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c index c1df75b9d813c..a92fd0c725254 100644 --- a/shared-module/usb_hid/__init__.c +++ b/shared-module/usb_hid/__init__.c @@ -113,11 +113,11 @@ size_t usb_hid_descriptor_length(void) { static const char usb_hid_interface_name[] = USB_INTERFACE_NAME " HID"; // This is the interface descriptor, not the report descriptor. -size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t *current_interface_string, uint16_t report_descriptor_length) { +size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string, uint16_t report_descriptor_length) { memcpy(descriptor_buf, usb_hid_descriptor_template, sizeof(usb_hid_descriptor_template)); - descriptor_buf[HID_DESCRIPTOR_INTERFACE_INDEX] = *current_interface; - (*current_interface)++; + descriptor_buf[HID_DESCRIPTOR_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_counts->current_interface++; usb_add_interface_string(*current_interface_string, usb_hid_interface_name); descriptor_buf[HID_DESCRIPTOR_INTERFACE_STRING_INDEX] = *current_interface_string; @@ -126,9 +126,13 @@ size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfac descriptor_buf[HID_DESCRIPTOR_LENGTH_INDEX] = report_descriptor_length & 0xFF; descriptor_buf[HID_DESCRIPTOR_LENGTH_INDEX + 1] = (report_descriptor_length >> 8); - descriptor_buf[HID_IN_ENDPOINT_INDEX] = 0x80 | (USB_HID_EP_NUM_IN ? USB_HID_EP_NUM_IN : *current_endpoint); - descriptor_buf[HID_OUT_ENDPOINT_INDEX] = USB_HID_EP_NUM_OUT ? USB_HID_EP_NUM_OUT : *current_endpoint; - (*current_endpoint)++; + descriptor_buf[HID_IN_ENDPOINT_INDEX] = + 0x80 | (USB_HID_EP_NUM_IN ? USB_HID_EP_NUM_IN : descriptor_counts->current_endpoint); + descriptor_counts->num_in_endpoints++; + descriptor_buf[HID_OUT_ENDPOINT_INDEX] = + USB_HID_EP_NUM_OUT ? USB_HID_EP_NUM_OUT : descriptor_counts->current_endpoint; + descriptor_counts->num_out_endpoints++; + descriptor_counts->current_endpoint++; return sizeof(usb_hid_descriptor_template); } diff --git a/shared-module/usb_hid/__init__.h b/shared-module/usb_hid/__init__.h index 24a4d57a69230..5069effd3d857 100644 --- a/shared-module/usb_hid/__init__.h +++ b/shared-module/usb_hid/__init__.h @@ -28,13 +28,14 @@ #define SHARED_MODULE_USB_HID___INIT___H #include "shared-module/usb_hid/Device.h" +#include "supervisor/usb.h" extern usb_hid_device_obj_t usb_hid_devices[]; bool usb_hid_enabled(void); void usb_hid_set_defaults(void); -size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t *current_interface_string, uint16_t report_descriptor_length); +size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string, uint16_t report_descriptor_length); size_t usb_hid_descriptor_length(void); size_t usb_hid_report_descriptor_length(void); diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c index c258d35c23a64..ac2e05adcb849 100644 --- a/shared-module/usb_midi/__init__.c +++ b/shared-module/usb_midi/__init__.c @@ -175,36 +175,38 @@ static const char midi_audio_control_interface_name[] = USB_INTERFACE_NAME " Aud static const char midi_in_jack_name[] = USB_INTERFACE_NAME " usb_midi.ports[0]"; static const char midi_out_jack_name[] = USB_INTERFACE_NAME " usb_midi.ports[0]"; -size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t *current_interface_string) { +size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string) { memcpy(descriptor_buf, usb_midi_descriptor_template, sizeof(usb_midi_descriptor_template)); - descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_NUMBER_INDEX] = *current_interface; - (*current_interface)++; + descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_NUMBER_INDEX] = descriptor_counts->current_interface; + descriptor_counts->current_interface++; descriptor_buf[MIDI_STREAMING_IN_ENDPOINT_INDEX] = - 0x80 | (USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : *current_endpoint); + 0x80 | (USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : descriptor_counts->current_endpoint); + descriptor_counts->num_in_endpoints++; descriptor_buf[MIDI_STREAMING_OUT_ENDPOINT_INDEX] = - USB_MIDI_EP_NUM_OUT ? USB_MIDI_EP_NUM_OUT : *current_endpoint; - (*current_endpoint)++; + USB_MIDI_EP_NUM_OUT ? USB_MIDI_EP_NUM_OUT : descriptor_counts->current_endpoint; + descriptor_counts->num_out_endpoints++; + descriptor_counts->current_endpoint++; - descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX] = *current_interface; - descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX_2] = *current_interface; - (*current_interface)++; + descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX] = descriptor_counts->current_interface; + descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX_2] = descriptor_counts->current_interface; + descriptor_counts->current_interface++; usb_add_interface_string(*current_interface_string, midi_streaming_interface_name); - descriptor_buf[MIDI_STREAMING_INTERFACE_STRING_INDEX] = *current_interface; + descriptor_buf[MIDI_STREAMING_INTERFACE_STRING_INDEX] = *current_interface_string; (*current_interface_string)++; usb_add_interface_string(*current_interface_string, midi_audio_control_interface_name); - descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_STRING_INDEX] = *current_interface; + descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_STRING_INDEX] = *current_interface_string; (*current_interface_string)++; usb_add_interface_string(*current_interface_string, midi_in_jack_name); - descriptor_buf[MIDI_IN_JACK_STRING_INDEX] = *current_interface; + descriptor_buf[MIDI_IN_JACK_STRING_INDEX] = *current_interface_string; (*current_interface_string)++; usb_add_interface_string(*current_interface_string, midi_out_jack_name); - descriptor_buf[MIDI_OUT_JACK_STRING_INDEX] = *current_interface; + descriptor_buf[MIDI_OUT_JACK_STRING_INDEX] = *current_interface_string; (*current_interface_string)++; return sizeof(usb_midi_descriptor_template); diff --git a/shared-module/usb_midi/__init__.h b/shared-module/usb_midi/__init__.h index 9ab61e12dbe06..8cc430efe338e 100644 --- a/shared-module/usb_midi/__init__.h +++ b/shared-module/usb_midi/__init__.h @@ -27,11 +27,13 @@ #ifndef SHARED_MODULE_USB_MIDI___INIT___H #define SHARED_MODULE_USB_MIDI___INIT___H +#include "supervisor/usb.h" + bool usb_midi_enabled(void); void usb_midi_set_defaults(void); void usb_midi_setup_ports(void); size_t usb_midi_descriptor_length(void); -size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t *current_interface_string); +size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string); #endif /* SHARED_MODULE_USB_MIDI___INIT___H */ diff --git a/supervisor/shared/safe_mode.c b/supervisor/shared/safe_mode.c index 661fd79af8397..ec85ea9d43eb1 100644 --- a/supervisor/shared/safe_mode.c +++ b/supervisor/shared/safe_mode.c @@ -117,13 +117,17 @@ void __attribute__((noinline,)) reset_into_safe_mode(safe_mode_t reason) { -#define FILE_AN_ISSUE translate("\nPlease file an issue with the contents of your CIRCUITPY drive at \nhttps://github.com/adafruit/circuitpython/issues\n") - void print_safe_mode_message(safe_mode_t reason) { if (reason == NO_SAFE_MODE) { return; } - serial_write("\n"); + + serial_write("\r\n"); + serial_write_compressed(translate("You are in safe mode because:\n")); + + const compressed_string_t *message = NULL; + + // First check for safe mode reasons that do not necessarily reflect bugs. switch (reason) { case USER_SAFE_MODE: @@ -133,40 +137,40 @@ void print_safe_mode_message(safe_mode_t reason) { serial_write_compressed(BOARD_USER_SAFE_MODE_ACTION); serial_write_compressed(translate("To exit, please reset the board without ")); serial_write_compressed(BOARD_USER_SAFE_MODE_ACTION); - #else - break; #endif - return; + break; case MANUAL_SAFE_MODE: - serial_write_compressed(translate("CircuitPython is in safe mode because you pressed the reset button during boot. Press again to exit safe mode.\n")); - return; + message = translate("You pressed the reset button during boot. Press again to exit safe mode."); + break; case PROGRAMMATIC_SAFE_MODE: - serial_write_compressed(translate("The `microcontroller` module was used to boot into safe mode. Press reset to exit safe mode.\n")); - return; - default: + message = translate("The `microcontroller` module was used to boot into safe mode. Press reset to exit safe mode."); break; - } - - serial_write_compressed(translate("You are in safe mode: something unanticipated happened.\n")); - switch (reason) { case BROWNOUT: - serial_write_compressed(translate("The microcontroller's power dipped. Make sure your power supply provides\nenough power for the whole circuit and press reset (after ejecting CIRCUITPY).\n")); - return; - case HEAP_OVERWRITTEN: - serial_write_compressed(translate("The CircuitPython heap was corrupted because the stack was too small.\nPlease increase the stack size if you know how, or if not:")); - serial_write_compressed(FILE_AN_ISSUE); - return; - case NO_HEAP: - serial_write_compressed(translate("CircuitPython was unable to allocate the heap.\n")); - serial_write_compressed(FILE_AN_ISSUE); - return; + message = translate("The microcontroller's power dipped. Make sure your power supply provides\nenough power for the whole circuit and press reset (after ejecting CIRCUITPY)."); + break; + case USB_TOO_MANY_ENDPOINTS: + message = translate("USB devices need more endpoints than are available."); + break; + case USB_TOO_MANY_INTERFACE_NAMES: + message = translate("USB devices specify too many interface names."); + break; + case WATCHDOG_RESET: + message = translate("Watchdog timer expired."); + break; default: break; } + if (message) { + serial_write_compressed(message); + serial_write("\r\n"); + return; + } + + // Something worse happened. + serial_write_compressed(translate("CircuitPython core code crashed hard. Whoops!\n")); - const compressed_string_t *message = NULL; switch (reason) { case HARD_CRASH: message = translate("Crash into the HardFault_Handler."); @@ -177,6 +181,12 @@ void print_safe_mode_message(safe_mode_t reason) { case MICROPY_FATAL_ERROR: message = translate("Fatal error."); break; + case NO_HEAP: + message = translate("CircuitPython was unable to allocate the heap."); + break; + case HEAP_OVERWRITTEN: + message = translate("The CircuitPython heap was corrupted because the stack was too small.\nIncrease the stack size if you know how. If not:"); + break; case GC_ALLOC_OUTSIDE_VM: message = translate("Attempted heap allocation when VM not running."); break; @@ -193,19 +203,10 @@ void print_safe_mode_message(safe_mode_t reason) { case MEM_MANAGE: message = translate("Invalid memory access."); break; - case WATCHDOG_RESET: - message = translate("Watchdog timer expired."); - break; - case USB_TOO_MANY_ENDPOINTS: - message = translate("USB devices need more endpoints than are available."); - break; - case USB_TOO_MANY_INTERFACE_NAMES: - message = translate("USB devices specify too many interface names."); - break; default: message = translate("Unknown reason."); break; } serial_write_compressed(message); - serial_write_compressed(FILE_AN_ISSUE); + serial_write_compressed(translate("\nPlease file an issue with the contents of your CIRCUITPY drive at \nhttps://github.com/adafruit/circuitpython/issues\n")); } diff --git a/supervisor/shared/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c index f1d2ac719692c..bad0d84523374 100644 --- a/supervisor/shared/usb/usb_desc.c +++ b/supervisor/shared/usb/usb_desc.c @@ -184,9 +184,16 @@ static void usb_build_configuration_descriptor(void) { configuration_descriptor[CONFIG_TOTAL_LENGTH_HI_INDEX] = (total_descriptor_length >> 8) & 0xFF; // Number interfaces and endpoints. - // Endpoint 0 is already used for USB control, so start with 1. - uint8_t current_interface = 0; - uint8_t current_endpoint = 1; + // Endpoint 0 is already used for USB control, + // so start with 1 for the current endpoint and for the number of in and out endpoints + // already in use. + + descriptor_counts_t descriptor_counts = { + .current_interface = 0, + .current_endpoint = 1, + .num_in_endpoints = 1, + .num_out_endpoints = 1, + }; uint8_t *descriptor_buf_remaining = configuration_descriptor + sizeof(configuration_descriptor_template); @@ -194,12 +201,13 @@ static void usb_build_configuration_descriptor(void) { if (usb_cdc_console_enabled()) { // Concatenate and fix up the CDC REPL descriptor. descriptor_buf_remaining += usb_cdc_add_descriptor( - descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string, true); + descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string, true /*console*/); + } if (usb_cdc_data_enabled()) { // Concatenate and fix up the CDC data descriptor. descriptor_buf_remaining += usb_cdc_add_descriptor( - descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string, false); + descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string, false /*console*/); } #endif @@ -207,14 +215,14 @@ static void usb_build_configuration_descriptor(void) { if (storage_usb_enabled()) { // Concatenate and fix up the MSC descriptor. descriptor_buf_remaining += storage_usb_add_descriptor( - descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string); + descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string); } #endif #if CIRCUITPY_USB_HID if (usb_hid_enabled()) { descriptor_buf_remaining += usb_hid_add_descriptor( - descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string, + descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string, usb_hid_report_descriptor_length()); } #endif @@ -223,18 +231,19 @@ static void usb_build_configuration_descriptor(void) { if (usb_midi_enabled()) { // Concatenate and fix up the MIDI descriptor. descriptor_buf_remaining += usb_midi_add_descriptor( - descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string); + descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string); } #endif // Now we know how many interfaces have been used. - configuration_descriptor[CONFIG_NUM_INTERFACES_INDEX] = current_interface; + configuration_descriptor[CONFIG_NUM_INTERFACES_INDEX] = descriptor_counts.current_interface; // Did we run out of endpoints? - if (current_endpoint - 1 > USB_NUM_EP) { + if (descriptor_counts.current_endpoint > USB_NUM_ENDPOINT_PAIRS || + descriptor_counts.num_in_endpoints > USB_NUM_IN_ENDPOINTS || + descriptor_counts.num_out_endpoints > USB_NUM_OUT_ENDPOINTS) { reset_into_safe_mode(USB_TOO_MANY_ENDPOINTS); } - } // str must not be on the heap. diff --git a/supervisor/usb.h b/supervisor/usb.h index 918da988975db..e0feb58ea86ee 100644 --- a/supervisor/usb.h +++ b/supervisor/usb.h @@ -50,6 +50,14 @@ void init_usb_hardware(void); // Temporary hook for code after init. Only used for RP2040. void post_usb_init(void); +// Indexes and counts updated as descriptors are built. +typedef struct { + size_t current_interface; + size_t current_endpoint; + size_t num_in_endpoints; + size_t num_out_endpoints; +} descriptor_counts_t; + // Shared implementation. bool usb_enabled(void); void usb_add_interface_string(uint8_t interface_string_index, const char str[]);