stm32/usbdev: Put all CDC state in a struct.
This commit is contained in:
parent
ede8a0235b
commit
980b33177b
@ -55,6 +55,8 @@ mp_uint_t pyb_usb_flags = 0;
|
||||
|
||||
#ifdef USE_DEVICE_MODE
|
||||
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;
|
||||
#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
|
||||
if (!(pyb_usb_flags & PYB_USB_FLAG_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(vid, pid, 0x0200, mode == USBD_MODE_CDC);
|
||||
if (USBD_SelectMode(mode, hid_info) != 0) {
|
||||
return false;
|
||||
}
|
||||
USBD_Init(&hUSBDDevice, (USBD_DescriptorsTypeDef*)&USBD_Descriptors, USB_PHY_ID);
|
||||
USBD_RegisterClass(&hUSBDDevice, &USBD_CDC_MSC_HID);
|
||||
USBD_CDC_RegisterInterface(&hUSBDDevice, (USBD_CDC_ItfTypeDef*)&USBD_CDC_fops);
|
||||
|
||||
// set up the USBD state
|
||||
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) {
|
||||
#if MICROPY_HW_HAS_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;
|
||||
#endif
|
||||
default:
|
||||
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops);
|
||||
USBD_MSC_RegisterStorage(usbd, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops);
|
||||
break;
|
||||
}
|
||||
USBD_HID_RegisterInterface(&hUSBDDevice, (USBD_HID_ItfTypeDef*)&USBD_HID_fops);
|
||||
USBD_Start(&hUSBDDevice);
|
||||
USBD_HID_RegisterInterface(usbd, (USBD_HID_ItfTypeDef*)&USBD_HID_fops);
|
||||
|
||||
// start the USB device
|
||||
USBD_LL_Init(usbd);
|
||||
USBD_LL_Start(usbd);
|
||||
}
|
||||
pyb_usb_flags |= PYB_USB_FLAG_DEV_ENABLED;
|
||||
#endif
|
||||
@ -143,13 +157,13 @@ bool usb_vcp_is_enabled(void) {
|
||||
}
|
||||
|
||||
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) {
|
||||
#ifdef USE_DEVICE_MODE
|
||||
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
|
||||
}
|
||||
@ -159,9 +173,9 @@ void usb_vcp_send_strn_cooked(const char *str, int len) {
|
||||
if (pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED) {
|
||||
for (const char *top = str + len; str < top; str++) {
|
||||
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 {
|
||||
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_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);
|
||||
|
||||
@ -375,7 +389,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc);
|
||||
/// \method any()
|
||||
/// Return `True` if any characters waiting, else `False`.
|
||||
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;
|
||||
} else {
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
@ -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);
|
||||
|
||||
// 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
|
||||
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_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) {
|
||||
// return EAGAIN error to indicate non-blocking
|
||||
*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) {
|
||||
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) {
|
||||
// return EAGAIN error to indicate non-blocking
|
||||
*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) {
|
||||
mp_uint_t flags = arg;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
|
@ -41,12 +41,9 @@
|
||||
#include "usbd_cdc_interface.h"
|
||||
#include "pendsv.h"
|
||||
|
||||
#include "py/mpstate.h"
|
||||
#include "py/obj.h"
|
||||
#include "lib/utils/interrupt_char.h"
|
||||
#include "irq.h"
|
||||
#include "timer.h"
|
||||
#include "usb.h"
|
||||
|
||||
// CDC control commands
|
||||
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
|
||||
@ -59,78 +56,26 @@
|
||||
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||
#define CDC_SEND_BREAK 0x23
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define APP_RX_DATA_SIZE 1024 // this must be 2 or greater, and a power of 2
|
||||
#define APP_TX_DATA_SIZE 1024 // I think this can be any value (was 2048)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
static __IO uint8_t dev_is_connected = 0; // indicates if we are connected
|
||||
|
||||
static uint8_t cdc_rx_packet_buf[CDC_DATA_FS_MAX_PACKET_SIZE]; // received data from USB OUT endpoint is stored in this buffer
|
||||
static uint8_t cdc_rx_user_buf[APP_RX_DATA_SIZE]; // received data is buffered here until the user reads it
|
||||
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;
|
||||
void usbd_cdc_init(usbd_cdc_itf_t *cdc, USBD_HandleTypeDef *pdev) {
|
||||
cdc->usb = pdev;
|
||||
cdc->rx_buf_put = 0;
|
||||
cdc->rx_buf_get = 0;
|
||||
cdc->tx_buf_ptr_in = 0;
|
||||
cdc->tx_buf_ptr_out = 0;
|
||||
cdc->tx_buf_ptr_out_shadow = 0;
|
||||
cdc->tx_buf_ptr_wait_count = 0;
|
||||
cdc->tx_need_empty_packet = 0;
|
||||
cdc->dev_is_connected = 0;
|
||||
USBD_CDC_SetTxBuffer(pdev, cdc->tx_buf, 0);
|
||||
USBD_CDC_SetRxBuffer(pdev, cdc->rx_packet_buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CDC_Itf_DeInit
|
||||
* DeInitializes 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_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) {
|
||||
// Manage the CDC class requests
|
||||
// cmd: command code
|
||||
// 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) {
|
||||
switch (cmd) {
|
||||
case CDC_SEND_ENCAPSULATED_COMMAND:
|
||||
/* Add your code here */
|
||||
@ -175,7 +120,7 @@ static int8_t CDC_Itf_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length) {
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
// needed (reducing latency), and often enough (increasing bandwidth).
|
||||
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
|
||||
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
|
||||
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
|
||||
// finish sending it over the USB in-endpoint.
|
||||
// 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
|
||||
// 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;
|
||||
if (USBx_INEP(CDC_IN_EP & 0x7f)->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ) {
|
||||
// USB in-endpoint is still reading the data
|
||||
UserTxBufPtrWaitCount++;
|
||||
cdc->tx_buf_ptr_wait_count++;
|
||||
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 buffsize;
|
||||
|
||||
if (UserTxBufPtrOutShadow > UserTxBufPtrIn) { // rollback
|
||||
buffsize = APP_TX_DATA_SIZE - UserTxBufPtrOutShadow;
|
||||
if (cdc->tx_buf_ptr_out_shadow > cdc->tx_buf_ptr_in) { // rollback
|
||||
buffsize = USBD_CDC_TX_DATA_SIZE - cdc->tx_buf_ptr_out_shadow;
|
||||
} 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) {
|
||||
UserTxBufPtrOutShadow += buffsize;
|
||||
if (UserTxBufPtrOutShadow == APP_TX_DATA_SIZE) {
|
||||
UserTxBufPtrOutShadow = 0;
|
||||
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;
|
||||
}
|
||||
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)
|
||||
// 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).
|
||||
// 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
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CDC_Itf_DataRx
|
||||
* Data received over USB OUT endpoint is processed here.
|
||||
* @param Buf: Buffer of data received
|
||||
* @param Len: Number of data received (in bytes)
|
||||
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL
|
||||
* @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) {
|
||||
// Data received over USB OUT endpoint is processed here.
|
||||
// Buf: buffer of data received
|
||||
// Len: number of data received (in bytes)
|
||||
// Returns USBD_OK if all operations are OK else USBD_FAIL
|
||||
// The buffer we are passed here is just cdc_rx_packet_buf, so we are free to modify it.
|
||||
int8_t usbd_cdc_receive(usbd_cdc_itf_t *cdc, uint8_t* Buf, uint32_t *Len) {
|
||||
// copy the incoming data into the circular buffer
|
||||
for (uint8_t *src = Buf, *top = Buf + *Len; src < top; ++src) {
|
||||
if (mp_interrupt_char != -1 && *src == mp_interrupt_char) {
|
||||
pendsv_kbd_intr();
|
||||
} else {
|
||||
uint16_t next_put = (cdc_rx_buf_put + 1) & (APP_RX_DATA_SIZE - 1);
|
||||
if (next_put == cdc_rx_buf_get) {
|
||||
uint16_t next_put = (cdc->rx_buf_put + 1) & (USBD_CDC_RX_DATA_SIZE - 1);
|
||||
if (next_put == cdc->rx_buf_get) {
|
||||
// overflow, we just discard the rest of the chars
|
||||
break;
|
||||
}
|
||||
cdc_rx_user_buf[cdc_rx_buf_put] = *src;
|
||||
cdc_rx_buf_put = next_put;
|
||||
cdc->rx_user_buf[cdc->rx_buf_put] = *src;
|
||||
cdc->rx_buf_put = next_put;
|
||||
}
|
||||
}
|
||||
|
||||
// initiate next USB packet transfer
|
||||
USBD_CDC_SetRxBuffer(pdev, cdc_rx_packet_buf);
|
||||
USBD_CDC_ReceivePacket(pdev);
|
||||
USBD_CDC_SetRxBuffer(cdc->usb, cdc->rx_packet_buf);
|
||||
USBD_CDC_ReceivePacket(cdc->usb);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
int USBD_CDC_IsConnected(void) {
|
||||
return dev_is_connected;
|
||||
}
|
||||
|
||||
int USBD_CDC_TxHalfEmpty(void) {
|
||||
int32_t tx_waiting = (int32_t)UserTxBufPtrIn - (int32_t)UserTxBufPtrOut;
|
||||
int usbd_cdc_tx_half_empty(usbd_cdc_itf_t *cdc) {
|
||||
int32_t tx_waiting = (int32_t)cdc->tx_buf_ptr_in - (int32_t)cdc->tx_buf_ptr_out;
|
||||
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.
|
||||
// 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++) {
|
||||
// Wait until the device is connected and the buffer has space, with a given timeout
|
||||
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.
|
||||
if (HAL_GetTick() - start >= 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
|
||||
UserTxBuffer[UserTxBufPtrIn] = buf[i];
|
||||
UserTxBufPtrIn = (UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1);
|
||||
cdc->tx_buf[cdc->tx_buf_ptr_in] = buf[i];
|
||||
cdc->tx_buf_ptr_in = (cdc->tx_buf_ptr_in + 1) & (USBD_CDC_TX_DATA_SIZE - 1);
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
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++) {
|
||||
// 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
|
||||
// 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,
|
||||
// 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
|
||||
// (wraparound of tick is taken care of by 2's complement arithmetic).
|
||||
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) {
|
||||
// IRQs disabled so buffer will never be drained; exit loop
|
||||
break;
|
||||
@ -365,28 +305,28 @@ void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len) {
|
||||
*/
|
||||
}
|
||||
|
||||
UserTxBuffer[UserTxBufPtrIn] = buf[i];
|
||||
UserTxBufPtrIn = (UserTxBufPtrIn + 1) & (APP_TX_DATA_SIZE - 1);
|
||||
cdc->tx_buf[cdc->tx_buf_ptr_in] = buf[i];
|
||||
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.
|
||||
int USBD_CDC_RxNum(void) {
|
||||
int32_t rx_waiting = (int32_t)cdc_rx_buf_put - (int32_t)cdc_rx_buf_get;
|
||||
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;
|
||||
if (rx_waiting < 0) {
|
||||
rx_waiting += APP_RX_DATA_SIZE;
|
||||
rx_waiting += USBD_CDC_RX_DATA_SIZE;
|
||||
}
|
||||
return rx_waiting;
|
||||
}
|
||||
|
||||
// timout in milliseconds.
|
||||
// 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
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
// Wait until we have at least 1 byte to read
|
||||
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.
|
||||
if (HAL_GetTick() - start >= 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
|
||||
buf[i] = cdc_rx_user_buf[cdc_rx_buf_get];
|
||||
cdc_rx_buf_get = (cdc_rx_buf_get + 1) & (APP_RX_DATA_SIZE - 1);
|
||||
buf[i] = cdc->rx_user_buf[cdc->rx_buf_get];
|
||||
cdc->rx_buf_get = (cdc->rx_buf_get + 1) & (USBD_CDC_RX_DATA_SIZE - 1);
|
||||
}
|
||||
|
||||
// Success, return number of bytes read
|
||||
|
@ -1,45 +1,66 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*/
|
||||
#ifndef 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
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.1
|
||||
* @date 26-February-2014
|
||||
* @brief Header for usbd_cdc_interface.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* 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 obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
extern const USBD_CDC_ItfTypeDef USBD_CDC_fops;
|
||||
|
||||
int USBD_CDC_IsConnected(void);
|
||||
|
||||
int USBD_CDC_TxHalfEmpty(void);
|
||||
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);
|
||||
|
||||
int USBD_CDC_RxNum(void);
|
||||
int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout);
|
||||
|
||||
#endif // MICROPY_INCLUDED_STMHAL_USBD_CDC_INTERFACE_H
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*/
|
||||
#ifndef 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
|
||||
* @author MCD Application Team
|
||||
* @version V1.0.1
|
||||
* @date 26-February-2014
|
||||
* @brief Header for usbd_cdc_interface.c file.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
|
||||
*
|
||||
* 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 obtain a copy of the License at:
|
||||
*
|
||||
* http://www.st.com/software_license_agreement_liberty_v2
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#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)
|
||||
|
||||
typedef struct _usbd_cdc_itf_t {
|
||||
USBD_HandleTypeDef *usb; // the parent USB device
|
||||
|
||||
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
|
||||
volatile uint16_t rx_buf_put; // circular buffer index
|
||||
uint16_t rx_buf_get; // circular buffer index
|
||||
|
||||
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
|
||||
|
@ -27,13 +27,6 @@ typedef struct {
|
||||
uint8_t datatype;
|
||||
} 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 {
|
||||
uint32_t data[CDC_DATA_FS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */
|
||||
uint8_t CmdOpCode;
|
||||
@ -86,6 +79,12 @@ typedef struct {
|
||||
uint32_t scsi_blk_len;
|
||||
} 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_REPORT_DESC_SIZE (74)
|
||||
|
||||
@ -103,7 +102,6 @@ int USBD_SelectMode(uint32_t mode, USBD_HID_ModeInfoTypeDef *hid_info);
|
||||
// returns the current usb mode
|
||||
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_SetRxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff);
|
||||
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_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_
|
||||
|
@ -95,7 +95,6 @@ static uint8_t usbd_config_desc_size;
|
||||
static uint8_t *hid_desc;
|
||||
static const uint8_t *hid_report_desc;
|
||||
|
||||
static USBD_CDC_ItfTypeDef *CDC_fops;
|
||||
static USBD_StorageTypeDef *MSC_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;
|
||||
}
|
||||
|
||||
usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
|
||||
|
||||
if (usbd_mode & USBD_MODE_CDC) {
|
||||
// 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);
|
||||
|
||||
// Init physical Interface components
|
||||
CDC_fops->Init(pdev);
|
||||
usbd_cdc_init(state->cdc, pdev);
|
||||
|
||||
// Init Xfer states
|
||||
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,
|
||||
MSC_MAX_PACKET);
|
||||
|
||||
// MSC uses the pClassData pointer because SCSI and BOT reference it
|
||||
pdev->pClassData = &MSC_BOT_ClassData;
|
||||
// Set the MSC data for SCSI and BOT to reference it
|
||||
state->msc = &MSC_BOT_ClassData;
|
||||
|
||||
// Init the BOT layer
|
||||
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) {
|
||||
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
|
||||
|
||||
// close endpoints
|
||||
USBD_LL_CloseEP(pdev, CDC_IN_EP);
|
||||
USBD_LL_CloseEP(pdev, CDC_OUT_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
|
||||
|
||||
// close endpoints
|
||||
@ -758,8 +758,8 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
|
||||
// DeInit the BOT layer
|
||||
MSC_BOT_DeInit(pdev);
|
||||
|
||||
// clear the pointer
|
||||
pdev->pClassData = NULL;
|
||||
// clear the state pointer
|
||||
state->msc = NULL;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
|
||||
|
||||
switch (req->bmRequest & USB_REQ_TYPE_MASK) {
|
||||
|
||||
// Class request
|
||||
@ -801,7 +803,7 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
|
||||
if (req->wLength) {
|
||||
if (req->bmRequest & 0x80) {
|
||||
// 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);
|
||||
} else {
|
||||
// host-to-device request
|
||||
@ -812,7 +814,7 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp
|
||||
} else {
|
||||
// Not a Data request
|
||||
// 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) {
|
||||
// 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) {
|
||||
if ((CDC_fops != NULL) && (CDC_ClassData.CmdOpCode != 0xff)) {
|
||||
CDC_fops->Control(CDC_ClassData.CmdOpCode, (uint8_t*)CDC_ClassData.data, CDC_ClassData.CmdLength);
|
||||
usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
usbd_cdc_msc_hid_state_t *state = pdev->pClassData;
|
||||
if ((usbd_mode & USBD_MODE_CDC) && epnum == (CDC_OUT_EP & 0x7f)) {
|
||||
/* Get the received data length */
|
||||
CDC_ClassData.RxLength = USBD_LL_GetRxDataSize (pdev, epnum);
|
||||
|
||||
/* USB data will be immediately processed, this allow next USB traffic being
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
CDC_ClassData.TxBuffer = pbuff;
|
||||
CDC_ClassData.TxLength = length;
|
||||
|
@ -104,7 +104,7 @@ static void MSC_BOT_Abort(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_status = USBD_BOT_STATUS_NORMAL;
|
||||
@ -132,7 +132,7 @@ void MSC_BOT_Init (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_status = USBD_BOT_STATUS_RECOVERY;
|
||||
@ -152,7 +152,7 @@ void MSC_BOT_Reset (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;
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ void MSC_BOT_DeInit (USBD_HandleTypeDef *pdev)
|
||||
void MSC_BOT_DataIn (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;
|
||||
|
||||
switch (hmsc->bot_state)
|
||||
{
|
||||
@ -199,7 +199,7 @@ void MSC_BOT_DataIn (USBD_HandleTypeDef *pdev,
|
||||
void MSC_BOT_DataOut (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;
|
||||
|
||||
switch (hmsc->bot_state)
|
||||
{
|
||||
@ -231,7 +231,7 @@ void MSC_BOT_DataOut (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.dDataResidue = hmsc->cbw.dDataLength;
|
||||
@ -300,7 +300,7 @@ static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev,
|
||||
uint8_t* buf,
|
||||
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);
|
||||
hmsc->csw.dDataResidue -= len;
|
||||
@ -320,7 +320,7 @@ static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev,
|
||||
void MSC_BOT_SendCSW (USBD_HandleTypeDef *pdev,
|
||||
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.bStatus = CSW_Status;
|
||||
@ -348,7 +348,7 @@ void MSC_BOT_SendCSW (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) &&
|
||||
(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)
|
||||
{
|
||||
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 */
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
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 */
|
||||
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;
|
||||
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*/
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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 ;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
@ -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) {
|
||||
// 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;
|
||||
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)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
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].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)
|
||||
{
|
||||
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;
|
||||
|
||||
// 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)
|
||||
{
|
||||
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;
|
||||
((USBD_StorageTypeDef *)pdev->pUserData)->PreventAllowMediumRemoval(lun, params[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)
|
||||
{
|
||||
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 */
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
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 */
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
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 )
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
|
||||
USBD_MSC_BOT_HandleTypeDef *hmsc = ((usbd_cdc_msc_hid_state_t*)pdev->pClassData)->msc;
|
||||
uint32_t len;
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user