improve scsi: support non read10, write10 out data

This commit is contained in:
hathach 2018-04-18 13:46:05 +07:00
parent e872962b25
commit 6280c50ad7
2 changed files with 38 additions and 28 deletions

View File

@ -199,37 +199,38 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u
} }
else else
{ {
// If not read10 & write10, invoke application callback // For other SCSI commands
void const *p_buffer = NULL; // 1. Zero : Invoke app callback, skip DATA and move to STATUS stage
// 2. OUT : queue transfer (invoke app callback there)
// TODO SCSI data out transfer is not yet supported // 3. IN : invoke app callback to get response
TU_ASSERT( !(p_cbw->xfer_bytes > 0 && !BIT_TEST_(p_cbw->dir, 7)), TUSB_ERROR_NOT_SUPPORTED_YET);
// Invoke callback
p_csw->status = tud_msc_scsi_cb(rhport, p_cbw->lun, p_cbw->command, p_msc->scsi_data, &p_msc->data_len);
if ( p_cbw->xfer_bytes == 0) if ( p_cbw->xfer_bytes == 0)
{ {
// There is no DATA, move to Status Stage p_csw->status = tud_msc_scsi_cb(rhport, p_cbw->lun, p_cbw->command, p_msc->scsi_data, &p_msc->data_len);
p_msc->stage = MSC_STAGE_STATUS; p_msc->stage = MSC_STAGE_STATUS;
}
else if ( !BIT_TEST_(p_cbw->dir, 7) )
{
TU_ASSERT( sizeof(p_msc->scsi_data) >= p_msc->data_len, TUSB_ERROR_NOT_ENOUGH_MEMORY); // needs to increase size for scsi_data
TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_out, p_msc->scsi_data, p_msc->data_len), TUSB_ERROR_DCD_EDPT_XFER );
} }
else else
{ {
// Data Phase (non READ10, WRITE10) p_csw->status = tud_msc_scsi_cb(rhport, p_cbw->lun, p_cbw->command, p_msc->scsi_data, &p_msc->data_len);
TU_ASSERT( p_cbw->xfer_bytes >= p_msc->data_len, TUSB_ERROR_INVALID_PARA ); // cannot return more than host expect TU_ASSERT( p_cbw->xfer_bytes >= p_msc->data_len, TUSB_ERROR_INVALID_PARA ); // cannot return more than host expect
TU_ASSERT( sizeof(p_msc->scsi_data) >= p_msc->data_len, TUSB_ERROR_NOT_ENOUGH_MEMORY); // needs to increase size for scsi_data TU_ASSERT( sizeof(p_msc->scsi_data) >= p_msc->data_len, TUSB_ERROR_NOT_ENOUGH_MEMORY); // needs to increase size for scsi_data
uint8_t const ep = BIT_TEST_(p_cbw->dir, 7) ? p_msc->ep_in : p_msc->ep_out;
if ( p_msc->data_len ) if ( p_msc->data_len )
{ {
TU_ASSERT( dcd_edpt_xfer(rhport, ep, p_msc->scsi_data, p_msc->data_len), TUSB_ERROR_DCD_EDPT_XFER ); TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_in, p_msc->scsi_data, p_msc->data_len), TUSB_ERROR_DCD_EDPT_XFER );
}else }else
{ {
// application does not provide data to response --> possibly unsupported SCSI command // application does not provide data to response --> possibly unsupported SCSI command
dcd_edpt_stall(rhport, ep); dcd_edpt_stall(rhport, p_msc->ep_in);
p_csw->status = MSC_CSW_STATUS_FAILED; p_csw->status = MSC_CSW_STATUS_FAILED;
p_msc->stage = MSC_STAGE_STATUS; p_msc->stage = MSC_STAGE_STATUS;
} }
} }
} }
@ -238,23 +239,32 @@ tusb_error_t mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, tusb_event_t event, u
case MSC_STAGE_DATA: case MSC_STAGE_DATA:
p_msc->xferred_len += xferred_bytes; p_msc->xferred_len += xferred_bytes;
// Data Stage is complete // Still transferring
if ( p_msc->xferred_len == p_msc->data_len ) if ( p_msc->xferred_len < p_msc->data_len )
{ {
p_msc->stage = MSC_STAGE_STATUS; if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) )
{
// Can be executed several times e.g write 8K bytes (several flash write)
read10_write10_data_xfer(rhport, p_msc);
}else
{
verify_breakpoint(); // unexpected error
}
} }
else if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) ) // Data Stage is complete
else
{ {
// Can be executed several times e.g write 8K bytes (several flash write) // Invoke callback if it is not READ10, WRITE10
read10_write10_data_xfer(rhport, p_msc); if ( ! ((SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0])) )
}else {
{ p_csw->status = tud_msc_scsi_cb(rhport, p_cbw->lun, p_cbw->command, p_msc->scsi_data, &p_msc->data_len);
// unlikely error }
verify_breakpoint();
p_msc->stage = MSC_STAGE_STATUS;
} }
break; break;
case MSC_STAGE_STATUS: break; // is processed immediately case MSC_STAGE_STATUS: break; // processed immediately after this switch
default : break; default : break;
} }

View File

@ -107,7 +107,7 @@ uint16_t tud_msc_write10_cb(uint8_t rhport, uint8_t lun, void** pp_buffer, uint3
* \param[in] scsi_cmd SCSI command contents, application should examine this command block to know which command host requested * \param[in] scsi_cmd SCSI command contents, application should examine this command block to know which command host requested
* \param[out] buffer Pointer to buffer which application need to update with the address to transfer data with host. * \param[out] buffer Pointer to buffer which application need to update with the address to transfer data with host.
* The buffer address can be anywhere since the stack will copy its contents to a internal USB-accessible buffer. * The buffer address can be anywhere since the stack will copy its contents to a internal USB-accessible buffer.
* \param[in] p_length Expected length from host, Application could update to actual data, but could not larger than original value. * \param[in] p_len Expected length from host, Application could update to actual data, but could not larger than original value.
* \retval non-zero Actual number of block that application can receive and must be less than or equal to \a \b block_count. * \retval non-zero Actual number of block that application can receive and must be less than or equal to \a \b block_count.
* \retval zero Indicate error in retrieving data from application. Tinyusb device stack will \b STALL the corresponding * \retval zero Indicate error in retrieving data from application. Tinyusb device stack will \b STALL the corresponding
* endpoint and return failed status in command status wrapper phase. * endpoint and return failed status in command status wrapper phase.