Explorar o código

added read capacity 10 with hacking code

hathach %!s(int64=12) %!d(string=hai) anos
pai
achega
a8a10e8650

+ 8 - 3
demos/host/src/msc_app.c

@@ -66,13 +66,18 @@ void tusbh_msc_mounted_cb(uint8_t dev_addr)
   uint8_t const* p_vendor  = tusbh_msc_get_vendor_name(dev_addr);
   uint8_t const* p_product = tusbh_msc_get_product_name(dev_addr);
 
-  printf("Vendor  Id: ");
+  printf("Vendor  Name: ");
   for(uint8_t i=0; i<8; i++) putchar(p_vendor[i]);
+  putchar('\n');
 
-  printf("\nProduct Id: ");
+  printf("Product Name: ");
   for(uint8_t i=0; i<16; i++) putchar(p_product[i]);
-
   putchar('\n');
+
+  uint32_t last_lba, block_size;
+  tusbh_msc_get_capacity(dev_addr, &last_lba, &block_size);
+  printf("Disk Size: %d MB\n", (last_lba+1)/ ((1024*1024)/block_size) );
+  printf("LBA 0-0x%X, Block Size: %d\n", last_lba, block_size);
 }
 
 //--------------------------------------------------------------------+

+ 23 - 10
tinyusb/class/msc.h

@@ -80,6 +80,7 @@ typedef enum {
   SCSI_CMD_TEST_UNIT_READY  = 0x00,
   SCSI_CMD_INQUIRY          = 0x12,
   SCSI_CMD_READ_CAPACITY_10 = 0x25,
+  SCSI_CMD_REQUEST_SENSE    = 0x03,
   SCSI_CMD_READ_10          = 0x28,
   SCSI_CMD_WRITE_10         = 0x2A,
 }scsi_cmd_type_t;
@@ -115,12 +116,13 @@ STATIC_ASSERT(sizeof(msc_cmd_status_wrapper_t) == 13, "size is not correct");
 // SCSI Primary Command (SPC-4)
 //--------------------------------------------------------------------+
 typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t  operation_code;
-  uint8_t  reserve;
-  uint8_t  page_code;
-  uint16_t alloc_length;
-  uint8_t  control;
-} scsi_inquiry_t;
+  uint8_t cmd_code;
+  uint8_t reserved1;
+  uint8_t page_code;
+  uint8_t reserved2;
+  uint8_t alloc_length;
+  uint8_t control;
+} scsi_inquiry_t, scsi_request_sense_t;
 
 STATIC_ASSERT(sizeof(scsi_inquiry_t) == 6, "size is not correct");
 
@@ -172,12 +174,23 @@ STATIC_ASSERT(sizeof(scsi_inquiry_data_t) == 36, "size is not correct");
 //--------------------------------------------------------------------+
 // SCSI Block Command (SBC-3)
 //--------------------------------------------------------------------+
-typedef struct {
-  uint8_t logical_block_addr[4];
-  uint8_t block_length[4];
-} msc_scsi_read_capacity10_t;
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t  cmd_code;
+  uint8_t  reserved1;
+  uint32_t logical_block_addr;
+  uint16_t reserved2;
+  uint8_t  partial_medium_indicator;
+  uint8_t  control;
+} scsi_read_capacity10_t;
+
+STATIC_ASSERT(sizeof(scsi_read_capacity10_t) == 10, "size is not correct");
 
+typedef struct {
+  uint32_t last_lba;
+  uint32_t block_size;
+} scsi_read_capacity10_data_t;
 
+STATIC_ASSERT(sizeof(scsi_read_capacity10_data_t) == 8, "size is not correct");
 
 #ifdef __cplusplus
  }

+ 123 - 37
tinyusb/class/msc_host.c

@@ -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

+ 14 - 8
tinyusb/class/msc_host.h

@@ -60,14 +60,20 @@
 //--------------------------------------------------------------------+
 bool          tusbh_msc_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
 tusb_interface_status_t tusbh_msc_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
-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_inquiry(uint8_t dev_addr, uint8_t instance_num, scsi_inquiry_data_t * p_inquiry_data) ATTR_WARN_UNUSED_RESULT;
-tusb_error_t  tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t instance_num) ATTR_WARN_UNUSED_RESULT;
-tusb_error_t  tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t instance_num, msc_scsi_read_capacity10_t * p_buffer) ATTR_WARN_UNUSED_RESULT;
-tusb_error_t  tusbh_msc_read10(uint8_t dev_addr, uint8_t instance_num, void * p_buffer, uint32_t length) ATTR_WARN_UNUSED_RESULT;
-tusb_error_t  tusbh_msc_write10(uint8_t dev_addr, uint8_t instance_num, void const * p_data, uint32_t length) ATTR_WARN_UNUSED_RESULT;
+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_inquiry(uint8_t dev_addr, scsi_inquiry_data_t * p_inquiry_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_read_capacity10(uint8_t dev_addr, scsi_read_capacity10_t * p_buffer) ATTR_WARN_UNUSED_RESULT;
+tusb_error_t  tusbh_msc_read10(uint8_t dev_addr, void * p_buffer, uint32_t length) 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_scsi_send(uint8_t dev_addr, uint8_t lun, bool is_direction_in,
+//                                  uint8_t const * p_command, uint8_t cmd_len,
+//                                  uint8_t * p_response, uint32_t resp_len) ATTR_WARN_UNUSED_RESULT;
+
 //------------- Application Callback -------------//
 void tusbh_msc_mounted_cb(uint8_t dev_addr);
 

+ 4 - 0
tinyusb/common/compiler/compiler_gcc.h

@@ -130,6 +130,10 @@
 *  @{
 */
 
+// built-in function to convert 32-bit Big-Endian to Little-Endian
+#define __be2le   __builtin_bswap32
+
+
 /** You can use the built-in function \b __builtin_constant_p to determine if a value is known to be constant at compile time and hence that GCC can perform constant-folding on expressions involving that value. The argument of the function is the value to test. The function returns the integer 1 if the argument is known to be a compile-time constant and 0 if it is not known to be a compile-time constant. A return of 0 does not indicate that the value is not a constant, but merely that GCC cannot prove it is a constant with the specified value of the -O option.
  You typically use this function in an embedded application where memory is a critical resource. If you have some complex calculation, you may want it to be folded if it involves constants, but need to call a function if it does not. For example:
  \code

+ 3 - 0
tinyusb/common/compiler/compiler_iar.h

@@ -83,6 +83,9 @@
 #define ATTR_USED
 #define ATTR_UNUSED
 
+// built-in function to convert 32-bit Big-Endian to Little-Endian
+#define __be2le   __REV
+
 #if 0
 
 				/** Indicates to the compiler that the function can not ever return, so that any stack restoring or

+ 2 - 0
tinyusb/common/errors.h

@@ -85,6 +85,8 @@
     ENTRY(TUSB_ERROR_CDCH_UNSUPPORTED_PROTOCOL       )\
     ENTRY(TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED         )\
     ENTRY(TUSB_ERROR_MSCH_UNSUPPORTED_PROTOCOL       )\
+    ENTRY(TUSB_ERROR_MSCH_UNKNOWN_SCSI_COMMAND       )\
+    ENTRY(TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED         )\
     ENTRY(TUSB_ERROR_NOT_SUPPORTED_YET               )\
     ENTRY(TUSB_ERROR_FAILED                          )\
 

+ 1 - 1
tinyusb/host/ehci/ehci.h

@@ -78,7 +78,7 @@
 
 // TODO allow user to configure
 #define EHCI_MAX_QHD  8
-#define EHCI_MAX_QTD  12
+#define EHCI_MAX_QTD  20
 #define EHCI_MAX_ITD  4
 #define EHCI_MAX_SITD 16