From fdf1ff545f41c23f63e86d6debaa852e731d7644 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 29 Aug 2021 15:44:27 +0700 Subject: [PATCH] responding with status per-spec in test case 4 --- src/class/msc/msc_device.c | 83 ++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 52dfcb836..7dcd4983e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -138,11 +138,16 @@ static inline uint32_t rdwr10_get_lba(uint8_t const command[]) return tu_ntohl(lba); } +static inline uint16_t rdwr10_get_blockcount(msc_cbw_t const* cbw) +{ + uint16_t const block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); + return tu_ntohs(block_count); +} + static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) { // first extract block count in the command - uint16_t block_count = tu_unaligned_read16(cbw->command + offsetof(scsi_write10_t, block_count)); - block_count = tu_ntohs(block_count); + uint16_t const block_count = rdwr10_get_blockcount(cbw); // invalid block count if (block_count == 0) return 0; @@ -150,6 +155,43 @@ static inline uint16_t rdwr10_get_blocksize(msc_cbw_t const* cbw) return cbw->total_bytes / block_count; } +uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) +{ + uint8_t status = MSC_CSW_STATUS_PASSED; + uint16_t const block_count = rdwr10_get_blockcount(cbw); + + if ( cbw->total_bytes == 0 ) + { + if ( block_count ) + { + TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di) or case 3 (Hn < Do) \r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + }else + { + // no data transfer, only exist in complaint test suite + } + }else + { + if ( SCSI_CMD_READ_10 == cbw->command[0] && !is_data_in(cbw->dir) ) + { + TU_LOG(MSC_DEBUG, " SCSI case 10 (Ho <> Di)\r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + } + else if ( SCSI_CMD_WRITE_10 == cbw->command[0] && is_data_in(cbw->dir) ) + { + TU_LOG(MSC_DEBUG, " SCSI case 8 (Hi <> Do)\r\n"); + status = MSC_CSW_STATUS_PHASE_ERROR; + } + else if ( !block_count ) + { + TU_LOG(MSC_DEBUG, " SCSI case 4 Hi > Dn\r\n"); + status = MSC_CSW_STATUS_FAILED; + } + } + + return status; +} + //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ @@ -368,30 +410,27 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t p_msc->total_len = p_cbw->total_bytes; p_msc->xferred_len = 0; - if ( SCSI_CMD_READ_10 == p_cbw->command[0] ) + // Read10 or Write10 + if ( (SCSI_CMD_READ_10 == p_cbw->command[0]) || (SCSI_CMD_WRITE_10 == p_cbw->command[0]) ) { - // Invalid CBW length == 0 or Direction bit is incorrect - // 6.7 The 13 Cases: case 2 (Hn < Di), case 3 (Hn < Do), case 10 (Ho <> Di) -> phase error - if ( rdwr10_get_blocksize(p_cbw) == 0 || !is_data_in(p_cbw->dir) ) + uint8_t const status = rdwr10_validate_cmd(p_cbw); + + if ( status != MSC_CSW_STATUS_PASSED) { - TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di), case 3 (Hn < Do), case 10 (Ho <> Di)\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_PHASE_ERROR); + fail_scsi_op(rhport, p_msc, status); + }else if ( p_cbw->total_bytes ) + { + if (SCSI_CMD_READ_10 == p_cbw->command[0]) + { + proc_read10_cmd(rhport, p_msc); + }else + { + proc_write10_cmd(rhport, p_msc); + } }else { - proc_read10_cmd(rhport, p_msc); - } - } - else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) - { - // Invalid CBW length == 0 or Direction bit is incorrect - // 6.7 The 13 Cases: case 2 (Hn < Do), case 3 (Hn < Do), case 8 (Hi <> Do) -> phase error - if ( rdwr10_get_blocksize(p_cbw) == 0 || is_data_in(p_cbw->dir) ) - { - TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di), case 3 (Hn < Do), case 8 (Hi <> Do)\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_PHASE_ERROR); - }else - { - proc_write10_cmd(rhport, p_msc); + // no data transfer, only exist in complaint test suite + p_msc->stage = MSC_STAGE_STATUS; } } else