defer proc_async_io_done()

This commit is contained in:
hathach
2025-07-01 21:52:57 +07:00
parent 216a35e59a
commit c96cc4369f
2 changed files with 39 additions and 34 deletions

View File

@@ -254,10 +254,10 @@ TU_ATTR_ALWAYS_INLINE static inline void set_sense_medium_not_present(uint8_t lu
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00);
} }
static void proc_async_io_done(void *bytes_processed) { static void proc_async_io_done(void *bytes_io) {
mscd_interface_t *p_msc = &_mscd_itf; mscd_interface_t *p_msc = &_mscd_itf;
TU_VERIFY(p_msc->pending_io, ); TU_VERIFY(p_msc->pending_io, );
const int32_t nbytes = (int32_t) (intptr_t) bytes_processed; const int32_t nbytes = (int32_t) (intptr_t) bytes_io;
const uint8_t cmd = p_msc->cbw.command[0]; const uint8_t cmd = p_msc->cbw.command[0];
p_msc->pending_io = 0; p_msc->pending_io = 0;
@@ -283,15 +283,9 @@ bool tud_msc_async_io_done(int32_t bytes_io, bool in_isr) {
// Precheck to avoid queueing multiple RW done callback // Precheck to avoid queueing multiple RW done callback
TU_VERIFY(_mscd_itf.pending_io); TU_VERIFY(_mscd_itf.pending_io);
if (bytes_io == 0) { if (bytes_io == 0) {
bytes_io = TUD_MSC_RET_ERROR; // 0 is treated as error, no sense to call this with BUSY here bytes_io = TUD_MSC_RET_ERROR; // 0 is treated as error, no reason to call this with BUSY here
} }
usbd_defer_func(proc_async_io_done, (void *) (intptr_t) bytes_io, in_isr);
if (in_isr) {
usbd_defer_func(proc_async_io_done, (void*) (intptr_t)bytes_io, in_isr);
} else {
proc_async_io_done((void*)(intptr_t) bytes_io);
}
return true; return true;
} }
@@ -827,21 +821,26 @@ static void proc_read10_cmd(mscd_interface_t* p_msc) {
} }
static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) { static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) {
uint8_t rhport = p_msc->rhport; const uint8_t rhport = p_msc->rhport;
if (nbytes == TUD_MSC_RET_ERROR) { if (nbytes > 0) {
// error -> endpoint is stalled & status in CSW set to failed
TU_LOG_DRV(" IO read() failed\r\n");
// set sense
msc_cbw_t const* p_cbw = &p_msc->cbw;
set_sense_medium_not_present(p_cbw->lun);
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
} else if (nbytes == TUD_MSC_RET_BUSY) {
// zero means not ready -> fake a transfer complete so that this driver callback will fire again
dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false);
} else {
TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes),); TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes),);
} else {
// nbytes is status
switch (nbytes) {
case TUD_MSC_RET_ERROR:
// error -> endpoint is stalled & status in CSW set to failed
TU_LOG_DRV(" IO read() failed\r\n");
set_sense_medium_not_present(p_msc->cbw.lun);
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
break;
case TUD_MSC_RET_BUSY:
// not ready yet -> fake a transfer complete so that this driver callback will fire again
dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false);
break;
default: break;
}
} }
} }
@@ -886,13 +885,20 @@ static void proc_write10_host_data(mscd_interface_t* p_msc, uint32_t xferred_byt
static void proc_write_io_data(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes) { static void proc_write_io_data(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes) {
if (nbytes < 0) { if (nbytes < 0) {
// negative means error -> failed this scsi op // nbytes is status
TU_LOG_DRV(" IO write() failed\r\n"); switch (nbytes) {
set_sense_medium_not_present(p_msc->cbw.lun); case TUD_MSC_RET_ERROR:
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); // IO error -> failed this scsi op
TU_LOG_DRV(" IO write() failed\r\n");
set_sense_medium_not_present(p_msc->cbw.lun);
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
break;
default: break;
}
} else { } else {
if ((uint32_t)nbytes < xferred_bytes) { if ((uint32_t)nbytes < xferred_bytes) {
// Application consume less than what we got (including zero) // Application consume less than what we got including TUD_MSC_RET_BUSY (0)
const uint32_t left_over = xferred_bytes - (uint32_t)nbytes; const uint32_t left_over = xferred_bytes - (uint32_t)nbytes;
if (nbytes > 0) { if (nbytes > 0) {
memmove(_mscd_epbuf.buf, _mscd_epbuf.buf + nbytes, left_over); memmove(_mscd_epbuf.buf, _mscd_epbuf.buf + nbytes, left_over);

View File

@@ -79,12 +79,11 @@ bool tud_msc_async_io_done(int32_t bytes_io, bool in_isr);
- offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE.
- Application fill the buffer (up to bufsize) with address contents and return number of bytes read or status. - Application fill the buffer (up to bufsize) with address contents and return number of bytes read or status.
- 0 < ret < bufsize: These bytes are transferred first and callback will be invoked again for remaining data. - 0 < ret < bufsize: These bytes are transferred first and callback will be invoked again for remaining data.
- ret == TUD_MSC_RET_BUSY - TUD_MSC_RET_BUSY
Application is buys e.g disk I/O not ready. Application is buys e.g disk I/O not ready. Callback will be invoked again with the same parameters later on.
Callback will be invoked again with the same parameters later on. - TUD_MSC_RET_ERROR
- ret == TUD_MSC_RET_ERROR
error such as invalid address. This request will be STALLed and scsi command will be failed error such as invalid address. This request will be STALLed and scsi command will be failed
- ret == TUD_MSC_RET_ASYNC - TUD_MSC_RET_ASYNC
Data I/O will be done asynchronously in a background task. Application should return immediately. Data I/O will be done asynchronously in a background task. Application should return immediately.
tud_msc_async_io_done() must be called once IO/ is done to signal completion. tud_msc_async_io_done() must be called once IO/ is done to signal completion.
*/ */