refactor dcd api and ep in/out irq callback process
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user