refactor dcd api and ep in/out irq callback process

This commit is contained in:
sakumisu
2022-07-28 21:25:29 +08:00
parent d2fb9b3624
commit f1bc0aef04
68 changed files with 1845 additions and 43022 deletions

View File

@@ -152,6 +152,9 @@ static void cdc_notify_handler(uint8_t event, void *arg)
usbd_cdc_acm_reset();
#endif
break;
case USBD_EVENT_CONFIGURED:
usbd_cdc_acm_setup();
break;
default:
break;
@@ -207,3 +210,7 @@ __WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
__WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
{
}
__WEAK void usbd_cdc_acm_setup(void)
{
}

View File

@@ -29,12 +29,17 @@
extern "C" {
#endif
/* Register api */
void usbd_cdc_add_acm_interface(usbd_class_t *devclass, usbd_interface_t *intf);
/* Setup request command callback api */
void usbd_cdc_acm_set_line_coding(uint8_t intf, uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits);
void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr);
void usbd_cdc_acm_set_rts(uint8_t intf, bool rts);
/* Setup cdc acm first rx transfer */
void usbd_cdc_acm_setup(void);
#ifdef __cplusplus
}
#endif

View File

@@ -175,6 +175,9 @@ static void hid_notify_handler(uint8_t event, void *arg)
case USBD_EVENT_RESET:
usbd_hid_reset();
break;
case USBD_EVENT_CONFIGURED:
usbd_hid_setup();
break;
default:
break;
@@ -258,4 +261,8 @@ __WEAK void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
__WEAK void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol)
{
}
__WEAK void usbd_hid_setup(void)
{
}

View File

@@ -29,9 +29,14 @@
extern "C" {
#endif
/* Register api */
void usbd_hid_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
/* Register desc api */
void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc);
void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
void usbd_hid_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
/* Setup request command callback api */
uint8_t usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type);
uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id);
uint8_t usbh_hid_get_protocol(uint8_t intf);
@@ -39,6 +44,9 @@ void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, u
void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol);
/* Setup hid first rx transfer */
void usbd_hid_setup(void);
#ifdef __cplusplus
}
#endif

View File

@@ -85,14 +85,7 @@ static uint32_t current_byte_read;
static void usbd_msc_reset(void)
{
uint8_t *buf = NULL;
buf = usbd_msc_cfg.block_buffer;
memset((uint8_t *)&usbd_msc_cfg, 0, sizeof(struct usbd_msc_cfg_priv));
usbd_msc_get_cap(0, &usbd_msc_cfg.scsi_blk_nbr, &usbd_msc_cfg.scsi_blk_size);
usbd_msc_cfg.block_buffer = buf;
usbd_msc_cfg.stage = MSC_READ_CBW;
}
/**
@@ -112,24 +105,10 @@ static int msc_storage_class_request_handler(struct usb_setup_packet *setup, uin
switch (setup->bRequest) {
case MSC_REQUEST_RESET:
USB_LOG_DBG("MSC_REQUEST_RESET\r\n");
if (setup->wLength) {
USB_LOG_WRN("Invalid length\r\n");
return -1;
}
usbd_msc_reset();
break;
case MSC_REQUEST_GET_MAX_LUN:
USB_LOG_DBG("MSC_REQUEST_GET_MAX_LUN\r\n");
if (setup->wLength != 1) {
USB_LOG_WRN("Invalid length\r\n");
return -1;
}
*data = (uint8_t *)(&usbd_msc_cfg.max_lun);
*len = 1;
break;
@@ -142,15 +121,32 @@ static int msc_storage_class_request_handler(struct usb_setup_packet *setup, uin
return 0;
}
void msc_storage_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
usbd_msc_reset();
break;
case USBD_EVENT_CONFIGURED:
USB_LOG_DBG("Start reading cbw\r\n");
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
break;
default:
break;
}
}
static void usbd_msc_bot_abort(void)
{
if ((usbd_msc_cfg.cbw.bmFlags == 0) && (usbd_msc_cfg.cbw.dDataLength != 0)) {
usbd_ep_set_stall(mass_ep_data[MSD_OUT_EP_IDX].ep_addr);
}
usbd_ep_set_stall(mass_ep_data[MSD_IN_EP_IDX].ep_addr);
usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
}
static void sendCSW(uint8_t CSW_Status)
static void usbd_msc_send_csw(uint8_t CSW_Status)
{
usbd_msc_cfg.csw.dSignature = MSC_CSW_Signature;
usbd_msc_cfg.csw.bStatus = CSW_Status;
@@ -160,13 +156,11 @@ static void sendCSW(uint8_t CSW_Status)
*/
usbd_msc_cfg.stage = MSC_WAIT_CSW;
if (usbd_ep_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.csw,
sizeof(struct CSW), NULL) != 0) {
USB_LOG_ERR("usb write failure\r\n");
}
USB_LOG_DBG("Send csw\r\n");
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.csw, sizeof(struct CSW));
}
static void sendLastData(uint8_t *buffer, uint8_t size)
static void usbd_msc_send_info(uint8_t *buffer, uint8_t size)
{
size = MIN(size, usbd_msc_cfg.cbw.dDataLength);
@@ -175,31 +169,14 @@ static void sendLastData(uint8_t *buffer, uint8_t size)
*/
usbd_msc_cfg.stage = MSC_SEND_CSW;
if (usbd_ep_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, buffer, size, NULL) != 0) {
USB_LOG_ERR("USB write failed\r\n");
}
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, buffer, size);
usbd_msc_cfg.csw.dDataResidue -= size;
usbd_msc_cfg.csw.bStatus = CSW_STATUS_CMD_PASSED;
}
/**
* @brief SCSI COMMAND
*/
static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len);
static bool SCSI_requestSense(uint8_t **data, uint32_t *len);
static bool SCSI_inquiry(uint8_t **data, uint32_t *len);
static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len);
static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len);
static bool SCSI_modeSense6(uint8_t **data, uint32_t *len);
static bool SCSI_modeSense10(uint8_t **data, uint32_t *len);
static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len);
static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len);
static bool SCSI_read10(uint8_t **data, uint32_t *len);
static bool SCSI_read12(uint8_t **data, uint32_t *len);
static bool SCSI_write10(uint8_t **data, uint32_t *len);
static bool SCSI_write12(uint8_t **data, uint32_t *len);
static bool SCSI_verify10(uint8_t **data, uint32_t *len);
static bool SCSI_processWrite(uint32_t nbytes);
static bool SCSI_processRead(void);
/**
* @brief SCSI_SetSenseData
@@ -216,258 +193,10 @@ static void SCSI_SetSenseData(uint32_t KCQ)
usbd_msc_cfg.ASQ = (uint8_t)(KCQ);
}
#ifdef CONFIG_USBDEV_MSC_THREAD
static void usbd_msc_thread_memory_read_done(void)
{
size_t flags;
uint32_t transfer_len;
uint32_t offset;
USB_LOG_DBG("read addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr);
flags = usb_osal_enter_critical_section();
transfer_len = MIN(usbd_msc_cfg.scsi_blk_len, MASS_STORAGE_BULK_EP_MPS);
offset = usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size;
usbd_msc_cfg.scsi_blk_addr += transfer_len;
usbd_msc_cfg.scsi_blk_len -= transfer_len;
usbd_msc_cfg.csw.dDataResidue -= transfer_len;
if (usbd_msc_cfg.scsi_blk_len == 0) {
usbd_msc_cfg.stage = MSC_SEND_CSW;
}
usb_osal_leave_critical_section(flags);
usbd_ep_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr,
&usbd_msc_cfg.block_buffer[offset], transfer_len, NULL);
}
#endif
static bool SCSI_processRead(void)
{
uint32_t transfer_len;
USB_LOG_DBG("read addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr);
transfer_len = MIN(usbd_msc_cfg.scsi_blk_len, MASS_STORAGE_BULK_EP_MPS);
/* we read an entire block */
if (!(usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size)) {
#ifdef CONFIG_USBDEV_MSC_THREAD
thread_op = MSC_THREAD_OP_READ_MEM;
usb_osal_sem_give(msc_sem);
return true;
#else
if (usbd_msc_sector_read((usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size), usbd_msc_cfg.block_buffer, usbd_msc_cfg.scsi_blk_size) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
return false;
}
#endif
}
usbd_ep_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr,
&usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], transfer_len, NULL);
usbd_msc_cfg.scsi_blk_addr += transfer_len;
usbd_msc_cfg.scsi_blk_len -= transfer_len;
usbd_msc_cfg.csw.dDataResidue -= transfer_len;
if (usbd_msc_cfg.scsi_blk_len == 0) {
usbd_msc_cfg.stage = MSC_SEND_CSW;
}
return true;
}
#ifdef CONFIG_USBDEV_MSC_THREAD
static void usbd_msc_thread_memory_write_done()
{
size_t flags;
uint32_t bytes_read;
USB_LOG_DBG("write addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr);
flags = usb_osal_enter_critical_section();
bytes_read = current_byte_read;
usbd_msc_cfg.scsi_blk_addr += bytes_read;
usbd_msc_cfg.scsi_blk_len -= bytes_read;
usbd_msc_cfg.csw.dDataResidue -= bytes_read;
usb_osal_leave_critical_section(flags);
thread_op = MSC_THREAD_OP_WRITE_DONE;
/*set ep ack to recv next data*/
usbd_ep_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, NULL, 0, NULL);
if (usbd_msc_cfg.scsi_blk_len == 0) {
sendCSW(CSW_STATUS_CMD_PASSED);
}
}
#endif
static bool SCSI_processWrite()
{
uint32_t bytes_read;
USB_LOG_DBG("write addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr);
/* we fill an array in RAM of 1 block before writing it in memory */
usbd_ep_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], MASS_STORAGE_BULK_EP_MPS,
&bytes_read);
/* if the array is filled, write it in memory */
if ((usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size) + bytes_read >= usbd_msc_cfg.scsi_blk_size) {
#ifdef CONFIG_USBDEV_MSC_THREAD
thread_op = MSC_THREAD_OP_WRITE_MEM;
current_byte_read = bytes_read;
usb_osal_sem_give(msc_sem);
return true;
#else
if (usbd_msc_sector_write((usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size), usbd_msc_cfg.block_buffer, usbd_msc_cfg.scsi_blk_size) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
return false;
}
#endif
}
usbd_msc_cfg.scsi_blk_addr += bytes_read;
usbd_msc_cfg.scsi_blk_len -= bytes_read;
usbd_msc_cfg.csw.dDataResidue -= bytes_read;
if (usbd_msc_cfg.scsi_blk_len == 0) {
sendCSW(CSW_STATUS_CMD_PASSED);
}
return true;
}
static bool SCSI_processVerify()
{
#if 0
uint32_t bytes_read;
uint8_t out_buffer[MASS_STORAGE_BULK_EP_MPS];
USB_LOG_DBG("verify addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr);
/* we fill an array in RAM of 1 block before writing it in memory */
usbd_ep_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, out_buffer, MASS_STORAGE_BULK_EP_MPS,
&bytes_read);
/* we read an entire block */
if (!(usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size)) {
if (usbd_msc_sector_read((usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size), usbd_msc_cfg.block_buffer, usbd_msc_cfg.scsi_blk_size) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
return false;
}
}
/* info are in RAM -> no need to re-read memory */
for (uint16_t i = 0U; i < bytes_read; i++) {
if (usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size + i] != out_buffer[i]) {
USB_LOG_DBG("Mismatch sector %d offset %d",
usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size, i);
memOK = false;
break;
}
}
usbd_msc_cfg.scsi_blk_addr += bytes_read;
usbd_msc_cfg.scsi_blk_len -= bytes_read;
usbd_msc_cfg.csw.dDataResidue -= bytes_read;
if (usbd_msc_cfg.scsi_blk_len == 0) {
sendCSW(CSW_STATUS_CMD_PASSED);
}
#endif
return true;
}
static bool SCSI_CBWDecode()
{
uint8_t *buf2send = usbd_msc_cfg.block_buffer;
uint32_t len2send = 0;
uint32_t bytes_read;
bool ret = false;
usbd_ep_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW,
&bytes_read);
if (bytes_read != sizeof(struct CBW)) {
USB_LOG_ERR("size != sizeof(cbw)\r\n");
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
usbd_msc_cfg.csw.dTag = usbd_msc_cfg.cbw.dTag;
usbd_msc_cfg.csw.dDataResidue = usbd_msc_cfg.cbw.dDataLength;
if ((usbd_msc_cfg.cbw.bLUN > 1) || (usbd_msc_cfg.cbw.dSignature != MSC_CBW_Signature) || (usbd_msc_cfg.cbw.bCBLength < 1) || (usbd_msc_cfg.cbw.bCBLength > 16)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
} else {
switch (usbd_msc_cfg.cbw.CB[0]) {
case SCSI_CMD_TESTUNITREADY:
ret = SCSI_testUnitReady(&buf2send, &len2send);
break;
case SCSI_CMD_REQUESTSENSE:
ret = SCSI_requestSense(&buf2send, &len2send);
break;
case SCSI_CMD_INQUIRY:
ret = SCSI_inquiry(&buf2send, &len2send);
break;
case SCSI_CMD_STARTSTOPUNIT:
ret = SCSI_startStopUnit(&buf2send, &len2send);
break;
case SCSI_CMD_PREVENTMEDIAREMOVAL:
ret = SCSI_preventAllowMediaRemoval(&buf2send, &len2send);
break;
case SCSI_CMD_MODESENSE6:
ret = SCSI_modeSense6(&buf2send, &len2send);
break;
case SCSI_CMD_MODESENSE10:
ret = SCSI_modeSense10(&buf2send, &len2send);
break;
case SCSI_CMD_READFORMATCAPACITIES:
ret = SCSI_readFormatCapacity(&buf2send, &len2send);
break;
case SCSI_CMD_READCAPACITY10:
ret = SCSI_readCapacity10(&buf2send, &len2send);
break;
case SCSI_CMD_READ10:
ret = SCSI_read10(NULL, 0);
break;
case SCSI_CMD_READ12:
ret = SCSI_read12(NULL, 0);
break;
case SCSI_CMD_WRITE10:
ret = SCSI_write10(NULL, 0);
break;
case SCSI_CMD_WRITE12:
ret = SCSI_write12(NULL, 0);
break;
case SCSI_CMD_VERIFY10:
ret = SCSI_verify10(NULL, 0);
break;
default:
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
ret = false;
break;
}
}
if (ret) {
if (usbd_msc_cfg.stage == MSC_READ_CBW) {
if (len2send) {
sendLastData(buf2send, len2send);
} else {
sendCSW(CSW_STATUS_CMD_PASSED);
}
}
}
return ret;
}
/**
* @brief SCSI Command list
*
*/
static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
{
@@ -871,6 +600,7 @@ static bool SCSI_write10(uint8_t **data, uint32_t *len)
return false;
}
usbd_msc_cfg.stage = MSC_DATA_OUT;
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], usbd_msc_cfg.scsi_blk_size);
return true;
}
@@ -904,6 +634,7 @@ static bool SCSI_write12(uint8_t **data, uint32_t *len)
return false;
}
usbd_msc_cfg.stage = MSC_DATA_OUT;
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], MASS_STORAGE_BULK_EP_MPS);
return true;
}
@@ -952,30 +683,222 @@ static bool SCSI_verify10(uint8_t **data, uint32_t *len)
return true;
}
static void mass_storage_bulk_out(uint8_t ep)
#ifdef CONFIG_USBDEV_MSC_THREAD
static void usbd_msc_thread_memory_read_done(void)
{
size_t flags;
uint32_t transfer_len;
flags = usb_osal_enter_critical_section();
transfer_len = MIN(usbd_msc_cfg.scsi_blk_len, usbd_msc_cfg.scsi_blk_size);
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr,
&usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], transfer_len);
usbd_msc_cfg.scsi_blk_addr += transfer_len;
usbd_msc_cfg.scsi_blk_len -= transfer_len;
usbd_msc_cfg.csw.dDataResidue -= transfer_len;
if (usbd_msc_cfg.scsi_blk_len == 0) {
usbd_msc_cfg.stage = MSC_SEND_CSW;
}
usb_osal_leave_critical_section(flags);
}
#endif
static bool SCSI_processRead(void)
{
uint32_t transfer_len;
USB_LOG_DBG("read addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr);
transfer_len = MIN(usbd_msc_cfg.scsi_blk_len, usbd_msc_cfg.scsi_blk_size);
/* we read an entire block */
if (!(usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size)) {
#ifdef CONFIG_USBDEV_MSC_THREAD
thread_op = MSC_THREAD_OP_READ_MEM;
usb_osal_sem_give(msc_sem);
return true;
#else
if (usbd_msc_sector_read((usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size), usbd_msc_cfg.block_buffer, usbd_msc_cfg.scsi_blk_size) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
return false;
}
#endif
}
usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr,
&usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], transfer_len);
usbd_msc_cfg.scsi_blk_addr += transfer_len;
usbd_msc_cfg.scsi_blk_len -= transfer_len;
usbd_msc_cfg.csw.dDataResidue -= transfer_len;
if (usbd_msc_cfg.scsi_blk_len == 0) {
usbd_msc_cfg.stage = MSC_SEND_CSW;
}
return true;
}
#ifdef CONFIG_USBDEV_MSC_THREAD
static void usbd_msc_thread_memory_write_done()
{
size_t flags;
uint32_t nbytes;
flags = usb_osal_enter_critical_section();
nbytes = current_byte_read;
usbd_msc_cfg.scsi_blk_addr += nbytes;
usbd_msc_cfg.scsi_blk_len -= nbytes;
usbd_msc_cfg.csw.dDataResidue -= nbytes;
if (usbd_msc_cfg.scsi_blk_len == 0) {
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
} else {
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], MASS_STORAGE_BULK_EP_MPS);
}
usb_osal_leave_critical_section(flags);
}
#endif
static bool SCSI_processWrite(uint32_t nbytes)
{
USB_LOG_DBG("write addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr);
/* if the array is filled, write it in memory */
if ((usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size) + nbytes >= usbd_msc_cfg.scsi_blk_size) {
#ifdef CONFIG_USBDEV_MSC_THREAD
thread_op = MSC_THREAD_OP_WRITE_MEM;
current_byte_read = nbytes;
usb_osal_sem_give(msc_sem);
return true;
#else
if (usbd_msc_sector_write((usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size), usbd_msc_cfg.block_buffer, usbd_msc_cfg.scsi_blk_size) != 0) {
SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
return false;
}
#endif
}
usbd_msc_cfg.scsi_blk_addr += nbytes;
usbd_msc_cfg.scsi_blk_len -= nbytes;
usbd_msc_cfg.csw.dDataResidue -= nbytes;
if (usbd_msc_cfg.scsi_blk_len == 0) {
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
} else {
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], usbd_msc_cfg.scsi_blk_size);
}
return true;
}
static bool SCSI_CBWDecode(uint32_t nbytes)
{
uint8_t *buf2send = usbd_msc_cfg.block_buffer;
uint32_t len2send = 0;
bool ret = false;
if (nbytes != sizeof(struct CBW)) {
USB_LOG_ERR("size != sizeof(cbw)\r\n");
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
}
usbd_msc_cfg.csw.dTag = usbd_msc_cfg.cbw.dTag;
usbd_msc_cfg.csw.dDataResidue = usbd_msc_cfg.cbw.dDataLength;
if ((usbd_msc_cfg.cbw.bLUN > 1) || (usbd_msc_cfg.cbw.dSignature != MSC_CBW_Signature) || (usbd_msc_cfg.cbw.bCBLength < 1) || (usbd_msc_cfg.cbw.bCBLength > 16)) {
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
return false;
} else {
USB_LOG_DBG("Decode CB:0x%02x\r\n",usbd_msc_cfg.cbw.CB[0]);
switch (usbd_msc_cfg.cbw.CB[0]) {
case SCSI_CMD_TESTUNITREADY:
ret = SCSI_testUnitReady(&buf2send, &len2send);
break;
case SCSI_CMD_REQUESTSENSE:
ret = SCSI_requestSense(&buf2send, &len2send);
break;
case SCSI_CMD_INQUIRY:
ret = SCSI_inquiry(&buf2send, &len2send);
break;
case SCSI_CMD_STARTSTOPUNIT:
ret = SCSI_startStopUnit(&buf2send, &len2send);
break;
case SCSI_CMD_PREVENTMEDIAREMOVAL:
ret = SCSI_preventAllowMediaRemoval(&buf2send, &len2send);
break;
case SCSI_CMD_MODESENSE6:
ret = SCSI_modeSense6(&buf2send, &len2send);
break;
case SCSI_CMD_MODESENSE10:
ret = SCSI_modeSense10(&buf2send, &len2send);
break;
case SCSI_CMD_READFORMATCAPACITIES:
ret = SCSI_readFormatCapacity(&buf2send, &len2send);
break;
case SCSI_CMD_READCAPACITY10:
ret = SCSI_readCapacity10(&buf2send, &len2send);
break;
case SCSI_CMD_READ10:
ret = SCSI_read10(NULL, 0);
break;
case SCSI_CMD_READ12:
ret = SCSI_read12(NULL, 0);
break;
case SCSI_CMD_WRITE10:
ret = SCSI_write10(NULL, 0);
break;
case SCSI_CMD_WRITE12:
ret = SCSI_write12(NULL, 0);
break;
case SCSI_CMD_VERIFY10:
ret = SCSI_verify10(NULL, 0);
break;
default:
SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
USB_LOG_WRN("unsupported cmd:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
ret = false;
break;
}
}
if (ret) {
if (usbd_msc_cfg.stage == MSC_READ_CBW) {
if (len2send) {
USB_LOG_DBG("Send info len:%d\r\n",len2send);
usbd_msc_send_info(buf2send, len2send);
} else {
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
}
}
}
return ret;
}
static void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
{
switch (usbd_msc_cfg.stage) {
case MSC_READ_CBW:
if (SCSI_CBWDecode() == false) {
if (SCSI_CBWDecode(nbytes) == false) {
USB_LOG_ERR("Command:0x%02x decode err\r\n", usbd_msc_cfg.cbw.CB[0]);
usbd_msc_bot_abort();
return;
}
break;
/* last command is write10 or write12,and has caculated blk_addr and blk_len,so the device start reading data from host*/
case MSC_DATA_OUT:
switch (usbd_msc_cfg.cbw.CB[0]) {
case SCSI_CMD_WRITE10:
case SCSI_CMD_WRITE12:
if (SCSI_processWrite() == false) {
sendCSW(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
//return;
}
break;
case SCSI_CMD_VERIFY10:
if (SCSI_processVerify() == false) {
sendCSW(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
//return;
if (SCSI_processWrite(nbytes) == false) {
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
}
break;
default:
@@ -985,65 +908,34 @@ static void mass_storage_bulk_out(uint8_t ep)
default:
break;
}
#ifdef CONFIG_USBDEV_MSC_THREAD
if (thread_op != MSC_THREAD_OP_WRITE_MEM) {
/*set ep ack to recv next data*/
usbd_ep_read(ep, NULL, 0, NULL);
}
#else
/*set ep ack to recv next data*/
usbd_ep_read(ep, NULL, 0, NULL);
#endif
}
/**
* @brief EP Bulk IN handler, used to send data to the Host
*
* @param ep Endpoint address.
* @param ep_status Endpoint status code.
*
* @return N/A.
*/
static void mass_storage_bulk_in(uint8_t ep)
static void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
{
switch (usbd_msc_cfg.stage) {
/* last command is read10 or read12,and has caculated blk_addr and blk_len,so the device has to send remain data to host*/
case MSC_DATA_IN:
switch (usbd_msc_cfg.cbw.CB[0]) {
case SCSI_CMD_READ10:
case SCSI_CMD_READ12:
if (SCSI_processRead() == false) {
sendCSW(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
return;
}
break;
default:
break;
}
break;
/*the device has to send a CSW*/
/*the device has to send a CSW*/
case MSC_SEND_CSW:
sendCSW(CSW_STATUS_CMD_PASSED);
usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
break;
/*the host has received the CSW*/
case MSC_WAIT_CSW:
usbd_msc_cfg.stage = MSC_READ_CBW;
break;
default:
break;
}
}
void msc_storage_notify_handler(uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
usbd_msc_reset();
USB_LOG_DBG("Start reading cbw\r\n");
usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
break;
default: