From fa6c06fb3814797b128913d59bf6624db513471d Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 13 May 2021 21:49:04 -0400 Subject: [PATCH] count in/out endpoints; allow more usb modules on low-endpoint boards --- locale/ID.po | 2 +- locale/de_DE.po | 4 +-- locale/en_GB.po | 4 +-- locale/es.po | 6 ++--- locale/fr.po | 4 +-- locale/hi.po | 2 +- locale/ja.po | 8 +++--- locale/nl.po | 4 +-- locale/pl.po | 4 +-- locale/pt_BR.po | 6 ++--- locale/sv.po | 4 +-- locale/zh_Latn_pinyin.po | 4 +-- ports/atmel-samd/mpconfigport.mk | 2 +- ports/cxd56/mpconfigport.mk | 2 +- ports/esp32s2/mpconfigport.mk | 17 +++++++----- ports/litex/mpconfigport.mk | 2 +- ports/mimxrt10xx/mpconfigport.mk | 2 +- ports/nrf/mpconfigport.mk | 2 +- ports/raspberrypi/mpconfigport.mk | 2 +- ports/stm/mpconfigport.mk | 15 +++-------- py/circuitpy_mpconfig.mk | 29 +++++++++++++------- shared-bindings/storage/__init__.c | 8 +++++- shared-bindings/usb_cdc/__init__.c | 8 +++++- shared-bindings/usb_hid/__init__.c | 18 +++++++++++-- shared-bindings/usb_midi/__init__.c | 11 ++++++-- shared-module/storage/__init__.c | 16 ++++++----- shared-module/storage/__init__.h | 3 ++- shared-module/usb_cdc/__init__.c | 42 +++++++++++++++-------------- shared-module/usb_cdc/__init__.h | 3 ++- shared-module/usb_hid/__init__.c | 16 ++++++----- shared-module/usb_hid/__init__.h | 3 ++- shared-module/usb_midi/__init__.c | 28 ++++++++++--------- shared-module/usb_midi/__init__.h | 4 ++- supervisor/shared/usb/usb_desc.c | 31 +++++++++++++-------- supervisor/usb.h | 8 ++++++ 35 files changed, 200 insertions(+), 124 deletions(-) diff --git a/locale/ID.po b/locale/ID.po index 33767f674f..21a16f4314 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/de_DE.po b/locale/de_DE.po index 3aaf33b57b..641baa8e04 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 7fbac0439c..ae8e3ff102 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 096d413b07..7349726454 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 c422a12a51..30be3b6cbe 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 369280fd9d..566ed31686 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 5bb6460559..b1ce5591fd 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 475ba432bf..ff030620eb 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 c419e6aaaa..0a8d30f604 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 dc95cee047..8e854609b7 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 4d511c50cd..aaef6de777 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 2978380792..4a31b32cfa 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/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index 060b17daf5..8d0ff41768 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 5dbc71825d..edc8e6ddf5 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 2671c30558..a8dded05de 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 d99b303f6d..ce6ed08841 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 31b0dbfdac..ac5e7fc8ed 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 b00a051479..b355b8f652 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 75c5d227f0..8bc70ed638 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/mpconfigport.mk b/ports/stm/mpconfigport.mk index ae021426df..551d2661d4 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 90e78da0da..eec52ca5fc 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,15 +358,16 @@ 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 @@ -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 754b6866c8..f19aaa4396 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 557c06a3ec..f16373fa73 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 8e85cc67f0..f5a7c1cf72 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 a3ed06dd8c..9c583fb78e 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 b1d038a7d3..cbe72c6f16 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_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 : *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_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 addc8e3d05..a07e2c2e0e 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 446c65931e..c5da1f41e0 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 ae39143017..5195c964e2 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 c1df75b9d8..a92fd0c725 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 24a4d57a69..5069effd3d 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 c258d35c23..ac2e05adcb 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 9ab61e12db..8cc430efe3 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/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c index c1be34a5fb..bad0d84523 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 > 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 918da98897..e0feb58ea8 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[]);