|
|
@@ -53,15 +53,18 @@
|
|
|
//--------------------------------------------------------------------+
|
|
|
typedef struct {
|
|
|
pipe_handle_t bulk_in, bulk_out;
|
|
|
- uint8_t interface_number;
|
|
|
- uint8_t max_lun;
|
|
|
+ uint8_t interface_number;
|
|
|
+
|
|
|
+ uint8_t max_lun;
|
|
|
+ uint16_t block_size;
|
|
|
+ uint32_t last_lba; // last logical block address
|
|
|
|
|
|
uint8_t vendor_id[8];
|
|
|
uint8_t product_id[16];
|
|
|
|
|
|
msc_cmd_block_wrapper_t cbw;
|
|
|
msc_cmd_status_wrapper_t csw;
|
|
|
- uint8_t buffer[100];
|
|
|
+ ATTR_ALIGNED(4) uint8_t buffer[100];
|
|
|
}msch_interface_t;
|
|
|
|
|
|
STATIC_VAR msch_interface_t msch_data[TUSB_CFG_HOST_DEVICE_MAX] TUSB_CFG_ATTR_USBRAM; // TODO to be static
|
|
|
@@ -76,26 +79,106 @@ STATIC_VAR uint8_t msch_buffer[10] TUSB_CFG_ATTR_USBRAM;
|
|
|
//--------------------------------------------------------------------+
|
|
|
// PUBLIC API
|
|
|
//--------------------------------------------------------------------+
|
|
|
-bool tusbh_msc_is_mounted(uint8_t dev_addr)
|
|
|
+bool tusbh_msc_is_mounted(uint8_t dev_addr)
|
|
|
{
|
|
|
return tusbh_device_is_configured(dev_addr) &&
|
|
|
pipehandle_is_valid(msch_data[dev_addr-1].bulk_in) &&
|
|
|
pipehandle_is_valid(msch_data[dev_addr-1].bulk_out);
|
|
|
}
|
|
|
|
|
|
-uint8_t const * tusbh_msc_get_vendor_name(uint8_t dev_addr)
|
|
|
+uint8_t const* tusbh_msc_get_vendor_name(uint8_t dev_addr)
|
|
|
{
|
|
|
return tusbh_msc_is_mounted(dev_addr) ? msch_data[dev_addr-1].vendor_id : NULL;
|
|
|
}
|
|
|
|
|
|
-uint8_t const * tusbh_msc_get_product_name(uint8_t dev_addr)
|
|
|
+uint8_t const* tusbh_msc_get_product_name(uint8_t dev_addr)
|
|
|
{
|
|
|
return tusbh_msc_is_mounted(dev_addr) ? msch_data[dev_addr-1].product_id : NULL;
|
|
|
}
|
|
|
|
|
|
+tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size)
|
|
|
+{
|
|
|
+ if ( !tusbh_msc_is_mounted(dev_addr) ) return TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED;
|
|
|
+ ASSERT(p_last_lba != NULL && p_block_size != NULL, TUSB_ERROR_INVALID_PARA);
|
|
|
+
|
|
|
+ (*p_last_lba) = msch_data[dev_addr-1].last_lba;
|
|
|
+ (*p_block_size) = (uint32_t) msch_data[dev_addr-1].block_size;
|
|
|
+
|
|
|
+ return TUSB_ERROR_NONE;
|
|
|
+}
|
|
|
+
|
|
|
//--------------------------------------------------------------------+
|
|
|
// CLASS-USBH API (don't require to verify parameters)
|
|
|
//--------------------------------------------------------------------+
|
|
|
+static tusb_error_t scsi_command_send(msch_interface_t * p_msch, scsi_cmd_type_t cmd_code, uint8_t lun)
|
|
|
+{
|
|
|
+ p_msch->cbw.signature = 0x43425355;
|
|
|
+ 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 = SCSI_CMD_INQUIRY,
|
|
|
+ .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 = SCSI_CMD_READ_CAPACITY_10,
|
|
|
+ .logical_block_addr = 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 = SCSI_CMD_REQUEST_SENSE,
|
|
|
+ .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( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
|
|
|
+ ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , p_msch->buffer, p_msch->cbw.xfer_bytes, false) );
|
|
|
+ //ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , &p_msch->csw, sizeof(msc_cmd_status_wrapper_t), true) );
|
|
|
+}
|
|
|
+
|
|
|
void msch_init(void)
|
|
|
{
|
|
|
memclr_(msch_data, sizeof(msch_interface_t)*TUSB_CFG_HOST_DEVICE_MAX);
|
|
|
@@ -142,31 +225,26 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con
|
|
|
SUBTASK_ASSERT( TUSB_ERROR_NONE == error /* && TODO STALL means zero */);
|
|
|
msch_data[dev_addr-1].max_lun = msch_buffer[0];
|
|
|
|
|
|
- //------------- SCSI Inquiry -------------//
|
|
|
- msch_data[dev_addr-1].cbw = (msc_cmd_block_wrapper_t) {
|
|
|
- .signature = 0x43425355,
|
|
|
- .tag = 0xCAFECAFE,
|
|
|
- .xfer_bytes = sizeof(scsi_inquiry_data_t),
|
|
|
- .flags = TUSB_DIR_DEV_TO_HOST_MASK,
|
|
|
- .lun = 0,
|
|
|
- .cmd_len = sizeof(scsi_inquiry_t),
|
|
|
- };
|
|
|
- scsi_inquiry_t cmd_inquiry =
|
|
|
- {
|
|
|
- .operation_code = SCSI_CMD_INQUIRY,
|
|
|
- .alloc_length = sizeof(scsi_inquiry_data_t)
|
|
|
- };
|
|
|
- memcpy(msch_data[dev_addr-1].cbw.command, &cmd_inquiry, sizeof(scsi_inquiry_t));
|
|
|
+#if 0
|
|
|
+ //------------- Reset -------------//
|
|
|
+ OSAL_SUBTASK_INVOKED_AND_WAIT(
|
|
|
+ usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
|
|
|
+ MSC_REQUEST_RESET, 0, msch_data[dev_addr-1].interface_number,
|
|
|
+ 0, NULL ),
|
|
|
+ error
|
|
|
+ );
|
|
|
+#endif
|
|
|
|
|
|
- hcd_pipe_xfer(msch_data[dev_addr-1].bulk_out, &msch_data[dev_addr-1].cbw, sizeof(msc_cmd_block_wrapper_t), false);
|
|
|
- hcd_pipe_xfer(msch_data[dev_addr-1].bulk_in , msch_data[dev_addr-1].buffer, sizeof(scsi_inquiry_data_t), false);
|
|
|
- hcd_pipe_xfer(msch_data[dev_addr-1].bulk_in , &msch_data[dev_addr-1].csw, sizeof(msc_cmd_status_wrapper_t), true);
|
|
|
|
|
|
// TODO timeout required, a proper synchronization
|
|
|
// while( !hcd_pipe_is_idle(msch_data[dev_addr-1].bulk_in) )
|
|
|
- {
|
|
|
- osal_task_delay(2);
|
|
|
- }
|
|
|
+
|
|
|
+ //------------- SCSI Inquiry -------------//
|
|
|
+ scsi_command_send(&msch_data[dev_addr-1], SCSI_CMD_INQUIRY, 0);
|
|
|
+ osal_task_delay(5);
|
|
|
+ ASSERT_STATUS( hcd_pipe_xfer(msch_data[dev_addr-1].bulk_in , (uint8_t*) &msch_data[dev_addr-1].csw, sizeof(msc_cmd_status_wrapper_t), true) );
|
|
|
+ osal_task_delay(5);
|
|
|
+ // check csw
|
|
|
|
|
|
memcpy(msch_data[dev_addr-1].vendor_id,
|
|
|
((scsi_inquiry_data_t*)msch_data[dev_addr-1].buffer)->vendor_id,
|
|
|
@@ -175,6 +253,24 @@ tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t con
|
|
|
((scsi_inquiry_data_t*)msch_data[dev_addr-1].buffer)->product_id,
|
|
|
16);
|
|
|
|
|
|
+#if 0
|
|
|
+ //------------- SCSI Request Sense -------------//
|
|
|
+ scsi_command_send(&msch_data[dev_addr-1], SCSI_CMD_REQUEST_SENSE, 0);
|
|
|
+ osal_task_delay(5);
|
|
|
+ ASSERT_STATUS( hcd_pipe_xfer(msch_data[dev_addr-1].bulk_in , (uint8_t*) &msch_data[dev_addr-1].csw, sizeof(msc_cmd_status_wrapper_t), true) );
|
|
|
+ osal_task_delay(5);
|
|
|
+#endif
|
|
|
+
|
|
|
+ //------------- SCSI Read Capacity 10 -------------//
|
|
|
+ scsi_command_send(&msch_data[dev_addr-1], SCSI_CMD_READ_CAPACITY_10, 0);
|
|
|
+ osal_task_delay(5);
|
|
|
+ ASSERT_STATUS( hcd_pipe_xfer(msch_data[dev_addr-1].bulk_in , (uint8_t*) &msch_data[dev_addr-1].csw, sizeof(msc_cmd_status_wrapper_t), true) );
|
|
|
+ osal_task_delay(5);
|
|
|
+ // check csw
|
|
|
+
|
|
|
+ msch_data[dev_addr-1].last_lba = __be2le( ((scsi_read_capacity10_data_t*)msch_data[dev_addr-1].buffer)->last_lba );
|
|
|
+ msch_data[dev_addr-1].block_size = (uint16_t) __be2le( ((scsi_read_capacity10_data_t*)msch_data[dev_addr-1].buffer)->block_size );
|
|
|
+
|
|
|
tusbh_msc_mounted_cb(dev_addr);
|
|
|
|
|
|
OSAL_SUBTASK_END
|
|
|
@@ -198,16 +294,6 @@ void msch_close(uint8_t dev_addr)
|
|
|
//--------------------------------------------------------------------+
|
|
|
// INTERNAL & HELPER
|
|
|
//--------------------------------------------------------------------+
|
|
|
-//static tusb_error_t scsi_command_send(msc_cmd_block_wrapper_t const * cbw, uint8_t * buffer, msc_cmd_status_wrapper_t const * csw)
|
|
|
-//{
|
|
|
-// tusb_error_t error;
|
|
|
-//
|
|
|
-// OSAL_SUBTASK_BEGIN
|
|
|
-//
|
|
|
-// hcd_pipe_xfer()
|
|
|
-//
|
|
|
-// OSAL_SUBTASK_END
|
|
|
-//}
|
|
|
|
|
|
|
|
|
#endif
|