From bcaafa382323c5d15988f20782c2737f05a4c002 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 11 Sep 2019 14:59:02 +1000 Subject: [PATCH] stm32/usb: Verify number of used endpoints doesn't exceed maximum. --- ports/stm32/usb.c | 15 ++++++++++++++- ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h | 2 +- ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c | 13 ++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 8b80629815..ca5cc682ec 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -57,6 +57,19 @@ #endif #endif +// Maximum number of endpoints (excluding EP0) +#if defined(STM32L0) || defined(STM32WB) +#define MAX_ENDPOINT(dev_id) (7) +#elif defined(STM32L4) +#define MAX_ENDPOINT(dev_id) (5) +#elif defined(STM32F4) +#define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 3 : 5) +#elif defined(STM32F7) +#define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 5 : 8) +#elif defined(STM32H7) +#define MAX_ENDPOINT(dev_id) (8) +#endif + STATIC void pyb_usb_vcp_init0(void); // this will be persistent across a soft-reset @@ -240,7 +253,7 @@ bool pyb_usb_dev_init(int dev_id, uint16_t vid, uint16_t pid, uint8_t mode, size // configure the VID, PID and the USBD mode (interfaces it will expose) 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) { + if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info, MAX_ENDPOINT(dev_id)) != 0) { return false; } 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 f3edc4dcb4..d934f4676c 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -165,7 +165,7 @@ static inline uint32_t usbd_cdc_max_packet(USBD_HandleTypeDef *pdev) { } // returns 0 on success, -1 on failure -int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info); +int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t max_endpoint); // returns the current usb mode uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd); 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 938c8e7115..0b94076543 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -489,7 +489,7 @@ uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd) { return usbd->usbd_mode; } -int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info) { +int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info, uint8_t max_endpoint) { // save mode usbd->usbd_mode = mode; @@ -656,6 +656,17 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode } } + // Verify that the endpoints that are used fit within the maximum number + d = usbd->usbd_config_desc; + const uint8_t *d_top = d + n; + while (d < d_top) { + if (d[0] == 7 && d[1] == USB_DESC_TYPE_ENDPOINT && (d[2] & 0x7f) > max_endpoint) { + // Endpoint out of range of hardware + return -1; + } + d += d[0]; + } + return 0; }