diff --git a/tinyusb/class/msc.h b/tinyusb/class/msc.h index fea1702a..5ca1db6b 100644 --- a/tinyusb/class/msc.h +++ b/tinyusb/class/msc.h @@ -206,11 +206,10 @@ typedef ATTR_PACKED_STRUCT(struct) { uint8_t reserved2; uint16_t block_count; uint8_t control; -} scsi_read10_t; +} scsi_read10_t, scsi_write10_t; STATIC_ASSERT(sizeof(scsi_read10_t) == 10, "size is not correct"); - - +STATIC_ASSERT(sizeof(scsi_write10_t) == 10, "size is not correct"); #ifdef __cplusplus } diff --git a/tinyusb/class/msc_host.c b/tinyusb/class/msc_host.c index d70cc9b9..b4fd5b12 100644 --- a/tinyusb/class/msc_host.c +++ b/tinyusb/class/msc_host.c @@ -105,9 +105,14 @@ tusb_interface_status_t tusbh_msc_status(uint8_t dev_addr) return TUSB_INTERFACE_STATUS_READY; } -//--------------------------------------------------------------------+ -// CLASS-USBH API (don't require to verify parameters) -//--------------------------------------------------------------------+ +static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) ATTR_ALWAYS_INLINE; +static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) +{ + p_cbw->signature = MSC_CBW_SIGNATURE; + p_cbw->tag = 0xCAFECAFE; + p_cbw->lun = lun; +} + static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) ATTR_WARN_UNUSED_RESULT; static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) { @@ -118,84 +123,88 @@ static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) return TUSB_ERROR_NONE; } -static tusb_error_t scsi_command_send(msch_interface_t * p_msch, scsi_cmd_type_t cmd_code, uint8_t lun, uint8_t* p_data) -{ - p_msch->cbw.signature = MSC_CBW_SIGNATURE; - p_msch->cbw.tag = 0xCAFECAFE; - p_msch->cbw.lun = lun; - - switch ( cmd_code ) - { - case SCSI_CMD_INQUIRY: - p_msch->cbw.xfer_bytes = sizeof(scsi_inquiry_data_t); - p_msch->cbw.flags = TUSB_DIR_DEV_TO_HOST_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); - - scsi_inquiry_t cmd_inquiry = - { - .cmd_code = cmd_code, - .alloc_length = sizeof(scsi_inquiry_data_t) - }; - - memcpy(p_msch->cbw.command, &cmd_inquiry, sizeof(scsi_inquiry_t)); - break; - - case SCSI_CMD_READ_CAPACITY_10: - p_msch->cbw.xfer_bytes = sizeof(scsi_read_capacity10_data_t); - p_msch->cbw.flags = TUSB_DIR_DEV_TO_HOST_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t); - - scsi_read_capacity10_t cmd_read_capacity10 = - { - .cmd_code = cmd_code, - .lba = 0, - .partial_medium_indicator = 0 - }; - - memcpy(p_msch->cbw.command, &cmd_read_capacity10, sizeof(scsi_read_capacity10_t)); - break; - - case SCSI_CMD_TEST_UNIT_READY: - break; - - case SCSI_CMD_READ_10: - - break; - - case SCSI_CMD_WRITE_10: - break; - - case SCSI_CMD_REQUEST_SENSE: - p_msch->cbw.xfer_bytes = 18; - p_msch->cbw.flags = TUSB_DIR_DEV_TO_HOST_MASK; - p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t); - - scsi_request_sense_t cmd_request_sense = - { - .cmd_code = cmd_code, - .alloc_length = 18 - }; - - memcpy(p_msch->cbw.command, &cmd_request_sense, sizeof(scsi_request_sense_t)); - break; - - default: - return TUSB_ERROR_MSCH_UNKNOWN_SCSI_COMMAND; - } - - ASSERT_STATUS( msch_command_xfer(p_msch, p_data) ); - - return TUSB_ERROR_NONE; -} - -tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint32_t block_count) +//--------------------------------------------------------------------+ +// PUBLIC API: SCSI COMMAND +//--------------------------------------------------------------------+ +tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) { msch_interface_t* p_msch = &msch_data[dev_addr-1]; //------------- Command Block Wrapper -------------// - p_msch->cbw.signature = MSC_CBW_SIGNATURE; - p_msch->cbw.tag = 0xCAFECAFE; - p_msch->cbw.lun = lun; + msc_cbw_add_signature(&p_msch->cbw, lun); + p_msch->cbw.xfer_bytes = sizeof(scsi_inquiry_data_t); + p_msch->cbw.flags = TUSB_DIR_DEV_TO_HOST_MASK; + p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t); + + //------------- SCSI command -------------// + scsi_inquiry_t cmd_inquiry = + { + .cmd_code = SCSI_CMD_INQUIRY, + .alloc_length = sizeof(scsi_inquiry_data_t) + }; + + memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&p_msch->cbw, lun); + p_msch->cbw.xfer_bytes = sizeof(scsi_read_capacity10_data_t); + p_msch->cbw.flags = TUSB_DIR_DEV_TO_HOST_MASK; + p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t); + + //------------- SCSI command -------------// + scsi_read_capacity10_t cmd_read_capacity10 = + { + .cmd_code = SCSI_CMD_READ_CAPACITY_10, + .lba = 0, + .partial_medium_indicator = 0 + }; + + memcpy(p_msch->cbw.command, &cmd_read_capacity10, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + p_msch->cbw.xfer_bytes = 18; + p_msch->cbw.flags = TUSB_DIR_DEV_TO_HOST_MASK; + p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t); + + //------------- SCSI command -------------// + scsi_request_sense_t cmd_request_sense = + { + .cmd_code = SCSI_CMD_REQUEST_SENSE, + .alloc_length = 18 + }; + + memcpy(p_msch->cbw.command, &cmd_request_sense, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) ); + + return TUSB_ERROR_NONE; +} + +tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&p_msch->cbw, lun); + p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes p_msch->cbw.flags = TUSB_DIR_DEV_TO_HOST_MASK; p_msch->cbw.cmd_len = sizeof(scsi_read10_t); @@ -205,7 +214,7 @@ tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, u { .cmd_code = SCSI_CMD_READ_10, .lba = __le2be(lba), - .block_count = ((uint8_t)block_count) << 8 // TODO a proper le to be for uint16_t + .block_count = u16_le2be(block_count) }; memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len); @@ -215,6 +224,35 @@ tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, u return TUSB_ERROR_NONE; } +tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) +{ + msch_interface_t* p_msch = &msch_data[dev_addr-1]; + + //------------- Command Block Wrapper -------------// + msc_cbw_add_signature(&p_msch->cbw, lun); + + p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes + p_msch->cbw.flags = TUSB_DIR_DEV_TO_HOST_MASK; + p_msch->cbw.cmd_len = sizeof(scsi_write10_t); + + //------------- SCSI command -------------// + scsi_write10_t cmd_write10 = + { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = __le2be(lba), + .block_count = u16_le2be(block_count) + }; + + memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len); + + ASSERT_STATUS ( msch_command_xfer(p_msch, p_buffer)); + + return TUSB_ERROR_NONE; +} + +//--------------------------------------------------------------------+ +// CLASS-USBH API (don't require to verify parameters) +//--------------------------------------------------------------------+ void msch_init(void) { memclr_(msch_data, sizeof(msch_interface_t)*TUSB_CFG_HOST_DEVICE_MAX); @@ -276,7 +314,7 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con enum { SCSI_XFER_TIMEOUT = 1000 }; //------------- SCSI Inquiry -------------// - scsi_command_send(&msch_data[dev_addr-1], SCSI_CMD_INQUIRY, 0, msch_buffer); + tusbh_msc_inquiry(dev_addr, 0, msch_buffer); osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); SUBTASK_ASSERT_STATUS(error); @@ -284,7 +322,7 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con memcpy(msch_data[dev_addr-1].product_id, ((scsi_inquiry_data_t*) msch_buffer)->product_id, 16); //------------- SCSI Read Capacity 10 -------------// - scsi_command_send(&msch_data[dev_addr-1], SCSI_CMD_READ_CAPACITY_10, 0, msch_buffer); + tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); SUBTASK_ASSERT_STATUS(error); @@ -304,12 +342,12 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con SUBTASK_ASSERT_STATUS(error); //------------- SCSI Request Sense -------------// - scsi_command_send(&msch_data[dev_addr-1], SCSI_CMD_REQUEST_SENSE, 0, msch_buffer); + tusbh_msc_request_sense(dev_addr, 0, msch_buffer); osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); SUBTASK_ASSERT_STATUS(error); //------------- Re-read SCSI Read Capactity -------------// - scsi_command_send(&msch_data[dev_addr-1], SCSI_CMD_READ_CAPACITY_10, 0, msch_buffer); + tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer); osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); SUBTASK_ASSERT_STATUS(error); } diff --git a/tinyusb/class/msc_host.h b/tinyusb/class/msc_host.h index 1a9b7183..df2f6d83 100644 --- a/tinyusb/class/msc_host.h +++ b/tinyusb/class/msc_host.h @@ -64,8 +64,9 @@ uint8_t const* tusbh_msc_get_vendor_name(uint8_t dev_addr); uint8_t const* tusbh_msc_get_product_name(uint8_t dev_addr); tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size); -tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint32_t block_count) ATTR_WARN_UNUSED_RESULT; -tusb_error_t tusbh_msc_write10(uint8_t dev_addr, void const * p_data, uint32_t length) ATTR_WARN_UNUSED_RESULT; +tusb_error_t tusbh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT; +tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT; +tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data) ATTR_WARN_UNUSED_RESULT; //tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT; //tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, scsi_inquiry_data_t * p_inquiry_data) ATTR_WARN_UNUSED_RESULT; diff --git a/tinyusb/common/common.h b/tinyusb/common/common.h index 3a43f123..73de8bce 100644 --- a/tinyusb/common/common.h +++ b/tinyusb/common/common.h @@ -134,6 +134,12 @@ static inline uint8_t u16_low_u8(uint16_t u16) return (uint8_t) (u16 & 0x00ff); } +static inline uint16_t u16_le2be(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint16_t u16_le2be(uint16_t u16) +{ + return (u16_low_u8(u16) << 8) | u16_high_u8(u16); +} + //------------- Min -------------// static inline uint8_t min8_of(uint8_t x, uint8_t y) ATTR_ALWAYS_INLINE ATTR_CONST; static inline uint8_t min8_of(uint8_t x, uint8_t y)