summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/usb.c15
-rw-r--r--ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h2
-rw-r--r--ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c13
3 files changed, 27 insertions, 3 deletions
diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c
index 8b8062981..ca5cc682e 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 f3edc4dcb..d934f4676 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 938c8e711..0b9407654 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;
}