stm32/usb: Verify number of used endpoints doesn't exceed maximum.

This commit is contained in:
Damien George 2019-09-11 14:59:02 +10:00
parent 6705767da1
commit bcaafa3823
3 changed files with 27 additions and 3 deletions

View File

@ -57,6 +57,19 @@
#endif #endif
#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); STATIC void pyb_usb_vcp_init0(void);
// this will be persistent across a soft-reset // 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) // configure the VID, PID and the USBD mode (interfaces it will expose)
int cdc_only = (mode & USBD_MODE_IFACE_MASK) == 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); 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; return false;
} }

View File

@ -165,7 +165,7 @@ static inline uint32_t usbd_cdc_max_packet(USBD_HandleTypeDef *pdev) {
} }
// returns 0 on success, -1 on failure // 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 // returns the current usb mode
uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd); uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd);

View File

@ -489,7 +489,7 @@ uint8_t USBD_GetMode(usbd_cdc_msc_hid_state_t *usbd) {
return usbd->usbd_mode; 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 // save mode
usbd->usbd_mode = 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; return 0;
} }