tinyusb  0.4
Click here to lend your support to tinyusb donation and make a donation at pledgie.com
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
msc_host.c
Go to the documentation of this file.
1 /**************************************************************************/
37 /**************************************************************************/
38 
39 #include "tusb_option.h"
40 
41 #if MODE_HOST_SUPPORTED & TUSB_CFG_HOST_MSC
42 
43 #define _TINY_USB_SOURCE_FILE_
44 
45 //--------------------------------------------------------------------+
46 // INCLUDE
47 //--------------------------------------------------------------------+
48 #include "common/common.h"
49 #include "msc_host.h"
50 
51 //--------------------------------------------------------------------+
52 // MACRO CONSTANT TYPEDEF
53 //--------------------------------------------------------------------+
54 TUSB_CFG_ATTR_USBRAM STATIC_VAR msch_interface_t msch_data[TUSB_CFG_HOST_DEVICE_MAX];
55 
56 
57 //------------- Initalization Data -------------//
58 OSAL_SEM_DEF(msch_semaphore);
59 static osal_semaphore_handle_t msch_sem_hdl;
60 
61 // buffer used to read scsi information when mounted, largest response data currently is inquiry
62 TUSB_CFG_ATTR_USBRAM ATTR_ALIGNED(4) STATIC_VAR uint8_t msch_buffer[sizeof(scsi_inquiry_data_t)];
63 
64 //--------------------------------------------------------------------+
65 // INTERNAL OBJECT & FUNCTION DECLARATION
66 //--------------------------------------------------------------------+
67 
68 //--------------------------------------------------------------------+
69 // PUBLIC API
70 //--------------------------------------------------------------------+
71 bool tusbh_msc_is_mounted(uint8_t dev_addr)
72 {
73  return tusbh_device_is_configured(dev_addr) && // is configured can be omitted
74  msch_data[dev_addr-1].is_initialized;
75 }
76 
77 bool tusbh_msc_is_busy(uint8_t dev_addr)
78 {
79  return msch_data[dev_addr-1].is_initialized &&
80  hcd_pipe_is_busy(msch_data[dev_addr-1].bulk_in);
81 }
82 
83 uint8_t const* tusbh_msc_get_vendor_name(uint8_t dev_addr)
84 {
85  return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].vendor_id : NULL;
86 }
87 
88 uint8_t const* tusbh_msc_get_product_name(uint8_t dev_addr)
89 {
90  return msch_data[dev_addr-1].is_initialized ? msch_data[dev_addr-1].product_id : NULL;
91 }
92 
93 tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t* p_last_lba, uint32_t* p_block_size)
94 {
95  if ( !msch_data[dev_addr-1].is_initialized ) return TUSB_ERROR_MSCH_DEVICE_NOT_MOUNTED;
96  ASSERT(p_last_lba != NULL && p_block_size != NULL, TUSB_ERROR_INVALID_PARA);
97 
98  (*p_last_lba) = msch_data[dev_addr-1].last_lba;
99  (*p_block_size) = (uint32_t) msch_data[dev_addr-1].block_size;
100 
101  return TUSB_ERROR_NONE;
102 }
103 
104 //--------------------------------------------------------------------+
105 // PUBLIC API: SCSI COMMAND
106 //--------------------------------------------------------------------+
107 static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun) ATTR_ALWAYS_INLINE;
108 static inline void msc_cbw_add_signature(msc_cmd_block_wrapper_t *p_cbw, uint8_t lun)
109 {
110  p_cbw->signature = MSC_CBW_SIGNATURE;
111  p_cbw->tag = 0xCAFECAFE;
112  p_cbw->lun = lun;
113 }
114 
115 static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer) ATTR_WARN_UNUSED_RESULT;
116 static tusb_error_t msch_command_xfer(msch_interface_t * p_msch, void* p_buffer)
117 {
118  if ( NULL != p_buffer)
119  { // there is data phase
120  if (p_msch->cbw.dir & TUSB_DIR_DEV_TO_HOST_MASK)
121  {
122  ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
123  ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_in , p_buffer, p_msch->cbw.xfer_bytes) );
124  }else
125  {
126  ASSERT_STATUS( hcd_pipe_queue_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t)) );
127  ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out , p_buffer, p_msch->cbw.xfer_bytes, false) );
128  }
129  }
130 
131  ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) &p_msch->csw, sizeof(msc_cmd_status_wrapper_t), true) );
132 
133  return TUSB_ERROR_NONE;
134 }
135 
136 tusb_error_t tusbh_msc_inquiry(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
137 {
138  msch_interface_t* p_msch = &msch_data[dev_addr-1];
139 
140  //------------- Command Block Wrapper -------------//
141  msc_cbw_add_signature(&p_msch->cbw, lun);
142  p_msch->cbw.xfer_bytes = sizeof(scsi_inquiry_data_t);
143  p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
144  p_msch->cbw.cmd_len = sizeof(scsi_inquiry_t);
145 
146  //------------- SCSI command -------------//
147  scsi_inquiry_t cmd_inquiry =
148  {
150  .alloc_length = sizeof(scsi_inquiry_data_t)
151  };
152 
153  memcpy(p_msch->cbw.command, &cmd_inquiry, p_msch->cbw.cmd_len);
154 
155  ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
156 
157  return TUSB_ERROR_NONE;
158 }
159 
160 tusb_error_t tusbh_msc_read_capacity10(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
161 {
162  msch_interface_t* p_msch = &msch_data[dev_addr-1];
163 
164  //------------- Command Block Wrapper -------------//
165  msc_cbw_add_signature(&p_msch->cbw, lun);
166  p_msch->cbw.xfer_bytes = sizeof(scsi_read_capacity10_data_t);
167  p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
168  p_msch->cbw.cmd_len = sizeof(scsi_read_capacity10_t);
169 
170  //------------- SCSI command -------------//
171  scsi_read_capacity10_t cmd_read_capacity10 =
172  {
174  .lba = 0,
175  .partial_medium_indicator = 0
176  };
177 
178  memcpy(p_msch->cbw.command, &cmd_read_capacity10, p_msch->cbw.cmd_len);
179 
180  ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
181 
182  return TUSB_ERROR_NONE;
183 }
184 
185 tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
186 {
187  (void) lun; // TODO [MSCH] multiple lun support
188 
189  msch_interface_t* p_msch = &msch_data[dev_addr-1];
190 
191  //------------- Command Block Wrapper -------------//
192  p_msch->cbw.xfer_bytes = 18;
193  p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
194  p_msch->cbw.cmd_len = sizeof(scsi_request_sense_t);
195 
196  //------------- SCSI command -------------//
197  scsi_request_sense_t cmd_request_sense =
198  {
200  .alloc_length = 18
201  };
202 
203  memcpy(p_msch->cbw.command, &cmd_request_sense, p_msch->cbw.cmd_len);
204 
205  ASSERT_STATUS ( msch_command_xfer(p_msch, p_data) );
206 
207  return TUSB_ERROR_NONE;
208 }
209 
210 tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_cmd_status_wrapper_t * p_csw)
211 {
212  msch_interface_t* p_msch = &msch_data[dev_addr-1];
213 
214  //------------- Command Block Wrapper -------------//
215  msc_cbw_add_signature(&p_msch->cbw, lun);
216 
217  p_msch->cbw.xfer_bytes = 0; // Number of bytes
218  p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV;
219  p_msch->cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
220 
221  //------------- SCSI command -------------//
222  scsi_test_unit_ready_t cmd_test_unit_ready =
223  {
225  .lun = lun // according to wiki
226  };
227 
228  memcpy(p_msch->cbw.command, &cmd_test_unit_ready, p_msch->cbw.cmd_len);
229 
230  // TODO MSCH refractor test uinit ready
231  ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_out, (uint8_t*) &p_msch->cbw, sizeof(msc_cmd_block_wrapper_t), false) );
232  ASSERT_STATUS( hcd_pipe_xfer(p_msch->bulk_in , (uint8_t*) p_csw, sizeof(msc_cmd_status_wrapper_t), true) );
233 
234  return TUSB_ERROR_NONE;
235 }
236 
237 tusb_error_t tusbh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count)
238 {
239  msch_interface_t* p_msch = &msch_data[dev_addr-1];
240 
241  //------------- Command Block Wrapper -------------//
242  msc_cbw_add_signature(&p_msch->cbw, lun);
243 
244  p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes
245  p_msch->cbw.dir = TUSB_DIR_DEV_TO_HOST_MASK;
246  p_msch->cbw.cmd_len = sizeof(scsi_read10_t);
247 
248  //------------- SCSI command -------------//
249  scsi_read10_t cmd_read10 =
250  {
252  .lba = __n2be(lba),
253  .block_count = u16_le2be(block_count)
254  };
255 
256  memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len);
257 
258  ASSERT_STATUS ( msch_command_xfer(p_msch, p_buffer));
259 
260  return TUSB_ERROR_NONE;
261 }
262 
263 tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count)
264 {
265  msch_interface_t* p_msch = &msch_data[dev_addr-1];
266 
267  //------------- Command Block Wrapper -------------//
268  msc_cbw_add_signature(&p_msch->cbw, lun);
269 
270  p_msch->cbw.xfer_bytes = p_msch->block_size*block_count; // Number of bytes
271  p_msch->cbw.dir = TUSB_DIR_HOST_TO_DEV;
272  p_msch->cbw.cmd_len = sizeof(scsi_write10_t);
273 
274  //------------- SCSI command -------------//
275  scsi_write10_t cmd_write10 =
276  {
278  .lba = __n2be(lba),
279  .block_count = u16_le2be(block_count)
280  };
281 
282  memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len);
283 
284  ASSERT_STATUS ( msch_command_xfer(p_msch, (void*) p_buffer));
285 
286  return TUSB_ERROR_NONE;
287 }
288 
289 //--------------------------------------------------------------------+
290 // CLASS-USBH API (don't require to verify parameters)
291 //--------------------------------------------------------------------+
292 void msch_init(void)
293 {
294  memclr_(msch_data, sizeof(msch_interface_t)*TUSB_CFG_HOST_DEVICE_MAX);
295  msch_sem_hdl = osal_semaphore_create( OSAL_SEM_REF(msch_semaphore) );
296 }
297 
298 tusb_error_t msch_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
299 {
300  tusb_error_t error;
301 
302  OSAL_SUBTASK_BEGIN
303 
304  if (! ( MSC_SUBCLASS_SCSI == p_interface_desc->bInterfaceSubClass &&
305  MSC_PROTOCOL_BOT == p_interface_desc->bInterfaceProtocol ) )
306  {
307  return TUSB_ERROR_MSC_UNSUPPORTED_PROTOCOL;
308  }
309 
310  //------------- Open Data Pipe -------------//
311  tusb_descriptor_endpoint_t const *p_endpoint;
312  p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc );
313 
314  for(uint32_t i=0; i<2; i++)
315  {
316  SUBTASK_ASSERT(TUSB_DESC_TYPE_ENDPOINT == p_endpoint->bDescriptorType);
317  SUBTASK_ASSERT(TUSB_XFER_BULK == p_endpoint->bmAttributes.xfer);
318 
319  pipe_handle_t * p_pipe_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ?
320  &msch_data[dev_addr-1].bulk_in : &msch_data[dev_addr-1].bulk_out;
321 
322  (*p_pipe_hdl) = hcd_pipe_open(dev_addr, p_endpoint, TUSB_CLASS_MSC);
323  SUBTASK_ASSERT( pipehandle_is_valid(*p_pipe_hdl) );
324 
325  p_endpoint = (tusb_descriptor_endpoint_t const *) descriptor_next( (uint8_t const*) p_endpoint );
326  }
327 
328  msch_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber;
329  (*p_length) += sizeof(tusb_descriptor_interface_t) + 2*sizeof(tusb_descriptor_endpoint_t);
330 
331 
332  //------------- Get Max Lun -------------//
333  OSAL_SUBTASK_INVOKED_AND_WAIT(
334  usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
335  MSC_REQUEST_GET_MAX_LUN, 0, msch_data[dev_addr-1].interface_number,
336  1, msch_buffer ),
337  error
338  );
339 
340  SUBTASK_ASSERT( TUSB_ERROR_NONE == error /* && TODO STALL means zero */);
341  msch_data[dev_addr-1].max_lun = msch_buffer[0];
342 
343 #if 0
344  //------------- Reset -------------//
345  OSAL_SUBTASK_INVOKED_AND_WAIT(
346  usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
347  MSC_REQUEST_RESET, 0, msch_data[dev_addr-1].interface_number,
348  0, NULL ),
349  error
350  );
351 #endif
352 
353  enum { SCSI_XFER_TIMEOUT = 2000 };
354  //------------- SCSI Inquiry -------------//
355  tusbh_msc_inquiry(dev_addr, 0, msch_buffer);
356  osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
357  SUBTASK_ASSERT_STATUS(error);
358 
359  memcpy(msch_data[dev_addr-1].vendor_id , ((scsi_inquiry_data_t*) msch_buffer)->vendor_id , 8);
360  memcpy(msch_data[dev_addr-1].product_id, ((scsi_inquiry_data_t*) msch_buffer)->product_id, 16);
361 
362  //------------- SCSI Read Capacity 10 -------------//
363  tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer);
364  osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
365  SUBTASK_ASSERT_STATUS(error);
366 
367  // NOTE: my toshiba thumb-drive stall the first Read Capacity and require the sequence
368  // Read Capacity --> Stalled --> Clear Stall --> Request Sense --> Read Capacity (2) to work
369  if ( hcd_pipe_is_stalled(msch_data[dev_addr-1].bulk_in) )
370  { // clear stall TODO abstract clear stall function
371  OSAL_SUBTASK_INVOKED_AND_WAIT(
372  usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_ENDPOINT),
373  TUSB_REQUEST_CLEAR_FEATURE, 0, hcd_pipe_get_endpoint_addr(msch_data[dev_addr-1].bulk_in),
374  0, NULL ),
375  error
376  );
377  SUBTASK_ASSERT_STATUS(error);
378 
379  hcd_pipe_clear_stall(msch_data[dev_addr-1].bulk_in);
380  osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error); // wait for SCSI status
381  SUBTASK_ASSERT_STATUS(error);
382 
383  //------------- SCSI Request Sense -------------//
384  (void) tusbh_msc_request_sense(dev_addr, 0, msch_buffer);
385  osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
386  SUBTASK_ASSERT_STATUS(error);
387 
388  //------------- Re-read SCSI Read Capactity -------------//
389  tusbh_msc_read_capacity10(dev_addr, 0, msch_buffer);
390  osal_semaphore_wait(msch_sem_hdl, SCSI_XFER_TIMEOUT, &error);
391  SUBTASK_ASSERT_STATUS(error);
392  }
393 
394  msch_data[dev_addr-1].last_lba = __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->last_lba );
395  msch_data[dev_addr-1].block_size = (uint16_t) __be2n( ((scsi_read_capacity10_data_t*)msch_buffer)->block_size );
396 
397  msch_data[dev_addr-1].is_initialized = true;
398  tusbh_msc_mounted_cb(dev_addr);
399 
400  OSAL_SUBTASK_END
401 }
402 
403 void msch_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
404 {
405  if ( pipehandle_is_equal(pipe_hdl, msch_data[pipe_hdl.dev_addr-1].bulk_in) )
406  {
407  if (msch_data[pipe_hdl.dev_addr-1].is_initialized)
408  {
409  tusbh_msc_isr(pipe_hdl.dev_addr, event, xferred_bytes);
410  }else
411  { // still initializing under open subtask
412  osal_semaphore_post(msch_sem_hdl);
413  }
414  }
415 }
416 
417 void msch_close(uint8_t dev_addr)
418 {
419  (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_in);
420  (void) hcd_pipe_close(msch_data[dev_addr-1].bulk_out);
421 
422  memclr_(&msch_data[dev_addr-1], sizeof(msch_interface_t));
423  osal_semaphore_reset(msch_sem_hdl);
424 
425  tusbh_msc_unmounted_cb(dev_addr); // invoke Application Callback
426 }
427 
428 //--------------------------------------------------------------------+
429 // INTERNAL & HELPER
430 //--------------------------------------------------------------------+
431 
432 
433 #endif
SCSI Read Capacity 10 Command: Read Capacity.
Definition: msc.h:320
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
Perform SCSI READ 10 command to read data from MassStorage device.
SCSI Read 10 Command.
Definition: msc.h:340
USB Standard Interface Descriptor (section 9.6.1 table 9-12)
#define ATTR_WARN_UNUSED_RESULT
The warn_unused_result attribute causes a warning to be emitted if a caller of the function with this...
Definition: compiler_gcc.h:118
uint8_t const * tusbh_msc_get_vendor_name(uint8_t dev_addr)
Get SCSI vendor's name of MassStorage device.
#define __n2be(x)
built-in function to convert 32-bit from native to Big Endian
Definition: compiler_gcc.h:135
The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/wri...
Definition: msc.h:125
uint8_t bInterfaceProtocol
Protocol code (assigned by the USB). These codes are qualified by the value of the bInterfaceClass ...
Constant value of 43425355h (little endian)
Definition: msc.h:69
uint8_t const * tusbh_msc_get_product_name(uint8_t dev_addr)
Get SCSI product's name of MassStorage device.
uint8_t lun
The device Logical Unit Number (LUN) to which the command block is being sent. For devices that suppo...
Definition: msc.h:102
uint32_t signature
Signature that helps identify this data packet as a CBW. The signature field shall contain the value ...
Definition: msc.h:98
The WRITE (10) command requests thatthe device server transfer the specified logical block(s) from th...
Definition: msc.h:134
#define TUSB_CFG_HOST_DEVICE_MAX
Maximum number of device host stack can manage If hub class is not enabled, set this equal to numbe...
uint8_t cmd_code
SCSI OpCode for SCSI_CMD_INQUIRY.
Definition: msc.h:170
uint8_t cmd_code
SCSI OpCode.
Definition: msc.h:341
#define __be2n(x)
built-in function to convert 32-bit from Big Endian to native
Definition: compiler_gcc.h:136
The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used t...
Definition: msc.h:131
Bulk-Only Transport.
Definition: msc.h:78
The READ (10) command requests that the device server read the specified logical block(s) and transfe...
Definition: msc.h:133
The SCSI Inquiry command is used to obtain basic information from a target device.
Definition: msc.h:126
SCSI Read Capacity 10 Response Data.
Definition: msc.h:332
tusb_error_t tusbh_msc_write10(uint8_t dev_addr, uint8_t lun, void const *p_buffer, uint32_t lba, uint16_t block_count) ATTR_WARN_UNUSED_RESULT
Perform SCSI WRITE 10 command to write data to MassStorage device.
struct tusb_descriptor_endpoint_t::@8 bmAttributes
This field describes the endpoint's attributes when it is configured using the bConfigurationValue. Bits 1..0: Transfer Type - 00 = Control - 01 = Isochronous - 10 = Bulk - 11 = Interrupt If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: Bits 3..2: Synchronization Type - 00 = No Synchronization - 01 = Asynchronous - 10 = Adaptive - 11 = Synchronous Bits 5..4: Usage Type - 00 = Data endpoint - 01 = Feedback endpoint - 10 = Implicit feedback Data endpoint - 11 = Reserved Refer to Chapter 5 of USB 2.0 specification for more information. All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host.
#define TUSB_CFG_ATTR_USBRAM
SCSI Inquiry Response Data.
Definition: msc.h:181
tusb_error_t tusbh_msc_request_sense(uint8_t dev_addr, uint8_t lun, uint8_t *p_data)
Perform SCSI REQUEST SENSE command, used to retrieve sense data from MassStorage device.
tusb_error_t tusbh_msc_get_capacity(uint8_t dev_addr, uint32_t *p_last_lba, uint32_t *p_block_size)
Get SCSI Capacity of MassStorage device.
uint8_t bDescriptorType
ENDPOINT Descriptor Type.
uint8_t bInterfaceSubClass
Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bInterfaceCla...
USB Standard Endpoint Descriptor (section 9.6.1 table 9-13)
tusb_error_t tusbh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, msc_cmd_status_wrapper_t *p_csw) ATTR_WARN_UNUSED_RESULT
Perform SCSI TEST UNIT READY command to test if MassStorage device is ready.
uint8_t cmd_code
SCSI OpCode for SCSI_CMD_READ_CAPACITY_10.
Definition: msc.h:321
void tusbh_msc_unmounted_cb(uint8_t dev_addr)
Callback function that will be invoked when a device with MassStorage interface is unmounted...
bool tusbh_msc_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT
Check if device supports MassStorage interface or not.
This request is used to reset the mass storage device and its associated interface. This class-specific request shall ready the device for the next CBW from the host.
Definition: msc.h:84
uint8_t bInterfaceNumber
Number of this interface. Zero-based value identifying the index in the array of concurrent interface...
uint32_t tag
Tag sent by the host. The device shall echo the contents of this field back to the host in the dCSWTa...
Definition: msc.h:99
bool tusbh_msc_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT
Check if the interface is currently busy or not.
The Get Max LUN device request is used to determine the number of logical units supported by the devi...
Definition: msc.h:83
Command Status Wrapper.
Definition: msc.h:110
tusb_error_t
Error Code returned.
Definition: tusb_errors.h:100
void tusbh_msc_isr(uint8_t dev_addr, tusb_event_t event, uint32_t xferred_bytes)
Callback function that is invoked when an transferring event occurred.
#define ATTR_ALIGNED(Bytes)
This attribute specifies a minimum alignment for the variable or structure field, measured in bytes...
Definition: compiler_gcc.h:72
The SCSI Read Capacity command is used to obtain data capacity information from a target device...
Definition: msc.h:130
Command Block Wrapper.
Definition: msc.h:97
SCSI transparent command set.
Definition: msc.h:65
uint8_t cmd_code
SCSI OpCode for SCSI_CMD_TEST_UNIT_READY.
Definition: msc.h:160
#define ATTR_ALWAYS_INLINE
Generally, functions are not inlined unless optimization is specified. For functions declared inline...
Definition: compiler_gcc.h:89
void tusbh_msc_mounted_cb(uint8_t dev_addr)
Callback function that will be invoked when a device with MassStorage interface is mounted...
SCSI Test Unit Ready Command.
Definition: msc.h:159
SCSI Inquiry Command.
Definition: msc.h:169
uint8_t bEndpointAddress
The address of the endpoint on the USB device described by this descriptor. The address is encoded as...