diff --git a/ports/atmel-samd/common-hal/microcontroller/Processor.c b/ports/atmel-samd/common-hal/microcontroller/Processor.c index 8c288a352e..44517f00c5 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Processor.c +++ b/ports/atmel-samd/common-hal/microcontroller/Processor.c @@ -346,7 +346,7 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { for (int i=0; i<4; i++) { for (int k=0; k<4; k++) { - raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; + raw_id[4 * i + (3 -k)] = (*(id_addresses[i]) >> k * 8) & 0xff; } } } diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index 7be9e203a8..559db97ca3 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -20,8 +20,6 @@ endif INTERNAL_LIBM = 1 -USB_SERIAL_NUMBER_LENGTH = 32 - # Number of USB endpoint pairs. USB_NUM_EP = 8 diff --git a/ports/cxd56/mpconfigport.mk b/ports/cxd56/mpconfigport.mk index e767c6326f..a010f16778 100644 --- a/ports/cxd56/mpconfigport.mk +++ b/ports/cxd56/mpconfigport.mk @@ -1,4 +1,3 @@ -USB_SERIAL_NUMBER_LENGTH = 10 USB_HIGHSPEED = 1 USB_RENUMBER_ENDPOINTS = 0 USB_CDC_EP_NUM_NOTIFICATION = 3 diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk index 5073d8812d..2671c30558 100644 --- a/ports/esp32s2/mpconfigport.mk +++ b/ports/esp32s2/mpconfigport.mk @@ -6,9 +6,6 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz # Internal math library is substantially smaller than toolchain one INTERNAL_LIBM = 1 -# Chip supplied serial number, in bytes -USB_SERIAL_NUMBER_LENGTH = 12 - # Longints can be implemented as mpz, as longlong, or not LONGINT_IMPL = MPZ diff --git a/ports/litex/mpconfigport.mk b/ports/litex/mpconfigport.mk index af6a94e64a..990b462dce 100644 --- a/ports/litex/mpconfigport.mk +++ b/ports/litex/mpconfigport.mk @@ -9,9 +9,6 @@ INTERNAL_LIBM = 1 # Number of USB endpoint pairs. USB_NUM_EP = 16 -# Chip supplied serial number, in bytes -USB_SERIAL_NUMBER_LENGTH = 30 - # 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 89c6d8c941..36d8f7deb8 100644 --- a/ports/mimxrt10xx/mpconfigport.mk +++ b/ports/mimxrt10xx/mpconfigport.mk @@ -14,7 +14,6 @@ endif INTERNAL_LIBM = 1 -USB_SERIAL_NUMBER_LENGTH = 32 USB_HIGHSPEED = 1 # Number of USB endpoint pairs. diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk index 83924ff795..2bb7cca59f 100644 --- a/ports/nrf/mpconfigport.mk +++ b/ports/nrf/mpconfigport.mk @@ -9,8 +9,6 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz INTERNAL_LIBM = 1 -USB_SERIAL_NUMBER_LENGTH = 16 - # Number of USB endpoint pairs. USB_NUM_EP = 8 diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index ddbd0ec63b..b8d602e146 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -47,8 +47,6 @@ CIRCUITPY_AUDIOMIXER ?= 0 INTERNAL_LIBM = 1 -USB_SERIAL_NUMBER_LENGTH = 16 - # Number of USB endpoint pairs. USB_NUM_EP = 8 diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk index a3216f2678..bfaff49274 100644 --- a/ports/stm/mpconfigport.mk +++ b/ports/stm/mpconfigport.mk @@ -1,7 +1,6 @@ MPY_TOOL_LONGINT_IMPL ?= -mlongint-impl=mpz LONGINT_IMPL ?= MPZ INTERNAL_LIBM ?= 1 -USB_SERIAL_NUMBER_LENGTH ?= 24 ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F405xx STM32F407xx)) CIRCUITPY_CANIO = 1 diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 786b72574c..368e30ac6d 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -58,7 +58,7 @@ static const uint8_t storage_usb_msc_descriptor_template[] = { // MSC Endpoint IN Descriptor 0x07, // 9 bLength 0x05, // 10 bDescriptorType (Endpoint) - 0xFF, // 11 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x8 | number] + 0xFF, // 11 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | number] #define MSC_IN_ENDPOINT_INDEX 11 0x02, // 12 bmAttributes (Bulk) 0x40, 0x00, // 13,14 wMaxPacketSize 64 @@ -81,12 +81,21 @@ size_t storage_usb_descriptor_length(void) { return sizeof(usb_msc_descriptor); } -size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t interface_number, uint8_t in_endpoint, uint8_t out_endpoint, uint8_t interface_string) { +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) { memcpy(descriptor_buf, storage_usb_msc_descriptor_template, sizeof(storage_usb_msc_descriptor_template)); - descriptor_buf[MSC_INTERFACE_INDEX] = interface_number; - descriptor_buf[MSC_INTERFACE_STRING_INDEX] = interface_string; - descriptor_buf[MSC_IN_ENDPOINT_INDEX] = in_endpoint_address; - descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = 0x80 | out_endpoint_address; + descriptor_buf[MSC_INTERFACE_INDEX] = *current_interface; + (*current_interface)++; + + descriptor_buf[MSC_IN_ENDPOINT_INDEX] = USB_MSC_EP_NUM_IN ? USB_MSC_EP_NUM_IN : *current_endpoint; + descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = 0x80 | (USB_MSC_EP_NUM_OUT ? USB_MSC_EP_NUM_OUT : *current_endpoint); + (*current_endpoint)++: + + usb_add_interface_string(*current_interface_string,); + descriptor_buf[MSC_INTERFACE_STRING_INDEX] = *current_interface_string; + (*current_interface_string)++; + return sizeof(storage_usb_msc_descriptor_template); } diff --git a/shared-module/storage/__init__.h b/shared-module/storage/__init__.h index 2f38ed8b19..58ece345d1 100644 --- a/shared-module/storage/__init__.h +++ b/shared-module/storage/__init__.h @@ -31,6 +31,6 @@ extern bool storage_usb_enabled; void storage_init(void); size_t storage_usb_descriptor_length(void); -size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t interface, uint8_t in_endpoint, uint8_t out_endpoint, uint8_tt interface_string); +size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string); #endif // SHARED_MODULE_STORAGE___INIT___H diff --git a/shared-module/usb_cdc/__init__.c b/shared-module/usb_cdc/__init__.c index 1a68148da6..307f0a8e68 100644 --- a/shared-module/usb_cdc/__init__.c +++ b/shared-module/usb_cdc/__init__.c @@ -140,21 +140,48 @@ size_t usb_cdc_descriptor_length(void) { return sizeof(usb_cdc_descriptor_template); } -size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8 comm_interface, uint8_t data_interface, uint8_t control_in_endpoint, uint8_t data_in_endpoint, uint8_t data_out_endpoint, uint8_t comm_interface_string, uint8_t data_interface_string) { +static const char[] repl_cdc_comm_interface_name = USB_INTERFACE_NAME " CDC control"; +static const char[] data_cdc_comm_interface_name = USB_INTERFACE_NAME " CDC2 control"; +static const char[] repl_cdc_data_interface_name = USB_INTERFACE_NAME " CDC data"; +static const char[] data_cdc_data_interface_name = USB_INTERFACE_NAME " CDC2 data"; + +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) { memcpy(descriptor_buf, usb_midi_descriptor_template, sizeof(usb_midi_descriptor_template)); - descriptor_buf[CDC_FIRST_INTERFACE_INDEX] = comm_interface; - descriptor_buf[CDC_COMM_INTERFACE_INDEX] = comm_interface; - descriptor_buf[CDC_CALL_MANAGEMENT_DATA_INTERFACE_INDEX] = data_interface; - descriptor_buf[CDC_UNION_MASTER_INTERFACE_INDEX] = comm_interface; - descriptor_buf[CDC_UNION_SLAVE_INTERFACE_INDEX] = data_interface; - descriptor_buf[CDC_DATA_INTERFACE_INDEX] = data_interface; - descriptor_buf[CDC_CONTROL_IN_ENDPOINT_INDEX] = control_in_endpoint; - descriptor_buf[CDC_DATA_OUT_ENDPOINT_INDEX] = data_out_endpoint; - descriptor_buf[CDC_DATA_IN_ENDPOINT_INDEX] = data_in_endpoint; + // 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_COMM_INTERFACE_STRING_INDEX] = comm_interface_string; - descriptor_buf[CDC_DATA_INTERFACE_STRING_INDEX] = data_interface_string; + // 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; + + descriptor_buf[CDC_CONTROL_IN_ENDPOINT_INDEX] = repl + ? (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] = repl + ? (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); + + descriptor_buf[CDC_DATA_IN_ENDPOINT_INDEX] = repl + ? (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_add_interface_string(*current_interface_string, + repl ? repl_cdc_comm_interface_name : data_cdc_comm_interface_name); + descriptor_buf[CDC_COMM_INTERFACE_STRING_INDEX] = *current_interface_string; + (*current_interface_string)++; + + usb_add_interface_string(*current_interface_string, + repl ? repl_cdc_data_interface_name : data_cdc_data_interface_name); + descriptor_buf[CDC_DATA_INTERFACE_STRING_INDEX] = *current_interface_string; + (*current_interface_string)++; return sizeof(usb_midi_descriptor_template); } diff --git a/shared-module/usb_cdc/__init__.h b/shared-module/usb_cdc/__init__.h index b7d635f49f..973569530f 100644 --- a/shared-module/usb_cdc/__init__.h +++ b/shared-module/usb_cdc/__init__.h @@ -34,6 +34,6 @@ extern bool usb_cdc_data_enabled; void usb_cdc_init(void); size_t usb_cdc_descriptor_length(void); -size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8 comm_interface, uint8_t data_interface, uint8_t control_in_endpoint, uint8_t data_in_endpoint, uint8_t data_out_endpoint, uint8_t comm_interface_string, uint8_t data_interface_string); +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); #endif /* SHARED_MODULE_USB_CDC___INIT___H */ diff --git a/shared-module/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c index d88f9787ac..5403b7fcef 100644 --- a/shared-module/usb_hid/__init__.c +++ b/shared-module/usb_hid/__init__.c @@ -24,4 +24,51 @@ * THE SOFTWARE. */ -// Nothing needed here. Tables of HID devices are generated in autogen_usb_descriptor.c at compile-time. +static const uint8_t usb_hid_descriptor_template[] = { + 0x09, // 0 bLength + 0x21, // 1 bDescriptorType (HID) + 0x11, 0x01, // 2 bcdHID 1.11 + 0x00, // 3 bCountryCode + 0x01, // 4 bNumDescriptors + 0x22, // 5 bDescriptorType[0] (HID) + 0xFF, 0xFF, // 6,7 wDescriptorLength[0] [SET AT RUNTIME: lo, hi] +#define HID_DESCRIPTOR_LENGTH_INDEX 6 + + 0x07, // 8 bLength + 0x05, // 9 bDescriptorType (Endpoint) + 0xFF, // 10 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | endpoint] +#define HID_IN_ENDPOINT_INDEX 10 + 0x03, // 11 bmAttributes (Interrupt) + 0x40, 0x00, // 12,13 wMaxPacketSize 64 + 0x08, // 14 bInterval 8 (unit depends on device speed) + + 0x07, // 15 bLength + 0x05, // 16 bDescriptorType (Endpoint) + 0xFF, // 17 bEndpointAddress (OUT/H2D) [SET AT RUNTIME] +#define HID_OUT_ENDPOINT_INDEX 17 + 0x03, // 18 bmAttributes (Interrupt) + 0x40, 0x00, // 19,20 wMaxPacketSize 64 + 0x08, // 21 bInterval 8 (unit depends on device speed) +}; + +// Is the HID device enabled? +bool usb_hid_enabled; + +size_t usb_hid_descriptor_length(void) { + return sizeof(usb_hid_descriptor); +} + +static const char[] usb_hid_interface_name = USB_INTERFACE_NAME " Mass Storage"; + +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) { + memcpy(descriptor_buf, usb_hid_descriptor_template, sizeof(usb_hid_descriptor_template)); + + 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] = USB_HID_EP_NUM_IN ? USB_HID_EP_NUM_IN : *current_endpoint; + descriptor_buf[HID_OUT_ENDPOINT_INDEX] = 0x80 | (USB_HID_EP_NUM_OUT ? USB_HID_EP_NUM_OUT : *current_endpoint); + (*current_endpoint)++: + + return sizeof(usb_hid_descriptor_template); +} diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c index 9f78856836..9fa95dbe22 100644 --- a/shared-module/usb_midi/__init__.c +++ b/shared-module/usb_midi/__init__.c @@ -163,21 +163,41 @@ size_t usb_midi_descriptor_length(void) { return sizeof(usb_midi_descriptor_template); } -size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, - uint8_t audio_control_interface, uint8_t midi_streaming_interface, uint8_t midi_streaming_in_endpoint, uint8_t midi_streaming_out_endpoint, uint8_t audio_control_interface_string, uint8_t midi_streaming_interface_string, uint8_t in_jack_string, uint8_t out_jack_string) { +static const char[] midi_streaming_interface_name = USB_INTERFACE_NAME " MIDI"; +static const char[] midi_audio_control_interface_name = USB_INTERFACE_NAME " Audio"; +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) { memcpy(descriptor_buf, usb_midi_descriptor_template, sizeof(usb_midi_descriptor_template)); - descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_NUMBER_INDEX] = audio_control_interface_number; - descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_STRING_INDEX] = audio_control_interface_string; - descriptor_buf[MSC_IN_ENDPOINT_INDEX] = midi_streaming_in_endpoint; - descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = 0x80 | midi_streaming_out_endpoint; + descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_NUMBER_INDEX] = *current_interface; + (*current_interface)++; - descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX] = midi_streaming_interface_number; - descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX_2] = midi_streaming_interface_number; - descriptor_buf[MIDI_STREAMING_INTERFACE_STRING_INDEX] = midi_streaming_interface_string; + descriptor_buf[MSC_IN_ENDPOINT_INDEX] = USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : *current_endpoint; + descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = + 0x80 | (USB_MIDI_EP_NUM_OUT ? USB_MIDI_EP_NUM_OUT : *current_endpoint); + (*current_endpoint)++; - descriptor_buf[MIDI_IN_JACK_STRING_INDEX] = in_jack_string; - descriptor_buf[MIDI_OUT_JACK_STRING_INDEX] = out_jack_string; + descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX] = *current_interface; + descriptor_buf[MIDI_STREAMING_INTERFACE_NUMBER_INDEX_2] = *current_interface; + (*current_interface)++; + + usb_add_interface_string(*current_interface, midi_streaming_interface_name); + descriptor_buf[MIDI_STREAMING_INTERFACE_STRING_INDEX] = *current_interface; + (*current_interface_string)++; + + usb_add_interface_string(*current_interface, midi_audio_control_interface_name); + descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_STRING_INDEX] = *current_interface; + (*current_interface_string)++; + + usb_add_interface_string(*current_interface, midi_in_jack_name); + descriptor_buf[MIDI_IN_JACK_STRING_INDEX] = *current_interface; + (*current_interface_string)++; + + usb_add_interface_string(*current_interface, midi_out_jack_name); + descriptor_buf[MIDI_OUT_JACK_STRING_INDEX] = *current_interface; + (*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 a57308e8b7..28871185cf 100644 --- a/shared-module/usb_midi/__init__.h +++ b/shared-module/usb_midi/__init__.h @@ -33,6 +33,6 @@ void usb_midi_init(void); void usb_midi_usb_init(void); size_t usb_midi_descriptor_length(void); -size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t audio_control_interface, uint8_t midi_streaming_interface, uint8_t midi_streaming_in_endpoint, uint8_t midi_streaming_out_endpoint, uint8_t audio_control_interface_string, uint8_t midi_streaming_interface_string, uint8_t in_jack_string, uint8_t out_jack_string); +size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interface, uint8_t *current_endpoint, uint8_t* current_interface_string); #endif /* SHARED_MODULE_USB_MIDI___INIT___H */ diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index 9d48a512bd..0605b3fc93 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -51,27 +51,6 @@ extern const tusb_desc_webusb_url_t desc_webusb_url; static bool web_serial_connected = false; #endif - - -// Serial number as hex characters. This writes directly to the USB -// descriptor. -extern uint16_t usb_serial_number[1 + COMMON_HAL_MCU_PROCESSOR_UID_LENGTH * 2]; - -void load_serial_number(void) { - // create serial number based on device unique id - uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH]; - common_hal_mcu_processor_get_uid(raw_id); - - usb_serial_number[0] = 0x300 | sizeof(usb_serial_number); - for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) { - for (int j = 0; j < 2; j++) { - uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf; - // Strings are UTF-16-LE encoded. - usb_serial_number[1 + i * 2 + j] = nibble_to_hex_upper[nibble]; - } - } -} - bool usb_enabled(void) { return tusb_inited(); } @@ -80,8 +59,13 @@ MP_WEAK void post_usb_init(void) { } void usb_init(void) { + usb_build_device_descriptor(); + usb_build_configuration_descriptor(); + usb_build_hid_descriptor(); + usb_build_string_descriptors(); + + init_usb_hardware(); - load_serial_number(); tusb_init(); diff --git a/supervisor/shared/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c index c894c8ab40..516c9d5e8b 100644 --- a/supervisor/shared/usb/usb_desc.c +++ b/supervisor/shared/usb/usb_desc.c @@ -46,9 +46,22 @@ #include "genhdr/autogen_usb_descriptor.h" +// ******* TODO PROTECT AGAINST GC. static uint8_t *device_descriptor; static uint8_t *config_descriptor; +// Table for collecting interface strings (interface names) as descriptor is built. +#define MAX_INTERFACE_STRINGS 16 +// slot 0 is not used. +static char * collected_interface_strings[]; +static uint16_t current_interface_string; + +static const char[] manufacturer_name = USB_MANUFACTURER; +static const char[] product_name = USB_PRODUCT; + +// Serial number string is UID length * 2 (2 nibbles per byte) + 1 byte for null termination. +static char serial_number_hex_string[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH * 2 + 1]; + static const uint8_t device_descriptor_template[] = { 0x12, // 0 bLength 0x01, // 1 bDescriptorType (Device) @@ -87,8 +100,27 @@ static const uint8_t configuration_descriptor_template[] = { 0x32, // 8 bMaxPower 100mA }; -void build_usb_device_descriptor(uint16_t vid, uint16_t pid, uint8_t manufacturer_string_index, uint8_t product_string_index, uint8_t serial_number_string_index) { +void usb_desc_init(void) { + uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH]; + common_hal_mcu_processor_get_uid(raw_id); + for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) { + for (int j = 0; j < 2; j++) { + uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf; + serial_number_hex_string[i * 2 + (1 - j)] = nibble_to_hex_upper[nibble]; + } + } + + // Null-terminate the string. + serial_number_hex_string[sizeof(serial_number_hex_string)] = '\0'; + + // Set to zero when allocated; we depend on that. + collected_interface_strings = m_malloc(MAX_INTERFACE_STRINGS + 1, false); + current_interface_string = 1; +} + + +void usb_build_device_descriptor(uint16_t vid, uint16_t pid, uint8_t *current_interface_string) { device_descriptor = m_malloc(sizeof(device_descriptor_template), false); memcpy(device_descriptor, device_descriptor_template, sizeof(device_descriptor_template)); @@ -96,12 +128,21 @@ void build_usb_device_descriptor(uint16_t vid, uint16_t pid, uint8_t manufacture device_descriptor[DEVICE_VID_HI_INDEX] = vid >> 8; device_descriptor[DEVICE_PID_LO_INDEX] = pid & 0xFF; device_descriptor[DEVICE_PID_HI_INDEX] = pid >> 8; - device_descriptor[DEVICE_MANUFACTURER_STRING_INDEX] = manufacturer_string_index; - device_descriptor[DEVICE_PRODUCT_STRING_INDEX] = product_string_index; - device_descriptor[DEVICE_SERIAL_NUMBER_STRING_INDEX] = serial_number_string_index; + + usb_add_interface_string(*current_interface_string, manufacturer_name); + device_descriptor[DEVICE_MANUFACTURER_STRING_INDEX] = *current_interface_string; + (*current_interface_string)++; + + usb_add_interface_string(*current_interface_string, product_name); + device_descriptor[DEVICE_PRODUCT_STRING_INDEX] = *current_interface_string; + (*current_interface_string)++; + + usb_add_interface_string(*current_interface_string, serial_number_hex_string); + device_descriptor[DEVICE_SERIAL_NUMBER_STRING_INDEX] = *current_interface_string; + (*current_interface_string)++; } -void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces) { +void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces) { size_t total_descriptor_length = sizeof(configuration_descriptor_template); // CDC should be first, for compatibility with Adafruit Windows 7 drivers. @@ -143,19 +184,22 @@ void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_inter configuration_descriptor[CONFIG_TOTAL_LENGTH_HI_INDEX] = (total_descriptor_length >> 8) & 0xFF; // Number interfaces and endpoints. - // Endpoint 0 is already used for USB control. + // Endpoint 0 is already used for USB control, so start with 1. uint8_t current_interface = 0; uint8_t current_endpoint = 1; - uint16_t current_interface_string = 1; uint8_t *descriptor_buf_remaining = configuration_descriptor + sizeof(configuration_descriptor_template); #if CIRCUITPY_USB_CDC if (usb_cdc_repl_enabled) { // Concatenate and fix up the CDC REPL descriptor. + descriptor_buf_remaining += usb_cdc_add_descriptor( + descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string, true); } if (usb_cdc_data_enabled) { // Concatenate and fix up the CDC data descriptor. + descriptor_buf_remaining += usb_cdc_add_descriptor( + descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string, false); } #endif @@ -163,13 +207,7 @@ void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_inter if (storage_usb_enabled) { // Concatenate and fix up the MSC descriptor. descriptor_buf_remaining += storage_usb_add_descriptor( - descriptor_buf_remaining, current_interface, - current_endpoint, // in - current_endpoint, // out - current_interface_string_index); - current_interface++; - current_endpoint++; - current_interface_string++; + descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string); } #endif @@ -177,26 +215,14 @@ void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_inter if (usb_midi_enabled) { // Concatenate and fix up the MIDI descriptor. descriptor_buf_remaining += usb_midi_add_descriptor( - descriptor_buf_remaining, - current_interface, // audio control - current_interface + 1, // MIDI streaming - current_endpoint, // in - current_endpoint, // out - current_interface_string, // audio control - current_interface_string + 1 // MIDI streaming - current_interface_string + 2 // in jack - current_interface_string + 3 // out jack - ); - current_interface += 2; // two interfaces: audio control and MIDI streaming - current_endpoint++; // MIDI streaming only (no audio data) - current_interface_string += 4; // two interface names: audio control and MIDI streaming - + descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string); } #endif #if CIRCUITPY_USB_HID if (usb_hid_enabled) { - // Concatenate and fix up the HID descriptor (not the report descriptors). + descriptor_buf_remaining += usb_hid_add_descriptor( + descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string); } #endif @@ -210,13 +236,33 @@ void build_usb_configuration_descriptor(uint16_t total_length, uint8_t num_inter } -// Invoked when received GET DEVICE DESCRIPTOR +void usb_add_interface_string(uint8_t interface_string_index, const char[] str) { + if (interface_string_index > MAX_INTERFACE_STRINGS) { + mp_raise_SystemError("Too many USB interface names"); + } + // 2 bytes for String Descriptor header, then 2 bytes for each character + const size_t str_len = strlen(str); + uint8_t descriptor_size = 2 + (str_len * 2); + uint16_t *string_descriptor = (uint16_t *) m_malloc(descriptor_size, false); + string_descriptor[0] = 0x0300 | descriptor_size; + // Convert to le16 + for (i = 0; i <= str_len; i++) { + string_descriptor[i + 1] = str[i]; + } + + collected_interface_strings[interface_string_index] = string_descriptor; +} + + +void usb_ + +// Invoked when GET DEVICE DESCRIPTOR is received. // Application return pointer to descriptor uint8_t const *tud_descriptor_device_cb(void) { return usb_descriptor_dev; } -// Invoked when received GET CONFIGURATION DESCRIPTOR +// Invoked when GET CONFIGURATION DESCRIPTOR is received. // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { @@ -225,7 +271,7 @@ uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { } #if CIRCUITPY_USB_HID -// Invoked when received GET HID REPORT DESCRIPTOR +// Invoked when GET HID REPORT DESCRIPTOR is received. // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) { @@ -234,9 +280,11 @@ uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) { } #endif -// Invoked when received GET STRING DESCRIPTOR request +// Invoked when GET STRING DESCRIPTOR request is received. // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - uint8_t const max_index = sizeof(string_descriptor_arr) / sizeof(string_descriptor_arr[0]); - return (index < max_index) ? string_descriptor_arr[index] : NULL; + if (index > MAX_INTERFACE_STRINGS) { + return NULL; + } + return collected_interface_strings[index]; } diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index 7fab262f64..1210896c7f 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -76,7 +76,6 @@ else supervisor/usb.c \ supervisor/shared/usb/usb_desc.c \ supervisor/shared/usb/usb.c \ - $(BUILD)/autogen_usb_descriptor.c \ ifeq ($(CIRCUITPY_USB_CDC), 1) SRC_SUPERVISOR += \ @@ -159,61 +158,24 @@ USB_HIGHSPEED ?= 0 USB_CDC_EP_NUM_NOTIFICATION ?= 0 USB_CDC_EP_NUM_DATA_OUT ?= 0 USB_CDC_EP_NUM_DATA_IN ?= 0 + +USB_CDC2_EP_NUM_NOTIFICATION ?= 0 +USB_CDC2_EP_NUM_DATA_OUT ?= 0 +USB_CDC2_EP_NUM_DATA_IN ?= 0 + USB_MSC_EP_NUM_OUT ?= 0 USB_MSC_EP_NUM_IN ?= 0 + USB_HID_EP_NUM_OUT ?= 0 USB_HID_EP_NUM_IN ?= 0 + USB_MIDI_EP_NUM_OUT ?= 0 USB_MIDI_EP_NUM_IN ?= 0 + USB_NUM_EP ?= 0 -USB_DESCRIPTOR_ARGS = \ - --manufacturer $(USB_MANUFACTURER)\ - --product $(USB_PRODUCT)\ - --vid $(USB_VID)\ - --pid $(USB_PID)\ - --serial_number_length $(USB_SERIAL_NUMBER_LENGTH)\ - --interface_name_prefix $(USB_INTERFACE_NAME)\ - --devices "$(USB_DEVICES)"\ - --hid_devices "$(USB_HID_DEVICES)"\ - --max_ep $(USB_NUM_EP) \ - --cdc_ep_num_notification $(USB_CDC_EP_NUM_NOTIFICATION)\ - --cdc_ep_num_data_out $(USB_CDC_EP_NUM_DATA_OUT)\ - --cdc_ep_num_data_in $(USB_CDC_EP_NUM_DATA_IN)\ - --msc_ep_num_out $(USB_MSC_EP_NUM_OUT)\ - --msc_ep_num_in $(USB_MSC_EP_NUM_IN)\ - --hid_ep_num_out $(USB_HID_EP_NUM_OUT)\ - --hid_ep_num_in $(USB_HID_EP_NUM_IN)\ - --midi_ep_num_out $(USB_MIDI_EP_NUM_OUT)\ - --midi_ep_num_in $(USB_MIDI_EP_NUM_IN)\ - --output_c_file $(BUILD)/autogen_usb_descriptor.c\ - --output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h - -ifeq ($(CIRCUITPY_USB_VENDOR), 1) -USB_DESCRIPTOR_ARGS += \ - --vendor_ep_num_out 0 --vendor_ep_num_in 0 \ - --webusb_url $(USB_WEBUSB_URL) -endif - -ifeq ($(USB_RENUMBER_ENDPOINTS), 0) -USB_DESCRIPTOR_ARGS += --no-renumber_endpoints -endif - -ifeq ($(USB_HIGHSPEED), 1) -USB_DESCRIPTOR_ARGS += --highspeed -endif - $(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h -$(BUILD)/autogen_usb_descriptor.c $(BUILD)/genhdr/autogen_usb_descriptor.h: autogen_usb_descriptor.intermediate - -.INTERMEDIATE: autogen_usb_descriptor.intermediate - -autogen_usb_descriptor.intermediate: ../../tools/gen_usb_descriptor.py Makefile | $(HEADER_BUILD) - $(STEPECHO) "GEN $@" - $(Q)install -d $(BUILD)/genhdr - $(Q)$(PYTHON3) ../../tools/gen_usb_descriptor.py $(USB_DESCRIPTOR_ARGS) - CIRCUITPY_DISPLAY_FONT ?= "../../tools/fonts/ter-u12n.bdf" $(BUILD)/autogen_display_resources.c: ../../tools/gen_display_resources.py $(HEADER_BUILD)/qstrdefs.generated.h Makefile | $(HEADER_BUILD) diff --git a/supervisor/usb.h b/supervisor/usb.h index f8fd713715..c8a699065d 100644 --- a/supervisor/usb.h +++ b/supervisor/usb.h @@ -53,6 +53,11 @@ bool usb_enabled(void); void usb_init(void); void usb_disconnect(void); +void usb_add_interface_string(uint8_t interface_string_index, const char[] str); +void usb_desc_init(void); +void usb_build_device_descriptor(uint16_t vid, uint16_t pid, uint8_t *current_interface_string); +void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces); + // Propagate plug/unplug events to the MSC logic. #if CIRCUITPY_USB_MSC void usb_msc_mount(void);