diff options
| author | sakumisu <[email protected]> | 2022-07-28 21:25:29 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2022-07-28 21:35:22 +0800 |
| commit | f1bc0aef0419d648967779d9807bd00784cb9987 (patch) | |
| tree | b6b3cfbde9794e6091b7cd63d0670f1b898bc024 /class | |
| parent | d2fb9b36246dc1285c29a8581b3a3b58cb213f1e (diff) | |
refactor dcd api and ep in/out irq callback process
Diffstat (limited to 'class')
| -rw-r--r-- | class/cdc/usbd_cdc.c | 7 | ||||
| -rw-r--r-- | class/cdc/usbd_cdc.h | 5 | ||||
| -rw-r--r-- | class/hid/usbd_hid.c | 7 | ||||
| -rw-r--r-- | class/hid/usbd_hid.h | 10 | ||||
| -rw-r--r-- | class/msc/usbd_msc.c | 590 |
5 files changed, 269 insertions, 350 deletions
diff --git a/class/cdc/usbd_cdc.c b/class/cdc/usbd_cdc.c index ef002fac..c6defc37 100644 --- a/class/cdc/usbd_cdc.c +++ b/class/cdc/usbd_cdc.c @@ -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) +{ +} diff --git a/class/cdc/usbd_cdc.h b/class/cdc/usbd_cdc.h index 19d41dcf..88e975f1 100644 --- a/class/cdc/usbd_cdc.h +++ b/class/cdc/usbd_cdc.h @@ -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 diff --git a/class/hid/usbd_hid.c b/class/hid/usbd_hid.c index 7aa38031..b0544e77 100644 --- a/class/hid/usbd_hid.c +++ b/class/hid/usbd_hid.c @@ -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) +{ }
\ No newline at end of file diff --git a/class/hid/usbd_hid.h b/class/hid/usbd_hid.h index 09f949fb..0f89c0b5 100644 --- a/class/hid/usbd_hid.h +++ b/class/hid/usbd_hid.h @@ -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 diff --git a/class/msc/usbd_msc.c b/class/msc/usbd_msc.c index 92148f6d..0e0464a9 100644 --- a/class/msc/usbd_msc.c +++ b/class/msc/usbd_msc.c @@ -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: |
