diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 791a6472a..8b8062981 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -97,6 +97,14 @@ STATIC const uint8_t usbd_fifo_size_cdc1[] = { #endif }; +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, HID +STATIC const uint8_t usbd_fifo_size_cdc1_msc_hid[] = { + 32, 8, 16, 4, 12, 8, 0, + #if MICROPY_HW_USB_HS + 116, 8, 64, 4, 56, 8, 0, 0, 0, 0, + #endif +}; + #if MICROPY_HW_USB_CDC_NUM >= 2 // RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD, CDC2_DATA STATIC const uint8_t usbd_fifo_size_cdc2[] = { @@ -105,6 +113,14 @@ STATIC const uint8_t usbd_fifo_size_cdc2[] = { 116, 8, 64, 2, 32, 2, 32, 0, 0, 0, #endif }; + +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD/HID, CDC2_DATA, HID +STATIC const uint8_t usbd_fifo_size_cdc2_msc_hid[] = { + 0, 0, 0, 0, 0, 0, 0, // FS: can't support 2xVCP+MSC+HID + #if MICROPY_HW_USB_HS + 102, 8, 64, 2, 32, 8, 32, 8, 0, 0, + #endif +}; #endif #if MICROPY_HW_USB_CDC_NUM >= 3 @@ -115,6 +131,14 @@ STATIC const uint8_t usbd_fifo_size_cdc3[] = { 82, 8, 64, 2, 32, 2, 32, 2, 32, 0, #endif }; + +// RX; EP0(in), MSC/HID, CDC_CMD, CDC_DATA, CDC2_CMD/HID, CDC2_DATA, CDC3_CMD/HID, CDC3_DATA, HID +STATIC const uint8_t usbd_fifo_size_cdc3_msc_hid[] = { + 0, 0, 0, 0, 0, 0, 0, // FS: can't support 3x VCP mode + #if MICROPY_HW_USB_HS + 82, 8, 64, 2, 25, 8, 25, 8, 25, 8, + #endif +}; #endif #endif @@ -242,14 +266,27 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size #endif const uint8_t *fifo_size = usbd_fifo_size_cdc1; + #if MICROPY_HW_USB_IS_MULTI_OTG + if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { + fifo_size = usbd_fifo_size_cdc1_msc_hid; + } + #endif #if MICROPY_HW_USB_CDC_NUM >= 3 if (mode & USBD_MODE_IFACE_CDC(2)) { - fifo_size = usbd_fifo_size_cdc3; + if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { + fifo_size = usbd_fifo_size_cdc3_msc_hid; + } else { + fifo_size = usbd_fifo_size_cdc3; + } } else #endif #if MICROPY_HW_USB_CDC_NUM >= 2 if (mode & USBD_MODE_IFACE_CDC(1)) { - fifo_size = usbd_fifo_size_cdc2; + if ((mode & USBD_MODE_MSC_HID) == USBD_MODE_MSC_HID) { + fifo_size = usbd_fifo_size_cdc2_msc_hid; + } else { + fifo_size = usbd_fifo_size_cdc2; + } } #endif @@ -414,6 +451,11 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * pid = USBD_PID_CDC_MSC; } mode = USBD_MODE_CDC_MSC; + } else if (strcmp(mode_str, "VCP+MSC+HID") == 0) { + if (pid == -1) { + pid = USBD_PID_CDC_MSC_HID; + } + mode = USBD_MODE_CDC_MSC_HID; #if MICROPY_HW_USB_CDC_NUM >= 2 } else if (strcmp(mode_str, "VCP+VCP") == 0) { if (pid == -1) { @@ -425,6 +467,11 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * pid = USBD_PID_CDC2_MSC; } mode = USBD_MODE_CDC2_MSC; + } else if (strcmp(mode_str, "2xVCP+MSC+HID") == 0) { + if (pid == -1) { + pid = USBD_PID_CDC2_MSC_HID; + } + mode = USBD_MODE_CDC2_MSC_HID; #endif #if MICROPY_HW_USB_CDC_NUM >= 3 } else if (strcmp(mode_str, "3xVCP") == 0) { @@ -437,6 +484,11 @@ STATIC mp_obj_t pyb_usb_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t * pid = USBD_PID_CDC3_MSC; } mode = USBD_MODE_CDC3_MSC; + } else if (strcmp(mode_str, "3xVCP+MSC+HID") == 0) { + if (pid == -1) { + pid = USBD_PID_CDC3_MSC_HID; + } + mode = USBD_MODE_CDC3_MSC_HID; #endif } else if (strcmp(mode_str, "CDC+HID") == 0 || strcmp(mode_str, "VCP+HID") == 0) { if (pid == -1) { diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h index cb017902e..457c7313c 100644 --- a/ports/stm32/usb.h +++ b/ports/stm32/usb.h @@ -40,6 +40,9 @@ #define USBD_PID_CDC2 (0x9805) #define USBD_PID_CDC3 (0x9806) #define USBD_PID_CDC3_MSC (0x9807) +#define USBD_PID_CDC_MSC_HID (0x9808) +#define USBD_PID_CDC2_MSC_HID (0x9809) +#define USBD_PID_CDC3_MSC_HID (0x980a) typedef enum { PYB_USB_STORAGE_MEDIUM_NONE = 0, diff --git a/ports/stm32/usbd_conf.h b/ports/stm32/usbd_conf.h index 83629bfc4..5237ba3a9 100644 --- a/ports/stm32/usbd_conf.h +++ b/ports/stm32/usbd_conf.h @@ -39,7 +39,7 @@ #include "py/mpconfig.h" -#define USBD_MAX_NUM_INTERFACES 5 +#define USBD_MAX_NUM_INTERFACES 8 #define USBD_MAX_NUM_CONFIGURATION 1 #define USBD_MAX_STR_DESC_SIZ 0x100 #if MICROPY_HW_USB_SELF_POWERED 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 a01e75bed..f3edc4dcb 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -18,16 +18,8 @@ #endif // Should be maximum of possible config descriptors that might be configured -#if MICROPY_HW_USB_CDC_NUM == 3 -// Maximum is MSC+CDC+CDC+CDC -#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58) + (8 + 58)) -#elif MICROPY_HW_USB_CDC_NUM == 2 -// Maximum is MSC+CDC+CDC -#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 23 + (8 + 58) + (8 + 58)) -#else -// Maximum is HID+CDC -#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + 32 + (8 + 58)) -#endif +// Maximum is: 9 + MSC + NxCDC + HID +#define MAX_TEMPLATE_CONFIG_DESC_SIZE (9 + (23) + MICROPY_HW_USB_CDC_NUM * (8 + 58) + (9 + 9 + 7 + 7)) // CDC, MSC and HID packet sizes #define MSC_FS_MAX_PACKET (64) @@ -118,7 +110,7 @@ typedef struct _usbd_cdc_msc_hid_state_t { USBD_HandleTypeDef *pdev; uint8_t usbd_mode; - uint8_t usbd_config_desc_size; + uint16_t usbd_config_desc_size; #if MICROPY_HW_USB_MSC USBD_MSC_BOT_HandleTypeDef MSC_BOT_ClassData; 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 63fe8ecef..7614dde69 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid0.h @@ -44,6 +44,9 @@ #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_CDC3_MSC (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2) | USBD_MODE_IFACE_MSC) +#define USBD_MODE_CDC_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) +#define USBD_MODE_CDC2_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) +#define USBD_MODE_CDC3_MSC_HID (USBD_MODE_IFACE_CDC(0) | USBD_MODE_IFACE_CDC(1) | USBD_MODE_IFACE_CDC(2) | USBD_MODE_IFACE_MSC | USBD_MODE_IFACE_HID) #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) 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 e13a93ddb..938c8e711 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -61,9 +61,11 @@ #define HID_DESC_OFFSET_PROTOCOL (7) #define HID_DESC_OFFSET_SUBDESC (9) #define HID_DESC_OFFSET_REPORT_DESC_LEN (16) +#define HID_DESC_OFFSET_IN_EP (20) #define HID_DESC_OFFSET_MAX_PACKET_LO (22) #define HID_DESC_OFFSET_MAX_PACKET_HI (23) #define HID_DESC_OFFSET_POLLING_INTERVAL (24) +#define HID_DESC_OFFSET_OUT_EP (27) #define HID_DESC_OFFSET_MAX_PACKET_OUT_LO (29) #define HID_DESC_OFFSET_MAX_PACKET_OUT_HI (30) #define HID_DESC_OFFSET_POLLING_INTERVAL_OUT (31) @@ -79,6 +81,9 @@ #define MSC_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_CDC (0) #define HID_IFACE_NUM_WITH_MSC (1) +#define HID_IFACE_NUM_WITH_CDC_MSC (3) +#define HID_IFACE_NUM_WITH_CDC2_MSC (5) +#define HID_IFACE_NUM_WITH_CDC3_MSC (7) #define CDC_IN_EP(i) (0x83 + 2 * (i)) #define CDC_OUT_EP(i) (0x03 + 2 * (i)) @@ -88,6 +93,12 @@ #define HID_OUT_EP_WITH_CDC (0x01) #define HID_IN_EP_WITH_MSC (0x83) #define HID_OUT_EP_WITH_MSC (0x03) +#define HID_IN_EP_WITH_CDC_MSC (0x84) +#define HID_OUT_EP_WITH_CDC_MSC (0x04) +#define HID_IN_EP_WITH_CDC2_MSC (0x86) +#define HID_OUT_EP_WITH_CDC2_MSC (0x06) +#define HID_IN_EP_WITH_CDC3_MSC (0x88) +#define HID_OUT_EP_WITH_CDC3_MSC (0x08) #define USB_DESC_TYPE_ASSOCIATION (0x0b) @@ -448,8 +459,9 @@ static size_t make_cdc_desc_ep(uint8_t *dest, int need_iad, uint8_t iface_num, u #endif #if MICROPY_HW_USB_HID -static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info) { +static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t iface_num) { memcpy(dest, hid_class_desc_data, sizeof(hid_class_desc_data)); + dest[2] = iface_num; dest[HID_DESC_OFFSET_SUBCLASS] = hid_info->subclass; dest[HID_DESC_OFFSET_PROTOCOL] = hid_info->protocol; dest[HID_DESC_OFFSET_REPORT_DESC_LEN] = hid_info->report_desc_len; @@ -461,6 +473,15 @@ static size_t make_hid_desc(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info) { dest[HID_DESC_OFFSET_POLLING_INTERVAL_OUT] = hid_info->polling_interval; return sizeof(hid_class_desc_data); } + +#if MICROPY_HW_USB_MSC +static size_t make_hid_desc_ep(uint8_t *dest, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t iface_num, uint8_t in_ep, uint8_t out_ep) { + size_t n = make_hid_desc(dest, hid_info, iface_num); + dest[HID_DESC_OFFSET_IN_EP] = in_ep; + dest[HID_DESC_OFFSET_OUT_EP] = out_ep; + return n; +} +#endif #endif // return the saved usb mode @@ -489,6 +510,21 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; num_itf = 3; break; + + #if MICROPY_HW_USB_HID + case USBD_MODE_CDC_MSC_HID: + n += make_msc_desc(d + n); + n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_MSC); + usbd->hid->desc = d + n; + n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC_MSC, HID_IN_EP_WITH_CDC_MSC, HID_OUT_EP_WITH_CDC_MSC); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->hid->in_ep = HID_IN_EP_WITH_CDC_MSC; + usbd->hid->out_ep = HID_OUT_EP_WITH_CDC_MSC; + usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC_MSC; + usbd->hid->report_desc = hid_info->report_desc; + num_itf = 4; + break; + #endif #endif #if MICROPY_HW_USB_CDC_NUM >= 2 @@ -511,6 +547,23 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode num_itf = 5; break; } + + case USBD_MODE_CDC2_MSC_HID: { + 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, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + usbd->hid->desc = d + n; + n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC2_MSC, HID_IN_EP_WITH_CDC2_MSC, HID_OUT_EP_WITH_CDC2_MSC); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; + usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_MSC; + usbd->hid->in_ep = HID_IN_EP_WITH_CDC2_MSC; + usbd->hid->out_ep = HID_OUT_EP_WITH_CDC2_MSC; + usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC2_MSC; + usbd->hid->report_desc = hid_info->report_desc; + num_itf = 6; + break; + } #endif #endif @@ -538,13 +591,31 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode num_itf = 7; break; } + + case USBD_MODE_CDC3_MSC_HID: { + 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, CDC_CMD_EP(1), CDC_OUT_EP(1), CDC_IN_EP(1)); + n += make_cdc_desc_ep(d + n, 1, CDC3_IFACE_NUM_WITH_MSC, CDC_CMD_EP(2), CDC_OUT_EP(2), CDC_IN_EP(2)); + usbd->hid->desc = d + n; + n += make_hid_desc_ep(d + n, hid_info, HID_IFACE_NUM_WITH_CDC3_MSC, HID_IN_EP_WITH_CDC3_MSC, HID_OUT_EP_WITH_CDC3_MSC); + usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc[1]->iface_num = CDC2_IFACE_NUM_WITH_MSC; + usbd->cdc[2]->iface_num = CDC3_IFACE_NUM_WITH_MSC; + usbd->hid->in_ep = HID_IN_EP_WITH_CDC3_MSC; + usbd->hid->out_ep = HID_OUT_EP_WITH_CDC3_MSC; + usbd->hid->iface_num = HID_IFACE_NUM_WITH_CDC3_MSC; + usbd->hid->report_desc = hid_info->report_desc; + num_itf = 8; + break; + } #endif #endif #if MICROPY_HW_USB_HID case USBD_MODE_CDC_HID: usbd->hid->desc = d + n; - n += make_hid_desc(d + n, hid_info); + n += make_hid_desc(d + n, hid_info, HID_IFACE_NUM_WITH_CDC); n += make_cdc_desc(d + n, 1, CDC_IFACE_NUM_WITH_HID); usbd->cdc[0]->iface_num = CDC_IFACE_NUM_WITH_HID; usbd->hid->in_ep = HID_IN_EP_WITH_CDC;