diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c index 1e8052d2ff..e86f69ac55 100644 --- a/ports/stm32/usb.c +++ b/ports/stm32/usb.c @@ -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) { // 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 USBD_HandleTypeDef *usbd = &usb_dev->hUSBDDevice; 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->pClass = &USBD_CDC_MSC_HID; 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; 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) { #if MICROPY_HW_HAS_SDCARD case PYB_USB_STORAGE_MEDIUM_SDCARD: diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index 23085510cc..a987646e7a 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -56,9 +56,8 @@ #define CDC_SET_CONTROL_LINE_STATE 0x22 #define CDC_SEND_BREAK 0x23 -uint8_t *usbd_cdc_init(usbd_cdc_itf_t *cdc, usbd_cdc_msc_hid_state_t *usbd) { - // Link the parent state - cdc->usbd = usbd; +uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) { + usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t*)cdc_in; // Reset all the CDC state // 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) // length: number of data to be sent (in bytes) // 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) { case CDC_SEND_ENCAPSULATED_COMMAND: /* 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). void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { 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) { // 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; - 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; if (cdc->tx_buf_ptr_out_shadow == USBD_CDC_TX_DATA_SIZE) { 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. // 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 -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 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) { @@ -223,7 +226,7 @@ int8_t usbd_cdc_receive(usbd_cdc_itf_t *cdc, size_t len) { } // 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; } diff --git a/ports/stm32/usbd_cdc_interface.h b/ports/stm32/usbd_cdc_interface.h index 36a89e7dbc..bfcdfaf333 100644 --- a/ports/stm32/usbd_cdc_interface.h +++ b/ports/stm32/usbd_cdc_interface.h @@ -35,7 +35,7 @@ #define USBD_CDC_TX_DATA_SIZE (1024) // I think this can be any value (was 2048) 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_user_buf[USBD_CDC_RX_DATA_SIZE]; // received data is buffered here until the user reads it 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 1ff22ba904..43a494ebd9 100644 --- a/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h +++ b/ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h @@ -44,12 +44,16 @@ #define CDC_OUT_EP (0x03) #define CDC_CMD_EP (0x82) +struct _usbd_cdc_msc_hid_state_t; + typedef struct { - uint32_t data[CDC_DATA_MAX_PACKET_SIZE / 4]; // Force 32bits alignment - uint8_t CmdOpCode; - uint8_t CmdLength; - volatile uint32_t TxState; -} USBD_CDC_HandleTypeDef; + struct _usbd_cdc_msc_hid_state_t *usbd; // The parent USB device + uint32_t ctl_packet_buf[CDC_DATA_MAX_PACKET_SIZE / 4]; // Force 32-bit alignment + uint8_t iface_num; + uint8_t cur_request; + uint8_t cur_length; + volatile uint8_t tx_in_progress; +} usbd_cdc_state_t; typedef struct _USBD_STORAGE { int8_t (* Init) (uint8_t lun); @@ -104,7 +108,6 @@ typedef struct _usbd_cdc_msc_hid_state_t { USBD_HandleTypeDef *pdev; uint8_t usbd_mode; - uint8_t cdc_iface_num; uint8_t hid_in_ep; uint8_t hid_out_ep; uint8_t hid_iface_num; @@ -112,7 +115,6 @@ typedef struct _usbd_cdc_msc_hid_state_t { uint8_t *hid_desc; const uint8_t *hid_report_desc; - USBD_CDC_HandleTypeDef CDC_ClassData; USBD_MSC_BOT_HandleTypeDef MSC_BOT_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_config_desc[MAX_TEMPLATE_CONFIG_DESC_SIZE] __ALIGN_END; - void *cdc; + usbd_cdc_state_t *cdc; void *hid; } 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); // These are provided externally to implement the CDC interface -struct _usbd_cdc_itf_t; -uint8_t *usbd_cdc_init(struct _usbd_cdc_itf_t *cdc, usbd_cdc_msc_hid_state_t *usbd); -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(struct _usbd_cdc_itf_t *cdc, size_t len); +uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc); +int8_t usbd_cdc_control(usbd_cdc_state_t *cdc, uint8_t cmd, uint8_t* pbuf, uint16_t length); +int8_t usbd_cdc_receive(usbd_cdc_state_t *cdc, size_t len); // These are provided externally to implement the HID interface struct _usbd_hid_itf_t; 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 2e1df0cb76..7944ae7778 100644 --- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c +++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c @@ -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: 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)); - usbd->cdc_iface_num = CDC_IFACE_NUM_WITH_MSC; + usbd->cdc->iface_num = CDC_IFACE_NUM_WITH_MSC; break; case USBD_MODE_CDC_HID: 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)); - 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_out_ep = HID_OUT_EP_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: usbd->usbd_config_desc_size = 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; /* @@ -701,11 +701,13 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { USBD_EP_TYPE_INTR, CDC_CMD_PACKET_SIZE); - // Init physical Interface components - uint8_t *buf = usbd_cdc_init(usbd->cdc, usbd); - // 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 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) { case USB_REQ_RECIPIENT_INTERFACE: { 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; } else if ((mode & USBD_MODE_MSC) && iface == MSC_IFACE_NUM_WITH_CDC) { 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->bmRequest & 0x80) { // device-to-host request - usbd_cdc_control(usbd->cdc, req->bRequest, (uint8_t*)usbd->CDC_ClassData.data, req->wLength); - USBD_CtlSendData(pdev, (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->ctl_packet_buf, req->wLength); } else { // host-to-device request - usbd->CDC_ClassData.CmdOpCode = req->bRequest; - usbd->CDC_ClassData.CmdLength = req->wLength; - USBD_CtlPrepareRx(pdev, (uint8_t*)usbd->CDC_ClassData.data, req->wLength); + usbd->cdc->cur_request = req->bRequest; + usbd->cdc->cur_length = req->wLength; + USBD_CtlPrepareRx(pdev, (uint8_t*)usbd->cdc->ctl_packet_buf, req->wLength); } } else { // 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) { usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData; - if (usbd->cdc != NULL && usbd->CDC_ClassData.CmdOpCode != 0xff) { - usbd_cdc_control(usbd->cdc, usbd->CDC_ClassData.CmdOpCode, (uint8_t*)usbd->CDC_ClassData.data, usbd->CDC_ClassData.CmdLength); - usbd->CDC_ClassData.CmdOpCode = 0xff; + if (usbd->cdc != NULL && usbd->cdc->cur_request != 0xff) { + usbd_cdc_control(usbd->cdc, usbd->cdc->cur_request, (uint8_t*)usbd->cdc->ctl_packet_buf, usbd->cdc->cur_length); + usbd->cdc->cur_request = 0xff; } 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) { 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))) { - usbd->CDC_ClassData.TxState = 0; + usbd->cdc->tx_in_progress = 0; return USBD_OK; } else if ((usbd->usbd_mode & USBD_MODE_MSC) && epnum == (MSC_IN_EP & 0x7f)) { 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 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 USBD_LL_Transmit(usbd->pdev, CDC_IN_EP, (uint8_t*)buf, len); // Tx transfer in progress - usbd->CDC_ClassData.TxState = 1; + usbd->cdc->tx_in_progress = 1; return USBD_OK; } else { return USBD_BUSY;