stm32/usbdev: Put all CDC state in a struct.

This commit is contained in:
Damien George 2017-08-31 13:54:49 +10:00
parent ede8a0235b
commit 980b33177b
7 changed files with 229 additions and 255 deletions

View File

@ -55,6 +55,8 @@ mp_uint_t pyb_usb_flags = 0;
#ifdef USE_DEVICE_MODE #ifdef USE_DEVICE_MODE
STATIC USBD_HandleTypeDef hUSBDDevice; STATIC USBD_HandleTypeDef hUSBDDevice;
STATIC usbd_cdc_msc_hid_state_t usbd_cdc_msc_hid_state;
STATIC usbd_cdc_itf_t usbd_cdc_itf;
pyb_usb_storage_medium_t pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_NONE; pyb_usb_storage_medium_t pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_NONE;
#endif #endif
@ -105,25 +107,37 @@ bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_H
#ifdef USE_DEVICE_MODE #ifdef USE_DEVICE_MODE
if (!(pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED)) { if (!(pyb_usb_flags & PYB_USB_FLAG_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(vid, pid, 0x0200, mode == USBD_MODE_CDC); USBD_SetVIDPIDRelease(vid, pid, 0x0200, mode == USBD_MODE_CDC);
if (USBD_SelectMode(mode, hid_info) != 0) { if (USBD_SelectMode(mode, hid_info) != 0) {
return false; return false;
} }
USBD_Init(&hUSBDDevice, (USBD_DescriptorsTypeDef*)&USBD_Descriptors, USB_PHY_ID);
USBD_RegisterClass(&hUSBDDevice, &USBD_CDC_MSC_HID); // set up the USBD state
USBD_CDC_RegisterInterface(&hUSBDDevice, (USBD_CDC_ItfTypeDef*)&USBD_CDC_fops); USBD_HandleTypeDef *usbd = &hUSBDDevice;
usbd->id = USB_PHY_ID;
usbd->dev_state = USBD_STATE_DEFAULT;
usbd->pDesc = (USBD_DescriptorsTypeDef*)&USBD_Descriptors;
usbd->pClass = &USBD_CDC_MSC_HID;
usbd_cdc_msc_hid_state.cdc = &usbd_cdc_itf;
usbd->pClassData = &usbd_cdc_msc_hid_state;
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:
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops); USBD_MSC_RegisterStorage(usbd, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops);
break; break;
#endif #endif
default: default:
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops); USBD_MSC_RegisterStorage(usbd, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops);
break; break;
} }
USBD_HID_RegisterInterface(&hUSBDDevice, (USBD_HID_ItfTypeDef*)&USBD_HID_fops); USBD_HID_RegisterInterface(usbd, (USBD_HID_ItfTypeDef*)&USBD_HID_fops);
USBD_Start(&hUSBDDevice);
// start the USB device
USBD_LL_Init(usbd);
USBD_LL_Start(usbd);
} }
pyb_usb_flags |= PYB_USB_FLAG_DEV_ENABLED; pyb_usb_flags |= PYB_USB_FLAG_DEV_ENABLED;
#endif #endif
@ -143,13 +157,13 @@ bool usb_vcp_is_enabled(void) {
} }
int usb_vcp_recv_byte(uint8_t *c) { int usb_vcp_recv_byte(uint8_t *c) {
return USBD_CDC_Rx(c, 1, 0); return usbd_cdc_rx(&usbd_cdc_itf, c, 1, 0);
} }
void usb_vcp_send_strn(const char *str, int len) { void usb_vcp_send_strn(const char *str, int len) {
#ifdef USE_DEVICE_MODE #ifdef USE_DEVICE_MODE
if (pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED) { if (pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED) {
USBD_CDC_TxAlways((const uint8_t*)str, len); usbd_cdc_tx_always(&usbd_cdc_itf, (const uint8_t*)str, len);
} }
#endif #endif
} }
@ -159,9 +173,9 @@ void usb_vcp_send_strn_cooked(const char *str, int len) {
if (pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED) { if (pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED) {
for (const char *top = str + len; str < top; str++) { for (const char *top = str + len; str < top; str++) {
if (*str == '\n') { if (*str == '\n') {
USBD_CDC_TxAlways((const uint8_t*)"\r\n", 2); usbd_cdc_tx_always(&usbd_cdc_itf, (const uint8_t*)"\r\n", 2);
} else { } else {
USBD_CDC_TxAlways((const uint8_t*)str, 1); usbd_cdc_tx_always(&usbd_cdc_itf, (const uint8_t*)str, 1);
} }
} }
} }
@ -362,7 +376,7 @@ STATIC mp_obj_t pyb_usb_vcp_setinterrupt(mp_obj_t self_in, mp_obj_t int_chr_in)
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_usb_vcp_setinterrupt_obj, pyb_usb_vcp_setinterrupt); STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_usb_vcp_setinterrupt_obj, pyb_usb_vcp_setinterrupt);
STATIC mp_obj_t pyb_usb_vcp_isconnected(mp_obj_t self_in) { STATIC mp_obj_t pyb_usb_vcp_isconnected(mp_obj_t self_in) {
return mp_obj_new_bool(USBD_CDC_IsConnected()); return mp_obj_new_bool(usbd_cdc_is_connected(&usbd_cdc_itf));
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_vcp_isconnected_obj, pyb_usb_vcp_isconnected); STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_vcp_isconnected_obj, pyb_usb_vcp_isconnected);
@ -375,7 +389,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc);
/// \method any() /// \method any()
/// Return `True` if any characters waiting, else `False`. /// Return `True` if any characters waiting, else `False`.
STATIC mp_obj_t pyb_usb_vcp_any(mp_obj_t self_in) { STATIC mp_obj_t pyb_usb_vcp_any(mp_obj_t self_in) {
if (USBD_CDC_RxNum() > 0) { if (usbd_cdc_rx_num(&usbd_cdc_itf) > 0) {
return mp_const_true; return mp_const_true;
} else { } else {
return mp_const_false; return mp_const_false;
@ -407,7 +421,7 @@ STATIC mp_obj_t pyb_usb_vcp_send(size_t n_args, const mp_obj_t *args, mp_map_t *
pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data); pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data);
// send the data // send the data
int ret = USBD_CDC_Tx(bufinfo.buf, bufinfo.len, vals[1].u_int); int ret = usbd_cdc_tx(&usbd_cdc_itf, bufinfo.buf, bufinfo.len, vals[1].u_int);
return mp_obj_new_int(ret); return mp_obj_new_int(ret);
} }
@ -433,7 +447,7 @@ STATIC mp_obj_t pyb_usb_vcp_recv(size_t n_args, const mp_obj_t *args, mp_map_t *
mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr); mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr);
// receive the data // receive the data
int ret = USBD_CDC_Rx((uint8_t*)vstr.buf, vstr.len, vals[1].u_int); int ret = usbd_cdc_rx(&usbd_cdc_itf, (uint8_t*)vstr.buf, vstr.len, vals[1].u_int);
// return the received data // return the received data
if (o_ret != MP_OBJ_NULL) { if (o_ret != MP_OBJ_NULL) {
@ -470,7 +484,7 @@ STATIC const mp_rom_map_elem_t pyb_usb_vcp_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table); STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table);
STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
int ret = USBD_CDC_Rx((byte*)buf, size, 0); int ret = usbd_cdc_rx(&usbd_cdc_itf, (byte*)buf, size, 0);
if (ret == 0) { if (ret == 0) {
// return EAGAIN error to indicate non-blocking // return EAGAIN error to indicate non-blocking
*errcode = MP_EAGAIN; *errcode = MP_EAGAIN;
@ -480,7 +494,7 @@ STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, i
} }
STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
int ret = USBD_CDC_Tx((const byte*)buf, size, 0); int ret = usbd_cdc_tx(&usbd_cdc_itf, (const byte*)buf, size, 0);
if (ret == 0) { if (ret == 0) {
// return EAGAIN error to indicate non-blocking // return EAGAIN error to indicate non-blocking
*errcode = MP_EAGAIN; *errcode = MP_EAGAIN;
@ -494,10 +508,10 @@ STATIC mp_uint_t pyb_usb_vcp_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_
if (request == MP_STREAM_POLL) { if (request == MP_STREAM_POLL) {
mp_uint_t flags = arg; mp_uint_t flags = arg;
ret = 0; ret = 0;
if ((flags & MP_STREAM_POLL_RD) && USBD_CDC_RxNum() > 0) { if ((flags & MP_STREAM_POLL_RD) && usbd_cdc_rx_num(&usbd_cdc_itf) > 0) {
ret |= MP_STREAM_POLL_RD; ret |= MP_STREAM_POLL_RD;
} }
if ((flags & MP_STREAM_POLL_WR) && USBD_CDC_TxHalfEmpty()) { if ((flags & MP_STREAM_POLL_WR) && usbd_cdc_tx_half_empty(&usbd_cdc_itf)) {
ret |= MP_STREAM_POLL_WR; ret |= MP_STREAM_POLL_WR;
} }
} else { } else {

View File

@ -41,12 +41,9 @@
#include "usbd_cdc_interface.h" #include "usbd_cdc_interface.h"
#include "pendsv.h" #include "pendsv.h"
#include "py/mpstate.h"
#include "py/obj.h" #include "py/obj.h"
#include "lib/utils/interrupt_char.h" #include "lib/utils/interrupt_char.h"
#include "irq.h" #include "irq.h"
#include "timer.h"
#include "usb.h"
// CDC control commands // CDC control commands
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00 #define CDC_SEND_ENCAPSULATED_COMMAND 0x00
@ -59,78 +56,26 @@
#define CDC_SET_CONTROL_LINE_STATE 0x22 #define CDC_SET_CONTROL_LINE_STATE 0x22
#define CDC_SEND_BREAK 0x23 #define CDC_SEND_BREAK 0x23
/* Private typedef -----------------------------------------------------------*/ void usbd_cdc_init(usbd_cdc_itf_t *cdc, USBD_HandleTypeDef *pdev) {
/* Private define ------------------------------------------------------------*/ cdc->usb = pdev;
#define APP_RX_DATA_SIZE 1024 // this must be 2 or greater, and a power of 2 cdc->rx_buf_put = 0;
#define APP_TX_DATA_SIZE 1024 // I think this can be any value (was 2048) cdc->rx_buf_get = 0;
cdc->tx_buf_ptr_in = 0;
/* Private macro -------------------------------------------------------------*/ cdc->tx_buf_ptr_out = 0;
/* Private variables ---------------------------------------------------------*/ cdc->tx_buf_ptr_out_shadow = 0;
cdc->tx_buf_ptr_wait_count = 0;
static __IO uint8_t dev_is_connected = 0; // indicates if we are connected cdc->tx_need_empty_packet = 0;
cdc->dev_is_connected = 0;
static uint8_t cdc_rx_packet_buf[CDC_DATA_FS_MAX_PACKET_SIZE]; // received data from USB OUT endpoint is stored in this buffer USBD_CDC_SetTxBuffer(pdev, cdc->tx_buf, 0);
static uint8_t cdc_rx_user_buf[APP_RX_DATA_SIZE]; // received data is buffered here until the user reads it USBD_CDC_SetRxBuffer(pdev, cdc->rx_packet_buf);
static volatile uint16_t cdc_rx_buf_put = 0; // circular buffer index
static uint16_t cdc_rx_buf_get = 0; // circular buffer index
static uint8_t UserTxBuffer[APP_TX_DATA_SIZE]; // data for USB IN endpoind is stored in this buffer
static uint16_t UserTxBufPtrIn = 0; // increment this pointer modulo APP_TX_DATA_SIZE when new data is available
static __IO uint16_t UserTxBufPtrOut = 0; // increment this pointer modulo APP_TX_DATA_SIZE when data is drained
static uint16_t UserTxBufPtrOutShadow = 0; // shadow of above
static uint8_t UserTxBufPtrWaitCount = 0; // used to implement a timeout waiting for low-level USB driver
static uint8_t UserTxNeedEmptyPacket = 0; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
/* Private function prototypes -----------------------------------------------*/
static int8_t CDC_Itf_Init (USBD_HandleTypeDef *pdev);
static int8_t CDC_Itf_DeInit (void);
static int8_t CDC_Itf_Control (uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Itf_Receive (USBD_HandleTypeDef *pdev, uint8_t* pbuf, uint32_t *Len);
const USBD_CDC_ItfTypeDef USBD_CDC_fops = {
CDC_Itf_Init,
CDC_Itf_DeInit,
CDC_Itf_Control,
CDC_Itf_Receive
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief CDC_Itf_Init
* Initializes the CDC media low layer
* @param None
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Itf_Init(USBD_HandleTypeDef *pdev) {
USBD_CDC_SetTxBuffer(pdev, UserTxBuffer, 0);
USBD_CDC_SetRxBuffer(pdev, cdc_rx_packet_buf);
cdc_rx_buf_put = 0;
cdc_rx_buf_get = 0;
return USBD_OK;
} }
/** // Manage the CDC class requests
* @brief CDC_Itf_DeInit // cmd: command code
* DeInitializes the CDC media low layer // pbuf: buffer containing command data (request parameters)
* @param None // length: number of data to be sent (in bytes)
* @retval Result of the opeartion: 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) {
static int8_t CDC_Itf_DeInit(void) {
return USBD_OK;
}
/**
* @brief CDC_Itf_Control
* Manage the CDC class requests
* @param Cmd: Command code
* @param Buf: Buffer containing command data (request parameters)
* @param Len: Number of data to be sent (in bytes)
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL
*/
static int8_t CDC_Itf_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length) {
switch (cmd) { switch (cmd) {
case CDC_SEND_ENCAPSULATED_COMMAND: case CDC_SEND_ENCAPSULATED_COMMAND:
/* Add your code here */ /* Add your code here */
@ -175,7 +120,7 @@ static int8_t CDC_Itf_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length) {
break; break;
case CDC_SET_CONTROL_LINE_STATE: case CDC_SET_CONTROL_LINE_STATE:
dev_is_connected = length & 1; // wValue is passed in Len (bit of a hack) cdc->dev_is_connected = length & 1; // wValue is passed in Len (bit of a hack)
break; break;
case CDC_SEND_BREAK: case CDC_SEND_BREAK:
@ -193,53 +138,56 @@ static int8_t CDC_Itf_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length) {
// SOF (start of frame) callback so that it is called exactly at the time it is // SOF (start of frame) callback so that it is called exactly at the time it is
// 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) {
if (!dev_is_connected) { usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData;
usbd_cdc_itf_t *cdc = 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 // CDC device is not connected to a host, so we are unable to send any data
return; return;
} }
if (UserTxBufPtrOut == UserTxBufPtrIn && !UserTxNeedEmptyPacket) { if (cdc->tx_buf_ptr_out == cdc->tx_buf_ptr_in && !cdc->tx_need_empty_packet) {
// No outstanding data to send // No outstanding data to send
return; return;
} }
if (UserTxBufPtrOut != UserTxBufPtrOutShadow) { if (cdc->tx_buf_ptr_out != cdc->tx_buf_ptr_out_shadow) {
// We have sent data and are waiting for the low-level USB driver to // We have sent data and are waiting for the low-level USB driver to
// finish sending it over the USB in-endpoint. // finish sending it over the USB in-endpoint.
// SOF occurs every 1ms, so we have a 500 * 1ms = 500ms timeout // SOF occurs every 1ms, so we have a 500 * 1ms = 500ms timeout
// We have a relatively large timeout because the USB host may be busy // We have a relatively large timeout because the USB host may be busy
// doing other things and we must give it a chance to read our data. // doing other things and we must give it a chance to read our data.
if (UserTxBufPtrWaitCount < 500) { if (cdc->tx_buf_ptr_wait_count < 500) {
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
if (USBx_INEP(CDC_IN_EP & 0x7f)->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ) { if (USBx_INEP(CDC_IN_EP & 0x7f)->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ) {
// USB in-endpoint is still reading the data // USB in-endpoint is still reading the data
UserTxBufPtrWaitCount++; cdc->tx_buf_ptr_wait_count++;
return; return;
} }
} }
UserTxBufPtrOut = UserTxBufPtrOutShadow; cdc->tx_buf_ptr_out = cdc->tx_buf_ptr_out_shadow;
} }
if (UserTxBufPtrOutShadow != UserTxBufPtrIn || UserTxNeedEmptyPacket) { if (cdc->tx_buf_ptr_out_shadow != cdc->tx_buf_ptr_in || cdc->tx_need_empty_packet) {
uint32_t buffptr; uint32_t buffptr;
uint32_t buffsize; uint32_t buffsize;
if (UserTxBufPtrOutShadow > UserTxBufPtrIn) { // rollback if (cdc->tx_buf_ptr_out_shadow > cdc->tx_buf_ptr_in) { // rollback
buffsize = APP_TX_DATA_SIZE - UserTxBufPtrOutShadow; buffsize = USBD_CDC_TX_DATA_SIZE - cdc->tx_buf_ptr_out_shadow;
} else { } else {
buffsize = UserTxBufPtrIn - UserTxBufPtrOutShadow; buffsize = cdc->tx_buf_ptr_in - cdc->tx_buf_ptr_out_shadow;
} }
buffptr = UserTxBufPtrOutShadow; buffptr = cdc->tx_buf_ptr_out_shadow;
USBD_CDC_SetTxBuffer(hpcd->pData, (uint8_t*)&UserTxBuffer[buffptr], buffsize); USBD_CDC_SetTxBuffer(hpcd->pData, (uint8_t*)&cdc->tx_buf[buffptr], buffsize);
if (USBD_CDC_TransmitPacket(hpcd->pData) == USBD_OK) { if (USBD_CDC_TransmitPacket(hpcd->pData) == USBD_OK) {
UserTxBufPtrOutShadow += buffsize; cdc->tx_buf_ptr_out_shadow += buffsize;
if (UserTxBufPtrOutShadow == APP_TX_DATA_SIZE) { if (cdc->tx_buf_ptr_out_shadow == USBD_CDC_TX_DATA_SIZE) {
UserTxBufPtrOutShadow = 0; cdc->tx_buf_ptr_out_shadow = 0;
} }
UserTxBufPtrWaitCount = 0; cdc->tx_buf_ptr_wait_count = 0;
// According to the USB specification, a packet size of 64 bytes (CDC_DATA_FS_MAX_PACKET_SIZE) // According to the USB specification, a packet size of 64 bytes (CDC_DATA_FS_MAX_PACKET_SIZE)
// gets held at the USB host until the next packet is sent. This is because a // gets held at the USB host until the next packet is sent. This is because a
@ -247,62 +195,54 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
// the host waits for all data to arrive (ie, waits for a packet < max packet size). // the host waits for all data to arrive (ie, waits for a packet < max packet size).
// To flush a packet of exactly max packet size, we need to send a zero-size packet. // To flush a packet of exactly max packet size, we need to send a zero-size packet.
// See eg http://www.cypress.com/?id=4&rID=92719 // See eg http://www.cypress.com/?id=4&rID=92719
UserTxNeedEmptyPacket = (buffsize > 0 && buffsize % CDC_DATA_FS_MAX_PACKET_SIZE == 0 && UserTxBufPtrOutShadow == UserTxBufPtrIn); cdc->tx_need_empty_packet = (buffsize > 0 && buffsize % CDC_DATA_FS_MAX_PACKET_SIZE == 0 && cdc->tx_buf_ptr_out_shadow == cdc->tx_buf_ptr_in);
} }
} }
} }
/** // Data received over USB OUT endpoint is processed here.
* @brief CDC_Itf_DataRx // Buf: buffer of data received
* Data received over USB OUT endpoint is processed here. // Len: number of data received (in bytes)
* @param Buf: Buffer of data received // Returns USBD_OK if all operations are OK else USBD_FAIL
* @param Len: Number of data received (in bytes) // The buffer we are passed here is just cdc_rx_packet_buf, so we are free to modify it.
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL int8_t usbd_cdc_receive(usbd_cdc_itf_t *cdc, uint8_t* Buf, uint32_t *Len) {
* @note The buffer we are passed here is just cdc_rx_packet_buf, so we are
* free to modify it.
*/
static int8_t CDC_Itf_Receive(USBD_HandleTypeDef *pdev, uint8_t* Buf, uint32_t *Len) {
// copy the incoming data into the circular buffer // copy the incoming data into the circular buffer
for (uint8_t *src = Buf, *top = Buf + *Len; src < top; ++src) { for (uint8_t *src = Buf, *top = Buf + *Len; src < top; ++src) {
if (mp_interrupt_char != -1 && *src == mp_interrupt_char) { if (mp_interrupt_char != -1 && *src == mp_interrupt_char) {
pendsv_kbd_intr(); pendsv_kbd_intr();
} else { } else {
uint16_t next_put = (cdc_rx_buf_put + 1) & (APP_RX_DATA_SIZE - 1); uint16_t next_put = (cdc->rx_buf_put + 1) & (USBD_CDC_RX_DATA_SIZE - 1);
if (next_put == cdc_rx_buf_get) { if (next_put == cdc->rx_buf_get) {
// overflow, we just discard the rest of the chars // overflow, we just discard the rest of the chars
break; break;
} }
cdc_rx_user_buf[cdc_rx_buf_put] = *src; cdc->rx_user_buf[cdc->rx_buf_put] = *src;
cdc_rx_buf_put = next_put; cdc->rx_buf_put = next_put;
} }
} }
// initiate next USB packet transfer // initiate next USB packet transfer
USBD_CDC_SetRxBuffer(pdev, cdc_rx_packet_buf); USBD_CDC_SetRxBuffer(cdc->usb, cdc->rx_packet_buf);
USBD_CDC_ReceivePacket(pdev); USBD_CDC_ReceivePacket(cdc->usb);
return USBD_OK; return USBD_OK;
} }
int USBD_CDC_IsConnected(void) { int usbd_cdc_tx_half_empty(usbd_cdc_itf_t *cdc) {
return dev_is_connected; int32_t tx_waiting = (int32_t)cdc->tx_buf_ptr_in - (int32_t)cdc->tx_buf_ptr_out;
}
int USBD_CDC_TxHalfEmpty(void) {
int32_t tx_waiting = (int32_t)UserTxBufPtrIn - (int32_t)UserTxBufPtrOut;
if (tx_waiting < 0) { if (tx_waiting < 0) {
tx_waiting += APP_TX_DATA_SIZE; tx_waiting += USBD_CDC_TX_DATA_SIZE;
} }
return tx_waiting <= APP_TX_DATA_SIZE / 2; return tx_waiting <= USBD_CDC_TX_DATA_SIZE / 2;
} }
// timout in milliseconds. // timout in milliseconds.
// Returns number of bytes written to the device. // Returns number of bytes written to the device.
int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout) { int usbd_cdc_tx(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len, uint32_t timeout) {
for (uint32_t i = 0; i < len; i++) { for (uint32_t i = 0; i < len; i++) {
// Wait until the device is connected and the buffer has space, with a given timeout // Wait until the device is connected and the buffer has space, with a given timeout
uint32_t start = HAL_GetTick(); uint32_t start = HAL_GetTick();
while (!dev_is_connected || ((UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1)) == UserTxBufPtrOut) { while (!cdc->dev_is_connected || ((cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1)) == cdc->tx_buf_ptr_out) {
// Wraparound of tick is taken care of by 2's complement arithmetic. // Wraparound of tick is taken care of by 2's complement arithmetic.
if (HAL_GetTick() - start >= timeout) { if (HAL_GetTick() - start >= timeout) {
// timeout // timeout
@ -316,8 +256,8 @@ int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout) {
} }
// Write data to device buffer // Write data to device buffer
UserTxBuffer[UserTxBufPtrIn] = buf[i]; cdc->tx_buf[cdc->tx_buf_ptr_in] = buf[i];
UserTxBufPtrIn = (UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1); cdc->tx_buf_ptr_in = (cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1);
} }
// Success, return number of bytes read // Success, return number of bytes read
@ -327,18 +267,18 @@ int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout) {
// Always write all of the data to the device tx buffer, even if the // Always write all of the data to the device tx buffer, even if the
// device is not connected, or if the buffer is full. Has a small timeout // device is not connected, or if the buffer is full. Has a small timeout
// to wait for the buffer to be drained, in the case the device is connected. // to wait for the buffer to be drained, in the case the device is connected.
void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len) { void usbd_cdc_tx_always(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len) {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
// If the CDC device is not connected to the host then we don't have anyone to receive our data. // If the CDC device is not connected to the host then we don't have anyone to receive our data.
// The device may become connected in the future, so we should at least try to fill the buffer // The device may become connected in the future, so we should at least try to fill the buffer
// and hope that it doesn't overflow by the time the device connects. // and hope that it doesn't overflow by the time the device connects.
// If the device is not connected then we should go ahead and fill the buffer straight away, // If the device is not connected then we should go ahead and fill the buffer straight away,
// ignoring overflow. Otherwise, we should make sure that we have enough room in the buffer. // ignoring overflow. Otherwise, we should make sure that we have enough room in the buffer.
if (dev_is_connected) { if (cdc->dev_is_connected) {
// If the buffer is full, wait until it gets drained, with a timeout of 500ms // If the buffer is full, wait until it gets drained, with a timeout of 500ms
// (wraparound of tick is taken care of by 2's complement arithmetic). // (wraparound of tick is taken care of by 2's complement arithmetic).
uint32_t start = HAL_GetTick(); uint32_t start = HAL_GetTick();
while (((UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1)) == UserTxBufPtrOut && HAL_GetTick() - start <= 500) { while (((cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1)) == cdc->tx_buf_ptr_out && HAL_GetTick() - start <= 500) {
if (query_irq() == IRQ_STATE_DISABLED) { if (query_irq() == IRQ_STATE_DISABLED) {
// IRQs disabled so buffer will never be drained; exit loop // IRQs disabled so buffer will never be drained; exit loop
break; break;
@ -365,28 +305,28 @@ void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len) {
*/ */
} }
UserTxBuffer[UserTxBufPtrIn] = buf[i]; cdc->tx_buf[cdc->tx_buf_ptr_in] = buf[i];
UserTxBufPtrIn = (UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1); cdc->tx_buf_ptr_in = (cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1);
} }
} }
// Returns number of bytes in the rx buffer. // Returns number of bytes in the rx buffer.
int USBD_CDC_RxNum(void) { int usbd_cdc_rx_num(usbd_cdc_itf_t *cdc) {
int32_t rx_waiting = (int32_t)cdc_rx_buf_put - (int32_t)cdc_rx_buf_get; int32_t rx_waiting = (int32_t)cdc->rx_buf_put - (int32_t)cdc->rx_buf_get;
if (rx_waiting < 0) { if (rx_waiting < 0) {
rx_waiting += APP_RX_DATA_SIZE; rx_waiting += USBD_CDC_RX_DATA_SIZE;
} }
return rx_waiting; return rx_waiting;
} }
// timout in milliseconds. // timout in milliseconds.
// Returns number of bytes read from the device. // Returns number of bytes read from the device.
int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout) { int usbd_cdc_rx(usbd_cdc_itf_t *cdc, uint8_t *buf, uint32_t len, uint32_t timeout) {
// loop to read bytes // loop to read bytes
for (uint32_t i = 0; i < len; i++) { for (uint32_t i = 0; i < len; i++) {
// Wait until we have at least 1 byte to read // Wait until we have at least 1 byte to read
uint32_t start = HAL_GetTick(); uint32_t start = HAL_GetTick();
while (cdc_rx_buf_put == cdc_rx_buf_get) { while (cdc->rx_buf_put == cdc->rx_buf_get) {
// Wraparound of tick is taken care of by 2's complement arithmetic. // Wraparound of tick is taken care of by 2's complement arithmetic.
if (HAL_GetTick() - start >= timeout) { if (HAL_GetTick() - start >= timeout) {
// timeout // timeout
@ -400,8 +340,8 @@ int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout) {
} }
// Copy byte from device to user buffer // Copy byte from device to user buffer
buf[i] = cdc_rx_user_buf[cdc_rx_buf_get]; buf[i] = cdc->rx_user_buf[cdc->rx_buf_get];
cdc_rx_buf_get = (cdc_rx_buf_get + 1) & (APP_RX_DATA_SIZE - 1); cdc->rx_buf_get = (cdc->rx_buf_get + 1) & (USBD_CDC_RX_DATA_SIZE - 1);
} }
// Success, return number of bytes read // Success, return number of bytes read

View File

@ -1,45 +1,66 @@
/* /*
* This file is part of the MicroPython project, http://micropython.org/ * This file is part of the MicroPython project, http://micropython.org/
*/ */
#ifndef MICROPY_INCLUDED_STMHAL_USBD_CDC_INTERFACE_H #ifndef MICROPY_INCLUDED_STMHAL_USBD_CDC_INTERFACE_H
#define MICROPY_INCLUDED_STMHAL_USBD_CDC_INTERFACE_H #define MICROPY_INCLUDED_STMHAL_USBD_CDC_INTERFACE_H
/** /**
****************************************************************************** ******************************************************************************
* @file USB_Device/CDC_Standalone/Inc/usbd_cdc_interface.h * @file USB_Device/CDC_Standalone/Inc/usbd_cdc_interface.h
* @author MCD Application Team * @author MCD Application Team
* @version V1.0.1 * @version V1.0.1
* @date 26-February-2014 * @date 26-February-2014
* @brief Header for usbd_cdc_interface.c file. * @brief Header for usbd_cdc_interface.c file.
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2> * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
* *
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License. * You may not use this file except in compliance with the License.
* You may obtain a copy of the License at: * You may obtain a copy of the License at:
* *
* http://www.st.com/software_license_agreement_liberty_v2 * http://www.st.com/software_license_agreement_liberty_v2
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
****************************************************************************** ******************************************************************************
*/ */
extern const USBD_CDC_ItfTypeDef USBD_CDC_fops; #define USBD_CDC_RX_DATA_SIZE (1024) // this must be 2 or greater, and a power of 2
#define USBD_CDC_TX_DATA_SIZE (1024) // I think this can be any value (was 2048)
int USBD_CDC_IsConnected(void);
typedef struct _usbd_cdc_itf_t {
int USBD_CDC_TxHalfEmpty(void); USBD_HandleTypeDef *usb; // the parent USB device
int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout);
void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len); uint8_t rx_packet_buf[CDC_DATA_FS_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
int USBD_CDC_RxNum(void); volatile uint16_t rx_buf_put; // circular buffer index
int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout); uint16_t rx_buf_get; // circular buffer index
#endif // MICROPY_INCLUDED_STMHAL_USBD_CDC_INTERFACE_H uint8_t tx_buf[USBD_CDC_TX_DATA_SIZE]; // data for USB IN endpoind is stored in this buffer
uint16_t tx_buf_ptr_in; // increment this pointer modulo APP_TX_DATA_SIZE when new data is available
volatile uint16_t tx_buf_ptr_out; // increment this pointer modulo APP_TX_DATA_SIZE when data is drained
uint16_t tx_buf_ptr_out_shadow; // shadow of above
uint8_t tx_buf_ptr_wait_count; // used to implement a timeout waiting for low-level USB driver
uint8_t tx_need_empty_packet; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
volatile uint8_t dev_is_connected; // indicates if we are connected
} usbd_cdc_itf_t;
static inline int usbd_cdc_is_connected(usbd_cdc_itf_t *cdc) {
return cdc->dev_is_connected;
}
int usbd_cdc_tx_half_empty(usbd_cdc_itf_t *cdc);
int usbd_cdc_tx(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len, uint32_t timeout);
void usbd_cdc_tx_always(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len);
int usbd_cdc_rx_num(usbd_cdc_itf_t *cdc);
int usbd_cdc_rx(usbd_cdc_itf_t *cdc, uint8_t *buf, uint32_t len, uint32_t timeout);
#endif // MICROPY_INCLUDED_STMHAL_USBD_CDC_INTERFACE_H

View File

@ -27,13 +27,6 @@ typedef struct {
uint8_t datatype; uint8_t datatype;
} USBD_CDC_LineCodingTypeDef; } USBD_CDC_LineCodingTypeDef;
typedef struct _USBD_CDC_Itf {
int8_t (* Init) (USBD_HandleTypeDef *pdev);
int8_t (* DeInit) (void);
int8_t (* Control) (uint8_t, uint8_t * , uint16_t);
int8_t (* Receive) (USBD_HandleTypeDef *pdev, uint8_t *, uint32_t *);
} USBD_CDC_ItfTypeDef;
typedef struct { typedef struct {
uint32_t data[CDC_DATA_FS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */ uint32_t data[CDC_DATA_FS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */
uint8_t CmdOpCode; uint8_t CmdOpCode;
@ -86,6 +79,12 @@ typedef struct {
uint32_t scsi_blk_len; uint32_t scsi_blk_len;
} USBD_MSC_BOT_HandleTypeDef; } USBD_MSC_BOT_HandleTypeDef;
typedef struct _usbd_cdc_msc_hid_state_t {
void *cdc;
void *msc;
void *hid;
} usbd_cdc_msc_hid_state_t;
#define USBD_HID_MOUSE_MAX_PACKET (4) #define USBD_HID_MOUSE_MAX_PACKET (4)
#define USBD_HID_MOUSE_REPORT_DESC_SIZE (74) #define USBD_HID_MOUSE_REPORT_DESC_SIZE (74)
@ -103,7 +102,6 @@ int USBD_SelectMode(uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info);
// returns the current usb mode // returns the current usb mode
uint8_t USBD_GetMode(); uint8_t USBD_GetMode();
uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, USBD_CDC_ItfTypeDef *fops);
uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint16_t length); uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint16_t length);
uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff); uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff);
uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev); uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev);
@ -119,4 +117,10 @@ uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t
uint8_t USBD_HID_SetNAK(USBD_HandleTypeDef *pdev); uint8_t USBD_HID_SetNAK(USBD_HandleTypeDef *pdev);
uint8_t USBD_HID_ClearNAK(USBD_HandleTypeDef *pdev); uint8_t USBD_HID_ClearNAK(USBD_HandleTypeDef *pdev);
// These are provided externally to implement the CDC interface
struct _usbd_cdc_itf_t;
void usbd_cdc_init(struct _usbd_cdc_itf_t *cdc, USBD_HandleTypeDef *pdev);
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, uint8_t* Buf, uint32_t *Len);
#endif // _USB_CDC_MSC_CORE_H_ #endif // _USB_CDC_MSC_CORE_H_

View File

@ -95,7 +95,6 @@ static uint8_t usbd_config_desc_size;
static uint8_t *hid_desc; static uint8_t *hid_desc;
static const uint8_t *hid_report_desc; static const uint8_t *hid_report_desc;
static USBD_CDC_ItfTypeDef *CDC_fops;
static USBD_StorageTypeDef *MSC_fops; static USBD_StorageTypeDef *MSC_fops;
static USBD_HID_ItfTypeDef *HID_fops; static USBD_HID_ItfTypeDef *HID_fops;
@ -647,6 +646,8 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
return 1; return 1;
} }
usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
if (usbd_mode & USBD_MODE_CDC) { if (usbd_mode & USBD_MODE_CDC) {
// CDC VCP component // CDC VCP component
@ -669,7 +670,7 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
CDC_CMD_PACKET_SIZE); CDC_CMD_PACKET_SIZE);
// Init physical Interface components // Init physical Interface components
CDC_fops->Init(pdev); usbd_cdc_init(state->cdc, pdev);
// Init Xfer states // Init Xfer states
CDC_ClassData.TxState =0; CDC_ClassData.TxState =0;
@ -694,8 +695,8 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
USBD_EP_TYPE_BULK, USBD_EP_TYPE_BULK,
MSC_MAX_PACKET); MSC_MAX_PACKET);
// MSC uses the pClassData pointer because SCSI and BOT reference it // Set the MSC data for SCSI and BOT to reference it
pdev->pClassData = &MSC_BOT_ClassData; state->msc = &MSC_BOT_ClassData;
// Init the BOT layer // Init the BOT layer
MSC_BOT_Init(pdev); MSC_BOT_Init(pdev);
@ -736,19 +737,18 @@ static uint8_t USBD_CDC_MSC_HID_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
} }
static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) { static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
if (usbd_mode & USBD_MODE_CDC) { usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
if ((usbd_mode & USBD_MODE_CDC) && state->cdc) {
// CDC VCP component // CDC VCP component
// close endpoints // close endpoints
USBD_LL_CloseEP(pdev, CDC_IN_EP); USBD_LL_CloseEP(pdev, CDC_IN_EP);
USBD_LL_CloseEP(pdev, CDC_OUT_EP); USBD_LL_CloseEP(pdev, CDC_OUT_EP);
USBD_LL_CloseEP(pdev, CDC_CMD_EP); USBD_LL_CloseEP(pdev, CDC_CMD_EP);
// DeInit physical Interface components
CDC_fops->DeInit();
} }
if (usbd_mode & USBD_MODE_MSC) { if ((usbd_mode & USBD_MODE_MSC) && state->msc) {
// MSC component // MSC component
// close endpoints // close endpoints
@ -758,8 +758,8 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
// DeInit the BOT layer // DeInit the BOT layer
MSC_BOT_DeInit(pdev); MSC_BOT_DeInit(pdev);
// clear the pointer // clear the state pointer
pdev->pClassData = NULL; state->msc = NULL;
} }
if (usbd_mode & USBD_MODE_HID) { if (usbd_mode & USBD_MODE_HID) {
@ -791,6 +791,8 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
SU: 21 20 0 1 SU: 21 20 0 1
*/ */
usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
switch (req->bmRequest & USB_REQ_TYPE_MASK) { switch (req->bmRequest & USB_REQ_TYPE_MASK) {
// Class request // Class request
@ -801,7 +803,7 @@ 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
CDC_fops->Control(req->bRequest, (uint8_t*)CDC_ClassData.data, req->wLength); usbd_cdc_control(state->cdc, req->bRequest, (uint8_t*)CDC_ClassData.data, req->wLength);
USBD_CtlSendData(pdev, (uint8_t*)CDC_ClassData.data, req->wLength); USBD_CtlSendData(pdev, (uint8_t*)CDC_ClassData.data, req->wLength);
} else { } else {
// host-to-device request // host-to-device request
@ -812,7 +814,7 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
} else { } else {
// Not a Data request // Not a Data request
// Transfer the command to the interface layer // Transfer the command to the interface layer
return CDC_fops->Control(req->bRequest, NULL, req->wValue); return usbd_cdc_control(state->cdc, req->bRequest, NULL, req->wValue);
} }
} else if ((usbd_mode & USBD_MODE_MSC) && req->wIndex == MSC_IFACE_NUM_WITH_CDC) { } else if ((usbd_mode & USBD_MODE_MSC) && req->wIndex == MSC_IFACE_NUM_WITH_CDC) {
// MSC component // MSC component
@ -931,8 +933,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) {
if ((CDC_fops != NULL) && (CDC_ClassData.CmdOpCode != 0xff)) { usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
CDC_fops->Control(CDC_ClassData.CmdOpCode, (uint8_t*)CDC_ClassData.data, CDC_ClassData.CmdLength); if (state->cdc != NULL && CDC_ClassData.CmdOpCode != 0xff) {
usbd_cdc_control(state->cdc, CDC_ClassData.CmdOpCode, (uint8_t*)CDC_ClassData.data, CDC_ClassData.CmdLength);
CDC_ClassData.CmdOpCode = 0xff; CDC_ClassData.CmdOpCode = 0xff;
} }
@ -957,13 +960,14 @@ static uint8_t USBD_CDC_MSC_HID_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
} }
static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) { static uint8_t USBD_CDC_MSC_HID_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum) {
usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
if ((usbd_mode & USBD_MODE_CDC) && epnum == (CDC_OUT_EP & 0x7f)) { if ((usbd_mode & USBD_MODE_CDC) && epnum == (CDC_OUT_EP & 0x7f)) {
/* Get the received data length */ /* Get the received data length */
CDC_ClassData.RxLength = USBD_LL_GetRxDataSize (pdev, epnum); CDC_ClassData.RxLength = USBD_LL_GetRxDataSize (pdev, epnum);
/* USB data will be immediately processed, this allow next USB traffic being /* USB data will be immediately processed, this allow next USB traffic being
NAKed till the end of the application Xfer */ NAKed till the end of the application Xfer */
CDC_fops->Receive(pdev, CDC_ClassData.RxBuffer, &CDC_ClassData.RxLength); usbd_cdc_receive(state->cdc, CDC_ClassData.RxBuffer, &CDC_ClassData.RxLength);
return USBD_OK; return USBD_OK;
} else if ((usbd_mode & USBD_MODE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) { } else if ((usbd_mode & USBD_MODE_MSC) && epnum == (MSC_OUT_EP & 0x7f)) {
@ -992,15 +996,6 @@ uint8_t *USBD_CDC_MSC_HID_GetDeviceQualifierDescriptor (uint16_t *length) {
return NULL; return NULL;
} }
uint8_t USBD_CDC_RegisterInterface(USBD_HandleTypeDef *pdev, USBD_CDC_ItfTypeDef *fops) {
if (fops == NULL) {
return USBD_FAIL;
} else {
CDC_fops = fops;
return USBD_OK;
}
}
uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint16_t length) { uint8_t USBD_CDC_SetTxBuffer(USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint16_t length) {
CDC_ClassData.TxBuffer = pbuff; CDC_ClassData.TxBuffer = pbuff;
CDC_ClassData.TxLength = length; CDC_ClassData.TxLength = length;

View File

@ -104,7 +104,7 @@ static void MSC_BOT_Abort(USBD_HandleTypeDef *pdev);
*/ */
void MSC_BOT_Init (USBD_HandleTypeDef *pdev) void MSC_BOT_Init (USBD_HandleTypeDef *pdev)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->bot_state = USBD_BOT_IDLE; hmsc->bot_state = USBD_BOT_IDLE;
hmsc->bot_status = USBD_BOT_STATUS_NORMAL; hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
@ -132,7 +132,7 @@ void MSC_BOT_Init (USBD_HandleTypeDef *pdev)
*/ */
void MSC_BOT_Reset (USBD_HandleTypeDef *pdev) void MSC_BOT_Reset (USBD_HandleTypeDef *pdev)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->bot_state = USBD_BOT_IDLE; hmsc->bot_state = USBD_BOT_IDLE;
hmsc->bot_status = USBD_BOT_STATUS_RECOVERY; hmsc->bot_status = USBD_BOT_STATUS_RECOVERY;
@ -152,7 +152,7 @@ void MSC_BOT_Reset (USBD_HandleTypeDef *pdev)
*/ */
void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev) void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->bot_state = USBD_BOT_IDLE; hmsc->bot_state = USBD_BOT_IDLE;
} }
@ -166,7 +166,7 @@ void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev)
void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev, void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum) uint8_t epnum)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
switch (hmsc->bot_state) switch (hmsc->bot_state)
{ {
@ -199,7 +199,7 @@ void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev,
void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev, void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum) uint8_t epnum)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
switch (hmsc->bot_state) switch (hmsc->bot_state)
{ {
@ -231,7 +231,7 @@ void MSC_BOT_DataOut (USBD_HandleTypeDef *pdev,
*/ */
static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev) static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef *pdev)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->csw.dTag = hmsc->cbw.dTag; hmsc->csw.dTag = hmsc->cbw.dTag;
hmsc->csw.dDataResidue = hmsc->cbw.dDataLength; hmsc->csw.dDataResidue = hmsc->cbw.dDataLength;
@ -300,7 +300,7 @@ static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev,
uint8_t* buf, uint8_t* buf,
uint16_t len) uint16_t len)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
len = MIN (hmsc->cbw.dDataLength, len); len = MIN (hmsc->cbw.dDataLength, len);
hmsc->csw.dDataResidue -= len; hmsc->csw.dDataResidue -= len;
@ -320,7 +320,7 @@ static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev,
void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev, void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev,
uint8_t CSW_Status) uint8_t CSW_Status)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE; hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE;
hmsc->csw.bStatus = CSW_Status; hmsc->csw.bStatus = CSW_Status;
@ -348,7 +348,7 @@ void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev,
static void MSC_BOT_Abort (USBD_HandleTypeDef *pdev) static void MSC_BOT_Abort (USBD_HandleTypeDef *pdev)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
if ((hmsc->cbw.bmFlags == 0) && if ((hmsc->cbw.bmFlags == 0) &&
(hmsc->cbw.dDataLength != 0) && (hmsc->cbw.dDataLength != 0) &&
@ -377,7 +377,7 @@ static void MSC_BOT_Abort (USBD_HandleTypeDef *pdev)
void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev, uint8_t epnum) void MSC_BOT_CplClrFeature (USBD_HandleTypeDef *pdev, uint8_t epnum)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
if(hmsc->bot_status == USBD_BOT_STATUS_ERROR )/* Bad CBW Signature */ if(hmsc->bot_status == USBD_BOT_STATUS_ERROR )/* Bad CBW Signature */
{ {

View File

@ -190,7 +190,7 @@ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
*/ */
static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
/* case 9 : Hi > D0 */ /* case 9 : Hi > D0 */
if (hmsc->cbw.dDataLength != 0) if (hmsc->cbw.dDataLength != 0)
@ -227,7 +227,7 @@ static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *par
{ {
uint8_t* pPage; uint8_t* pPage;
uint16_t len; uint16_t len;
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
if (params[1] & 0x01)/*Evpd is set*/ if (params[1] & 0x01)/*Evpd is set*/
{ {
@ -264,7 +264,7 @@ static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *par
*/ */
static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0) if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0)
{ {
@ -300,7 +300,7 @@ static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_
*/ */
static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
uint16_t blk_size; uint16_t blk_size;
uint32_t blk_nbr; uint32_t blk_nbr;
@ -345,7 +345,7 @@ static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, ui
*/ */
static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
uint16_t len = 8 ; uint16_t len = 8 ;
hmsc->bot_data_length = len; hmsc->bot_data_length = len;
@ -367,7 +367,7 @@ static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *
static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
{ {
uint16_t len = 8; uint16_t len = 8;
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->bot_data_length = len; hmsc->bot_data_length = len;
@ -381,7 +381,7 @@ static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t
static int8_t SCSI_SynchronizeCache(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) { static int8_t SCSI_SynchronizeCache(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) {
// nothing to synchronize, so just return "success" // nothing to synchronize, so just return "success"
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->bot_data_length = 0; hmsc->bot_data_length = 0;
return 0; return 0;
} }
@ -397,7 +397,7 @@ static int8_t SCSI_SynchronizeCache(USBD_HandleTypeDef *pdev, uint8_t lun, uint
static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
{ {
uint8_t i; uint8_t i;
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++) for(i=0 ; i < REQUEST_SENSE_DATA_LEN ; i++)
{ {
@ -439,7 +439,7 @@ static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t
*/ */
void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC) void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey; hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey;
hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8; hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8;
@ -458,7 +458,7 @@ void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_
*/ */
static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->bot_data_length = 0; hmsc->bot_data_length = 0;
// On Mac OS X, when the device is ejected a SCSI_START_STOP_UNIT command is sent. // On Mac OS X, when the device is ejected a SCSI_START_STOP_UNIT command is sent.
@ -479,7 +479,7 @@ static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t
*/ */
static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
hmsc->bot_data_length = 0; hmsc->bot_data_length = 0;
((USBD_StorageTypeDef *)pdev->pUserData)->PreventAllowMediumRemoval(lun, params[0]); ((USBD_StorageTypeDef *)pdev->pUserData)->PreventAllowMediumRemoval(lun, params[0]);
return 0; return 0;
@ -494,7 +494,7 @@ static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, ui
*/ */
static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ if(hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
{ {
@ -562,7 +562,7 @@ static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *para
static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */
{ {
@ -652,7 +652,7 @@ static int8_t SCSI_Write10 (USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *pa
static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params) static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
if ((params[1]& 0x02) == 0x02) if ((params[1]& 0x02) == 0x02)
{ {
@ -687,7 +687,7 @@ static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *pa
*/ */
static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr) static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , uint32_t blk_offset , uint16_t blk_nbr)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr ) if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr )
{ {
@ -708,7 +708,7 @@ static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef *pdev, uint8_t lun , u
*/ */
static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun) static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
{ {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
uint32_t len; uint32_t len;
len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET); len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);
@ -756,7 +756,7 @@ static int8_t SCSI_ProcessRead (USBD_HandleTypeDef *pdev, uint8_t lun)
static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun) static int8_t SCSI_ProcessWrite (USBD_HandleTypeDef *pdev, uint8_t lun)
{ {
uint32_t len; uint32_t len;
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData; USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET); len = MIN(hmsc->scsi_blk_len , MSC_MEDIA_PACKET);