GEX core repository.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
gex-core/USB/MSC_CDC/usbd_msc_cdc.c

351 lines
14 KiB

//
// Created by MightyPork on 2017/11/07.
//
#include "platform.h"
#include "framework/system_settings.h"
#include "usbd_desc.h"
#include "task_main.h"
#include "usbd_msc.h"
#include "usbd_cdc.h"
#include "usbd_msc_cdc.h"
#define USBD_MSC_CDC_CONFIG_DESC_SIZ 98
/* USB Mass storage device Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
// NOTE: This must NOT be in flash, otherwise the driver / peripheral crashes
__ALIGN_BEGIN uint8_t USBD_MSC_CDC_CfgFSDesc[USBD_MSC_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
{
/*0*/ 0x09, /* bLength: Configuation Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
LOBYTE(USBD_MSC_CDC_CONFIG_DESC_SIZ), // TODO
HIBYTE(USBD_MSC_CDC_CONFIG_DESC_SIZ),
3, /* bNumInterfaces - 1 MSC + 2 composite CDC ACM */
0x01, /* bConfigurationValue: */
0, /* iConfiguration: - string descriptor */
0xC0, /* bmAttributes: - self powered */
150, /* MaxPower 300 mA */
/******************** Mass Storage interface ********************/
/*9*/ 0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints*/
0x08, /* bInterfaceClass: MSC Class */ // #14
0x06, /* bInterfaceSubClass : SCSI transparent*/
0x50, /* nInterfaceProtocol */
0x04, /* iInterface: String descriptor */
/******************** Mass Storage Endpoints ********************/
/*18*/ 0x07, /*Endpoint descriptor length = 7*/
0x05, /*Endpoint descriptor type */
MSC_EPIN_ADDR, /*Endpoint address (IN, address 1) */
0x02, /*Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET),
HIBYTE(MSC_MAX_FS_PACKET),
0x00, /*Polling interval in milliseconds */
/*25*/ 0x07, /*Endpoint descriptor length = 7 */
0x05, /*Endpoint descriptor type */
MSC_EPOUT_ADDR, /*Endpoint address (OUT, address 1) */
0x02, /*Bulk endpoint type */
LOBYTE(MSC_MAX_FS_PACKET),
HIBYTE(MSC_MAX_FS_PACKET),
0x00, /*Polling interval in milliseconds*/
/********************** IFACE ASSOC *************************/
/*32*/ 0x08, /* bLength */
USB_DESC_TYPE_IFACE_ASSOCIATION, /* bDescriptorType */
0x01, /* bFirstInterface */
0x02, /* bInterfaceCount */
0x02, /* bFunctionClass */ // #36
0x02, /* bFunctionSubClass (ACM) */
0x01, /* bFunctionProtocol (AT-COMMANDS) */
0x05, /* iFunction: string descriptor */
/********************** ACM interface **********************/
/*40*/ 0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints: One endpoints used */
0x02, /* bInterfaceClass: Communication Interface Class */ // #45
0x02, /* bInterfaceSubClass: Abstract Control Model */
0x01, /* bInterfaceProtocol: Common AT commands */
0x05, /* iInterface: string descriptor */
/**************** Header Functional Descriptor ***************/
/*49*/ 0x05, /* bLength: Endpoint Descriptor size */
0x24, /* bDescriptorType: CS_INTERFACE */
0x00, /* bDescriptorSubtype: Header Func Desc */
0x10, /* bcdCDC: spec release number */
0x01,
/*********** Call Management Functional Descriptor **********/
/*54*/ 0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x01, /* bDescriptorSubtype: Call Management Func Desc */
0x00, /* bmCapabilities: D0+D1 */
0x02, /* bDataInterface: 2 */
/*************** ACM Functional Descriptor ***************/
/*59*/ 0x04, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
0x06, /* bmCapabilities XXX was:0x02? */
/************* Union Functional Descriptor **************/
/*63*/ 0x05, /* bFunctionLength */
0x24, /* bDescriptorType: CS_INTERFACE */
0x06, /* bDescriptorSubtype: Union func desc */
0x01, /* bMasterInterface: Communication class interface */
0x02, /* bSlaveInterface0: Data Class Interface */
/******************** CDC Endpoints ********************/
/// Command endpoint
/*68*/ 0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CMD_EP, /* bEndpointAddress */
0x03, /* bmAttributes: Interrupt */
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: TODO: 2?*/
HIBYTE(CDC_CMD_PACKET_SIZE),
0xFF, /* bInterval: TODO was 0x10?*/
/********** CDC Data Class Interface Descriptor ***********/
/*75*/ 0x09, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
0x02, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: Two endpoints used */
0x0A, /* bInterfaceClass: CDC */ // #80
0x00, /* bInterfaceSubClass: */
0x00, /* bInterfaceProtocol: */
0x06, /* iInterface: TODO: string descriptor */
/// Endpoint OUT Descriptor
/*84*/ 0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_OUT_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: TODO 8? */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00, /* bInterval: ignore for Bulk transfer */
/// Endpoint IN Descriptor
/*91*/ 0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_IN_EP, /* bEndpointAddress */
0x02, /* bmAttributes: Bulk */
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: TODO 16? */
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
0x00 /* bInterval: ignore for Bulk transfer */
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_MSC_CDC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
MSC_MAX_FS_PACKET,
0x01,
0x00,
};
static uint8_t USBD_MSC_CDC_Init(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
// this is not correct, but will work if neither returns BUSY (which they don't)
uint8_t ret = 0;
ret |= USBD_MSC_Init(pdev, cfgidx);
ret |= USBD_CDC_Init(pdev, cfgidx);
return ret;
}
static uint8_t USBD_MSC_CDC_DeInit(struct _USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
uint8_t ret = 0;
ret |= USBD_MSC_DeInit(pdev, cfgidx);
ret |= USBD_CDC_DeInit(pdev, cfgidx);
return ret;
}
/* Control Endpoints*/
static uint8_t USBD_MSC_CDC_Setup(struct _USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
static uint8_t interface_bit;
// handle common
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest) {
// those don't really do anything useful, but each class implements
// them and it would send the data twice.
case USB_REQ_GET_INTERFACE :
USBD_CtlSendData(pdev, &interface_bit, 1);
return USBD_OK;
case USB_REQ_SET_INTERFACE :
interface_bit = (uint8_t) (req->wValue);
return USBD_OK;
}
}
// class specific, or Interface -> Clear Feature
USBD_MSC_Setup(pdev, req);
USBD_CDC_Setup(pdev, req);
return USBD_OK;
}
#if 0
static uint8_t USBD_MSC_CDC_EP0_TxSent(struct _USBD_HandleTypeDef *pdev)
{
// not handled by either
xTaskNotify(tskUsbEventHandle, USBEVT_FLAG_EP0_TX_SENT, eSetBits);
return USBD_OK;
}
#endif
static uint8_t USBD_MSC_CDC_EP0_RxReady(struct _USBD_HandleTypeDef *pdev)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(tskMainHandle, USBEVT_FLAG_EP0_RX_RDY, eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
//USBD_CDC_EP0_RxReady(pdev);
return USBD_OK;
}
/* Class Specific Endpoints*/
static uint8_t USBD_MSC_CDC_DataIn(struct _USBD_HandleTypeDef *pdev, uint8_t epnum)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(tskMainHandle, USBEVT_FLAG_EPx_IN(epnum), eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
// if (epnum == MSC_EPIN_ADDR||epnum==MSC_EPOUT_ADDR) USBD_MSC_DataIn(pdev, epnum);
// else if (epnum == CDC_IN_EP||epnum == CDC_CMD_EP) USBD_CDC_DataIn(pdev, epnum);
return USBD_OK;
}
static uint8_t USBD_MSC_CDC_DataOut(struct _USBD_HandleTypeDef *pdev, uint8_t epnum)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(tskMainHandle, USBEVT_FLAG_EPx_OUT(epnum), eSetBits, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
// if (epnum == MSC_EPIN_ADDR||epnum == MSC_EPOUT_ADDR) USBD_MSC_DataOut(pdev, epnum);
// else if (epnum == CDC_OUT_EP||epnum == CDC_CMD_EP) USBD_CDC_DataOut(pdev, epnum);
return USBD_OK;
}
#if 0
static uint8_t USBD_MSC_CDC_SOF(struct _USBD_HandleTypeDef *pdev)
{
// not handled by either
return USBD_OK;
}
static uint8_t USBD_MSC_CDC_IsoINIncomplete(struct _USBD_HandleTypeDef *pdev, uint8_t epnum)
{
// not handled by either
return USBD_OK;
}
static uint8_t USBD_MSC_CDC_IsoOUTIncomplete(struct _USBD_HandleTypeDef *pdev, uint8_t epnum)
{
// not handled by either
return USBD_OK;
}
static uint8_t *USBD_MSC_CDC_GetUsrStrDescriptor(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length)
{
// not handled by either
return USBD_OK;
}
#endif
#if 0
uint8_t *USBD_MSC_CDC_GetHSCfgDesc (uint16_t *length)
{
// *length = sizeof (USBD_MSC_CDC_CfgHSDesc);
// return USBD_MSC_CDC_CfgHSDesc;
*length = sizeof (USBD_MSC_CDC_CfgFSDesc);
return USBD_MSC_CDC_CfgFSDesc;
}
#endif
uint8_t *USBD_MSC_CDC_GetFSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_MSC_CDC_CfgFSDesc);
// Optionally hide CDC-ACM by setting its class to Vendor Specific
bool cdc_visible = SystemSettings.visible_vcom;
USBD_MSC_CDC_CfgFSDesc[36] = (uint8_t) (cdc_visible ? 0x02 : 0xFF);
USBD_MSC_CDC_CfgFSDesc[45] = (uint8_t) (cdc_visible ? 0x02 : 0xFF);
USBD_MSC_CDC_CfgFSDesc[80] = (uint8_t) (cdc_visible ? 0x0A : 0xFF);
// Optionally hide settings (if lock jumper is installed)
bool msc_visible = SystemSettings.editable;
USBD_MSC_CDC_CfgFSDesc[14] = (uint8_t) (msc_visible ? 0x08 : 0xFF);
return USBD_MSC_CDC_CfgFSDesc;
}
#if 0
uint8_t *USBD_MSC_CDC_GetOtherSpeedCfgDesc (uint16_t *length)
{
// *length = sizeof (USBD_MSC_CDC_OtherSpeedCfgDesc);
// return USBD_MSC_CDC_OtherSpeedCfgDesc;
*length = sizeof (USBD_MSC_CDC_CfgFSDesc);
return USBD_MSC_CDC_CfgFSDesc;
}
#endif
uint8_t *USBD_MSC_CDC_GetDeviceQualifierDescriptor (uint16_t *length)
{
*length = sizeof (USBD_MSC_CDC_DeviceQualifierDesc);
return USBD_MSC_CDC_DeviceQualifierDesc;
}
uint8_t *USBD_MSC_CDC_GetUsrStrDescriptor(struct _USBD_HandleTypeDef *pdev, uint8_t index, uint16_t *length)
{
const char *str;
switch (index) {
case 0x04: str = "Settings Virtual Mass Storage"; break;
case 0x05: str = "Virtual Comport ACM"; break;
case 0x06: str = "Virtual Comport CDC"; break;
default: str = "No Descriptor";
}
USBD_GetString ((uint8_t *) str, USBD_StrDesc, length);
return USBD_StrDesc;
}
USBD_ClassTypeDef USBD_MSC_CDC =
{
USBD_MSC_CDC_Init,
USBD_MSC_CDC_DeInit,
USBD_MSC_CDC_Setup,
NULL, // USBD_MSC_CDC_EP0_TxSent,
USBD_MSC_CDC_EP0_RxReady,
USBD_MSC_CDC_DataIn,
USBD_MSC_CDC_DataOut,
NULL, // USBD_MSC_CDC_SOF,
NULL, // USBD_MSC_CDC_IsoINIncomplete,
NULL, // USBD_MSC_CDC_IsoOUTIncomplete,
// we return only the FS one, others are useless
USBD_MSC_CDC_GetFSCfgDesc, //USBD_MSC_CDC_GetHSCfgDesc,
USBD_MSC_CDC_GetFSCfgDesc,
USBD_MSC_CDC_GetFSCfgDesc, //USBD_MSC_CDC_GetOtherSpeedCfgDesc,
USBD_MSC_CDC_GetDeviceQualifierDescriptor,
USBD_MSC_CDC_GetUsrStrDescriptor
};