Open FFBoard
Open source force feedback firmware
msc_host.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2019 Ha Thach (tinyusb.org)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#include "tusb_option.h"
28
29#if CFG_TUH_ENABLED && CFG_TUH_MSC
30
31#include "host/usbh.h"
32#include "host/usbh_pvt.h"
33
34#include "msc_host.h"
35
36// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
37#ifndef CFG_TUH_MSC_LOG_LEVEL
38 #define CFG_TUH_MSC_LOG_LEVEL CFG_TUH_LOG_LEVEL
39#endif
40
41#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MSC_LOG_LEVEL, __VA_ARGS__)
42
43//--------------------------------------------------------------------+
44// MACRO CONSTANT TYPEDEF
45//--------------------------------------------------------------------+
46enum {
51};
52
53typedef struct {
54 uint8_t itf_num;
55 uint8_t ep_in;
56 uint8_t ep_out;
57
58 uint8_t max_lun;
59
60 volatile bool configured; // Receive SET_CONFIGURE
61 volatile bool mounted; // Enumeration is complete
62
63 struct {
64 uint32_t block_size;
65 uint32_t block_count;
66 } capacity[CFG_TUH_MSC_MAXLUN];
67
68 //------------- SCSI -------------//
69 uint8_t stage;
70 void* buffer;
72 uintptr_t complete_arg;
73
74 CFG_TUH_MEM_ALIGN msc_cbw_t cbw;
75 CFG_TUH_MEM_ALIGN msc_csw_t csw;
77
78CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX];
79
80// buffer used to read scsi information when mounted
81// largest response data currently is inquiry TODO Inquiry is not part of enum anymore
82CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN
83static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
84
85// FIXME potential nul reference
86TU_ATTR_ALWAYS_INLINE
87static inline msch_interface_t* get_itf(uint8_t dev_addr) {
88 return &_msch_itf[dev_addr - 1];
89}
90
91//--------------------------------------------------------------------+
92// PUBLIC API
93//--------------------------------------------------------------------+
94uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) {
96 return p_msc->max_lun;
97}
98
99uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) {
101 return p_msc->capacity[lun].block_count;
102}
103
104uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) {
106 return p_msc->capacity[lun].block_size;
107}
108
111 return p_msc->mounted;
112}
113
114bool tuh_msc_ready(uint8_t dev_addr) {
116 return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in) && !usbh_edpt_busy(dev_addr, p_msc->ep_out);
117}
118
119//--------------------------------------------------------------------+
120// PUBLIC API: SCSI COMMAND
121//--------------------------------------------------------------------+
122static inline void cbw_init(msc_cbw_t* cbw, uint8_t lun) {
123 tu_memclr(cbw, sizeof(msc_cbw_t));
125 cbw->tag = 0x54555342; // TUSB
126 cbw->lun = lun;
127}
128
129bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data,
130 tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
132 TU_VERIFY(p_msc->configured);
133
134 // claim endpoint
135 TU_VERIFY(usbh_edpt_claim(daddr, p_msc->ep_out));
136
137 p_msc->cbw = *cbw;
138 p_msc->stage = MSC_STAGE_CMD;
139 p_msc->buffer = data;
140 p_msc->complete_cb = complete_cb;
141 p_msc->complete_arg = arg;
142
143 if (!usbh_edpt_xfer(daddr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))) {
145 return false;
146 }
147
148 return true;
149}
150
151bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response,
152 tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
154 TU_VERIFY(p_msc->configured);
155
156 msc_cbw_t cbw;
157 cbw_init(&cbw, lun);
158
160 cbw.dir = TUSB_DIR_IN_MASK;
161 cbw.cmd_len = sizeof(scsi_read_capacity10_t);
163
164 return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
165}
166
167bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response,
168 tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
170 TU_VERIFY(p_msc->mounted);
171
172 msc_cbw_t cbw;
173 cbw_init(&cbw, lun);
174
175 cbw.total_bytes = sizeof(scsi_inquiry_resp_t);
176 cbw.dir = TUSB_DIR_IN_MASK;
177 cbw.cmd_len = sizeof(scsi_inquiry_t);
178
179 scsi_inquiry_t const cmd_inquiry = {
181 .alloc_length = sizeof(scsi_inquiry_resp_t)
182 };
183 memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len);
184
185 return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
186}
187
188bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
190 TU_VERIFY(p_msc->configured);
191
192 msc_cbw_t cbw;
193 cbw_init(&cbw, lun);
194
195 cbw.total_bytes = 0;
196 cbw.dir = TUSB_DIR_OUT;
197 cbw.cmd_len = sizeof(scsi_test_unit_ready_t);
199 cbw.command[1] = lun; // according to wiki TODO need verification
200
201 return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb, arg);
202}
203
204bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void* response,
205 tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
206 msc_cbw_t cbw;
207 cbw_init(&cbw, lun);
208
209 cbw.total_bytes = 18; // TODO sense response
210 cbw.dir = TUSB_DIR_IN_MASK;
211 cbw.cmd_len = sizeof(scsi_request_sense_t);
212
213 scsi_request_sense_t const cmd_request_sense = {
215 .alloc_length = 18
216 };
217 memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len);
218
219 return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg);
220}
221
222bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void* buffer, uint32_t lba, uint16_t block_count,
223 tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
225 TU_VERIFY(p_msc->mounted);
226
227 msc_cbw_t cbw;
228 cbw_init(&cbw, lun);
229
230 cbw.total_bytes = block_count * p_msc->capacity[lun].block_size;
231 cbw.dir = TUSB_DIR_IN_MASK;
232 cbw.cmd_len = sizeof(scsi_read10_t);
233
234 scsi_read10_t const cmd_read10 = {
236 .lba = tu_htonl(lba),
237 .block_count = tu_htons(block_count)
238 };
239 memcpy(cbw.command, &cmd_read10, cbw.cmd_len);
240
241 return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb, arg);
242}
243
244bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const* buffer, uint32_t lba, uint16_t block_count,
245 tuh_msc_complete_cb_t complete_cb, uintptr_t arg) {
247 TU_VERIFY(p_msc->mounted);
248
249 msc_cbw_t cbw;
250 cbw_init(&cbw, lun);
251
252 cbw.total_bytes = block_count * p_msc->capacity[lun].block_size;
253 cbw.dir = TUSB_DIR_OUT;
254 cbw.cmd_len = sizeof(scsi_write10_t);
255
256 scsi_write10_t const cmd_write10 = {
258 .lba = tu_htonl(lba),
259 .block_count = tu_htons(block_count)
260 };
261 memcpy(cbw.command, &cmd_write10, cbw.cmd_len);
262
263 return tuh_msc_scsi_command(dev_addr, &cbw, (void*) (uintptr_t) buffer, complete_cb, arg);
264}
265
266#if 0
267// MSC interface Reset (not used now)
268bool tuh_msc_reset(uint8_t dev_addr) {
269 tusb_control_request_t const new_request = {
271 .recipient = TUSB_REQ_RCPT_INTERFACE,
272 .type = TUSB_REQ_TYPE_CLASS,
273 .direction = TUSB_DIR_OUT
274 },
275 .bRequest = MSC_REQ_RESET,
276 .wValue = 0,
277 .wIndex = p_msc->itf_num,
278 .wLength = 0
279 };
280 TU_ASSERT( usbh_control_xfer( dev_addr, &new_request, NULL ) );
281}
282#endif
283
284//--------------------------------------------------------------------+
285// CLASS-USBH API
286//--------------------------------------------------------------------+
287bool msch_init(void) {
288 TU_LOG_DRV("sizeof(msch_interface_t) = %u\r\n", sizeof(msch_interface_t));
289 tu_memclr(_msch_itf, sizeof(_msch_itf));
290 return true;
291}
292
293bool msch_deinit(void) {
294 return true;
295}
296
297void msch_close(uint8_t dev_addr) {
298 TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX,);
300 TU_VERIFY(p_msc->configured,);
301
302 TU_LOG_DRV(" MSCh close addr = %d\r\n", dev_addr);
303
304 // invoke Application Callback
305 if (p_msc->mounted) {
307 }
308
309 tu_memclr(p_msc, sizeof(msch_interface_t));
310}
311
312bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) {
314 msc_cbw_t const * cbw = &p_msc->cbw;
315 msc_csw_t * csw = &p_msc->csw;
316
317 switch (p_msc->stage) {
318 case MSC_STAGE_CMD:
319 // Must be Command Block
320 TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t));
321
322 if (cbw->total_bytes && p_msc->buffer) {
323 // Data stage if any
324 p_msc->stage = MSC_STAGE_DATA;
325 uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out;
326 TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes));
327 } else {
328 // Status stage
329 p_msc->stage = MSC_STAGE_STATUS;
330 TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t)));
331 }
332 break;
333
334 case MSC_STAGE_DATA:
335 // Status stage
336 p_msc->stage = MSC_STAGE_STATUS;
337 TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t)));
338 break;
339
340 case MSC_STAGE_STATUS:
341 // SCSI op is complete
342 p_msc->stage = MSC_STAGE_IDLE;
343
344 if (p_msc->complete_cb) {
345 tuh_msc_complete_data_t const cb_data = {
346 .cbw = cbw,
347 .csw = csw,
348 .scsi_data = p_msc->buffer,
349 .user_arg = p_msc->complete_arg
350 };
351 p_msc->complete_cb(dev_addr, &cb_data);
352 }
353 break;
354
355 // unknown state
356 default:
357 break;
358 }
359
360 return true;
361}
362
363//--------------------------------------------------------------------+
364// MSC Enumeration
365//--------------------------------------------------------------------+
367static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
368static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
369static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data);
370
371bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) {
372 (void) rhport;
373 TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass &&
375
376 // msc driver length is fixed
377 uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) +
378 desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
379 TU_ASSERT(drv_len <= max_len);
380
382 tusb_desc_endpoint_t const* ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(desc_itf);
383
384 for (uint32_t i = 0; i < 2; i++) {
385 TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
386 TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc));
387
388 if (TUSB_DIR_IN == tu_edpt_dir(ep_desc->bEndpointAddress)) {
389 p_msc->ep_in = ep_desc->bEndpointAddress;
390 } else {
391 p_msc->ep_out = ep_desc->bEndpointAddress;
392 }
393
394 ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(ep_desc);
395 }
396
397 p_msc->itf_num = desc_itf->bInterfaceNumber;
398
399 return true;
400}
401
402bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) {
404 TU_ASSERT(p_msc->itf_num == itf_num);
405
406 p_msc->configured = true;
407
408 //------------- Get Max Lun -------------//
409 TU_LOG_DRV("MSC Get Max Lun\r\n");
412 .recipient = TUSB_REQ_RCPT_INTERFACE,
413 .type = TUSB_REQ_TYPE_CLASS,
414 .direction = TUSB_DIR_IN
415 },
416 .bRequest = MSC_REQ_GET_MAX_LUN,
417 .wValue = 0,
418 .wIndex = itf_num,
419 .wLength = 1
420 };
421
422 tuh_xfer_t xfer = {
423 .daddr = dev_addr,
424 .ep_addr = 0,
425 .setup = &request,
427 .complete_cb = config_get_maxlun_complete,
428 .user_data = 0
429 };
430 TU_ASSERT(tuh_control_xfer(&xfer));
431
432 return true;
433}
434
436 uint8_t const daddr = xfer->daddr;
438
439 // STALL means zero
440 p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0;
441 p_msc->max_lun++; // MAX LUN is minus 1 by specs
442
443 TU_LOG_DRV(" Max LUN = %u\r\n", p_msc->max_lun);
444
445 // TODO multiple LUN support
446 TU_LOG_DRV("SCSI Test Unit Ready\r\n");
447 uint8_t const lun = 0;
449}
450
451static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
452 msc_cbw_t const* cbw = cb_data->cbw;
453 msc_csw_t const* csw = cb_data->csw;
454
455 if (csw->status == 0) {
456 // Unit is ready, read its capacity
457 TU_LOG_DRV("SCSI Read Capacity\r\n");
460 } else {
461 // Note: During enumeration, some device fails Test Unit Ready and require a few retries
462 // with Request Sense to start working !!
463 // TODO limit number of retries
464 TU_LOG_DRV("SCSI Request Sense\r\n");
466 }
467
468 return true;
469}
470
471static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
472 msc_cbw_t const* cbw = cb_data->cbw;
473 msc_csw_t const* csw = cb_data->csw;
474
475 TU_ASSERT(csw->status == 0);
477 return true;
478}
479
480static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) {
481 msc_cbw_t const* cbw = cb_data->cbw;
482 msc_csw_t const* csw = cb_data->csw;
483
484 TU_ASSERT(csw->status == 0);
485
487
488 // Capacity response field: Block size and Last LBA are both Big-Endian
490 p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1;
491 p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
492
493 // Mark enumeration is complete
494 p_msc->mounted = true;
496
497 // notify usbh that driver enumeration is complete
499
500 return true;
501}
502
503#endif
static struct @612 data
xfer_td_t xfer[EP_CBI_COUNT+1][2]
Definition: dcd_nrf5x.c:119
uint8_t dev_addr
Definition: dcd_pic32mz.c:81
uint8_t const * buffer
Definition: midi_device.h:100
@ MSC_PROTOCOL_BOT
Bulk-Only Transport.
Definition: msc.h:61
struct TU_ATTR_PACKED scsi_read_capacity10_t
SCSI Read Capacity 10 Command: Read Capacity.
struct TU_ATTR_PACKED scsi_inquiry_resp_t
SCSI Inquiry Response Data.
struct TU_ATTR_PACKED scsi_request_sense_t
struct TU_ATTR_PACKED scsi_inquiry_t
SCSI Inquiry Command.
struct TU_ATTR_PACKED scsi_read10_t
SCSI Read 10 Command.
struct TU_ATTR_PACKED scsi_write10_t
@ MSC_CBW_SIGNATURE
Constant value of 43425355h (little endian)
Definition: msc.h:51
struct TU_ATTR_PACKED scsi_test_unit_ready_t
SCSI Test Unit Ready Command.
@ SCSI_CMD_TEST_UNIT_READY
The SCSI Test Unit Ready command is used to determine if a device is ready to transfer data (read/wri...
Definition: msc.h:113
@ SCSI_CMD_REQUEST_SENSE
The SCSI Request Sense command is part of the SCSI computer protocol standard. This command is used t...
Definition: msc.h:120
@ SCSI_CMD_WRITE_10
The WRITE (10) command requests that the device server transfer the specified logical block(s) from t...
Definition: msc.h:123
@ SCSI_CMD_READ_CAPACITY_10
The SCSI Read Capacity command is used to obtain data capacity information from a target device.
Definition: msc.h:119
@ SCSI_CMD_READ_10
The READ (10) command requests that the device server read the specified logical block(s) and transfe...
Definition: msc.h:122
@ SCSI_CMD_INQUIRY
The SCSI Inquiry command is used to obtain basic information from a target device.
Definition: msc.h:114
@ MSC_REQ_RESET
This request is used to reset the mass storage device and its associated interface....
Definition: msc.h:68
@ MSC_REQ_GET_MAX_LUN
The Get Max LUN device request is used to determine the number of logical units supported by the devi...
Definition: msc.h:67
static CFG_TUH_MEM_SECTION msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]
Definition: msc_host.c:78
bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
Definition: msc_host.c:167
static void cbw_init(msc_cbw_t *cbw, uint8_t lun)
Definition: msc_host.c:122
bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
Definition: msc_host.c:204
CFG_TUH_MEM_SECTION static CFG_TUH_MEM_ALIGN uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]
Definition: msc_host.c:83
uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun)
Definition: msc_host.c:104
bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
Definition: msc_host.c:371
static TU_ATTR_ALWAYS_INLINE msch_interface_t * get_itf(uint8_t dev_addr)
Definition: msc_host.c:87
bool tuh_msc_ready(uint8_t dev_addr)
Definition: msc_host.c:114
void msch_close(uint8_t dev_addr)
Definition: msc_host.c:297
bool msch_init(void)
Definition: msc_host.c:287
uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun)
Definition: msc_host.c:99
bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
Definition: msc_host.c:402
static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data)
Definition: msc_host.c:451
bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
Definition: msc_host.c:312
static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data)
Definition: msc_host.c:471
bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
Definition: msc_host.c:151
uint8_t tuh_msc_get_maxlun(uint8_t dev_addr)
Definition: msc_host.c:94
bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
Definition: msc_host.c:188
bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const *buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
Definition: msc_host.c:244
static void config_get_maxlun_complete(tuh_xfer_t *xfer)
Definition: msc_host.c:435
@ MSC_STAGE_IDLE
Definition: msc_host.c:47
@ MSC_STAGE_STATUS
Definition: msc_host.c:50
@ MSC_STAGE_DATA
Definition: msc_host.c:49
@ MSC_STAGE_CMD
Definition: msc_host.c:48
bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void *buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
Definition: msc_host.c:222
bool tuh_msc_reset(uint8_t dev_addr)
Definition: msc_host.c:268
static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data)
Definition: msc_host.c:480
bool msch_deinit(void)
Definition: msc_host.c:293
bool tuh_msc_mounted(uint8_t dev_addr)
Definition: msc_host.c:109
bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const *cbw, void *data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg)
Definition: msc_host.c:129
TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr)
bool(* tuh_msc_complete_cb_t)(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data)
Definition: msc_host.h:51
TU_ATTR_WEAK void tuh_msc_mount_cb(uint8_t dev_addr)
static void * memcpy(void *dst, const void *src, size_t n)
Definition: ringbuffer.c:8
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
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:85
uint8_t cmd_code
SCSI OpCode for SCSI_CMD_TEST_UNIT_READY.
Definition: msc.h:151
uint8_t status
indicates the success or failure of the command. Values from msc_csw_status_t
Definition: msc.h:101
uint8_t lun
The device Logical Unit Number (LUN) to which the command block is being sent. For devices that suppo...
Definition: msc.h:88
uint8_t cmd_len
The valid length of the CBWCBin bytes. This defines the valid length of the command block....
Definition: msc.h:89
uint8_t dir
Bit 7 of this field define transfer direction - 0 : Data-Out from host to the device....
Definition: msc.h:87
struct TU_ATTR_PACKED::@16::TU_ATTR_PACKED bmRequestType_bit
uint32_t signature
Signature that helps identify this data packet as a CBW. The signature field shall contain the value ...
Definition: msc.h:84
uint8_t bmAttributes
See: audio_clock_source_attribute_t.
Definition: audio.h:672
uint8_t * buffer
Definition: video_device.c:111
uint8_t bDescriptorType
Descriptor Type. Value: TUSB_DESC_CS_INTERFACE.
Definition: audio.h:657
uint8_t command[16]
The command block to be executed by the device. The device shall interpret the first cmd_len bytes in...
Definition: msc.h:90
uint8_t bEndpointAddress
Definition: video.h:306
uint8_t bInterfaceSubClass
Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bInterfaceCla...
Definition: tusb_types.h:350
uint32_t total_bytes
The number of bytes of data that the host expects to transfer on the Bulk-In or Bulk-Out endpoint (as...
Definition: msc.h:86
uint8_t bNumEndpoints
Number of endpoints used by this interface (excluding endpoint zero). If this value is zero,...
Definition: tusb_types.h:348
uint8_t bInterfaceProtocol
Protocol code (assigned by the USB). These codes are qualified by the value of the bInterfaceClass ...
Definition: tusb_types.h:351
uint8_t bInterfaceNumber
Number of this interface. Zero-based value identifying the index in the array of concurrent interface...
Definition: tusb_types.h:346
CFG_TUH_MEM_ALIGN msc_cbw_t cbw
Definition: msc_host.c:74
tuh_msc_complete_cb_t complete_cb
Definition: msc_host.c:71
uint32_t block_count
Definition: msc_host.c:65
uintptr_t complete_arg
Definition: msc_host.c:72
uint32_t block_size
Definition: msc_host.c:64
uint8_t ep_out
Definition: msc_host.c:56
struct msch_interface_t::@44 capacity[CFG_TUH_MSC_MAXLUN]
void * buffer
Definition: msc_host.c:70
volatile bool mounted
Definition: msc_host.c:61
CFG_TUH_MEM_ALIGN msc_csw_t csw
Definition: msc_host.c:75
uint8_t stage
Definition: msc_host.c:69
uint8_t ep_in
Definition: msc_host.c:55
volatile bool configured
Definition: msc_host.c:60
uint8_t max_lun
Definition: msc_host.c:58
uint8_t itf_num
Definition: msc_host.c:54
SCSI Read Capacity 10 Response Data.
Definition: msc.h:357
uint32_t last_lba
The last Logical Block Address of the device.
Definition: msc.h:358
uint32_t block_size
Block size in bytes.
Definition: msc.h:359
@ TUSB_DIR_IN
Definition: tusb_types.h:67
@ TUSB_DIR_OUT
Definition: tusb_types.h:66
@ TUSB_DIR_IN_MASK
Definition: tusb_types.h:69
xfer_result_t
Definition: tusb_types.h:236
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
@ TUSB_REQ_RCPT_INTERFACE
Definition: tusb_types.h:152
@ TUSB_XFER_BULK
Definition: tusb_types.h:61
TU_ATTR_PACKED_END TU_ATTR_BIT_FIELD_ORDER_END static TU_ATTR_ALWAYS_INLINE tusb_dir_t tu_edpt_dir(uint8_t addr)
Definition: tusb_types.h:502
struct TU_ATTR_PACKED tusb_desc_endpoint_t
USB Endpoint Descriptor.
@ TUSB_REQ_TYPE_CLASS
Definition: tusb_types.h:145
static TU_ATTR_ALWAYS_INLINE uint8_t const * tu_desc_next(void const *desc)
Definition: tusb_types.h:531
@ TUSB_DESC_ENDPOINT
Definition: tusb_types.h:97
void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
Definition: usbh.c:1717
CFG_TUH_MEM_ALIGN tusb_control_request_t request
Definition: usbh.c:259
bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
Definition: usbh.c:861
uint8_t daddr
Definition: usbh.c:264
bool tuh_control_xfer(tuh_xfer_t *xfer)
Definition: usbh.c:602
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
Definition: usbh.c:846
tuh_xfer_cb_t complete_cb
Definition: usbh.c:261
bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const *desc_ep)
Definition: usbh.c:930
bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
Definition: usbh.c:935
static TU_ATTR_ALWAYS_INLINE bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: usbh_pvt.h:87