From 7c2961873fa3d40c7fc2e3d6ab27b24c59139895 Mon Sep 17 00:00:00 2001 From: Blake Felt Date: Sat, 17 Sep 2022 20:34:09 -0600 Subject: [PATCH 1/8] shared/tinyusb: Create for reuse. Add usb_device module. --- ports/rp2/CMakeLists.txt | 10 +- ports/rp2/main.c | 5 + ports/rp2/mpconfigport.h | 7 + ports/rp2/tusb_port.c | 151 ------------ {ports/rp2 => shared/tinyusb}/tusb_config.h | 8 +- shared/tinyusb/usbd.c | 17 ++ shared/tinyusb/usbd.h | 11 + shared/tinyusb/usbd_descriptor.c | 250 ++++++++++++++++++++ 8 files changed, 304 insertions(+), 155 deletions(-) delete mode 100644 ports/rp2/tusb_port.c rename {ports/rp2 => shared/tinyusb}/tusb_config.h (90%) create mode 100644 shared/tinyusb/usbd.c create mode 100644 shared/tinyusb/usbd.h create mode 100644 shared/tinyusb/usbd_descriptor.c diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 37ac78b7339f4..f27602c387732 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -125,10 +125,11 @@ set(MICROPY_SOURCE_PORT pendsv.c rp2_flash.c rp2_pio.c - tusb_port.c uart.c msc_disk.c mbedtls/mbedtls_port.c + ${MICROPY_DIR}/shared/tinyusb/usbd_descriptor.c + ${MICROPY_DIR}/shared/tinyusb/usbd.c ) set(MICROPY_SOURCE_QSTR @@ -136,6 +137,8 @@ set(MICROPY_SOURCE_QSTR ${MICROPY_DIR}/shared/readline/readline.c ${MICROPY_DIR}/shared/runtime/mpirq.c ${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c + ${MICROPY_DIR}/shared/tinyusb/usbd.c + ${MICROPY_DIR}/shared/tinyusb/usbd_descriptor.c ${PROJECT_SOURCE_DIR}/machine_adc.c ${PROJECT_SOURCE_DIR}/machine_i2c.c ${PROJECT_SOURCE_DIR}/machine_i2s.c @@ -233,6 +236,11 @@ if(MICROPY_BLUETOOTH_NIMBLE) list(APPEND MICROPY_INC_CORE ${NIMBLE_INCLUDE}) endif() +# tinyusb helper +target_include_directories(${MICROPY_TARGET} PRIVATE + ${MICROPY_DIR}/shared/tinyusb/ +) + if (MICROPY_PY_NETWORK_CYW43) string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/cyw43-driver) if((NOT (${ECHO_SUBMODULES})) AND NOT EXISTS ${MICROPY_DIR}/lib/cyw43-driver/src/cyw43.h) diff --git a/ports/rp2/main.c b/ports/rp2/main.c index 1062236a3916b..c8128412bdb32 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -43,6 +43,7 @@ #include "modrp2.h" #include "mpbthciport.h" #include "genhdr/mpversion.h" +#include "usbd.h" #include "pico/stdlib.h" #include "pico/binary_info.h" @@ -87,6 +88,7 @@ int main(int argc, char **argv) { #if MICROPY_HW_ENABLE_USBDEV bi_decl(bi_program_feature("USB REPL")) tusb_init(); + usbd_descriptor_reset(); // run now just in case usb initialization occurs early #endif #if MICROPY_PY_THREAD @@ -159,6 +161,9 @@ int main(int argc, char **argv) { machine_pin_init(); rp2_pio_init(); machine_i2s_init0(); + #if MICROPY_HW_ENABLE_USBDEV + usbd_descriptor_reset(); + #endif #if MICROPY_PY_BLUETOOTH mp_bluetooth_hci_init(); diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index a3725789f0848..2518a275b0bbc 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -198,6 +198,13 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k; // Miscellaneous settings +#ifndef MICROPY_HW_USB_VID +#define MICROPY_HW_USB_VID (0x2E8A) // Raspberry Pi +#endif +#ifndef MICROPY_HW_USB_PID +#define MICROPY_HW_USB_PID (0x0005) // RP2 MicroPython +#endif + // Entering a critical section. extern uint32_t mp_thread_begin_atomic_section(void); extern void mp_thread_end_atomic_section(uint32_t); diff --git a/ports/rp2/tusb_port.c b/ports/rp2/tusb_port.c deleted file mode 100644 index 4aac08791e94e..0000000000000 --- a/ports/rp2/tusb_port.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "tusb.h" -#include "pico/unique_id.h" - -#ifndef MICROPY_HW_USB_VID -#define MICROPY_HW_USB_VID (0x2E8A) // Raspberry Pi -#endif -#ifndef MICROPY_HW_USB_PID -#define MICROPY_HW_USB_PID (0x0005) // RP2 MicroPython -#endif - -#if CFG_TUD_MSC -#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) -#else -#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) -#endif -#define USBD_MAX_POWER_MA (250) - -#define USBD_ITF_CDC (0) // needs 2 interfaces -#define USBD_ITF_MSC (2) -#if CFG_TUD_MSC -#define USBD_ITF_MAX (3) -#else -#define USBD_ITF_MAX (2) -#endif - -#define USBD_CDC_EP_CMD (0x81) -#define USBD_CDC_EP_OUT (0x02) -#define USBD_CDC_EP_IN (0x82) -#define USBD_CDC_CMD_MAX_SIZE (8) -#define USBD_CDC_IN_OUT_MAX_SIZE (64) - -#define EPNUM_MSC_OUT (0x03) -#define EPNUM_MSC_IN (0x83) - -#define USBD_STR_0 (0x00) -#define USBD_STR_MANUF (0x01) -#define USBD_STR_PRODUCT (0x02) -#define USBD_STR_SERIAL (0x03) -#define USBD_STR_CDC (0x04) -#define USBD_STR_MSC (0x05) - -// Note: descriptors returned from callbacks must exist long enough for transfer to complete - -static const tusb_desc_device_t usbd_desc_device = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = MICROPY_HW_USB_VID, - .idProduct = MICROPY_HW_USB_PID, - .bcdDevice = 0x0100, - .iManufacturer = USBD_STR_MANUF, - .iProduct = USBD_STR_PRODUCT, - .iSerialNumber = USBD_STR_SERIAL, - .bNumConfigurations = 1, -}; - -static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = { - TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN, - 0, USBD_MAX_POWER_MA), - - TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, - USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), - #if CFG_TUD_MSC - TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), - #endif -}; - -static const char *const usbd_desc_str[] = { - [USBD_STR_MANUF] = "MicroPython", - [USBD_STR_PRODUCT] = "Board in FS mode", - [USBD_STR_SERIAL] = NULL, // generated dynamically - [USBD_STR_CDC] = "Board CDC", - #if CFG_TUD_MSC - [USBD_STR_MSC] = "Board MSC", - #endif -}; - -const uint8_t *tud_descriptor_device_cb(void) { - return (const uint8_t *)&usbd_desc_device; -} - -const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { - (void)index; - return usbd_desc_cfg; -} - -const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - #define DESC_STR_MAX (20) - static uint16_t desc_str[DESC_STR_MAX]; - - uint8_t len; - if (index == 0) { - desc_str[1] = 0x0409; // supported language is English - len = 1; - } else { - if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { - return NULL; - } - // check, if serial is requested - if (index == USBD_STR_SERIAL) { - pico_unique_board_id_t id; - pico_get_unique_board_id(&id); - // byte by byte conversion - for (len = 0; len < 16; len += 2) { - const char *hexdig = "0123456789abcdef"; - desc_str[1 + len] = hexdig[id.id[len >> 1] >> 4]; - desc_str[1 + len + 1] = hexdig[id.id[len >> 1] & 0x0f]; - } - } else { - const char *str = usbd_desc_str[index]; - for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { - desc_str[1 + len] = str[len]; - } - } - } - - // first byte is length (including header), second byte is string type - desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * len + 2); - - return desc_str; -} diff --git a/ports/rp2/tusb_config.h b/shared/tinyusb/tusb_config.h similarity index 90% rename from ports/rp2/tusb_config.h rename to shared/tinyusb/tusb_config.h index ce321616a6bc3..61409cad6bc3d 100644 --- a/ports/rp2/tusb_config.h +++ b/shared/tinyusb/tusb_config.h @@ -22,9 +22,11 @@ * THE SOFTWARE. * */ -#ifndef MICROPY_INCLUDED_RP2_TUSB_CONFIG_H -#define MICROPY_INCLUDED_RP2_TUSB_CONFIG_H +#ifndef MICROPY_INCLUDED_EXTMOD_TUSB_CONFIG_H +#define MICROPY_INCLUDED_EXTMOD_TUSB_CONFIG_H + +#include #include "mpconfigport.h" #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE) @@ -41,4 +43,4 @@ #define CFG_TUD_MSC_BUFSIZE (MICROPY_FATFS_MAX_SS) #endif -#endif // MICROPY_INCLUDED_RP2_TUSB_CONFIG_H +#endif // MICROPY_INCLUDED_EXTMOD_TUSB_CONFIG_H diff --git a/shared/tinyusb/usbd.c b/shared/tinyusb/usbd.c new file mode 100644 index 0000000000000..660d297ed8c71 --- /dev/null +++ b/shared/tinyusb/usbd.c @@ -0,0 +1,17 @@ + +#include "py/runtime.h" +#include "usbd.h" + +STATIC const mp_rom_map_elem_t usb_device_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_device) }, + + { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&usbd_descriptor_type) }, +}; +STATIC MP_DEFINE_CONST_DICT(usb_device_module_globals, usb_device_module_globals_table); + +const mp_obj_module_t mp_module_usb_device = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&usb_device_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_usb_device, mp_module_usb_device); diff --git a/shared/tinyusb/usbd.h b/shared/tinyusb/usbd.h new file mode 100644 index 0000000000000..7aced0dc45de7 --- /dev/null +++ b/shared/tinyusb/usbd.h @@ -0,0 +1,11 @@ + +#ifndef MICROPY_INCLUDED_USBD_SHARED_H_ +#define MICROPY_INCLUDED_USBD_SHARED_H_ + +#include "py/obj.h" + +void usbd_descriptor_reset(void); + +extern const mp_obj_type_t usbd_descriptor_type; + +#endif diff --git a/shared/tinyusb/usbd_descriptor.c b/shared/tinyusb/usbd_descriptor.c new file mode 100644 index 0000000000000..85a6e807bb47c --- /dev/null +++ b/shared/tinyusb/usbd_descriptor.c @@ -0,0 +1,250 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "usbd.h" +#include "mpconfigport.h" + +#include "pico/unique_id.h" + +#define DESC_STR_MAX (31) + +// tusb.h is not available when running the string preprocessor +#ifndef NO_QSTR +#include "tusb.h" +#endif + +#if CFG_TUD_MSC +#define USBD_DESC_DEFAULT_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) +#else +#define USBD_DESC_DEFAULT_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) +#endif +#define USBD_MAX_POWER_MA (250) + +#define USBD_ITF_CDC (0) // needs 2 interfaces +#define USBD_ITF_MSC (2) +#if CFG_TUD_MSC +#define USBD_ITF_MAX (3) +#else +#define USBD_ITF_MAX (2) +#endif + +#define USBD_CDC_EP_CMD (0x81) +#define USBD_CDC_EP_OUT (0x02) +#define USBD_CDC_EP_IN (0x82) +#define USBD_CDC_CMD_MAX_SIZE (8) +#define USBD_CDC_IN_OUT_MAX_SIZE (64) + +#define EPNUM_MSC_OUT (0x03) +#define EPNUM_MSC_IN (0x83) + +#define USBD_STR_0 (0x00) +#define USBD_STR_MANUF (0x01) +#define USBD_STR_PRODUCT (0x02) +#define USBD_STR_SERIAL (0x03) +#define USBD_STR_CDC (0x04) +#define USBD_STR_MSC (0x05) + +// Note: descriptors returned from callbacks must exist long enough for transfer to complete + +typedef struct _usb_device_descriptor_obj_t { + mp_obj_base_t base; +} usb_device_descriptor_obj_t; + +// singleton +STATIC const usb_device_descriptor_obj_t usb_device_descriptor_obj = {{&usbd_descriptor_type}}; + +STATIC mp_obj_t usb_device_descriptor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + return (mp_obj_t)&usb_device_descriptor_obj; +} + +const tusb_desc_device_t usbd_desc_device_default = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .idVendor = MICROPY_HW_USB_VID, + .idProduct = MICROPY_HW_USB_PID, + .bcdDevice = 0x0100, + .iManufacturer = USBD_STR_MANUF, + .iProduct = USBD_STR_PRODUCT, + .iSerialNumber = USBD_STR_SERIAL, + .bNumConfigurations = 1, +}; +static tusb_desc_device_t usbd_desc_device; + +// device(bDeviceClass=None, bDeviceSubclass=None, bDeviceProtocol=None, +// idVendor=None, idProduct=None, bcdDevice=None) +STATIC mp_obj_t usb_device_descriptor_device(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { + ARG_bDeviceClass, ARG_bDeviceSubClass, ARG_bDeviceProtocol, + ARG_idVendor, ARG_idProduct, ARG_bcdDevice + }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bDeviceClass, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_bDeviceSubclass, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_bDeviceProtocol, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_idVendor, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_idProduct, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_bcdDevice, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} } + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_bDeviceClass].u_obj != mp_const_none) { + usbd_desc_device.bDeviceClass = mp_obj_get_int(args[ARG_bDeviceClass].u_obj); + } + if (args[ARG_bDeviceSubClass].u_obj != mp_const_none) { + usbd_desc_device.bDeviceSubClass = mp_obj_get_int(args[ARG_bDeviceSubClass].u_obj); + } + if (args[ARG_bDeviceProtocol].u_obj != mp_const_none) { + usbd_desc_device.bDeviceProtocol = mp_obj_get_int(args[ARG_bDeviceProtocol].u_obj); + } + if (args[ARG_idVendor].u_obj != mp_const_none) { + usbd_desc_device.idVendor = mp_obj_get_int(args[ARG_idVendor].u_obj); + } + if (args[ARG_idProduct].u_obj != mp_const_none) { + usbd_desc_device.idProduct = mp_obj_get_int(args[ARG_idProduct].u_obj); + } + if (args[ARG_bDeviceClass].u_obj != mp_const_none) { + usbd_desc_device.bDeviceClass = mp_obj_get_int(args[ARG_bDeviceClass].u_obj); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(usb_device_descriptor_device_obj, 1, usb_device_descriptor_device); + +static const uint8_t usbd_desc_cfg[USBD_DESC_DEFAULT_LEN] = { + TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_DEFAULT_LEN, + 0, USBD_MAX_POWER_MA), + + TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, + USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), + #if CFG_TUD_MSC + TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), + #endif +}; + +static const char *const usbd_desc_str[] = { + [USBD_STR_MANUF] = "MicroPython", + [USBD_STR_PRODUCT] = "Board in FS mode", + [USBD_STR_SERIAL] = NULL, // generated dynamically + [USBD_STR_CDC] = "Board CDC", + #if CFG_TUD_MSC + [USBD_STR_MSC] = "Board MSC", + #endif +}; + + +const uint8_t *tud_descriptor_device_cb(void) { + return (const uint8_t *)&usbd_desc_device; +} + +const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { + (void)index; + return usbd_desc_cfg; +} + +const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { + static uint16_t desc_str[DESC_STR_MAX]; + + uint8_t len; + if (index == 0) { + desc_str[1] = 0x0409; // supported language is English + len = 1; + } else { + if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { + return NULL; + } + // check, if serial is requested + if (index == USBD_STR_SERIAL) { + pico_unique_board_id_t id; + pico_get_unique_board_id(&id); + // byte by byte conversion + for (len = 0; len < 16; len += 2) { + const char *hexdig = "0123456789abcdef"; + desc_str[1 + len] = hexdig[id.id[len >> 1] >> 4]; + desc_str[1 + len + 1] = hexdig[id.id[len >> 1] & 0x0f]; + } + } else { + const char *str = usbd_desc_str[index]; + for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { + desc_str[1 + len] = str[len]; + } + } + } + + // first byte is length (including header), second byte is string type + desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * len + 2); + + return desc_str; +} + +void usbd_descriptor_reset(void) { + usbd_desc_device = usbd_desc_device_default; +} + +STATIC const mp_rom_map_elem_t usb_device_descriptors_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_device), (mp_obj_t)&usb_device_descriptor_device_obj}, + + { MP_ROM_QSTR(MP_QSTR_CLASS_UNSPECIFIED), MP_ROM_INT(TUSB_CLASS_UNSPECIFIED)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_AUDIO), MP_ROM_INT(TUSB_CLASS_AUDIO)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_CDC), MP_ROM_INT(TUSB_CLASS_CDC)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_HID), MP_ROM_INT(TUSB_CLASS_HID)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_PHYSICAL), MP_ROM_INT(TUSB_CLASS_PHYSICAL)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_IMAGE), MP_ROM_INT(TUSB_CLASS_IMAGE)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_PRINTER), MP_ROM_INT(TUSB_CLASS_PRINTER)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_MSC), MP_ROM_INT(TUSB_CLASS_MSC)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_HUB), MP_ROM_INT(TUSB_CLASS_HUB)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_CDC_DATA), MP_ROM_INT(TUSB_CLASS_CDC_DATA)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_SMART_CARD), MP_ROM_INT(TUSB_CLASS_SMART_CARD)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_CONTENT_SECURITY), MP_ROM_INT(TUSB_CLASS_CONTENT_SECURITY)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_VIDEO), MP_ROM_INT(TUSB_CLASS_VIDEO)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_PERSONAL_HEALTHCARE), MP_ROM_INT(TUSB_CLASS_PERSONAL_HEALTHCARE)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_AUDIO_VIDEO), MP_ROM_INT(TUSB_CLASS_AUDIO_VIDEO)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_DIAGNOSTIC), MP_ROM_INT(TUSB_CLASS_DIAGNOSTIC)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_WIRELESS_CONTROLLER), MP_ROM_INT(TUSB_CLASS_WIRELESS_CONTROLLER)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_MISC), MP_ROM_INT(TUSB_CLASS_MISC)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_APPLICATION_SPECIFIC), MP_ROM_INT(TUSB_CLASS_APPLICATION_SPECIFIC)}, + { MP_ROM_QSTR(MP_QSTR_CLASS_VENDOR_SPECIFIC), MP_ROM_INT(TUSB_CLASS_VENDOR_SPECIFIC)}, +}; +STATIC MP_DEFINE_CONST_DICT(usb_device_descriptors_locals_dict, usb_device_descriptors_locals_dict_table); + +const mp_obj_type_t usbd_descriptor_type = { + { &mp_type_type }, + .name = MP_QSTR_Descriptors, + .make_new = usb_device_descriptor_make_new, + .locals_dict = (mp_obj_t)&usb_device_descriptors_locals_dict, +}; \ No newline at end of file From f944b456cb00ec5b89b6bdd9931c0d777798ba70 Mon Sep 17 00:00:00 2001 From: Blake Felt Date: Sun, 18 Sep 2022 02:04:15 -0600 Subject: [PATCH 2/8] shared/tinyusb: Set up dynamic usb descriptors. Not used in python yet. --- shared/tinyusb/tusb_config.h | 2 + shared/tinyusb/usbd_descriptor.c | 154 +++++++++++++++++++++++++++---- 2 files changed, 137 insertions(+), 19 deletions(-) diff --git a/shared/tinyusb/tusb_config.h b/shared/tinyusb/tusb_config.h index 61409cad6bc3d..c886aa4f16731 100644 --- a/shared/tinyusb/tusb_config.h +++ b/shared/tinyusb/tusb_config.h @@ -43,4 +43,6 @@ #define CFG_TUD_MSC_BUFSIZE (MICROPY_FATFS_MAX_SS) #endif +#define MICROPY_HW_USB_MAX_DESCRIPTORS 10 + #endif // MICROPY_INCLUDED_EXTMOD_TUSB_CONFIG_H diff --git a/shared/tinyusb/usbd_descriptor.c b/shared/tinyusb/usbd_descriptor.c index 85a6e807bb47c..e032c7e24e744 100644 --- a/shared/tinyusb/usbd_descriptor.c +++ b/shared/tinyusb/usbd_descriptor.c @@ -146,26 +146,139 @@ STATIC mp_obj_t usb_device_descriptor_device(mp_uint_t n_args, const mp_obj_t *p } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(usb_device_descriptor_device_obj, 1, usb_device_descriptor_device); -static const uint8_t usbd_desc_cfg[USBD_DESC_DEFAULT_LEN] = { - TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_DEFAULT_LEN, - 0, USBD_MAX_POWER_MA), +typedef struct { + uint8_t cfg[512]; + int len; + int itf_count; + int in_count; + int out_count; + char names[MICROPY_HW_USB_MAX_DESCRIPTORS][DESC_STR_MAX]; + int names_len; +} desc_cfg_t; +static desc_cfg_t usbd_desc_cfg; + +uint8_t usbd_desc_cfg_cdc[] = {TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE)}; - TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, - USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE), - #if CFG_TUD_MSC - TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), - #endif -}; +#if CFG_TUD_MSC +uint8_t usbd_desc_cfg_msc[] = {TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64)}; +#endif + +static int desc_cfg_namesfull(desc_cfg_t *cfg) { + if (cfg->names_len >= MICROPY_HW_USB_MAX_DESCRIPTORS) { + return -1; + } + return 0; +} + +static int desc_cfg_addname(desc_cfg_t *cfg, char *name) { + int len; + char *spot; + + if (desc_cfg_namesfull(cfg)) { + return -1; + } + len = strlen(name); + if (len > DESC_STR_MAX-1) { + len = DESC_STR_MAX-1; + } + spot = cfg->names[cfg->names_len]; + memcpy(spot, name, len); + spot[len] = 0; + cfg->names_len++; + return cfg->names_len; +} + +static int desc_cfg_adddesc(desc_cfg_t *cfg, uint8_t *desc, int len, char *name) { + uint8_t *new_desc; + uint8_t *line; + tusb_desc_interface_t *desc_itf; + tusb_desc_endpoint_t *desc_endpoint; + int i; + + if (desc_cfg_namesfull(cfg)) { + return -1; + } + + // get the new spot + new_desc = &(cfg->cfg[cfg->len]); + // and copy the descriptor over + memcpy(new_desc, desc, len); + + for (i=0; ibAlternateSetting == 0) { + desc_itf->bInterfaceNumber = cfg->itf_count; + cfg->itf_count++; + if (name) { + desc_itf->iInterface = desc_cfg_addname(cfg, name); + name = NULL; // only save name once + } + } + } else if (line[1] == TUSB_DESC_ENDPOINT) { + desc_endpoint = (tusb_desc_endpoint_t*) line; + if (desc_endpoint->bEndpointAddress & 0x80) { // if it's in + desc_endpoint->bEndpointAddress = 0x80 | cfg->in_count; + cfg->in_count++; + } else { // if it's out + desc_endpoint->bEndpointAddress = cfg->out_count; + cfg->out_count++; + } + } + i += line[0]; // jump to the next "line" + if (line[0] == 0) { // no infinite loops for me! + return 0; // also, this means we didn't save it at all (desc_len not updated) + } + } + cfg->len += len; + + return 0; +} + + +static void desc_cfg_init(desc_cfg_t *cfg) { + tusb_desc_configuration_t const initial_cfg = + { + .bLength = sizeof(tusb_desc_configuration_t), + .bDescriptorType = TUSB_DESC_CONFIGURATION, -static const char *const usbd_desc_str[] = { - [USBD_STR_MANUF] = "MicroPython", - [USBD_STR_PRODUCT] = "Board in FS mode", - [USBD_STR_SERIAL] = NULL, // generated dynamically - [USBD_STR_CDC] = "Board CDC", + // Total Length & Interface Number will be updated later + .wTotalLength = 0, + .bNumInterfaces = 0, + .bConfigurationValue = 1, + .iConfiguration = 0x00, + .bmAttributes = TU_BIT(7) | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, + .bMaxPower = TUSB_DESC_CONFIG_POWER_MA(USBD_MAX_POWER_MA) + }; + + // clear the config + memset(cfg->cfg, 0, sizeof(cfg->cfg)); + // copy the initial contents + memcpy(cfg->cfg, &initial_cfg, sizeof(tusb_desc_configuration_t)); + cfg->len = sizeof(tusb_desc_configuration_t); + cfg->itf_count = 0; + cfg->in_count = 1; + cfg->out_count = 1; + cfg->names_len = 0; + desc_cfg_addname(cfg, ""); // language code + desc_cfg_addname(cfg, "MicroPython"); + desc_cfg_addname(cfg, "Board in FS mode"); + desc_cfg_addname(cfg, ""); // this is the serial number, will be dynamic + + desc_cfg_adddesc(cfg, usbd_desc_cfg_cdc, sizeof(usbd_desc_cfg_cdc), "Board CDC"); #if CFG_TUD_MSC - [USBD_STR_MSC] = "Board MSC", + desc_cfg_adddesc(cfg, usbd_desc_cfg_msc, sizeof(usbd_desc_cfg_msc), "Board MSC"); #endif -}; +} + +static void desc_cfg_finalize(desc_cfg_t *cfg) { + tusb_desc_configuration_t *conf; + + conf = (tusb_desc_configuration_t*) cfg->cfg; + conf->wTotalLength = cfg->len; // update total length + conf->bNumInterfaces = cfg->itf_count; // update interface count +} const uint8_t *tud_descriptor_device_cb(void) { @@ -174,7 +287,9 @@ const uint8_t *tud_descriptor_device_cb(void) { const uint8_t *tud_descriptor_configuration_cb(uint8_t index) { (void)index; - return usbd_desc_cfg; + + desc_cfg_finalize(&usbd_desc_cfg); + return usbd_desc_cfg.cfg; } const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { @@ -185,7 +300,7 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { desc_str[1] = 0x0409; // supported language is English len = 1; } else { - if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) { + if (index > usbd_desc_cfg.names_len) { return NULL; } // check, if serial is requested @@ -199,7 +314,7 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { desc_str[1 + len + 1] = hexdig[id.id[len >> 1] & 0x0f]; } } else { - const char *str = usbd_desc_str[index]; + const char *str = usbd_desc_cfg.names[index]; for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) { desc_str[1 + len] = str[len]; } @@ -214,6 +329,7 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { void usbd_descriptor_reset(void) { usbd_desc_device = usbd_desc_device_default; + desc_cfg_init(&usbd_desc_cfg); } STATIC const mp_rom_map_elem_t usb_device_descriptors_locals_dict_table[] = { From 9fd9faef2aaa808042af8cd954de2e3b8eae434e Mon Sep 17 00:00:00 2001 From: Blake Felt Date: Sun, 18 Sep 2022 14:58:45 -0600 Subject: [PATCH 3/8] shared/tinyusb: Add USB device HID. Fix name setup in dynamic USB descriptors. --- ports/rp2/CMakeLists.txt | 2 + ports/rp2/main.c | 4 +- ports/rp2/mpconfigport.h | 1 + shared/tinyusb/tusb_config.h | 10 +- shared/tinyusb/usbd.c | 9 ++ shared/tinyusb/usbd.h | 11 +- shared/tinyusb/usbd_descriptor.c | 8 +- shared/tinyusb/usbd_hid.c | 180 +++++++++++++++++++++++++++++++ 8 files changed, 219 insertions(+), 6 deletions(-) create mode 100644 shared/tinyusb/usbd_hid.c diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index f27602c387732..56d6de027da3b 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -129,6 +129,7 @@ set(MICROPY_SOURCE_PORT msc_disk.c mbedtls/mbedtls_port.c ${MICROPY_DIR}/shared/tinyusb/usbd_descriptor.c + ${MICROPY_DIR}/shared/tinyusb/usbd_hid.c ${MICROPY_DIR}/shared/tinyusb/usbd.c ) @@ -139,6 +140,7 @@ set(MICROPY_SOURCE_QSTR ${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c ${MICROPY_DIR}/shared/tinyusb/usbd.c ${MICROPY_DIR}/shared/tinyusb/usbd_descriptor.c + ${MICROPY_DIR}/shared/tinyusb/usbd_hid.c ${PROJECT_SOURCE_DIR}/machine_adc.c ${PROJECT_SOURCE_DIR}/machine_i2c.c ${PROJECT_SOURCE_DIR}/machine_i2s.c diff --git a/ports/rp2/main.c b/ports/rp2/main.c index c8128412bdb32..572e9e42c18f2 100644 --- a/ports/rp2/main.c +++ b/ports/rp2/main.c @@ -88,7 +88,7 @@ int main(int argc, char **argv) { #if MICROPY_HW_ENABLE_USBDEV bi_decl(bi_program_feature("USB REPL")) tusb_init(); - usbd_descriptor_reset(); // run now just in case usb initialization occurs early + usbd_reset_all(); // run now just in case usb initialization occurs early #endif #if MICROPY_PY_THREAD @@ -162,7 +162,7 @@ int main(int argc, char **argv) { rp2_pio_init(); machine_i2s_init0(); #if MICROPY_HW_ENABLE_USBDEV - usbd_descriptor_reset(); + usbd_reset_all(); #endif #if MICROPY_PY_BLUETOOTH diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 2518a275b0bbc..f0c3f7e1e950e 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -109,6 +109,7 @@ #define MICROPY_VFS_FAT (1) #define MICROPY_SSL_MBEDTLS (1) #define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP) +#define MICROPY_HW_USB_HID (1) // fatfs configuration #define MICROPY_FATFS_ENABLE_LFN (1) diff --git a/shared/tinyusb/tusb_config.h b/shared/tinyusb/tusb_config.h index c886aa4f16731..115637d86f0e6 100644 --- a/shared/tinyusb/tusb_config.h +++ b/shared/tinyusb/tusb_config.h @@ -43,6 +43,14 @@ #define CFG_TUD_MSC_BUFSIZE (MICROPY_FATFS_MAX_SS) #endif -#define MICROPY_HW_USB_MAX_DESCRIPTORS 10 +#if MICROPY_HW_USB_HID +#define CFG_TUD_HID (1) +#endif + +// HID buffer size Should be sufficient to hold ID (if any) + Data +#define CFG_TUD_HID_EP_BUFSIZE (64) + +#define MICROPY_HW_USB_MAX_DESCRIPTORS (10) +#define MICROPY_HW_USB_MAX_HID (3) #endif // MICROPY_INCLUDED_EXTMOD_TUSB_CONFIG_H diff --git a/shared/tinyusb/usbd.c b/shared/tinyusb/usbd.c index 660d297ed8c71..b0d2fc96998d4 100644 --- a/shared/tinyusb/usbd.c +++ b/shared/tinyusb/usbd.c @@ -1,11 +1,20 @@ #include "py/runtime.h" #include "usbd.h" +#include "tusb_config.h" + +void usbd_reset_all(void) { + usbd_reset_descriptor(); + usbd_reset_hid(); +} STATIC const mp_rom_map_elem_t usb_device_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_device) }, { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&usbd_descriptor_type) }, + #if MICROPY_HW_USB_HID + { MP_ROM_QSTR(MP_QSTR_HID), MP_ROM_PTR(&usbd_hid_type) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(usb_device_module_globals, usb_device_module_globals_table); diff --git a/shared/tinyusb/usbd.h b/shared/tinyusb/usbd.h index 7aced0dc45de7..57d23b3502e7a 100644 --- a/shared/tinyusb/usbd.h +++ b/shared/tinyusb/usbd.h @@ -4,8 +4,17 @@ #include "py/obj.h" -void usbd_descriptor_reset(void); +// external + +void usbd_reset_all(void); +void usbd_reset_descriptor(void); +void usbd_reset_hid(void); + +// internal extern const mp_obj_type_t usbd_descriptor_type; +extern const mp_obj_type_t usbd_hid_type; + +int usbd_desc_add_descriptor(uint8_t *desc, int len, char *name); #endif diff --git a/shared/tinyusb/usbd_descriptor.c b/shared/tinyusb/usbd_descriptor.c index e032c7e24e744..5e9f7e5cb6c6d 100644 --- a/shared/tinyusb/usbd_descriptor.c +++ b/shared/tinyusb/usbd_descriptor.c @@ -185,7 +185,7 @@ static int desc_cfg_addname(desc_cfg_t *cfg, char *name) { memcpy(spot, name, len); spot[len] = 0; cfg->names_len++; - return cfg->names_len; + return cfg->names_len - 1; } static int desc_cfg_adddesc(desc_cfg_t *cfg, uint8_t *desc, int len, char *name) { @@ -237,6 +237,10 @@ static int desc_cfg_adddesc(desc_cfg_t *cfg, uint8_t *desc, int len, char *name) } +int usbd_desc_add_descriptor(uint8_t *desc, int len, char *name) { + return desc_cfg_adddesc(&usbd_desc_cfg, desc, len, name); +} + static void desc_cfg_init(desc_cfg_t *cfg) { tusb_desc_configuration_t const initial_cfg = { @@ -327,7 +331,7 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { return desc_str; } -void usbd_descriptor_reset(void) { +void usbd_reset_descriptor(void) { usbd_desc_device = usbd_desc_device_default; desc_cfg_init(&usbd_desc_cfg); } diff --git a/shared/tinyusb/usbd_hid.c b/shared/tinyusb/usbd_hid.c new file mode 100644 index 0000000000000..22f8e672a43df --- /dev/null +++ b/shared/tinyusb/usbd_hid.c @@ -0,0 +1,180 @@ + +#include "py/runtime.h" +#include "usbd.h" + +// tusb.h is not available when running the string preprocessor +#ifndef NO_QSTR +#include "tusb.h" +#endif + +#if MICROPY_HW_USB_HID + +typedef struct { + uint8_t descriptors[MICROPY_HW_USB_MAX_HID][255]; + int len; +} usbd_desc_hid_t; +usbd_desc_hid_t usbd_desc_hid; + +void usbd_reset_hid(void) { + usbd_desc_hid.len = 0; +} + +static int usbd_desc_hid_add(usbd_desc_hid_t *hid, char *name, uint8_t protocol, uint8_t ep_bufsize, uint8_t interval, uint8_t *desc, uint8_t desc_len) { + uint8_t *spot; + + // trim the endpoint buffer size if too big + if (ep_bufsize > CFG_TUD_HID_EP_BUFSIZE) { + ep_bufsize = CFG_TUD_HID_EP_BUFSIZE; + } + + uint8_t descriptor[] = { + TUD_HID_DESCRIPTOR(0, 0, protocol, desc_len, 0x80, ep_bufsize, interval), + }; + // check for hid slots + if (hid->len > MICROPY_HW_USB_MAX_HID) { + return -1; + } + // check for description too big + if (desc_len > 255) { + return -1; + } + + // try to save the usb descriptor + if (usbd_desc_add_descriptor(descriptor, sizeof(descriptor), name)) { + return -1; + } + + // save the hid descriptor + spot = hid->descriptors[hid->len]; + memcpy(spot, desc, desc_len); + hid->len++; + return 0; +} + +uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance) { + if (instance >= usbd_desc_hid.len) { + return NULL; + } + return usbd_desc_hid.descriptors[instance]; +} + +void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) { + (void) instance; + (void) protocol; +} + +void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) { + (void) instance; + (void) report; + (void) len; +} + +uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { + (void) instance; + (void) report_id; + (void) report_type; + (void) buffer; + (void) reqlen; + + return 0; +} + +void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { + (void) instance; + (void) report_id; + (void) report_type; + (void) buffer; + (void) bufsize; +} + +typedef struct _usb_device_hid_obj_t { + mp_obj_base_t base; +} usb_device_hid_obj_t; + +// singleton +STATIC const usb_device_hid_obj_t usb_device_hid_obj = {{&usbd_hid_type}}; + +STATIC mp_obj_t usb_device_hid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + return (mp_obj_t)&usb_device_hid_obj; +} + +// HID.add_descriptor(name, protocol, ep_bufsize, interval, descriptor) +STATIC mp_obj_t usbd_hid_add_descriptor(size_t n_args, const mp_obj_t *args) { + (void) n_args; + mp_buffer_info_t bufinfo = {0}; + char *name; + uint8_t protocol; + uint8_t ep_bufsize; + uint8_t interval; + int err; + + mp_check_self(mp_obj_is_str_or_bytes(args[1])); + name = (char*) mp_obj_str_get_str(args[1]); + protocol = mp_obj_get_int(args[2]); + ep_bufsize = mp_obj_get_int(args[3]); + interval = mp_obj_get_int(args[4]); + mp_get_buffer_raise(args[5], &bufinfo, MP_BUFFER_READ); + err = usbd_desc_hid_add(&usbd_desc_hid, name, protocol, ep_bufsize, interval, bufinfo.buf, bufinfo.len); + if (err) { + mp_raise_ValueError(MP_ERROR_TEXT("could not add descriptor")); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(usbd_hid_add_descriptor_obj, 6, 6, usbd_hid_add_descriptor); + +// HID.report(instance, report_id, buffer) +STATIC mp_obj_t usbd_hid_report(size_t n_args, const mp_obj_t *args) { + (void) n_args; + mp_buffer_info_t bufinfo = {0}; + uint8_t report_id; + uint8_t instance; + + instance = mp_obj_get_int(args[1]); + report_id = mp_obj_get_int(args[2]); + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + + // run the task once if not ready, then just exit + if (!tud_hid_n_ready(instance)) { + tud_task(); + if (!tud_hid_n_ready(instance)) { + return mp_obj_new_bool(false); + } + } + + return mp_obj_new_bool(tud_hid_n_report(instance, report_id, bufinfo.buf, bufinfo.len)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(usbd_hid_report_obj, 4, 4, usbd_hid_report); + +// HID.ready(instance) +STATIC mp_obj_t usbd_hid_ready(mp_obj_t obj0, mp_obj_t obj1) { + (void) obj0; + int instance; + + instance = mp_obj_get_int(obj1); + return mp_obj_new_bool(tud_hid_n_ready(instance)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(usbd_hid_ready_obj, usbd_hid_ready); + +STATIC const mp_rom_map_elem_t usb_device_hid_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_add_descriptor), (mp_obj_t)&usbd_hid_add_descriptor_obj}, + { MP_ROM_QSTR(MP_QSTR_report), (mp_obj_t)&usbd_hid_report_obj}, + { MP_ROM_QSTR(MP_QSTR_ready), (mp_obj_t)&usbd_hid_ready_obj}, +}; +STATIC MP_DEFINE_CONST_DICT(usb_device_hid_locals_dict, usb_device_hid_locals_dict_table); + +const mp_obj_type_t usbd_hid_type = { + { &mp_type_type }, + .name = MP_QSTR_HID, + .make_new = usb_device_hid_make_new, + .locals_dict = (mp_obj_t)&usb_device_hid_locals_dict, +}; + +#else // #if MICROPY_HW_USB_HID + +void usbd_reset_hid(void) { + +} + +#endif \ No newline at end of file From 9d7800db1da6b3c7efefcd46d7bd7a208277d510 Mon Sep 17 00:00:00 2001 From: Blake Felt Date: Sun, 18 Sep 2022 15:07:16 -0600 Subject: [PATCH 4/8] shared/tinyusb: Add a few USB device functions. --- shared/tinyusb/usbd.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/shared/tinyusb/usbd.c b/shared/tinyusb/usbd.c index b0d2fc96998d4..cd2324b32bb41 100644 --- a/shared/tinyusb/usbd.c +++ b/shared/tinyusb/usbd.c @@ -3,14 +3,38 @@ #include "usbd.h" #include "tusb_config.h" +// tusb.h is not available when running the string preprocessor +#ifndef NO_QSTR +#include "tusb.h" +#endif + void usbd_reset_all(void) { usbd_reset_descriptor(); usbd_reset_hid(); } +STATIC mp_obj_t usbd_ready(void) { + return mp_obj_new_bool(tud_ready()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(usbd_ready_obj, usbd_ready); + +STATIC mp_obj_t usbd_connected(void) { + return mp_obj_new_bool(tud_connected()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(usbd_connected_obj, usbd_connected); + +STATIC mp_obj_t usbd_remote_wakeup(void) { + return mp_obj_new_bool(tud_remote_wakeup()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(usbd_remote_wakeup_obj, usbd_remote_wakeup); + STATIC const mp_rom_map_elem_t usb_device_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usb_device) }, + { MP_ROM_QSTR(MP_QSTR_ready), (mp_obj_t)&usbd_ready_obj}, + { MP_ROM_QSTR(MP_QSTR_connected), (mp_obj_t)&usbd_connected_obj}, + { MP_ROM_QSTR(MP_QSTR_remote_wakeup), (mp_obj_t)&usbd_remote_wakeup_obj}, + { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&usbd_descriptor_type) }, #if MICROPY_HW_USB_HID { MP_ROM_QSTR(MP_QSTR_HID), MP_ROM_PTR(&usbd_hid_type) }, From 58d7819a5c5a08be9bbda7e0d1844dcb860c3f77 Mon Sep 17 00:00:00 2001 From: Blake Felt Date: Sun, 18 Sep 2022 20:33:41 -0600 Subject: [PATCH 5/8] shared/tinyusb: Remove the last pico dependency for USB devices. --- ports/rp2/CMakeLists.txt | 1 + ports/rp2/usbd.c | 14 ++++++++++++++ shared/tinyusb/usbd_descriptor.c | 19 +++++++++++-------- 3 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 ports/rp2/usbd.c diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 56d6de027da3b..021b830e0f899 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -126,6 +126,7 @@ set(MICROPY_SOURCE_PORT rp2_flash.c rp2_pio.c uart.c + usbd.c msc_disk.c mbedtls/mbedtls_port.c ${MICROPY_DIR}/shared/tinyusb/usbd_descriptor.c diff --git a/ports/rp2/usbd.c b/ports/rp2/usbd.c new file mode 100644 index 0000000000000..a36006b87b118 --- /dev/null +++ b/ports/rp2/usbd.c @@ -0,0 +1,14 @@ + +#include "usbd.h" +#include "string.h" +#include "pico/unique_id.h" + +int usbd_serialnumber(uint8_t *buf) { + pico_unique_board_id_t id; + const int len = 8; + + pico_get_unique_board_id(&id); + memcpy(buf, id.id, len); + + return len; +} diff --git a/shared/tinyusb/usbd_descriptor.c b/shared/tinyusb/usbd_descriptor.c index 5e9f7e5cb6c6d..13b4d4be325b2 100644 --- a/shared/tinyusb/usbd_descriptor.c +++ b/shared/tinyusb/usbd_descriptor.c @@ -31,8 +31,6 @@ #include "usbd.h" #include "mpconfigport.h" -#include "pico/unique_id.h" - #define DESC_STR_MAX (31) // tusb.h is not available when running the string preprocessor @@ -309,13 +307,18 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { } // check, if serial is requested if (index == USBD_STR_SERIAL) { - pico_unique_board_id_t id; - pico_get_unique_board_id(&id); + uint8_t buffer[32]; + int buflen; + const char *hexdig = "0123456789abcdef"; + + buflen = usbd_serialnumber(buffer); // byte by byte conversion - for (len = 0; len < 16; len += 2) { - const char *hexdig = "0123456789abcdef"; - desc_str[1 + len] = hexdig[id.id[len >> 1] >> 4]; - desc_str[1 + len + 1] = hexdig[id.id[len >> 1] & 0x0f]; + len = 0; + for (int i=0; i> 4]; + desc_str[2 + len] = hexdig[val & 0x0F]; + len += 2; } } else { const char *str = usbd_desc_cfg.names[index]; From ae28b98137d80ba286c4ac56e29526c01386395f Mon Sep 17 00:00:00 2001 From: Blake Felt Date: Sun, 18 Sep 2022 20:34:39 -0600 Subject: [PATCH 6/8] shared/tinyusb: Add header file from last commit. --- shared/tinyusb/usbd.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shared/tinyusb/usbd.h b/shared/tinyusb/usbd.h index 57d23b3502e7a..23bd65012338a 100644 --- a/shared/tinyusb/usbd.h +++ b/shared/tinyusb/usbd.h @@ -4,7 +4,11 @@ #include "py/obj.h" -// external +// defined externally (needed per port) + +int usbd_serialnumber(uint8_t *buf); + +// external use void usbd_reset_all(void); void usbd_reset_descriptor(void); From 6bc27181751c5d4f0128ecf335fed75d6f5c9a2c Mon Sep 17 00:00:00 2001 From: Blake Felt Date: Sun, 18 Sep 2022 20:40:29 -0600 Subject: [PATCH 7/8] shared/tinyusb: Change retry handling when sending usbd hid report. --- shared/tinyusb/usbd_hid.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/shared/tinyusb/usbd_hid.c b/shared/tinyusb/usbd_hid.c index 22f8e672a43df..747fff4a8a679 100644 --- a/shared/tinyusb/usbd_hid.c +++ b/shared/tinyusb/usbd_hid.c @@ -136,9 +136,13 @@ STATIC mp_obj_t usbd_hid_report(size_t n_args, const mp_obj_t *args) { mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); // run the task once if not ready, then just exit - if (!tud_hid_n_ready(instance)) { - tud_task(); - if (!tud_hid_n_ready(instance)) { + if (!tud_hid_n_ready(instance)) { // if the hid is not ready + if (tud_task_event_ready()) { // if there is an event ready, process it then try again + tud_task(); + if (!tud_hid_n_ready(instance)) { // processed but still not ready, return false + return mp_obj_new_bool(false); + } + } else { // no event and not ready, return false return mp_obj_new_bool(false); } } From 60c2792b2120bc6677fda1344473fcc9dab9ec61 Mon Sep 17 00:00:00 2001 From: Blake Felt Date: Sun, 18 Sep 2022 21:14:08 -0600 Subject: [PATCH 8/8] shared/tinyusb: Add function to change USB names and power settings. --- shared/tinyusb/usbd_descriptor.c | 77 ++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/shared/tinyusb/usbd_descriptor.c b/shared/tinyusb/usbd_descriptor.c index 13b4d4be325b2..b16ee4d16c565 100644 --- a/shared/tinyusb/usbd_descriptor.c +++ b/shared/tinyusb/usbd_descriptor.c @@ -102,12 +102,24 @@ const tusb_desc_device_t usbd_desc_device_default = { }; static tusb_desc_device_t usbd_desc_device; +typedef struct { + uint8_t cfg[512]; + int len; + int itf_count; + int in_count; + int out_count; + char names[MICROPY_HW_USB_MAX_DESCRIPTORS][DESC_STR_MAX]; + int names_len; +} desc_cfg_t; +static desc_cfg_t usbd_desc_cfg; + // device(bDeviceClass=None, bDeviceSubclass=None, bDeviceProtocol=None, -// idVendor=None, idProduct=None, bcdDevice=None) +// idVendor=None, idProduct=None, bcdDevice=None, bmAttributes=None, bMaxPower=None) STATIC mp_obj_t usb_device_descriptor_device(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bDeviceClass, ARG_bDeviceSubClass, ARG_bDeviceProtocol, - ARG_idVendor, ARG_idProduct, ARG_bcdDevice + ARG_idVendor, ARG_idProduct, ARG_bcdDevice, + ARG_bmAttributes, ARG_bMaxPower }; static const mp_arg_t allowed_args[] = { { MP_QSTR_bDeviceClass, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, @@ -115,9 +127,13 @@ STATIC mp_obj_t usb_device_descriptor_device(mp_uint_t n_args, const mp_obj_t *p { MP_QSTR_bDeviceProtocol, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, { MP_QSTR_idVendor, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, { MP_QSTR_idProduct, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, - { MP_QSTR_bcdDevice, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} } + { MP_QSTR_bcdDevice, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_bmAttributes, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} }, + { MP_QSTR_bMaxPower, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE} } }; + tusb_desc_configuration_t *desc_config; + desc_config = (tusb_desc_configuration_t*) usbd_desc_cfg.cfg; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -139,21 +155,55 @@ STATIC mp_obj_t usb_device_descriptor_device(mp_uint_t n_args, const mp_obj_t *p if (args[ARG_bDeviceClass].u_obj != mp_const_none) { usbd_desc_device.bDeviceClass = mp_obj_get_int(args[ARG_bDeviceClass].u_obj); } + if (args[ARG_bmAttributes].u_obj != mp_const_none) { + desc_config->bmAttributes = mp_obj_get_int(args[ARG_bmAttributes].u_obj); + } + if (args[ARG_bMaxPower].u_obj != mp_const_none) { + desc_config->bMaxPower = mp_obj_get_int(args[ARG_bMaxPower].u_obj); + } + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(usb_device_descriptor_device_obj, 1, usb_device_descriptor_device); -typedef struct { - uint8_t cfg[512]; - int len; - int itf_count; - int in_count; - int out_count; - char names[MICROPY_HW_USB_MAX_DESCRIPTORS][DESC_STR_MAX]; - int names_len; -} desc_cfg_t; -static desc_cfg_t usbd_desc_cfg; +STATIC mp_obj_t usb_device_descriptor_strings(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { + ARG_Manufacturer, ARG_Product, ARG_CDC, ARG_MSC + }; + char *name; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_Manufacturer, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE}}, + { MP_QSTR_Product, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE}}, + { MP_QSTR_CDC, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE}}, + { MP_QSTR_MSC, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE}} + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_Manufacturer].u_obj != mp_const_none) { + name = (char*) mp_obj_str_get_str(args[ARG_Manufacturer].u_obj); + strcpy(usbd_desc_cfg.names[1], name); + } + if (args[ARG_Product].u_obj != mp_const_none) { + name = (char*) mp_obj_str_get_str(args[ARG_Product].u_obj); + strcpy(usbd_desc_cfg.names[2], name); + } + if (args[ARG_CDC].u_obj != mp_const_none) { + name = (char*) mp_obj_str_get_str(args[ARG_CDC].u_obj); + strcpy(usbd_desc_cfg.names[4], name); + } + #if CFG_TUD_MSC + if (args[ARG_MSC].u_obj != mp_const_none) { + name = (char*) mp_obj_str_get_str(args[ARG_MSC].u_obj); + strcpy(usbd_desc_cfg.names[5], name); + } + #endif + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(usb_device_descriptor_strings_obj, 1, usb_device_descriptor_strings); uint8_t usbd_desc_cfg_cdc[] = {TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD, USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE)}; @@ -341,6 +391,7 @@ void usbd_reset_descriptor(void) { STATIC const mp_rom_map_elem_t usb_device_descriptors_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_device), (mp_obj_t)&usb_device_descriptor_device_obj}, + { MP_ROM_QSTR(MP_QSTR_strings), (mp_obj_t)&usb_device_descriptor_strings_obj}, { MP_ROM_QSTR(MP_QSTR_CLASS_UNSPECIFIED), MP_ROM_INT(TUSB_CLASS_UNSPECIFIED)}, { MP_ROM_QSTR(MP_QSTR_CLASS_AUDIO), MP_ROM_INT(TUSB_CLASS_AUDIO)}, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy