stm32/usb: Combine CDC lower-layer and interface state into one struct.

This commit is contained in:
Damien George 2018-05-14 16:15:58 +10:00
parent ed32284b70
commit bf08a99ccd
5 changed files with 53 additions and 47 deletions

View File

@ -119,12 +119,6 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H
if (!usb_dev->enabled) { if (!usb_dev->enabled) {
// only init USB once in the device's power-lifetime // only init USB once in the device's power-lifetime
// configure the VID, PID and the USBD mode (interfaces it will expose)
USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, mode == USBD_MODE_CDC);
if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info) != 0) {
return false;
}
// set up the USBD state // set up the USBD state
USBD_HandleTypeDef *usbd = &usb_dev->hUSBDDevice; USBD_HandleTypeDef *usbd = &usb_dev->hUSBDDevice;
usbd->id = MICROPY_HW_USB_MAIN_DEV; usbd->id = MICROPY_HW_USB_MAIN_DEV;
@ -132,10 +126,16 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H
usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors; usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors;
usbd->pClass = &USBD_CDC_MSC_HID; usbd->pClass = &USBD_CDC_MSC_HID;
usb_dev->usbd_cdc_msc_hid_state.pdev = usbd; usb_dev->usbd_cdc_msc_hid_state.pdev = usbd;
usb_dev->usbd_cdc_msc_hid_state.cdc = &usb_dev->usbd_cdc_itf; usb_dev->usbd_cdc_msc_hid_state.cdc = &usb_dev->usbd_cdc_itf.base;
usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf; usb_dev->usbd_cdc_msc_hid_state.hid = &usb_dev->usbd_hid_itf;
usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state; usbd->pClassData = &usb_dev->usbd_cdc_msc_hid_state;
// configure the VID, PID and the USBD mode (interfaces it will expose)
USBD_SetVIDPIDRelease(&usb_dev->usbd_cdc_msc_hid_state, vid, pid, 0x0200, mode == USBD_MODE_CDC);
if (USBD_SelectMode(&usb_dev->usbd_cdc_msc_hid_state, mode, hid_info) != 0) {
return false;
}
switch (pyb_usb_storage_medium) { switch (pyb_usb_storage_medium) {
#if MICROPY_HW_HAS_SDCARD #if MICROPY_HW_HAS_SDCARD
case PYB_USB_STORAGE_MEDIUM_SDCARD: case PYB_USB_STORAGE_MEDIUM_SDCARD:

View File

@ -56,9 +56,8 @@
#define CDC_SET_CONTROL_LINE_STATE 0x22 #define CDC_SET_CONTROL_LINE_STATE 0x22
#define CDC_SEND_BREAK 0x23 #define CDC_SEND_BREAK 0x23
uint8_t *usbd_cdc_init(usbd_cdc_itf_t *cdc, usbd_cdc_msc_hid_state_t *usbd) { uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) {
// Link the parent state usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in;
cdc->usbd = usbd;
// Reset all the CDC state // Reset all the CDC state
// Note: we don't reset tx_buf_ptr_in in order to allow the output buffer to // Note: we don't reset tx_buf_ptr_in in order to allow the output buffer to
@ -80,7 +79,9 @@ uint8_t *usbd_cdc_init(usbd_cdc_itf_t *cdc, usbd_cdc_msc_hid_state_t *usbd) {
// pbuf: buffer containing command data (request parameters) // pbuf: buffer containing command data (request parameters)
// length: number of data to be sent (in bytes) // length: number of data to be sent (in bytes)
// Returns USBD_OK if all operations are OK else USBD_FAIL // Returns USBD_OK if all operations are OK else USBD_FAIL
int8_t usbd_cdc_control(usbd_cdc_itf_t *cdc, uint8_t cmd, uint8_t* pbuf, uint16_t length) { int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, uint16_t length) {
usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in;
switch (cmd) { switch (cmd) {
case CDC_SEND_ENCAPSULATED_COMMAND: case CDC_SEND_ENCAPSULATED_COMMAND:
/* Add your code here */ /* Add your code here */
@ -144,7 +145,7 @@ int8_t usbd_cdc_control(usbd_cdc_itf_t *cdc, uint8_t cmd, uint8_t* pbuf, uint16_
// needed (reducing latency), and often enough (increasing bandwidth). // needed (reducing latency), and often enough (increasing bandwidth).
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData; usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData;
usbd_cdc_itf_t *cdc = usbd->cdc; usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)usbd->cdc;
if (cdc == NULL || !cdc->dev_is_connected) { if (cdc == NULL || !cdc->dev_is_connected) {
// CDC device is not connected to a host, so we are unable to send any data // CDC device is not connected to a host, so we are unable to send any data
@ -185,7 +186,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
buffptr = cdc->tx_buf_ptr_out_shadow; buffptr = cdc->tx_buf_ptr_out_shadow;
if (USBD_CDC_TransmitPacket(cdc->usbd, buffsize, &cdc->tx_buf[buffptr]) == USBD_OK) { if (USBD_CDC_TransmitPacket(cdc->base.usbd, buffsize, &cdc->tx_buf[buffptr]) == USBD_OK) {
cdc->tx_buf_ptr_out_shadow += buffsize; cdc->tx_buf_ptr_out_shadow += buffsize;
if (cdc->tx_buf_ptr_out_shadow == USBD_CDC_TX_DATA_SIZE) { if (cdc->tx_buf_ptr_out_shadow == USBD_CDC_TX_DATA_SIZE) {
cdc->tx_buf_ptr_out_shadow = 0; cdc->tx_buf_ptr_out_shadow = 0;
@ -206,7 +207,9 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
// Data received over USB OUT endpoint is processed here. // Data received over USB OUT endpoint is processed here.
// len: number of bytes received into the buffer we passed to USBD_CDC_ReceivePacket // len: number of bytes received into the buffer we passed to USBD_CDC_ReceivePacket
// Returns USBD_OK if all operations are OK else USBD_FAIL // Returns USBD_OK if all operations are OK else USBD_FAIL
int8_t usbd_cdc_receive(usbd_cdc_itf_t *cdc, size_t len) { int8_t usbd_cdc_receive(usbd_cdc_state_t *cdc_in, size_t len) {
usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in;
// copy the incoming data into the circular buffer // copy the incoming data into the circular buffer
for (const uint8_t *src = cdc->rx_packet_buf, *top = cdc->rx_packet_buf + len; src < top; ++src) { for (const uint8_t *src = cdc->rx_packet_buf, *top = cdc->rx_packet_buf + len; src < top; ++src) {
if (mp_interrupt_char != -1 && *src == mp_interrupt_char) { if (mp_interrupt_char != -1 && *src == mp_interrupt_char) {
@ -223,7 +226,7 @@ int8_t usbd_cdc_receive(usbd_cdc_itf_t *cdc, size_t len) {
} }
// initiate next USB packet transfer // initiate next USB packet transfer
USBD_CDC_ReceivePacket(cdc->usbd, cdc->rx_packet_buf); USBD_CDC_ReceivePacket(cdc->base.usbd, cdc->rx_packet_buf);
return USBD_OK; return USBD_OK;
} }

View File

@ -35,7 +35,7 @@
#define USBD_CDC_TX_DATA_SIZE (1024) // I think this can be any value (was 2048) #define USBD_CDC_TX_DATA_SIZE (1024) // I think this can be any value (was 2048)
typedef struct _usbd_cdc_itf_t { typedef struct _usbd_cdc_itf_t {
usbd_cdc_msc_hid_state_t *usbd; // the parent USB device usbd_cdc_state_t base; // state for the base CDC layer
uint8_t rx_packet_buf[CDC_DATA_MAX_PACKET_SIZE]; // received data from USB OUT endpoint is stored in this buffer uint8_t rx_packet_buf[CDC_DATA_MAX_PACKET_SIZE]; // received data from USB OUT endpoint is stored in this buffer
uint8_t rx_user_buf[USBD_CDC_RX_DATA_SIZE]; // received data is buffered here until the user reads it uint8_t rx_user_buf[USBD_CDC_RX_DATA_SIZE]; // received data is buffered here until the user reads it

View File

@ -44,12 +44,16 @@
#define CDC_OUT_EP (0x03) #define CDC_OUT_EP (0x03)
#define CDC_CMD_EP (0x82) #define CDC_CMD_EP (0x82)
struct _usbd_cdc_msc_hid_state_t;
typedef struct { typedef struct {
uint32_t data[CDC_DATA_MAX_PACKET_SIZE / 4]; // Force 32bits alignment struct _usbd_cdc_msc_hid_state_t *usbd; // The parent USB device
uint8_t CmdOpCode; uint32_t ctl_packet_buf[CDC_DATA_MAX_PACKET_SIZE / 4]; // Force 32-bit alignment
uint8_t CmdLength; uint8_t iface_num;
volatile uint32_t TxState; uint8_t cur_request;
} USBD_CDC_HandleTypeDef; uint8_t cur_length;
volatile uint8_t tx_in_progress;
} usbd_cdc_state_t;
typedef struct _USBD_STORAGE { typedef struct _USBD_STORAGE {
int8_t (* Init) (uint8_t lun); int8_t (* Init) (uint8_t lun);
@ -104,7 +108,6 @@ typedef struct _usbd_cdc_msc_hid_state_t {
USBD_HandleTypeDef *pdev; USBD_HandleTypeDef *pdev;
uint8_t usbd_mode; uint8_t usbd_mode;
uint8_t cdc_iface_num;
uint8_t hid_in_ep; uint8_t hid_in_ep;
uint8_t hid_out_ep; uint8_t hid_out_ep;
uint8_t hid_iface_num; uint8_t hid_iface_num;
@ -112,7 +115,6 @@ typedef struct _usbd_cdc_msc_hid_state_t {
uint8_t *hid_desc; uint8_t *hid_desc;
const uint8_t *hid_report_desc; const uint8_t *hid_report_desc;
USBD_CDC_HandleTypeDef CDC_ClassData;
USBD_MSC_BOT_HandleTypeDef MSC_BOT_ClassData; USBD_MSC_BOT_HandleTypeDef MSC_BOT_ClassData;
USBD_HID_HandleTypeDef HID_ClassData; USBD_HID_HandleTypeDef HID_ClassData;
@ -121,7 +123,7 @@ typedef struct _usbd_cdc_msc_hid_state_t {
__ALIGN_BEGIN uint8_t usbd_str_desc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; __ALIGN_BEGIN uint8_t usbd_str_desc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;
__ALIGN_BEGIN uint8_t usbd_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END; __ALIGN_BEGIN uint8_t usbd_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END;
void *cdc; usbd_cdc_state_t *cdc;
void *hid; void *hid;
} usbd_cdc_msc_hid_state_t; } usbd_cdc_msc_hid_state_t;
@ -178,10 +180,9 @@ uint8_t USBD_HID_SetNAK(usbd_cdc_msc_hid_state_t *usbd);
uint8_t USBD_HID_ClearNAK(usbd_cdc_msc_hid_state_t *usbd); uint8_t USBD_HID_ClearNAK(usbd_cdc_msc_hid_state_t *usbd);
// These are provided externally to implement the CDC interface // These are provided externally to implement the CDC interface
struct _usbd_cdc_itf_t; uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc);
uint8_t *usbd_cdc_init(struct _usbd_cdc_itf_t *cdc, usbd_cdc_msc_hid_state_t *usbd); int8_t usbd_cdc_control(usbd_cdc_state_t *cdc, uint8_t cmd, uint8_t* pbuf, uint16_t length);
int8_t usbd_cdc_control(struct _usbd_cdc_itf_t *cdc, uint8_t cmd, uint8_t* pbuf, uint16_t length); int8_t usbd_cdc_receive(usbd_cdc_state_t *cdc, size_t len);
int8_t usbd_cdc_receive(struct _usbd_cdc_itf_t *cdc, size_t len);
// These are provided externally to implement the HID interface // These are provided externally to implement the HID interface
struct _usbd_hid_itf_t; struct _usbd_hid_itf_t;

View File

@ -617,13 +617,13 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
case USBD_MODE_CDC_MSC: case USBD_MODE_CDC_MSC:
usbd->usbd_config_desc_size = sizeof(cdc_msc_template_config_desc); usbd->usbd_config_desc_size = sizeof(cdc_msc_template_config_desc);
memcpy(usbd->usbd_config_desc, cdc_msc_template_config_desc, sizeof(cdc_msc_template_config_desc)); memcpy(usbd->usbd_config_desc, cdc_msc_template_config_desc, sizeof(cdc_msc_template_config_desc));
usbd->cdc_iface_num = CDC_IFACE_NUM_WITH_MSC; usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC;
break; break;
case USBD_MODE_CDC_HID: case USBD_MODE_CDC_HID:
usbd->usbd_config_desc_size = sizeof(cdc_hid_template_config_desc); usbd->usbd_config_desc_size = sizeof(cdc_hid_template_config_desc);
memcpy(usbd->usbd_config_desc, cdc_hid_template_config_desc, sizeof(cdc_hid_template_config_desc)); memcpy(usbd->usbd_config_desc, cdc_hid_template_config_desc, sizeof(cdc_hid_template_config_desc));
usbd->cdc_iface_num = CDC_IFACE_NUM_WITH_HID; usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_HID;
usbd->hid_in_ep = HID_IN_EP_WITH_CDC; usbd->hid_in_ep = HID_IN_EP_WITH_CDC;
usbd->hid_out_ep = HID_OUT_EP_WITH_CDC; usbd->hid_out_ep = HID_OUT_EP_WITH_CDC;
usbd->hid_iface_num = HID_IFACE_NUM_WITH_CDC; usbd->hid_iface_num = HID_IFACE_NUM_WITH_CDC;
@ -633,7 +633,7 @@ int USBD_SelectMode(usbd_cdc_msc_hid_state_t *usbd, uint32_t mode, USBD_HID_Mode
case USBD_MODE_CDC: case USBD_MODE_CDC:
usbd->usbd_config_desc_size = sizeof(cdc_template_config_desc); usbd->usbd_config_desc_size = sizeof(cdc_template_config_desc);
memcpy(usbd->usbd_config_desc, cdc_template_config_desc, sizeof(cdc_template_config_desc)); memcpy(usbd->usbd_config_desc, cdc_template_config_desc, sizeof(cdc_template_config_desc));
usbd->cdc_iface_num = CDC_IFACE_NUM_ALONE; usbd->cdc->iface_num = CDC_IFACE_NUM_ALONE;
break; break;
/* /*
@ -701,11 +701,13 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
USBD_EP_TYPE_INTR, USBD_EP_TYPE_INTR,
CDC_CMD_PACKET_SIZE); CDC_CMD_PACKET_SIZE);
// Init physical Interface components
uint8_t *buf = usbd_cdc_init(usbd->cdc, usbd);
// Init Xfer states // Init Xfer states
usbd->CDC_ClassData.TxState = 0; usbd->cdc->usbd = usbd;
usbd->cdc->cur_request = 0xff;
usbd->cdc->tx_in_progress = 0;
// Init physical Interface components
uint8_t *buf = usbd_cdc_init(usbd->cdc);
// Prepare Out endpoint to receive next packet // Prepare Out endpoint to receive next packet
USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, buf, mp); USBD_LL_PrepareReceive(pdev, CDC_OUT_EP, buf, mp);
@ -826,7 +828,7 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) { switch (req->bmRequest & USB_REQ_RECIPIENT_MASK) {
case USB_REQ_RECIPIENT_INTERFACE: { case USB_REQ_RECIPIENT_INTERFACE: {
uint16_t iface = req->wIndex; uint16_t iface = req->wIndex;
if ((mode & USBD_MODE_CDC) && iface == usbd->cdc_iface_num) { if ((mode & USBD_MODE_CDC) && iface == usbd->cdc->iface_num) {
recipient = USBD_MODE_CDC; recipient = USBD_MODE_CDC;
} else if ((mode & USBD_MODE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) { } else if ((mode & USBD_MODE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) {
recipient = USBD_MODE_MSC; recipient = USBD_MODE_MSC;
@ -862,13 +864,13 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
if (req->wLength) { if (req->wLength) {
if (req->bmRequest & 0x80) { if (req->bmRequest & 0x80) {
// device-to-host request // device-to-host request
usbd_cdc_control(usbd->cdc, req->bRequest, (uint8_t*)usbd->CDC_ClassData.data, req->wLength); usbd_cdc_control(usbd->cdc, req->bRequest, (uint8_t*)usbd->cdc->ctl_packet_buf, req->wLength);
USBD_CtlSendData(pdev, (uint8_t*)usbd->CDC_ClassData.data, req->wLength); USBD_CtlSendData(pdev, (uint8_t*)usbd->cdc->ctl_packet_buf, req->wLength);
} else { } else {
// host-to-device request // host-to-device request
usbd->CDC_ClassData.CmdOpCode = req->bRequest; usbd->cdc->cur_request = req->bRequest;
usbd->CDC_ClassData.CmdLength = req->wLength; usbd->cdc->cur_length = req->wLength;
USBD_CtlPrepareRx(pdev, (uint8_t*)usbd->CDC_ClassData.data, req->wLength); USBD_CtlPrepareRx(pdev, (uint8_t*)usbd->cdc->ctl_packet_buf, req->wLength);
} }
} else { } else {
// Not a Data request // Not a Data request
@ -991,9 +993,9 @@ static uint8_t EP0_TxSent(USBD_HandleTypeDef *pdev) {
static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) { static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) {
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
if (usbd->cdc != NULL && usbd->CDC_ClassData.CmdOpCode != 0xff) { if (usbd->cdc != NULL && usbd->cdc->cur_request != 0xff) {
usbd_cdc_control(usbd->cdc, usbd->CDC_ClassData.CmdOpCode, (uint8_t*)usbd->CDC_ClassData.data, usbd->CDC_ClassData.CmdLength); usbd_cdc_control(usbd->cdc, usbd->cdc->cur_request, (uint8_t*)usbd->cdc->ctl_packet_buf, usbd->cdc->cur_length);
usbd->CDC_ClassData.CmdOpCode = 0xff; usbd->cdc->cur_request = 0xff;
} }
return USBD_OK; return USBD_OK;
@ -1002,7 +1004,7 @@ static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) {
static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) { static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum) {
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
if ((usbd->usbd_mode & USBD_MODE_CDC) && (epnum == (CDC_IN_EP & 0x7f) || epnum == (CDC_CMD_EP & 0x7f))) { if ((usbd->usbd_mode & USBD_MODE_CDC) && (epnum == (CDC_IN_EP & 0x7f) || epnum == (CDC_CMD_EP & 0x7f))) {
usbd->CDC_ClassData.TxState = 0; usbd->cdc->tx_in_progress = 0;
return USBD_OK; return USBD_OK;
} else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { } else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) {
MSC_BOT_DataIn(pdev, epnum); MSC_BOT_DataIn(pdev, epnum);
@ -1105,12 +1107,12 @@ uint8_t *USBD_CDC_MSC_HID_GetDeviceQualifierDescriptor(USBD_HandleTypeDef *pdev,
// data received on non-control OUT endpoint // data received on non-control OUT endpoint
uint8_t USBD_CDC_TransmitPacket(usbd_cdc_msc_hid_state_t *usbd, size_t len, const uint8_t *buf) { uint8_t USBD_CDC_TransmitPacket(usbd_cdc_msc_hid_state_t *usbd, size_t len, const uint8_t *buf) {
if (usbd->CDC_ClassData.TxState == 0) { if (usbd->cdc->tx_in_progress == 0) {
// transmit next packet // transmit next packet
USBD_LL_Transmit(usbd->pdev, CDC_IN_EP, (uint8_t*)buf, len); USBD_LL_Transmit(usbd->pdev, CDC_IN_EP, (uint8_t*)buf, len);
// Tx transfer in progress // Tx transfer in progress
usbd->CDC_ClassData.TxState = 1; usbd->cdc->tx_in_progress = 1;
return USBD_OK; return USBD_OK;
} else { } else {
return USBD_BUSY; return USBD_BUSY;