diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 9d276a8342..9cd3b36e14 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -91,10 +91,6 @@ msgstr "" msgid "%q must be 1-255" msgstr "" -#: shared-bindings/usb_hid/Device.c -msgid "%q must be > 1-255" -msgstr "" - #: shared-bindings/memorymonitor/AllocationAlarm.c msgid "%q must be >= 0" msgstr "" @@ -111,10 +107,6 @@ msgstr "" msgid "%q must be None or 1-255" msgstr "" -#: shared-bindings/usb_hid/Device.c -msgid "%q must be None or > 1-255" -msgstr "" - #: shared-module/vectorio/Polygon.c msgid "%q must be a tuple of length 2" msgstr "" @@ -1643,6 +1635,10 @@ msgstr "" msgid "Not connected" msgstr "" +#: supervisor/shared/usb/usb_desc.c +msgid "Not enough USB endpoints" +msgstr "" + #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c #: shared-bindings/audiopwmio/PWMAudioOut.c msgid "Not playing" @@ -2149,6 +2145,10 @@ msgstr "" msgid "To exit, please reset the board without " msgstr "" +#: supervisor/shared/usb/usb_desc.c +msgid "Too many USB interface names" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample." diff --git a/main.c b/main.c index 21e7775a9f..610fb0d302 100755 --- a/main.c +++ b/main.c @@ -103,6 +103,10 @@ #include "shared-module/usb_cdc/__init__.h" #endif +#if CIRCUITPY_USB_HID +#include "shared-module/usb_hid/__init__.h" +#endif + #if CIRCUITPY_USB_MIDI #include "shared-module/usb_midi/__init__.h" #endif @@ -189,6 +193,10 @@ STATIC void start_mp(supervisor_allocation* heap) { usb_cdc_init(); #endif + #if CIRCUITPY_USB_HID + usb_hid_init(); + #endif + #if CIRCUITPY_USB_MIDI usb_midi_init(); #endif diff --git a/ports/cxd56/mpconfigport.h b/ports/cxd56/mpconfigport.h index 27c82337bc..bce68f83f2 100644 --- a/ports/cxd56/mpconfigport.h +++ b/ports/cxd56/mpconfigport.h @@ -36,6 +36,13 @@ #define MICROPY_BYTES_PER_GC_BLOCK (32) +// CXD56 architecture uses fixed endpoint numbers +#define USB_CDC_EP_NUM_NOTIFICATION (3) +#define USB_CDC_EP_NUM_DATA_OUT (2) +#define USB_CDC_EP_NUM_DATA_IN (2) +#define USB_MSC_EP_NUM_OUT (5) +#define USB_MSC_EP_NUM_IN (4) + #define MICROPY_PORT_ROOT_POINTERS \ CIRCUITPY_COMMON_ROOT_POINTERS \ diff --git a/ports/cxd56/mpconfigport.mk b/ports/cxd56/mpconfigport.mk index a010f16778..5dbc71825d 100644 --- a/ports/cxd56/mpconfigport.mk +++ b/ports/cxd56/mpconfigport.mk @@ -1,10 +1,4 @@ USB_HIGHSPEED = 1 -USB_RENUMBER_ENDPOINTS = 0 -USB_CDC_EP_NUM_NOTIFICATION = 3 -USB_CDC_EP_NUM_DATA_OUT = 2 -USB_CDC_EP_NUM_DATA_IN = 1 -USB_MSC_EP_NUM_OUT = 5 -USB_MSC_EP_NUM_IN = 4 # Number of USB endpoint pairs. USB_NUM_EP = 6 diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 15881f41bd..99f7168565 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -992,4 +992,57 @@ void supervisor_run_background_tasks_if_tick(void); #define CIRCUITPY_VERBOSE_BLE 0 +// USB settings + +// If the port requires certain USB endpoint numbers, define these in mpconfigport.h. + +#ifndef USB_CDC_EP_NUM_NOTIFICATION +#define USB_CDC_EP_NUM_NOTIFICATION (0) +#endif + +#ifndef USB_CDC_EP_NUM_DATA_OUT +#define USB_CDC_EP_NUM_DATA_OUT (0) +#endif + +#ifndef USB_CDC_EP_NUM_DATA_IN +#define USB_CDC_EP_NUM_DATA_IN (0) +#endif + +#ifndef USB_CDC2_EP_NUM_NOTIFICATION +#define USB_CDC2_EP_NUM_NOTIFICATION (0) +#endif + +#ifndef USB_CDC2_EP_NUM_DATA_OUT +#define USB_CDC2_EP_NUM_DATA_OUT (0) +#endif + +#ifndef USB_CDC2_EP_NUM_DATA_IN +#define USB_CDC2_EP_NUM_DATA_IN (0) +#endif + +#ifndef USB_MSC_EP_NUM_OUT +#define USB_MSC_EP_NUM_OUT (0) +#endif + +#ifndef USB_MSC_EP_NUM_IN +#define USB_MSC_EP_NUM_IN (0) +#endif + +#ifndef USB_HID_EP_NUM_OUT +#define USB_HID_EP_NUM_OUT (0) +#endif + +#ifndef USB_HID_EP_NUM_IN +#define USB_HID_EP_NUM_IN (0) +#endif + +#ifndef USB_MIDI_EP_NUM_OUT +#define USB_MIDI_EP_NUM_OUT (0) +#endif + +#ifndef USB_MIDI_EP_NUM_IN +#define USB_MIDI_EP_NUM_IN (0) +#endif + + #endif // __INCLUDED_MPCONFIG_CIRCUITPY_H diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 8801213655..b87ffaedba 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -271,6 +271,9 @@ CFLAGS += -DCIRCUITPY_RGBMATRIX=$(CIRCUITPY_RGBMATRIX) CIRCUITPY_ROTARYIO ?= 1 CFLAGS += -DCIRCUITPY_ROTARYIO=$(CIRCUITPY_ROTARYIO) +CIRCUITPY_ROTARYIO_SOFTENCODER ?= 0 +CFLAGS += -DCIRCUITPY_ROTARYIO_SOFTENCODER=$(CIRCUITPY_ROTARYIO_SOFTENCODER) + CIRCUITPY_RTC ?= 1 CFLAGS += -DCIRCUITPY_RTC=$(CIRCUITPY_RTC) @@ -366,6 +369,7 @@ CFLAGS += -DCIRCUITPY_USB_VENDOR=$(CIRCUITPY_USB_VENDOR) ifndef USB_NUM_EP $(error "USB_NUM_EP (number of USB endpoint pairs)must be defined") endif +CFLAGS += -DUSB_NUM_EP=$(USB_NUM_EP) # For debugging. CIRCUITPY_USTACK ?= 0 diff --git a/shared-bindings/storage/__init__.h b/shared-bindings/storage/__init__.h index cd9366c1bc..0303e0440c 100644 --- a/shared-bindings/storage/__init__.h +++ b/shared-bindings/storage/__init__.h @@ -30,6 +30,8 @@ #include #include +#include "shared-module/storage/__init__.h" + void common_hal_storage_mount(mp_obj_t vfs_obj, const char *path, bool readonly); void common_hal_storage_umount_path(const char *path); void common_hal_storage_umount_object(mp_obj_t vfs_obj); diff --git a/shared-bindings/usb_hid/Device.c b/shared-bindings/usb_hid/Device.c index 13afbbf3e6..af2ed81085 100644 --- a/shared-bindings/usb_hid/Device.c +++ b/shared-bindings/usb_hid/Device.c @@ -44,7 +44,7 @@ //| """Create a description of a USB HID device. To create an actual device, //| pass a `Device` to `usb_hid.configure_usb()`. //| -//| :param ReadableBuffer descriptor: The USB HID Report descriptor bytes. The descriptor is not +//| :param ReadableBuffer report_descriptor: The USB HID Report descriptor bytes. The descriptor is not //| not verified for correctness; it is up to you to make sure it is not malformed. //| :param int usage_page: The Usage Page value from the descriptor. Must match what is in the descriptor. //| :param int usage: The Usage value from the descriptor. Must match what is in the descriptor. @@ -60,9 +60,9 @@ STATIC mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { usb_hid_device_obj_t *self = m_new_obj(usb_hid_device_obj_t); self->base.type = &usb_hid_device_type; - enum { ARG_descriptor, ARG_usage, ARG_usage_page, ARG_in_report_length, ARG_out_report_length, ARG_report_id_index }; + enum { ARG_report_descriptor, ARG_usage, ARG_usage_page, ARG_in_report_length, ARG_out_report_length, ARG_report_id_index }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_descriptor, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_report_descriptor, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_usage_page, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_usage, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_in_report_length, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT } , @@ -74,7 +74,7 @@ STATIC mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_descriptor].u_obj, &bufinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[ARG_report_descriptor].u_obj, &bufinfo, MP_BUFFER_READ); mp_obj_t descriptor = mp_obj_new_bytearray(bufinfo.len, bufinfo.buf); const mp_int_t usage_page_arg = args[ARG_usage_page].u_int; diff --git a/shared-bindings/usb_hid/__init__.c b/shared-bindings/usb_hid/__init__.c index 8d5d67d52a..953a97ab7b 100644 --- a/shared-bindings/usb_hid/__init__.c +++ b/shared-bindings/usb_hid/__init__.c @@ -67,17 +67,25 @@ STATIC mp_obj_t usb_hid_configure_usb(mp_obj_t devices) { } MP_DEFINE_CONST_FUN_OBJ_1(usb_hid_configure_usb_obj, usb_hid_configure_usb); - -STATIC const mp_rom_map_elem_t usb_hid_module_globals_table[] = { +// usb_hid.devices is set once the usb devices are determined, after boot.py runs. +STATIC mp_map_elem_t usb_hid_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid) }, { MP_ROM_QSTR(MP_QSTR_configure_usb), MP_OBJ_FROM_PTR(&usb_hid_configure_usb_obj) }, - { MP_ROM_QSTR(MP_QSTR_devices), MP_ROM_PTR(&common_hal_usb_hid_devices) }, - { MP_ROM_QSTR(MP_QSTR_Device), MP_ROM_PTR(&usb_hid_device_type) }, + { MP_ROM_QSTR(MP_QSTR_devices), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_Device), MP_OBJ_FROM_PTR(&usb_hid_device_type) }, }; -STATIC MP_DEFINE_CONST_DICT(usb_hid_module_globals, usb_hid_module_globals_table); +STATIC MP_DEFINE_MUTABLE_DICT(usb_hid_module_globals, usb_hid_module_globals_table); const mp_obj_module_t usb_hid_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t *)&usb_hid_module_globals, }; + +void usb_hid_set_devices(mp_obj_t devices) { + mp_map_elem_t *elem = + mp_map_lookup(&usb_hid_module_globals.map, MP_ROM_QSTR(MP_QSTR_devices), MP_MAP_LOOKUP); + if (elem) { + elem->value = devices; + } +} diff --git a/shared-bindings/usb_hid/__init__.h b/shared-bindings/usb_hid/__init__.h index 532625d623..3e51170cc4 100644 --- a/shared-bindings/usb_hid/__init__.h +++ b/shared-bindings/usb_hid/__init__.h @@ -29,9 +29,12 @@ #include "py/obj.h" #include "py/objtuple.h" +#include "shared-module/usb_hid/__init__.h" extern mp_obj_tuple_t common_hal_usb_hid_devices; +void usb_hid_set_devices(mp_obj_t devices); + void common_hal_usb_hid_configure_usb_defaults(void); bool common_hal_usb_hid_configure_usb(mp_obj_t devices_seq); diff --git a/shared-bindings/usb_midi/__init__.h b/shared-bindings/usb_midi/__init__.h index 25e0fbfcbf..dab3dc8f72 100644 --- a/shared-bindings/usb_midi/__init__.h +++ b/shared-bindings/usb_midi/__init__.h @@ -28,6 +28,7 @@ #define MICROPY_INCLUDED_SHARED_BINDINGS_USB_MIDI___INIT___H #include "py/obj.h" +#include "shared-module/usb_midi/__init__.h" extern mp_obj_dict_t usb_midi_module_globals; diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 3a4fc1f3b5..6a16ba9ebe 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -41,7 +41,7 @@ #include "supervisor/usb.h" #include "tusb.h" -static const uint8_t storage_usb_msc_descriptor_template[] = { +static const uint8_t usb_msc_descriptor_template[] = { // MSC Interface Descriptor 0x09, // 0 bLength 0x04, // 1 bDescriptorType (Interface) @@ -75,28 +75,32 @@ static const uint8_t storage_usb_msc_descriptor_template[] = { }; // Is the MSC device enabled? -bool storage_usb_enabled; +bool storage_usb_is_enabled; -size_t storage_usb_descriptor_length(void) { - return sizeof(usb_msc_descriptor); +bool storage_usb_enabled(void) { + return storage_usb_is_enabled; } -static const char[] storage_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " Mass Storage"; +size_t storage_usb_descriptor_length(void) { + return sizeof(usb_msc_descriptor_template); +} + +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)); + 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] = 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)++: + (*current_endpoint)++; - usb_add_interface_string(*current_interface_string,); + usb_add_interface_string(*current_interface_string, storage_interface_name); descriptor_buf[MSC_INTERFACE_STRING_INDEX] = *current_interface_string; (*current_interface_string)++; - return sizeof(storage_usb_msc_descriptor_template); + return sizeof(usb_msc_descriptor_template); } @@ -118,7 +122,7 @@ STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_ } void storage_init(void) { - storage_usb_enabled = true; + storage_usb_is_enabled = true; } void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool readonly) { @@ -238,6 +242,6 @@ bool common_hal_storage_configure_usb(bool enabled) { if (tud_connected()) { return false; } - storage_usb_enabled = enabled; + storage_usb_is_enabled = enabled; return true; } diff --git a/shared-module/storage/__init__.h b/shared-module/storage/__init__.h index 58ece345d1..e9149bfa1b 100644 --- a/shared-module/storage/__init__.h +++ b/shared-module/storage/__init__.h @@ -27,7 +27,7 @@ #ifndef SHARED_MODULE_STORAGE___INIT___H #define SHARED_MODULE_STORAGE___INIT___H -extern bool storage_usb_enabled; +bool storage_usb_enabled(void); void storage_init(void); size_t storage_usb_descriptor_length(void); diff --git a/shared-module/usb_cdc/__init__.c b/shared-module/usb_cdc/__init__.c index a918476320..5de32fcde2 100644 --- a/shared-module/usb_cdc/__init__.c +++ b/shared-module/usb_cdc/__init__.c @@ -37,9 +37,6 @@ #error CFG_TUD_CDC must be exactly 2 #endif -bool usb_cdc_repl_enabled; -bool usb_cdc_data_enabled; - static const uint8_t usb_cdc_descriptor_template[] = { // CDC IAD Descriptor 0x08, // 0 bLength @@ -135,10 +132,10 @@ static const uint8_t usb_cdc_descriptor_template[] = { 0x00, // 65 bInterval 0 (unit depends on device speed) }; -static const char[] repl_cdc_comm_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " CDC control"; -static const char[] data_cdc_comm_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " CDC2 control"; -static const char[] repl_cdc_data_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " CDC data"; -static const char[] data_cdc_data_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " CDC2 data"; +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"; static usb_cdc_serial_obj_t usb_cdc_repl_obj = { .base.type = &usb_cdc_serial_type, @@ -154,6 +151,17 @@ static usb_cdc_serial_obj_t usb_cdc_data_obj = { .idx = 1, }; +static bool usb_cdc_repl_is_enabled; +static bool usb_cdc_data_is_enabled; + +bool usb_cdc_repl_enabled(void) { + return usb_cdc_repl_is_enabled; +} + +bool usb_cdc_data_enabled(void) { + return usb_cdc_data_enabled; +} + size_t usb_cdc_descriptor_length(void) { return sizeof(usb_cdc_descriptor_template); } @@ -200,8 +208,8 @@ size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfac } void usb_cdc_init(void) { - usb_cdc_repl_enabled = true; - usb_cdc_data_enabled = false; + usb_cdc_repl_is_enabled = true; + usb_cdc_data_is_enabled = false; } bool common_hal_usb_cdc_configure_usb(bool repl_enabled, bool data_enabled) { diff --git a/shared-module/usb_cdc/__init__.h b/shared-module/usb_cdc/__init__.h index 973569530f..770ee13170 100644 --- a/shared-module/usb_cdc/__init__.h +++ b/shared-module/usb_cdc/__init__.h @@ -29,8 +29,8 @@ #include "py/objtuple.h" -extern bool usb_cdc_repl_enabled; -extern bool usb_cdc_data_enabled; +bool usb_cdc_repl_enabled(void); +bool usb_cdc_data_enabled(void); void usb_cdc_init(void); size_t usb_cdc_descriptor_length(void); diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c index 02f43c167c..532be81051 100644 --- a/shared-module/usb_hid/Device.c +++ b/shared-module/usb_hid/Device.c @@ -28,12 +28,13 @@ #include "py/runtime.h" #include "shared-bindings/usb_hid/Device.h" +#include "shared-module/usb_hid/__init__.h" #include "shared-module/usb_hid/Device.h" #include "supervisor/shared/translate.h" #include "supervisor/shared/tick.h" #include "tusb.h" -static const uint8_t keyboard_descriptor[] = { +static const uint8_t keyboard_report_descriptor[] = { 0x05, 0x01, // 0,1 Usage Page (Generic Desktop Ctrls) 0x09, 0x06, // 2,3 Usage (Keyboard) 0xA1, 0x01, // 4,5 Collection (Application) @@ -69,9 +70,9 @@ static const uint8_t keyboard_descriptor[] = { }; const usb_hid_device_obj_t usb_hid_device_keyboard_obj = { - .descriptor = keyboard_descriptor, - .descriptor_length = sizeof(keyboard_descriptor), - .usage_page = 0x01 + .report_descriptor = keyboard_report_descriptor, + .report_descriptor_length = sizeof(keyboard_report_descriptor), + .usage_page = 0x01, .usage = 0x06, .in_report_length = 8, .out_report_length = 1, @@ -79,7 +80,7 @@ const usb_hid_device_obj_t usb_hid_device_keyboard_obj = { }; -static const uint8_t mouse_descriptor[] = { +static const uint8_t mouse_report_descriptor[] = { 0x05, 0x01, // 0,1 Usage Page (Generic Desktop Ctrls) 0x09, 0x02, // 2,3 Usage (Mouse) 0xA1, 0x01, // 4,5 Collection (Application) @@ -117,17 +118,16 @@ static const uint8_t mouse_descriptor[] = { }; const usb_hid_device_obj_t usb_hid_device_mouse_obj = { - .descriptor = mouse_descriptor, - .descriptor_length = sizeof(mouse_descriptor), - .usage_page = 0x01 + .report_descriptor = mouse_report_descriptor, + .report_descriptor_length = sizeof(mouse_report_descriptor), + .usage_page = 0x01, .usage = 0x02, .in_report_length = 4, .out_report_length = 0, - .descriptor = { .report_id_index = MOUSE_REPORT_ID_INDEX, }; -static const uint8_t consumer_control_descriptor[] = { +static const uint8_t consumer_control_report_descriptor[] = { 0x05, 0x0C, // 0,1 Usage Page (Consumer) 0x09, 0x01, // 2,3 Usage (Consumer Control) 0xA1, 0x01, // 4,5 Collection (Application) @@ -144,9 +144,9 @@ static const uint8_t consumer_control_descriptor[] = { }; const usb_hid_device_obj_t usb_hid_device_consumer_control_obj = { - .descriptor = consumer_control_descriptor, - .descriptor_length = sizeof(consumer_control_descriptor), - .usage_page = 0x0C + .report_descriptor = consumer_control_report_descriptor, + .report_descriptor_length = sizeof(consumer_control_report_descriptor), + .usage_page = 0x0C, .usage = 0x01, .in_report_length = 2, .out_report_length = 0, @@ -154,14 +154,14 @@ const usb_hid_device_obj_t usb_hid_device_consumer_control_obj = { }; -void common_hal_usb_hid_device_construct(usb_hid_device_obj_t *self, mp_obj_t descriptor, uint8_t usage_page, uint8_t usage, uint8_t in_report_length, uint8_t out_report_length, uint8_t report_id_index) { +void common_hal_usb_hid_device_construct(usb_hid_device_obj_t *self, mp_obj_t report_descriptor, uint8_t usage_page, uint8_t usage, uint8_t in_report_length, uint8_t out_report_length, uint8_t report_id_index) { // report buffer pointers are NULL at start, and are created on demand. - self->descriptor_obj = descriptor; + self->report_descriptor_obj = report_descriptor; mp_buffer_info_t bufinfo; - mp_get_buffer_raise(descriptor, &bufinfo, MP_BUFFER_READ); - self->descriptor = bufinfo.buf; - self->descriptor_length = bufinfo.len; + mp_get_buffer_raise(report_descriptor, &bufinfo, MP_BUFFER_READ); + self->report_descriptor = bufinfo.buf; + self->report_descriptor_length = bufinfo.len; self->usage_page = usage_page; self->usage = usage; @@ -195,20 +195,11 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t * memcpy(self->in_report_buffer, report, len); - if (!tud_hid_report(self->in_report_id, self->in_report_buffer, len)) { + if (!tud_hid_report(self->report_id, self->in_report_buffer, len)) { mp_raise_msg(&mp_type_OSError, translate("USB Error")); } } -static usb_hid_device_obj_t *get_hid_device(uint8_t report_id) { - for (uint8_t i = 0; i < USB_HID_NUM_DEVICES; i++) { - if (usb_hid_devices[i].report_id == report_id) { - return &usb_hid_devices[i]; - } - } - return NULL; -} - // Callbacks invoked when receive Get_Report request through control endpoint uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { (void)itf; @@ -218,7 +209,7 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t } // fill buffer with current report - memcpy(buffer, get_hid_device(report_id)->in_report_buffer, reqlen); + memcpy(buffer, usb_hid_get_device_with_report_id(report_id)->in_report_buffer, reqlen); return reqlen; } @@ -233,7 +224,7 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep return; } - usb_hid_device_obj_t *hid_device = get_hid_device(report_id); + usb_hid_device_obj_t *hid_device = usb_hid_get_device_with_report_id(report_id); if (hid_device && hid_device->out_report_length >= bufsize) { memcpy(hid_device->out_report_buffer, buffer, bufsize); diff --git a/shared-module/usb_hid/Device.h b/shared-module/usb_hid/Device.h index e6ac32bb54..fb46f4a710 100644 --- a/shared-module/usb_hid/Device.h +++ b/shared-module/usb_hid/Device.h @@ -35,13 +35,13 @@ typedef struct { mp_obj_base_t base; // If not MP_OBJ_NULL, points to Python array object whose contents are the descriptor. - mp_obj_t descriptor_obj; + mp_obj_t report_descriptor_obj; // If not NULL, points to raw bytes that are the descriptor. - uint8_t *descriptor; + const uint8_t *report_descriptor; uint8_t *in_report_buffer; uint8_t *out_report_buffer; uint16_t report_id_index; - uint16_t descriptor_length; + uint16_t report_descriptor_length; uint8_t usage_page; uint8_t usage; uint8_t report_id; @@ -49,8 +49,8 @@ typedef struct { uint8_t out_report_length; } usb_hid_device_obj_t; -extern usb_hid_device_obj_t usb_hid_device_keyboard_obj; -extern usb_hid_device_obj_t usb_hid_device_mouse_obj; -extern usb_hid_device_obj_t usb_hid_device_consumer_control_obj; +extern const usb_hid_device_obj_t usb_hid_device_keyboard_obj; +extern const usb_hid_device_obj_t usb_hid_device_mouse_obj; +extern const usb_hid_device_obj_t usb_hid_device_consumer_control_obj; #endif /* SHARED_MODULE_USB_HID_DEVICE_H */ diff --git a/shared-module/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c index 5d364e20a1..a59fa069d8 100644 --- a/shared-module/usb_hid/__init__.c +++ b/shared-module/usb_hid/__init__.c @@ -26,70 +26,106 @@ #include -#include "shared-module/usb_hid/__init__.h" +#include "tusb.h" + +#include "py/gc.h" +#include "shared-bindings/usb_hid/__init__.h" +#include "shared-module/usb_hid/Device.h" #include "supervisor/memory.h" +#include "supervisor/usb.h" 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) + 0x04, // 1 bDescriptorType (Interface) + 0xFF, // 2 bInterfaceNumber 3 +#define HID_DESCRIPTOR_INTERFACE_INDEX (2) + 0x00, // 3 bAlternateSetting + 0x02, // 4 bNumEndpoints 2 + 0x03, // 5 bInterfaceClass: HID + 0x00, // 6 bInterfaceSubClass: NOBOOT + 0x00, // 7 bInterfaceProtocol: NONE + 0xFF, // 8 iInterface (String Index) [SET AT RUNTIME] +#define HID_DESCRIPTOR_INTERFACE_STRING_INDEX (8) - 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) + 0x09, // 9 bLength + 0x21, // 10 bDescriptorType (HID) + 0x11, 0x01, // 11,12 bcdHID 1.11 + 0x00, // 13 bCountryCode + 0x01, // 14 bNumDescriptors + 0x22, // 15 bDescriptorType[0] (HID) + 0xFF, 0xFF, // 16,17 wDescriptorLength[0] [SET AT RUNTIME: lo, hi] +#define HID_DESCRIPTOR_LENGTH_INDEX (16) - 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) + 0x07, // 18 bLength + 0x05, // 19 bDescriptorType (Endpoint) + 0xFF, // 20 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | endpoint] +#define HID_IN_ENDPOINT_INDEX (20) + 0x03, // 21 bmAttributes (Interrupt) + 0x40, 0x00, // 22,23 wMaxPacketSize 64 + 0x08, // 24 bInterval 8 (unit depends on device speed) + + 0x07, // 25 bLength + 0x05, // 26 bDescriptorType (Endpoint) + 0xFF, // 27 bEndpointAddress (OUT/H2D) [SET AT RUNTIME] +#define HID_OUT_ENDPOINT_INDEX (26) + 0x03, // 28 bmAttributes (Interrupt) + 0x40, 0x00, // 29,30 wMaxPacketSize 64 + 0x08, // 31 bInterval 8 (unit depends on device speed) }; -// Sequence of devices to configure. +// Sequence of devices to configure. Passed to usb_hid.configure_usb(). +// Not used after boot.py finishes and VM restarts. static mp_obj_t hid_devices_seq; // Is the HID device enabled? -bool usb_hid_enabled; -supervisor_allocation *hid_report_descriptor_allocation; -supervisor_allocation *hid_devices_allocation; +static bool usb_hid_is_enabled; +static supervisor_allocation *hid_report_descriptor_allocation; +static size_t total_hid_report_descriptor_length; +static supervisor_allocation *hid_devices_allocation; +static mp_int_t hid_devices_num; // This is the interface descriptor, not the report descriptor. size_t usb_hid_descriptor_length(void) { return sizeof(usb_hid_descriptor_template); } -static const char usb_hid_interface_name[] = MP_STRINGIFY(USB_INTERFACE_NAME) " HID"; +// Total length of the report descriptor, with all configured devices. +size_t usb_hid_report_descriptor_length(void) { + return total_hid_report_descriptor_length; +} + +bool usb_hid_enabled(void) { + return usb_hid_is_enabled; +} + +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) { memcpy(descriptor_buf, usb_hid_descriptor_template, sizeof(usb_hid_descriptor_template)); + descriptor_buf[HID_DESCRIPTOR_INTERFACE_INDEX] = *current_interface; + (*current_interface)++; + + usb_add_interface_string(*current_interface, usb_hid_interface_name); + descriptor_buf[HID_DESCRIPTOR_INTERFACE_STRING_INDEX] = *current_interface_string; + (*current_interface_string)++; + 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)++: + (*current_endpoint)++; return sizeof(usb_hid_descriptor_template); } static mp_obj_t default_hid_devices[] = { - MP_OBJ_FROM_PTR(usb_hid_device_keyboard_obj), - MP_OBJ_FROM_PTR(usb_hid_device_mouse_obj), - MP_OBJ_FROM_PTR(usb_hid_device_consumer_control_obj), + MP_OBJ_FROM_PTR(&usb_hid_device_keyboard_obj), + MP_OBJ_FROM_PTR(&usb_hid_device_mouse_obj), + MP_OBJ_FROM_PTR(&usb_hid_device_consumer_control_obj), }; // Set the default list of devices that will be included. Called before boot.py runs, in the boot.py VM. @@ -97,78 +133,79 @@ void common_hal_usb_hid_configure_usb_defaults(void) { common_hal_usb_hid_configure_usb(mp_obj_new_tuple(sizeof(default_hid_devices), default_hid_devices)); } -bool common_hal_usb_hid_configure_usb(mp_obj_t devices_seq) { +bool common_hal_usb_hid_configure_usb(mp_obj_t devices) { // We can't change the devices once we're connected. if (tud_connected()) { return false; } // Remember the devices for use in usb_hid_post_boot_py. - hid_devices_seq = devices_seq; + hid_devices_seq = devices; return true; } +void usb_hid_init(void) { + usb_hid_is_enabled = true; +} + // Build the combined HID report descriptor and save the chosen devices. // Both are saved in supervisor allocations. void usb_hid_post_boot_py(void) { - size_t total_report_descriptors_length = 0; // Build a combined report descriptor - mp_int_t len = mp_obj_get_int(mp_obj_len(hid_devices_seq)); + hid_devices_num = mp_obj_get_int(mp_obj_len(hid_devices_seq)); // First get the total size. - for (size_t i = 0; i < len; i++) { - mp_obj_t item = mp_obj_subscr(devices_seq, mp_obj_new_small_int(i), MP_OBJ_SENTINEL); - if (!MP_OBJ_IS_TYPE(item, &usb_hid_device_type)) { - return USB_CONFIG_NON_DEVICE; for (size_t i = 0; i < len; i++) { - mp_obj_t item = (devices, mp_obj_new_small_int(i), MP_OBJ_SENTINEL); - if (!MP_OBJ_IS_TYPE(item, &usb_hid_device_type)) { - return USB_CONFIG_NON_DEVICE; - } - total_report_descriptors_length += device->report_descriptor_length; + total_hid_report_descriptor_length = 0; + for (mp_int_t i = 0; i < hid_devices_num; i++) { + // hid_devices_seq has already been validated to contain only usb_hid_device_obj_t objects. + usb_hid_device_obj_t *device = + MP_OBJ_TO_PTR(mp_obj_subscr(hid_devices_seq, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL)); + total_hid_report_descriptor_length += device->report_descriptor_length; } - } - total_report_descriptors_length += device->report_descriptor_length; - } - if (len == 1) { - // Don't need space for a report id if there's only one device. - total_report_descriptors_length -= 2; + // Don't need space for a report id if there's only one device. + if (hid_devices_num == 1) { + total_hid_report_descriptor_length -= 2; } // Allocate storage that persists across VMs to build the combined descriptor // and to remember the device details. hid_report_descriptor_allocation = - allocate_memory(total_report_descriptors_length, false /*highaddress*/, true /*movable*/); + allocate_memory(align32_size(total_hid_report_descriptor_length), + false /*highaddress*/, true /*movable*/); - hid_devices_allocation = allocate_memory(sizeof(usb_hid_device_obj_t) * len); - usb_hid_device_obj_t hid_devices[] = (usb_hid_device_obj_t[]) hid_devices_allocation->ptr; + hid_devices_allocation = + allocate_memory(align32_size(sizeof(usb_hid_device_obj_t) * hid_devices_num), + false /*highaddress*/, true /*movable*/); + usb_hid_device_obj_t *hid_devices = (usb_hid_device_obj_t *) hid_devices_allocation->ptr; - uint8_t *descriptor_start = (uint8_t *) hid_report_descriptor_allocation->ptr; + uint8_t *report_descriptor_start = (uint8_t *) hid_report_descriptor_allocation->ptr; - for (size_t i = 0; i < len; i++) { - usb_hid_device_obj_t *device = MP_OBJ_TO_PTR(hid_devices_seq, mp_obj_new_small_int(i), MP_OBJ_SENTINEL); + for (mp_int_t i = 0; i < hid_devices_num; i++) { + usb_hid_device_obj_t *device = + MP_OBJ_TO_PTR(mp_obj_subscr(hid_devices_seq, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL)); // Copy the report descriptor for this device. - if (len == 1) { + if (hid_devices_num == 1) { // Theres only one device, so it shouldn't have a report ID. // Copy the descriptor, but splice out the report id indicator and value (2 bytes). - memcpy(descriptor_start, device->descriptor, device->report_id_index - 1); - descriptor_start += device->report_id_index - 1; - memcpy(descriptor_start, device->descriptor + device->report_id_index + 1, + memcpy(report_descriptor_start, device->report_descriptor, device->report_id_index - 1); + report_descriptor_start += device->report_id_index - 1; + memcpy(report_descriptor_start, device->report_descriptor + device->report_id_index + 1, device->report_descriptor_length - device->report_id_index - 1); } else { // Copy the whole descriptor and fill in the report id. - memcpy(descriptor_start, device->descriptor, device->descriptor_len); - descriptor_start[device->report_id_index] = i + 1; - descriptor_start += device->descriptor_len; + memcpy(report_descriptor_start, device->report_descriptor, device->report_descriptor_length); + report_descriptor_start[device->report_id_index] = i + 1; + report_descriptor_start += device->report_descriptor_length; } // Copy the device data and discard any descriptor-bytes object pointer. memcpy(&hid_devices[i], device, sizeof(usb_hid_device_obj_t)); - hid_devices[i].descriptor_obj = mp_const_none; + hid_devices[i].report_descriptor_obj = mp_const_none; } // No longer keeping the Python object of devices to configure. @@ -176,13 +213,31 @@ void usb_hid_post_boot_py(void) { } void usb_hid_gc_collect(void) { - // Once tud_mounted() is true, we're done with the constructed descriptors. if (tud_mounted()) { + // Once tud_mounted() is true, we're done with the constructed descriptors. free_memory(hid_report_descriptor_allocation); - free_memory(usb_hid_devices_allocation); - } else { - gc_collect_ptr(hid_devices_seq); - gc_collect_ptr(hid_report_descriptor_allocation->ptr); - gc_collect_ptr(usb_hid_devices_allocation_ptr); } + + gc_collect_ptr(hid_devices_seq); + gc_collect_ptr(hid_report_descriptor_allocation->ptr); + gc_collect_ptr(hid_devices_allocation->ptr); +} + +#if CIRCUITPY_USB_HID +// 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) { + return (uint8_t *) hid_report_descriptor_allocation->ptr; +} +#endif + +usb_hid_device_obj_t *usb_hid_get_device_with_report_id(uint8_t report_id) { + for (uint8_t i = 0; i < hid_devices_num; i++) { + usb_hid_device_obj_t *hid_devices = (usb_hid_device_obj_t *) hid_devices_allocation->ptr; + if (hid_devices[i].report_id == report_id) { + return &hid_devices[i]; + } + } + return NULL; } diff --git a/shared-module/usb_hid/__init__.h b/shared-module/usb_hid/__init__.h index f95a94c679..048e6107bc 100644 --- a/shared-module/usb_hid/__init__.h +++ b/shared-module/usb_hid/__init__.h @@ -29,10 +29,19 @@ #include "shared-module/usb_hid/Device.h" -extern bool usb_hid_enabled; extern usb_hid_device_obj_t usb_hid_devices[]; +bool usb_hid_enabled(void); + +void usb_hid_init(void); +void usb_hid_post_boot_py(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_descriptor_length(void); +size_t usb_hid_report_descriptor_length(void); + +usb_hid_device_obj_t *usb_hid_get_device_with_report_id(uint8_t report_id); + void usb_hid_gc_collect(void); - #endif // SHARED_MODULE_USB_HID___INIT___H diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c index d1402d3e59..8897fd39b7 100644 --- a/shared-module/usb_midi/__init__.c +++ b/shared-module/usb_midi/__init__.c @@ -33,6 +33,7 @@ #include "shared-bindings/usb_midi/PortIn.h" #include "shared-bindings/usb_midi/PortOut.h" #include "supervisor/memory.h" +#include "supervisor/usb.h" #include "tusb.h" supervisor_allocation *usb_midi_allocation; @@ -79,7 +80,7 @@ static const uint8_t usb_midi_descriptor_template[] = { 0x24, // 28 bDescriptorType: CLASS SPECIFIC INTERFACE 0x01, // 29 bDescriptorSubtype: MIDI STREAMING HEADER 0x00, 0x01, // 30,31 bsdMSC (MIDI STREAMING) version 1.0 - 0x25, 0x00 // 32,33 wLength + 0x25, 0x00, // 32,33 wLength // MIDI Embedded In Jack Descriptor 0x06, // 34 bLength @@ -155,17 +156,21 @@ static const uint8_t usb_midi_descriptor_template[] = { }; // Is the USB MIDI device enabled? -bool usb_midi_enabled; +static bool usb_midi_is_enabled; + +bool usb_midi_enabled(void) { + return usb_midi_is_enabled; +} size_t usb_midi_descriptor_length(void) { return sizeof(usb_midi_descriptor_template); } -static const char[] midi_streaming_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " MIDI"; -static const char[] midi_audio_control_interface_name = MP_STRINGIFY(USB_INTERFACE_NAME) " Audio"; -static const char[] midi_in_jack_name = MP_STRINGIFY(USB_INTERFACE_NAME) " usb_midi.ports[0]"; -static const char[] midi_out_jack_name = MP_STRINGIFY(USB_INTERFACE_NAME) " usb_midi.ports[0]"; +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)); @@ -173,8 +178,9 @@ size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfa descriptor_buf[MIDI_AUDIO_CONTROL_INTERFACE_NUMBER_INDEX] = *current_interface; (*current_interface)++; - descriptor_buf[MSC_IN_ENDPOINT_INDEX] = USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : *current_endpoint; - descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = + descriptor_buf[MIDI_STREAMING_IN_ENDPOINT_INDEX] = + USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : *current_endpoint; + descriptor_buf[MIDI_STREAMING_OUT_ENDPOINT_INDEX] = 0x80 | (USB_MIDI_EP_NUM_OUT ? USB_MIDI_EP_NUM_OUT : *current_endpoint); (*current_endpoint)++; @@ -203,13 +209,13 @@ size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, uint8_t *current_interfa void usb_midi_init(void) { - usb_midi_enabled = true; + usb_midi_is_enabled = true; } void usb_midi_usb_init(void) { mp_obj_tuple_t *ports; - if (usb_midi_enabled) { + if (usb_midi_is_enabled) { // TODO(tannewt): Make this dynamic. size_t tuple_size = align32_size(sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t *) * 2); size_t portin_size = align32_size(sizeof(usb_midi_portin_obj_t)); @@ -241,6 +247,6 @@ bool common_hal_usb_midi_configure_usb(bool enabled) { if (tud_connected()) { return false; } - usb_midi_enabled = enabled; + usb_midi_is_enabled = enabled; return true; } diff --git a/shared-module/usb_midi/__init__.h b/shared-module/usb_midi/__init__.h index 28871185cf..4bb5e5f52a 100644 --- a/shared-module/usb_midi/__init__.h +++ b/shared-module/usb_midi/__init__.h @@ -27,11 +27,11 @@ #ifndef SHARED_MODULE_USB_MIDI___INIT___H #define SHARED_MODULE_USB_MIDI___INIT___H -extern bool usb_midi_enabled; void usb_midi_init(void); void usb_midi_usb_init(void); +bool usb_midi_enabled(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); diff --git a/supervisor/shared/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c index 04a482886e..d866c71f4b 100644 --- a/supervisor/shared/usb/usb_desc.c +++ b/supervisor/shared/usb/usb_desc.c @@ -26,6 +26,9 @@ #include "lib/tinyusb/src/tusb.h" +#include "py/gc.h" +#include "py/objstr.h" +#include "py/runtime.h" #include "supervisor/usb.h" #if CIRCUITPY_USB_CDC @@ -44,20 +47,17 @@ #include "shared-bindings/storage/__init__.h" #endif -// For COMMON_HAL_MCU_PROCESSOR_UID_LENGTH -#include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/Processor.h" -uint8_t *device_descriptor; -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 uint16_t **collected_interface_strings; +static uint8_t current_interface_string; -static const char manufacturer_name[] = MP_STRINGIFY(USB_MANUFACTURER); -static const char product_name[] = MP_STRINGIFY(USB_PRODUCT); +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]; @@ -86,6 +86,8 @@ static const uint8_t device_descriptor_template[] = { 0x01, // 17 bNumConfigurations 1 }; +static uint8_t device_descriptor[sizeof(device_descriptor_template)]; + static const uint8_t configuration_descriptor_template[] = { 0x09, // 0 bLength 0x02, // 1 bDescriptorType (Configuration) @@ -100,6 +102,8 @@ static const uint8_t configuration_descriptor_template[] = { 0x32, // 8 bMaxPower 100mA }; +static uint8_t configuration_descriptor[sizeof(configuration_descriptor_template)]; + // Initialization done before boot.py is run. // Turn on or off various USB devices. On devices with limited endpoints, // some may be off by default. @@ -132,55 +136,53 @@ static void usb_build_device_descriptor(uint16_t vid, uint16_t pid) { device_descriptor[DEVICE_PID_LO_INDEX] = pid & 0xFF; device_descriptor[DEVICE_PID_HI_INDEX] = pid >> 8; - 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, 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, 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)++; + usb_add_interface_string(current_interface_string, serial_number_hex_string); + device_descriptor[DEVICE_SERIAL_NUMBER_STRING_INDEX] = current_interface_string; + current_interface_string++; } -static void usb_build_configuration_descriptor(uint16_t total_length, uint8_t num_interfaces) { +static void usb_build_configuration_descriptor(void) { size_t total_descriptor_length = sizeof(configuration_descriptor_template); // CDC should be first, for compatibility with Adafruit Windows 7 drivers. - // In the past, the order has been CDC, MSC, MIDI, HID, so preserve - // that order. + // In the past, the order has been CDC, MSC, MIDI, HID, so preserve that order. #if CIRCUITPY_USB_CDC - if (usb_cdc_repl_enabled) { + if (usb_cdc_repl_enabled()) { total_descriptor_length += usb_cdc_descriptor_length(); } - if (usb_cdc_data_enabled) { + if (usb_cdc_data_enabled()) { total_descriptor_length += usb_cdc_descriptor_length(); } #endif #if CIRCUITPY_USB_MSC - if (storage_usb_enabled) { + if (storage_usb_enabled()) { total_descriptor_length += storage_usb_descriptor_length(); } #endif #if CIRCUITPY_USB_MIDI - if (usb_midi_enabled) { + if (usb_midi_enabled()) { total_descriptor_length += usb_midi_descriptor_length(); } #endif #if CIRCUITPY_USB_HID - if (usb_hid_enabled) { + if (usb_hid_enabled()) { total_descriptor_length += usb_hid_descriptor_length(); } #endif // Now we now how big the configuration descriptor will be. // Copy the top-level template, and fix up its length. - memcpy(config_descriptor, configuration_descriptor_template, sizeof(configuration_descriptor_template)); configuration_descriptor[CONFIG_TOTAL_LENGTH_LO_INDEX] = total_descriptor_length & 0xFF; configuration_descriptor[CONFIG_TOTAL_LENGTH_HI_INDEX] = (total_descriptor_length >> 8) & 0xFF; @@ -192,38 +194,39 @@ static void usb_build_configuration_descriptor(uint16_t total_length, uint8_t nu uint8_t *descriptor_buf_remaining = configuration_descriptor + sizeof(configuration_descriptor_template); #if CIRCUITPY_USB_CDC - if (usb_cdc_repl_enabled) { + 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); + descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string, true); } - if (usb_cdc_data_enabled) { + 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); + descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string, false); } #endif #if CIRCUITPY_USB_MSC - if (storage_usb_enabled) { + 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, *current_interface_string); + descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string); } #endif #if CIRCUITPY_USB_MIDI - if (usb_midi_enabled) { + if (usb_midi_enabled()) { // Concatenate and fix up the MIDI descriptor. descriptor_buf_remaining += usb_midi_add_descriptor( - descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string); + descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string); } #endif #if CIRCUITPY_USB_HID - if (usb_hid_enabled) { + if (usb_hid_enabled()) { descriptor_buf_remaining += usb_hid_add_descriptor( - descriptor_buf_remaining, *current_interface, *current_endpoint, *current_interface_string); + descriptor_buf_remaining, ¤t_interface, ¤t_endpoint, ¤t_interface_string, + usb_hid_report_descriptor_length()); } #endif @@ -232,14 +235,14 @@ static void usb_build_configuration_descriptor(uint16_t total_length, uint8_t nu // Did we run out of endpoints? if (current_endpoint - 1 > USB_NUM_EP) { - mp_raise_SystemError("Not enough USB endpoints"); + mp_raise_RuntimeError(translate("Not enough USB endpoints")); } } -void usb_add_interface_string(uint8_t interface_string_index, const char[] str) { +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"); + mp_raise_RuntimeError(translate("Too many USB interface names")); } // 2 bytes for String Descriptor header, then 2 bytes for each character const size_t str_len = strlen(str); @@ -247,7 +250,7 @@ void usb_add_interface_string(uint8_t interface_string_index, const char[] str) 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++) { + for (size_t i = 0; i <= str_len; i++) { string_descriptor[i + 1] = str[i]; } @@ -261,8 +264,8 @@ void usb_desc_post_boot_py(void) { usb_hid_post_boot_py(); } -// Called in a the new VM created after boot.py is run. The USB devices to be used are now chosen. -static void usb_desc_init(void) { +// Called in the new VM created after boot.py is run. The USB devices to be used are now chosen. +void usb_desc_init(void) { uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH]; common_hal_mcu_processor_get_uid(raw_id); @@ -282,14 +285,12 @@ static void usb_desc_init(void) { usb_build_device_descriptor(USB_VID, USB_PID); usb_build_configuration_descriptor(); - usb_build_hid_descriptor(); - usb_build_string_descriptors(); } void usb_desc_gc_collect(void) { // Once tud_mounted() is true, we're done with the constructed descriptors. if (tud_mounted()) { - gc_free(device_descriptor_allocation); + gc_free(device_descriptor); gc_free(configuration_descriptor); } else { gc_collect_ptr(device_descriptor); @@ -301,7 +302,7 @@ void usb_desc_gc_collect(void) { // Invoked when GET DEVICE DESCRIPTOR is received. // Application return pointer to descriptor uint8_t const *tud_descriptor_device_cb(void) { - return usb_descriptor_dev; + return device_descriptor; } // Invoked when GET CONFIGURATION DESCRIPTOR is received. @@ -309,18 +310,9 @@ uint8_t const *tud_descriptor_device_cb(void) { // Descriptor contents must exist long enough for transfer to complete uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { (void)index; // for multiple configurations - return config_desc; + return configuration_descriptor; } -#if CIRCUITPY_USB_HID -// 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) { - return hid_report_descriptor; -} -#endif - // 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) { diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index 34a5a5cc7f..305b6a2c39 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -134,14 +134,16 @@ ifeq ($(CIRCUITPY_DISPLAYIO), 1) endif endif +# Preserve double quotes in these values by single-quoting them. + USB_INTERFACE_NAME ?= "CircuitPython" -CFLAGS += -DUSB_INTERFACE_NAME=$(USB_INTERFACE_NAME) +CFLAGS += -DUSB_INTERFACE_NAME='$(USB_INTERFACE_NAME)' ifneq ($(USB_VID),) CFLAGS += -DUSB_VID=$(USB_VID) -CFLAGS += -DSUB_PID=$(USB_PID) -CFLAGS += -DUSB_MANUFACTURER=$(USB_MANUFACTURER) -CFLAGS += -DUSB_PRODUCT=$(USB_PRODUCT) +CFLAGS += -DUSB_PID=$(USB_PID) +CFLAGS += -DUSB_MANUFACTURER='$(USB_MANUFACTURER)' +CFLAGS += -DUSB_PRODUCT='$(USB_PRODUCT)' endif # In the following URL, don't include the https:// prefix. @@ -149,39 +151,12 @@ endif USB_WEBUSB_URL ?= "circuitpython.org" ifeq ($(CIRCUITPY_USB_CDC),1) -# Inform TinyUSB there are two CDC devices. +# Inform TinyUSB there will be up to two CDC devices. CFLAGS += -DCFG_TUD_CDC=2 endif USB_HIGHSPEED ?= 0 -************ move these from make variables to cpp only ??? -USB_CDC_EP_NUM_NOTIFICATION ?= 0 -CFLAGS += -DUSB_CDC_EP_NUM_NOTIFICATION=$(USB_CDC_EP_NUM_NOTIFICATION) -USB_CDC_EP_NUM_DATA_OUT ?= 0 -CFLAGS += -DUSB_CDC_EP_NUM_DATA_OUT=$(USB_CDC_EP_NUM_DATA_OUT) -USB_CDC_EP_NUM_DATA_IN ?= 0 -CFLAGS += -DUSB_CDC_EP_NUM_DATA_IN=$(USB_CDC_EP_NUM_DATA_IN) - -USB_CDC2_EP_NUM_NOTIFICATION ?= 0 -CFLAGS += -DUSB_CDC2_EP_NUM_NOTIFICATION=$(USB_CDC2_EP_NUM_NOTIFICATION) -USB_CDC2_EP_NUM_DATA_OUT ?= 0 -CFLAGS += -DUSB_CDC2_EP_NUM_DATA_OUT=$(USB_CDC2_EP_NUM_DATA_OUT) -USB_CDC2_EP_NUM_DATA_IN ?= 0 -CFLAGS += -DUSB_CDC2_EP_NUM_DATA_IN=$(USB_CDC2_EP_NUM_DATA_IN) - -USB_MSC_EP_NUM_OUT ?= 0 -CFLAGS += -DUSB -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 - $(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h CIRCUITPY_DISPLAY_FONT ?= "../../tools/fonts/ter-u12n.bdf"