From 0c29502ad995cfacc3b11f26a135707a06b8c27d Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 18 May 2019 23:01:36 +1000 Subject: [PATCH] stm32/usb: Refactor CDC VCP code to enable N CDC interfaces. The board config option MICROPY_HW_USB_ENABLE_CDC2 is now changed to MICROPY_HW_USB_CDC_NUM, and the latter should be defined to the maximum number of CDC interfaces to support (defaults to 1). --- ports/stm32/main.c | 4 - ports/stm32/mpconfigboard_common.h | 4 + ports/stm32/usb.c | 79 +++--- ports/stm32/usb.h | 3 +- ports/stm32/usbd_cdc_interface.c | 17 +- ports/stm32/usbd_conf.c | 4 +- .../stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 14 +- .../usbdev/class/inc/usbd_cdc_msc_hid0.h | 28 +- .../stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 255 ++++++++---------- 9 files changed, 183 insertions(+), 225 deletions(-) diff --git a/ports/stm32/main.c b/ports/stm32/main.c index ff4589f9d4..02449a1b80 100644 --- a/ports/stm32/main.c +++ b/ports/stm32/main.c @@ -558,10 +558,6 @@ soft_reset: #if MICROPY_HW_ENABLE_USB pyb_usb_init0(); - - // Activate USB_VCP(0) on dupterm slot 1 for the REPL - MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj); - usb_vcp_attach_to_repl(&pyb_usb_vcp_obj, true); #endif // Initialise the local flash filesystem. diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index b9fa3833ec..036e1f6ccd 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -264,6 +264,10 @@ #define MICROPY_HW_MAX_CAN (1) #endif +// Configure maximum number of CDC VCP interfaces +#ifndef MICROPY_HW_USB_CDC_NUM +#define MICROPY_HW_USB_CDC_NUM (1) +#endif // Pin definition header file #define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h" diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 8b7608a150..c9c22d5d2b 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -55,6 +55,8 @@ #endif #endif +STATIC void pyb_usb_vcp_init0(void); + // this will be persistent across a soft-reset mp_uint_t pyb_usb_flags = 0; @@ -62,10 +64,7 @@ typedef struct _usb_device_t { uint32_t enabled; USBD_HandleTypeDef hUSBDDevice; usbd_cdc_msc_hid_state_t usbd_cdc_msc_hid_state; - usbd_cdc_itf_t usbd_cdc_itf; - #if MICROPY_HW_USB_ENABLE_CDC2 - usbd_cdc_itf_t usbd_cdc2_itf; - #endif + usbd_cdc_itf_t usbd_cdc_itf[MICROPY_HW_USB_CDC_NUM]; usbd_hid_itf_t usbd_hid_itf; } usb_device_t; @@ -111,16 +110,15 @@ const mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj = { }; void pyb_usb_init0(void) { - usb_device.usbd_cdc_itf.attached_to_repl = false; - #if MICROPY_HW_USB_ENABLE_CDC2 - usb_device.usbd_cdc2_itf.attached_to_repl = false; - #endif + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + usb_device.usbd_cdc_itf[i].attached_to_repl = false; + } MP_STATE_PORT(pyb_hid_report_desc) = MP_OBJ_NULL; + + pyb_usb_vcp_init0(); } -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info) { - bool high_speed = (mode & USBD_MODE_HIGH_SPEED) != 0; - mode &= 0x7f; +bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info) { usb_device_t *usb_dev = &usb_device; if (!usb_dev->enabled) { // only init USB once in the device's power-lifetime @@ -132,15 +130,15 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors; usbd->pClass = &USBD_CDC_MSC_HID; usb_dev->usbd_cdc_msc_hid_state.pdev = usbd; - usb_dev->usbd_cdc_msc_hid_state.cdc = &usb_dev->usbd_cdc_itf.base; - #if MICROPY_HW_USB_ENABLE_CDC2 - usb_dev->usbd_cdc_msc_hid_state.cdc2 = &usb_dev->usbd_cdc2_itf.base; - #endif + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + usb_dev->usbd_cdc_msc_hid_state.cdc[i] = &usb_dev->usbd_cdc_itf[i].base; + } usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf.base; usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state; // configure the VID, PID and the USBD mode (interfaces it will expose) - USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, mode == USBD_MODE_CDC); + int cdc_only = (mode & USBD_MODE_IFACE_MASK) == USBD_MODE_CDC; + USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, cdc_only); if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info) != 0) { return false; } @@ -157,7 +155,7 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H } // start the USB device - USBD_LL_Init(usbd, high_speed); + USBD_LL_Init(usbd, (mode & USBD_MODE_HIGH_SPEED) != 0); USBD_LL_Start(usbd); usb_dev->enabled = true; } @@ -179,22 +177,17 @@ bool usb_vcp_is_enabled(void) { } int usb_vcp_recv_byte(uint8_t *c) { - return usbd_cdc_rx(&usb_device.usbd_cdc_itf, c, 1, 0); + return usbd_cdc_rx(&usb_device.usbd_cdc_itf[0], c, 1, 0); } void usb_vcp_send_strn(const char *str, int len) { if (usb_device.enabled) { - usbd_cdc_tx_always(&usb_device.usbd_cdc_itf, (const uint8_t*)str, len); + usbd_cdc_tx_always(&usb_device.usbd_cdc_itf[0], (const uint8_t*)str, len); } } usbd_cdc_itf_t *usb_vcp_get(int idx) { - #if MICROPY_HW_USB_ENABLE_CDC2 - if (idx == 1) { - return &usb_device.usbd_cdc2_itf; - } - #endif - return &usb_device.usbd_cdc_itf; + return &usb_device.usbd_cdc_itf[idx]; } /******************************************************************************/ @@ -243,7 +236,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * return MP_OBJ_NEW_QSTR(MP_QSTR_host); #else uint8_t mode = USBD_GetMode(&usb_device.usbd_cdc_msc_hid_state); - switch (mode) { + switch (mode & USBD_MODE_IFACE_MASK) { case USBD_MODE_CDC: return MP_OBJ_NEW_QSTR(MP_QSTR_VCP); case USBD_MODE_MSC: @@ -298,13 +291,13 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // note: we support CDC as a synonym for VCP for backward compatibility uint16_t vid = args[1].u_int; uint16_t pid = args[2].u_int; - usb_device_mode_t mode; + uint8_t mode; if (strcmp(mode_str, "CDC+MSC") == 0 || strcmp(mode_str, "VCP+MSC") == 0) { if (args[2].u_int == -1) { pid = USBD_PID_CDC_MSC; } mode = USBD_MODE_CDC_MSC; - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM >= 2 } else if (strcmp(mode_str, "VCP+VCP") == 0) { if (args[2].u_int == -1) { pid = USBD_PID_CDC2; @@ -337,7 +330,7 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * // get hid info if user selected such a mode USBD_HID_ModeInfoTypeDef hid_info; - if (mode & USBD_MODE_HID) { + if (mode & USBD_MODE_IFACE_HID) { mp_obj_t *items; mp_obj_get_array_fixed_n(args[3].u_obj, 5, &items); hid_info.subclass = mp_obj_get_int(items[0]); @@ -388,13 +381,21 @@ typedef struct _pyb_usb_vcp_obj_t { usbd_cdc_itf_t *cdc_itf; } pyb_usb_vcp_obj_t; -const pyb_usb_vcp_obj_t pyb_usb_vcp_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf}; -#if MICROPY_HW_USB_ENABLE_CDC2 -STATIC const pyb_usb_vcp_obj_t pyb_usb_vcp2_obj = {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc2_itf}; -#endif +const pyb_usb_vcp_obj_t pyb_usb_vcp_obj[MICROPY_HW_USB_CDC_NUM] = { + {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[0]}, + #if MICROPY_HW_USB_CDC_NUM >= 2 + {{&pyb_usb_vcp_type}, &usb_device.usbd_cdc_itf[1]}, + #endif +}; + +STATIC void pyb_usb_vcp_init0(void) { + // Activate USB_VCP(0) on dupterm slot 1 for the REPL + MP_STATE_VM(dupterm_objs[1]) = MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0]); + usb_vcp_attach_to_repl(&pyb_usb_vcp_obj[0], true); +} STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf; + int id = ((pyb_usb_vcp_obj_t*)MP_OBJ_TO_PTR(self_in))->cdc_itf - &usb_device.usbd_cdc_itf[0]; mp_printf(print, "USB_VCP(%u)", id); } @@ -411,12 +412,8 @@ STATIC mp_obj_t pyb_usb_vcp_make_new(const mp_obj_type_t *type, size_t n_args, s // TODO raise exception if USB is not configured for VCP int id = (n_args == 0) ? 0 : mp_obj_get_int(args[0]); - if (id == 0) { - return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj); - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if (id == 1) { - return MP_OBJ_FROM_PTR(&pyb_usb_vcp2_obj); - #endif + if (0 <= id && id < MICROPY_HW_USB_CDC_NUM) { + return MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[id]); } else { mp_raise_ValueError(NULL); } @@ -457,7 +454,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_vcp_isconnected_obj, pyb_usb_vcp_isconn // deprecated in favour of USB_VCP.isconnected STATIC mp_obj_t pyb_have_cdc(void) { - return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj)); + return pyb_usb_vcp_isconnected(MP_OBJ_FROM_PTR(&pyb_usb_vcp_obj[0])); } MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc); diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index 3d57bf9129..6678e1e173 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -58,14 +58,13 @@ extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_mouse_obj; extern const struct _mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj; extern const mp_obj_type_t pyb_usb_vcp_type; extern const mp_obj_type_t pyb_usb_hid_type; -extern const pyb_usb_vcp_obj_t pyb_usb_vcp_obj; MP_DECLARE_CONST_FUN_OBJ_KW(pyb_usb_mode_obj); MP_DECLARE_CONST_FUN_OBJ_0(pyb_have_cdc_obj); // deprecated MP_DECLARE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj); // deprecated void pyb_usb_init0(void); -bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info); +bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, uint8_t mode, USBD_HID_ModeInfoTypeDef *hid_info); void pyb_usb_dev_deinit(void); bool usb_vcp_is_enabled(void); int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0 diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index 4a4a8beb85..49f0deec71 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -217,18 +217,13 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { } else { usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData; hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; - usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc; - if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) { - cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED; - usbd_cdc_try_tx(cdc); + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc[i]; + if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) { + cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED; + usbd_cdc_try_tx(cdc); + } } - #if MICROPY_HW_USB_ENABLE_CDC2 - cdc = (usbd_cdc_itf_t*)usbd->cdc2; - if (cdc->connect_state == USBD_CDC_CONNECT_STATE_CONNECTING) { - cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTED; - usbd_cdc_try_tx(cdc); - } - #endif } } diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index b7c1665f0a..c2e86ccb5b 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -334,7 +334,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { if (pdev->id == USB_PHY_FS_ID) { // Set LL Driver parameters pcd_fs_handle.Instance = USB_OTG_FS; - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM == 2 pcd_fs_handle.Init.dev_endpoints = 6; #else pcd_fs_handle.Init.dev_endpoints = 4; @@ -364,7 +364,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { HAL_PCD_Init(&pcd_fs_handle); // We have 320 32-bit words in total to use here - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM == 2 HAL_PCD_SetRxFiFo(&pcd_fs_handle, 128); HAL_PCD_SetTxFiFo(&pcd_fs_handle, 0, 32); // EP0 HAL_PCD_SetTxFiFo(&pcd_fs_handle, 1, 64); // MSC / HID diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h index 1857273e07..f20485a7c0 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -18,12 +18,13 @@ #define USBD_SUPPORT_HS_MODE (0) #endif -// Needed for the CDC+MSC+HID state and should be maximum of all template -// config descriptors defined in usbd_cdc_msc_hid.c -#if MICROPY_HW_USB_ENABLE_CDC2 +// Should be maximum of possible config descriptors that might be configured +#if MICROPY_HW_USB_CDC_NUM == 2 +// Maximum is MSC+CDC+CDC #define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58)) #else -#define MAX_TEMPLATE_CONFIG_DESC_SIZE (107) +// Maximum is HID+CDC +#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 32 + (8 + 58)) #endif // CDC, MSC and HID packet sizes @@ -124,10 +125,7 @@ typedef struct _usbd_cdc_msc_hid_state_t { __ALIGN_BEGIN uint8_t usbd_str_desc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; __ALIGN_BEGIN uint8_t usbd_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END; - usbd_cdc_state_t *cdc; - #if MICROPY_HW_USB_ENABLE_CDC2 - usbd_cdc_state_t *cdc2; - #endif + usbd_cdc_state_t *cdc[MICROPY_HW_USB_CDC_NUM]; usbd_hid_state_t *hid; } usbd_cdc_msc_hid_state_t; diff --git a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h index c876dcf298..1cb879180d 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h @@ -29,18 +29,22 @@ // these are exports for the CDC/MSC/HID interface that are independent // from any other definitions/declarations -// only CDC_MSC and CDC_HID are available -typedef enum { - USBD_MODE_CDC = 0x01, - USBD_MODE_MSC = 0x02, - USBD_MODE_HID = 0x04, - USBD_MODE_CDC2 = 0x08, - USBD_MODE_CDC_MSC = USBD_MODE_CDC | USBD_MODE_MSC, - USBD_MODE_CDC_HID = USBD_MODE_CDC | USBD_MODE_HID, - USBD_MODE_MSC_HID = USBD_MODE_MSC | USBD_MODE_HID, - USBD_MODE_CDC2_MSC = USBD_MODE_CDC | USBD_MODE_MSC | USBD_MODE_CDC2, - USBD_MODE_HIGH_SPEED = 0x80, // or with one of the above -} usb_device_mode_t; +// These can be or'd together (but not all combinations may be available) +#define USBD_MODE_IFACE_MASK (0x7f) +#define USBD_MODE_IFACE_CDC(i) (0x01 << (i)) +#define USBD_MODE_IFACE_HID (0x10) +#define USBD_MODE_IFACE_MSC (0x20) +#define USBD_MODE_HIGH_SPEED (0x80) + +// Convenience macros for supported mode combinations +#define USBD_MODE_CDC (USBD_MODE_IFACE_CDC(0)) +#define USBD_MODE_CDC2 (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1)) +#define USBD_MODE_CDC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_HID) +#define USBD_MODE_CDC_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC) +#define USBD_MODE_CDC2_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC) +#define USBD_MODE_HID (USBD_MODE_IFACE_HID) +#define USBD_MODE_MSC (USBD_MODE_IFACE_MSC) +#define USBD_MODE_MSC_HID (USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) typedef struct _USBD_HID_ModeInfoTypeDef { uint8_t subclass; // 0=no sub class, 1=boot diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c index 47436a4b63..bfb5d3058a 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -38,6 +38,8 @@ #define MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC_MSC_TEMPLATE_CDC_DESC_OFFSET (40) +#define CDC2_TEMPLATE_CDC_DESC_OFFSET (9 + 8) +#define CDC2_TEMPLATE_CDC2_DESC_OFFSET (9 + (8 + 58) + 8) #define CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET (9) #define CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET (9 + 23 + 8) #define CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET (9 + 23 + (8 + 58) + 8) @@ -69,13 +71,9 @@ #define HID_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_MSC (1) -#define CDC_IN_EP (0x83) -#define CDC_OUT_EP (0x03) -#define CDC_CMD_EP (0x82) - -#define CDC2_IN_EP (0x85) -#define CDC2_OUT_EP (0x05) -#define CDC2_CMD_EP (0x84) +#define CDC_IN_EP(i) (0x83 + 2 * (i)) +#define CDC_OUT_EP(i) (0x03 + 2 * (i)) +#define CDC_CMD_EP(i) (0x82 + 2 * (i)) #define HID_IN_EP_WITH_CDC (0x81) #define HID_OUT_EP_WITH_CDC (0x01) @@ -232,7 +230,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { // Endpoint CMD Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_CMD_EP, // bEndpointAddress + CDC_CMD_EP(0), // bEndpointAddress 0x03, // bmAttributes: Interrupt LOBYTE(CDC_CMD_PACKET_SIZE), // wMaxPacketSize: HIBYTE(CDC_CMD_PACKET_SIZE), @@ -253,7 +251,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { // Endpoint OUT Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_OUT_EP, // bEndpointAddress + CDC_OUT_EP(0), // bEndpointAddress 0x02, // bmAttributes: Bulk LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), @@ -262,7 +260,7 @@ static const uint8_t cdc_class_desc_data[CDC_CLASS_DESC_SIZE] = { // Endpoint IN Descriptor 0x07, // bLength: Endpoint Descriptor size USB_DESC_TYPE_ENDPOINT, // bDescriptorType: Endpoint - CDC_IN_EP, // bEndpointAddress + CDC_IN_EP(0), // bEndpointAddress 0x02, // bmAttributes: Bulk LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),// wMaxPacketSize: HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), @@ -421,7 +419,7 @@ static size_t make_cdc_desc(uint8_t *dest, int need_iad, uint8_t iface_num) { return need_iad ? 8 + 58 : 58; } -#if MICROPY_HW_USB_ENABLE_CDC2 +#if MICROPY_HW_USB_CDC_NUM >= 2 static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, uint8_t cmd_ep, uint8_t out_ep, uint8_t in_ep) { size_t n = make_cdc_desc(dest, need_iad, iface_num); if (need_iad) { @@ -461,7 +459,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode size_t n = HEAD_DESC_SIZE; uint8_t *d = usbd->usbd_config_desc; uint8_t num_itf = 0; - switch (usbd->usbd_mode) { + switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) { case USBD_MODE_MSC: n += make_msc_desc(d + n); num_itf = 1; @@ -470,19 +468,16 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode case USBD_MODE_CDC_MSC: n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); - usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; num_itf = 3; break; - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM >= 2 case USBD_MODE_CDC2: { - // Ensure the first interface is also enabled - usbd->usbd_mode |= USBD_MODE_CDC; - n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_ALONE); - n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP); - usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE; - usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_CDC; + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_CDC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_CDC; num_itf = 4; break; } @@ -490,9 +485,9 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode case USBD_MODE_CDC2_MSC: { n += make_msc_desc(d + n); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); - n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC2_CMD_EP, CDC2_OUT_EP, CDC2_IN_EP); - usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC; - usbd->cdc2->iface_num = CDC2_IFACE_NUM_WITH_MSC; + n += make_cdc_desc_ep(d + n, 1, CDC2_IFACE_NUM_WITH_MSC, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; num_itf = 5; break; } @@ -502,7 +497,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode usbd->hid->desc = d + n; n += make_hid_desc(d + n, hid_info); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_HID); - usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_HID; + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_HID; usbd->hid->in_ep = HID_IN_EP_WITH_CDC; usbd->hid->out_ep = HID_OUT_EP_WITH_CDC; usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC; @@ -512,7 +507,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode case USBD_MODE_CDC: n += make_cdc_desc(d + n, 0, CDC_IFACE_NUM_ALONE); - usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE; + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_ALONE; num_itf = 2; break; @@ -533,18 +528,13 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode make_head_desc(d, n, num_itf); usbd->usbd_config_desc_size = n; - if (usbd->usbd_mode & USBD_MODE_CDC) { - usbd->cdc->in_ep = CDC_IN_EP; - usbd->cdc->out_ep = CDC_OUT_EP; + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) { + usbd->cdc[i]->in_ep = CDC_IN_EP(i); + usbd->cdc[i]->out_ep = CDC_OUT_EP(i); + } } - #if MICROPY_HW_USB_ENABLE_CDC2 - if (usbd->usbd_mode & USBD_MODE_CDC2) { - usbd->cdc2->in_ep = CDC2_IN_EP; - usbd->cdc2->out_ep = CDC2_OUT_EP; - } - #endif - return 0; } @@ -578,19 +568,14 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if (usbd->usbd_mode & USBD_MODE_CDC) { - // CDC VCP component - usbd_cdc_state_init(pdev, usbd, usbd->cdc, CDC_CMD_EP); + // CDC VCP component(s) + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if (usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) { + usbd_cdc_state_init(pdev, usbd, usbd->cdc[i], CDC_CMD_EP(i)); + } } - #if MICROPY_HW_USB_ENABLE_CDC2 - if (usbd->usbd_mode & USBD_MODE_CDC2) { - // CDC VCP #2 component - usbd_cdc_state_init(pdev, usbd, usbd->cdc2, CDC2_CMD_EP); - } - #endif - - if (usbd->usbd_mode & USBD_MODE_MSC) { + if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) { // MSC component int mp = usbd_msc_max_packet(pdev); @@ -611,7 +596,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { MSC_BOT_Init(pdev); } - if (usbd->usbd_mode & USBD_MODE_HID) { + if (usbd->usbd_mode & USBD_MODE_IFACE_HID) { // HID component // get max packet lengths from descriptor @@ -644,31 +629,20 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if ((usbd->usbd_mode & USBD_MODE_CDC) && usbd->cdc) { - // CDC VCP component + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && usbd->cdc[i]) { + // CDC VCP component - usbd_cdc_deinit(usbd->cdc); + usbd_cdc_deinit(usbd->cdc[i]); - // close endpoints - USBD_LL_CloseEP(pdev, CDC_IN_EP); - USBD_LL_CloseEP(pdev, CDC_OUT_EP); - USBD_LL_CloseEP(pdev, CDC_CMD_EP); + // close endpoints + USBD_LL_CloseEP(pdev, CDC_IN_EP(i)); + USBD_LL_CloseEP(pdev, CDC_OUT_EP(i)); + USBD_LL_CloseEP(pdev, CDC_CMD_EP(i)); + } } - #if MICROPY_HW_USB_ENABLE_CDC2 - if ((usbd->usbd_mode & USBD_MODE_CDC2) && usbd->cdc2) { - // CDC VCP #2 component - - usbd_cdc_deinit(usbd->cdc2); - - // close endpoints - USBD_LL_CloseEP(pdev, CDC2_IN_EP); - USBD_LL_CloseEP(pdev, CDC2_OUT_EP); - USBD_LL_CloseEP(pdev, CDC2_CMD_EP); - } - #endif - - if (usbd->usbd_mode & USBD_MODE_MSC) { + if (usbd->usbd_mode & USBD_MODE_IFACE_MSC) { // MSC component // close endpoints @@ -679,7 +653,7 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) MSC_BOT_DeInit(pdev); } - if (usbd->usbd_mode & USBD_MODE_HID) { + if (usbd->usbd_mode & USBD_MODE_IFACE_HID) { // HID component // close endpoints @@ -717,35 +691,35 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) { case USB_REQ_RECIPIENT_INTERFACE: { uint16_t iface = req->wIndex; - if ((mode & USBD_MODE_CDC) && iface == usbd->cdc->iface_num) { - recipient = USBD_MODE_CDC; - cdc = usbd->cdc; - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if ((mode & USBD_MODE_CDC2) && iface == usbd->cdc2->iface_num) { - recipient = USBD_MODE_CDC; - cdc = usbd->cdc2; - #endif - } else if ((mode & USBD_MODE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) { + if ((mode & USBD_MODE_IFACE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) { recipient = USBD_MODE_MSC; - } else if ((mode & USBD_MODE_HID) && iface == usbd->hid->iface_num) { + } else if ((mode & USBD_MODE_IFACE_HID) && iface == usbd->hid->iface_num) { recipient = USBD_MODE_HID; + } else { + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((mode & USBD_MODE_IFACE_CDC(i)) && iface == usbd->cdc[i]->iface_num) { + recipient = USBD_MODE_CDC; + cdc = usbd->cdc[i]; + break; + } + } } break; } case USB_REQ_RECIPIENT_ENDPOINT: { uint8_t ep = req->wIndex & 0x7f; - if ((mode & USBD_MODE_CDC) && (ep == CDC_OUT_EP || ep == (CDC_CMD_EP & 0x7f))) { - recipient = USBD_MODE_CDC; - cdc = usbd->cdc; - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if ((mode & USBD_MODE_CDC2) && (ep == CDC2_OUT_EP || ep == (CDC2_CMD_EP & 0x7f))) { - recipient = USBD_MODE_CDC; - cdc = usbd->cdc2; - #endif - } else if ((mode & USBD_MODE_MSC) && ep == MSC_OUT_EP) { + if ((mode & USBD_MODE_IFACE_MSC) && ep == MSC_OUT_EP) { recipient = USBD_MODE_MSC; - } else if ((mode & USBD_MODE_HID) && ep == usbd->hid->out_ep) { + } else if ((mode & USBD_MODE_IFACE_HID) && ep == usbd->hid->out_ep) { recipient = USBD_MODE_HID; + } else { + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((mode & USBD_MODE_IFACE_CDC(i)) && (ep == CDC_OUT_EP(i) || ep == (CDC_CMD_EP(i) & 0x7f))) { + recipient = USBD_MODE_CDC; + cdc = usbd->cdc[i]; + break; + } + } } break; } @@ -894,36 +868,32 @@ static uint8_t EP0_TxSent(USBD_HandleTypeDef *pdev) { static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if (usbd->cdc != NULL && usbd->cdc->cur_request != 0xff) { - usbd_cdc_control(usbd->cdc, usbd->cdc->cur_request, (uint8_t*)usbd->cdc->ctl_packet_buf, usbd->cdc->cur_length); - usbd->cdc->cur_request = 0xff; + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if (usbd->cdc[i] != NULL && usbd->cdc[i]->cur_request != 0xff) { + usbd_cdc_control(usbd->cdc[i], usbd->cdc[i]->cur_request, (uint8_t*)usbd->cdc[i]->ctl_packet_buf, usbd->cdc[i]->cur_length); + usbd->cdc[i]->cur_request = 0xff; + } } - #if MICROPY_HW_USB_ENABLE_CDC2 - if (usbd->cdc2 != NULL && usbd->cdc2->cur_request != 0xff) { - usbd_cdc_control(usbd->cdc2, usbd->cdc2->cur_request, (uint8_t*)usbd->cdc2->ctl_packet_buf, usbd->cdc2->cur_length); - usbd->cdc2->cur_request = 0xff; - } - #endif - return USBD_OK; } static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if ((usbd->usbd_mode & USBD_MODE_CDC) && (epnum == (CDC_IN_EP & 0x7f) || epnum == (CDC_CMD_EP & 0x7f))) { - usbd->cdc->tx_in_progress = 0; - usbd_cdc_tx_ready(usbd->cdc); - return USBD_OK; - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if ((usbd->usbd_mode & USBD_MODE_CDC2) && (epnum == (CDC2_IN_EP & 0x7f) || epnum == (CDC2_CMD_EP & 0x7f))) { - usbd->cdc2->tx_in_progress = 0; - usbd_cdc_tx_ready(usbd->cdc2); - return USBD_OK; - #endif - } else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { + + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && (epnum == (CDC_IN_EP(i) & 0x7f) || epnum == (CDC_CMD_EP(i) & 0x7f))) { + usbd->cdc[i]->tx_in_progress = 0; + usbd_cdc_tx_ready(usbd->cdc[i]); + return USBD_OK; + } + } + + if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { MSC_BOT_DataIn(pdev, epnum); return USBD_OK; - } else if ((usbd->usbd_mode & USBD_MODE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) { + } + + if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->in_ep & 0x7f)) { /* Ensure that the FIFO is empty before a new transfer, this condition could be caused by a new transfer before the end of the previous transfer */ usbd->hid->state = HID_IDLE; @@ -935,26 +905,23 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if ((usbd->usbd_mode & USBD_MODE_CDC) && epnum == (CDC_OUT_EP & 0x7f)) { - /* Get the received data length */ - size_t len = USBD_LL_GetRxDataSize (pdev, epnum); - /* USB data will be immediately processed, this allow next USB traffic being - NAKed till the end of the application Xfer */ - return usbd_cdc_receive(usbd->cdc, len); + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if ((usbd->usbd_mode & USBD_MODE_IFACE_CDC(i)) && epnum == (CDC_OUT_EP(i) & 0x7f)) { + size_t len = USBD_LL_GetRxDataSize(pdev, epnum); + // USB data will be immediately processed, and next USB traffic is NAKed until it's done + return usbd_cdc_receive(usbd->cdc[i], len); + } + } - #if MICROPY_HW_USB_ENABLE_CDC2 - } else if ((usbd->usbd_mode & USBD_MODE_CDC2) && epnum == (CDC2_OUT_EP & 0x7f)) { - size_t len = USBD_LL_GetRxDataSize(pdev, epnum); - return usbd_cdc_receive(usbd->cdc2, len); - - #endif - } else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) { + if ((usbd->usbd_mode & USBD_MODE_IFACE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) { MSC_BOT_DataOut(pdev, epnum); return USBD_OK; - } else if ((usbd->usbd_mode & USBD_MODE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) { + } + + if ((usbd->usbd_mode & USBD_MODE_IFACE_HID) && epnum == (usbd->hid->out_ep & 0x7f)) { size_t len = USBD_LL_GetRxDataSize(pdev, epnum); - usbd_hid_receive(usbd->hid, len); + return usbd_hid_receive(usbd->hid, len); } return USBD_OK; @@ -981,49 +948,47 @@ static uint8_t *USBD_CDC_MSC_HID_GetCfgDesc(USBD_HandleTypeDef *pdev, uint16_t * usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; #if USBD_SUPPORT_HS_MODE - uint8_t *cdc_desc = NULL; - #if MICROPY_HW_USB_ENABLE_CDC2 - uint8_t *cdc2_desc = NULL; - #endif + uint8_t *cdc_desc[MICROPY_HW_USB_CDC_NUM] = {0}; uint8_t *msc_desc = NULL; - switch (usbd->usbd_mode) { + switch (usbd->usbd_mode & USBD_MODE_IFACE_MASK) { case USBD_MODE_MSC: msc_desc = usbd->usbd_config_desc + MSC_TEMPLATE_MSC_DESC_OFFSET; break; case USBD_MODE_CDC_MSC: - cdc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[0] = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_CDC_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC_MSC_TEMPLATE_MSC_DESC_OFFSET; break; - #if MICROPY_HW_USB_ENABLE_CDC2 + #if MICROPY_HW_USB_CDC_NUM >= 2 + case USBD_MODE_CDC2: + cdc_desc[0] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[1] = usbd->usbd_config_desc + CDC2_TEMPLATE_CDC2_DESC_OFFSET; + break; + case USBD_MODE_CDC2_MSC: - cdc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET; - cdc2_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET; + cdc_desc[0] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[1] = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_CDC2_DESC_OFFSET; msc_desc = usbd->usbd_config_desc + CDC2_MSC_TEMPLATE_MSC_DESC_OFFSET; break; #endif case USBD_MODE_CDC_HID: - cdc_desc = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[0] = usbd->usbd_config_desc + CDC_HID_TEMPLATE_CDC_DESC_OFFSET; break; case USBD_MODE_CDC: - cdc_desc = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET; + cdc_desc[0] = usbd->usbd_config_desc + CDC_TEMPLATE_CDC_DESC_OFFSET; break; } // configure CDC descriptors, if needed - if (cdc_desc != NULL) { - usbd_cdc_desc_config_max_packet(pdev, cdc_desc); + for (int i = 0; i < MICROPY_HW_USB_CDC_NUM; ++i) { + if (cdc_desc[i] != NULL) { + usbd_cdc_desc_config_max_packet(pdev, cdc_desc[i]); + } } - #if MICROPY_HW_USB_ENABLE_CDC2 - if (cdc2_desc != NULL) { - usbd_cdc_desc_config_max_packet(pdev, cdc2_desc); - } - #endif - if (msc_desc != NULL) { uint32_t mp = usbd_msc_max_packet(pdev); msc_desc[13] = LOBYTE(mp);