From 9a3f3f34b271c43151678b0a51823255100d1e4b Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 13 Feb 2021 05:54:08 -0800 Subject: [PATCH] USB mass storage descriptor (#2330) * enable msd * modify descriptors for composite device * makefile cleanup * format * define * embiggen fifos * needed that * cleanup too while we're at it * rename endpoints * switchable descriptors * guard the request hook too * don't need this changed yet * cleanup * update ep0 response * cleanup * use the msd hook from chibios * this was wrong * this was covered by other PR * this is also covered * s --- .../ports/stm32/serial_over_usb/usbcfg.c | 113 +++++++++++++++--- 1 file changed, 99 insertions(+), 14 deletions(-) diff --git a/firmware/hw_layer/ports/stm32/serial_over_usb/usbcfg.c b/firmware/hw_layer/ports/stm32/serial_over_usb/usbcfg.c index e4658df429..44845aa0e1 100644 --- a/firmware/hw_layer/ports/stm32/serial_over_usb/usbcfg.c +++ b/firmware/hw_layer/ports/stm32/serial_over_usb/usbcfg.c @@ -30,12 +30,31 @@ SerialUSBDriver SDU1; #define USBD1_DATA_AVAILABLE_EP 2 #define USBD1_INTERRUPT_REQUEST_EP 3 +#if HAL_USE_USB_MSD + // Descriptor that includes MSD is larger and has an extra interface + #define DESCRIPTOR_SIZE 98 + #define NUM_INTERFACES 3 + #define USB_MSD_EP_SIZE 64 + + #define MSD_IF 0 + #define CDC_INT_IF 1 + #define CDC_DATA_IF 2 +#else + // Alternate descriptor is smaller, no MSD + #define DESCRIPTOR_SIZE 75 + #define NUM_INTERFACES 2 + + // only two interfaces + #define CDC_INT_IF 0 + #define CDC_DATA_IF 1 +#endif + /* * USB Device Descriptor. */ static const uint8_t vcom_device_descriptor_data[18] = { USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */ - 0xEF, /* bDeviceClass (misc). */ + 0xEF, /* bDeviceClass ( misc ). */ 0x02, /* bDeviceSubClass. */ 0x01, /* bDeviceProtocol. */ 0x40, /* bMaxPacketSize. */ @@ -57,23 +76,44 @@ static const USBDescriptor vcom_device_descriptor = { }; /* Configuration Descriptor tree for a CDC.*/ -static const uint8_t vcom_configuration_descriptor_data[75] = { +static const uint8_t vcom_configuration_descriptor_data[DESCRIPTOR_SIZE] = { /* Configuration Descriptor.*/ - USB_DESC_CONFIGURATION(75, /* wTotalLength. */ - 0x02, /* bNumInterfaces. */ + USB_DESC_CONFIGURATION(DESCRIPTOR_SIZE,/* wTotalLength. */ + NUM_INTERFACES,/* bNumInterfaces. */ 0x01, /* bConfigurationValue. */ 0, /* iConfiguration. */ 0xC0, /* bmAttributes (self powered). */ - 100), /* bMaxPower (200mA). */ - /* IAD Descriptor - describes that Interfaces 0 and 1 belong to CDC */ - USB_DESC_INTERFACE_ASSOCIATION(0x00, /* bFirstInterface. */ + 100), /* bMaxPower (200mA). */ +#if HAL_USE_USB_MSD + USB_DESC_INTERFACE (MSD_IF, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x08, /* bInterfaceClass (mass storage) */ + 0x06, /* bInterfaceSubClass (SCSI + transparent storage class). */ + 0x50, /* bInterfaceProtocol (Bulk Only). */ + 0), /* iInterface. */ + /* Mass Storage Data In Endpoint Descriptor.*/ + USB_DESC_ENDPOINT (USB_MSD_DATA_EP | 0x80, + 0x02, /* bmAttributes (Bulk). */ + 64, /* wMaxPacketSize. */ + 0x00), /* bInterval. 1ms */ + /* Mass Storage Data Out Endpoint Descriptor.*/ + USB_DESC_ENDPOINT (USB_MSD_DATA_EP, + 0x02, /* bmAttributes (Bulk). */ + 64, /* wMaxPacketSize. */ + 0x00), /* bInterval. 1ms */ +#endif // HAL_USE_USB_MSD + // CDC + /* IAD Descriptor - describes that EP2+3 belong to CDC */ + USB_DESC_INTERFACE_ASSOCIATION(CDC_INT_IF, /* bFirstInterface. */ 0x02, /* bInterfaceCount. */ 0x02, /* bFunctionClass (CDC). */ 0x02, /* bFunctionSubClass. (2) */ 0x01, /* bFunctionProtocol (1) */ - 0), /* iInterface. */ + 2), /* iInterface. */ /* Interface Descriptor.*/ - USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + USB_DESC_INTERFACE (CDC_INT_IF, /* bInterfaceNumber. */ 0x00, /* bAlternateSetting. */ 0x01, /* bNumEndpoints. */ 0x02, /* bInterfaceClass (Communications @@ -96,7 +136,7 @@ static const uint8_t vcom_configuration_descriptor_data[75] = { USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management Functional Descriptor). */ USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ - USB_DESC_BYTE (0x01), /* bDataInterface. */ + USB_DESC_BYTE (CDC_DATA_IF), /* bDataInterface. */ /* ACM Functional Descriptor.*/ USB_DESC_BYTE (4), /* bFunctionLength. */ USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ @@ -108,9 +148,9 @@ static const uint8_t vcom_configuration_descriptor_data[75] = { USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union Functional Descriptor). */ - USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + USB_DESC_BYTE (CDC_INT_IF), /* bMasterInterface (Communication Class Interface). */ - USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + USB_DESC_BYTE (CDC_DATA_IF), /* bSlaveInterface0 (Data Class Interface). */ /* Endpoint 3 Descriptor.*/ USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80, @@ -118,7 +158,7 @@ static const uint8_t vcom_configuration_descriptor_data[75] = { 0x0008, /* wMaxPacketSize. */ 0xFF), /* bInterval. */ /* Interface Descriptor.*/ - USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + USB_DESC_INTERFACE (CDC_DATA_IF, /* bInterfaceNumber. */ 0x00, /* bAlternateSetting. */ 0x02, /* bNumEndpoints. */ 0x0A, /* bInterfaceClass (Data Class @@ -251,6 +291,34 @@ static const USBDescriptor *get_descriptor(USBDriver *usbp, return NULL; } +#if HAL_USE_USB_MSD + /** + * @brief IN MSD state + */ + static USBInEndpointState msdInstate; + + /** + * @brief OUT MSD state + */ + static USBOutEndpointState msdOutstate; + + /** + * @brief MSD initialization structure (both IN and OUT). + */ + static const USBEndpointConfig msdEpConfig = { + USB_EP_MODE_TYPE_BULK, + NULL, + NULL, + NULL, + USB_MSD_EP_SIZE, + USB_MSD_EP_SIZE, + &msdInstate, + &msdOutstate, + 4, + NULL + }; +#endif //HAL_USE_MSD + // IN CDC data state. static USBInEndpointState cdcDataInstate; // OUT CDC data state. @@ -298,6 +366,10 @@ static void usb_event(USBDriver *usbp, usbevent_t event) { /* Enables the endpoints specified into the configuration. Note, this callback is invoked from an ISR so I-Class functions must be used.*/ +#if HAL_USE_USB_MSD + usbInitEndpointI(usbp, USB_MSD_DATA_EP, &msdEpConfig); +#endif + usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &cdcDataEpConfig); usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &cdcInterruptEpConfig); @@ -344,13 +416,26 @@ static void sof_handler(USBDriver *usbp) { osalSysUnlockFromISR(); } +// We need a custom hook to handle both MSD and CDC at the same time +static bool hybridRequestHook(USBDriver *usbp) { +#if HAL_USE_USB_MSD + // Try the MSD driver first + if (msd_request_hook(usbp)) { + return true; + } +#endif // HAL_USE_USB_MSD + + // if not MSD, it must be serial + return sduRequestsHook(usbp); +} + /* * USB driver configuration. */ const USBConfig usbcfg = { usb_event, get_descriptor, - sduRequestsHook, + hybridRequestHook, sof_handler };