1 /*
2 * Copyright (c) 2022, sakumisu
3 * Copyright (c) 2024, zhihong chen
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7 #include "usbd_core.h"
8 #include "usbd_msc.h"
9 #include "usb_scsi.h"
10
11 #undef USB_DBG_TAG
12 #define USB_DBG_TAG "usbd_msc"
13 #include "usb_log.h"
14
15 #define MSD_OUT_EP_IDX 0
16 #define MSD_IN_EP_IDX 1
17
18 /* Describe EndPoints configuration */
19 static struct usbd_endpoint mass_ep_data[CONFIG_USBDEV_MAX_BUS][2];
20
21 /* MSC Bulk-only Stage */
22 enum Stage {
23 MSC_READ_CBW = 0, /* Command Block Wrapper */
24 MSC_DATA_OUT = 1, /* Data Out Phase */
25 MSC_DATA_IN = 2, /* Data In Phase */
26 MSC_SEND_CSW = 3, /* Command Status Wrapper */
27 MSC_WAIT_CSW = 4, /* Command Status Wrapper */
28 };
29
30 /* Device data structure */
31 USB_NOCACHE_RAM_SECTION struct usbd_msc_priv {
32 /* state of the bulk-only state machine */
33 enum Stage stage;
34 USB_MEM_ALIGNX struct CBW cbw;
35 USB_MEM_ALIGNX struct CSW csw;
36
37 USB_MEM_ALIGNX bool readonly;
38 bool popup;
39 uint8_t sKey; /* Sense key */
40 uint8_t ASC; /* Additional Sense Code */
41 uint8_t ASQ; /* Additional Sense Qualifier */
42 uint8_t max_lun;
43 uint32_t start_sector;
44 uint32_t nsectors;
45 uint32_t scsi_blk_size[CONFIG_USBDEV_MSC_MAX_LUN];
46 uint32_t scsi_blk_nbr[CONFIG_USBDEV_MSC_MAX_LUN];
47
48 USB_MEM_ALIGNX uint8_t block_buffer[CONFIG_USBDEV_MSC_MAX_BUFSIZE];
49
50 #if defined(CONFIG_USBDEV_MSC_THREAD)
51 usb_osal_mq_t usbd_msc_mq;
52 usb_osal_thread_t usbd_msc_thread;
53 uint32_t nbytes;
54 #elif defined(CONFIG_USBDEV_MSC_POLLING)
55 uint32_t event;
56 uint32_t nbytes;
57 #endif
58 } g_usbd_msc[CONFIG_USBDEV_MAX_BUS];
59
60 #ifdef CONFIG_USBDEV_MSC_THREAD
61 static void usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV);
62 #endif
63
usdb_msc_set_max_lun(uint8_t busid)64 static void usdb_msc_set_max_lun(uint8_t busid)
65 {
66 g_usbd_msc[busid].max_lun = CONFIG_USBDEV_MSC_MAX_LUN - 1u;
67 }
68
usbd_msc_reset(uint8_t busid)69 static void usbd_msc_reset(uint8_t busid)
70 {
71 g_usbd_msc[busid].stage = MSC_READ_CBW;
72 g_usbd_msc[busid].readonly = false;
73 }
74
msc_storage_class_interface_request_handler(uint8_t busid,struct usb_setup_packet * setup,uint8_t ** data,uint32_t * len)75 static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
76 {
77 USB_LOG_DBG("MSC Class request: "
78 "bRequest 0x%02x\r\n",
79 setup->bRequest);
80
81 switch (setup->bRequest) {
82 case MSC_REQUEST_RESET:
83 usbd_msc_reset(busid);
84 break;
85
86 case MSC_REQUEST_GET_MAX_LUN:
87 (*data)[0] = g_usbd_msc[busid].max_lun;
88 *len = 1;
89 break;
90
91 default:
92 USB_LOG_WRN("Unhandled MSC Class bRequest 0x%02x\r\n", setup->bRequest);
93 return -1;
94 }
95
96 return 0;
97 }
98
msc_storage_notify_handler(uint8_t busid,uint8_t event,void * arg)99 void msc_storage_notify_handler(uint8_t busid, uint8_t event, void *arg)
100 {
101 (void)arg;
102
103 switch (event) {
104 case USBD_EVENT_INIT:
105 #if defined(CONFIG_USBDEV_MSC_THREAD)
106 g_usbd_msc[busid].usbd_msc_mq = usb_osal_mq_create(1);
107 if (g_usbd_msc[busid].usbd_msc_mq == NULL) {
108 USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_mq\r\n");
109 }
110 g_usbd_msc[busid].usbd_msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbdev_msc_thread, (void *)(uint32_t)busid);
111 if (g_usbd_msc[busid].usbd_msc_thread == NULL) {
112 USB_LOG_ERR("No memory to alloc for g_usbd_msc[busid].usbd_msc_thread\r\n");
113 }
114 #elif defined(CONFIG_USBDEV_MSC_POLLING)
115 g_usbd_msc[busid].event = 0;
116 #endif
117 break;
118 case USBD_EVENT_DEINIT:
119 #if defined(CONFIG_USBDEV_MSC_THREAD)
120 if (g_usbd_msc[busid].usbd_msc_mq) {
121 usb_osal_mq_delete(g_usbd_msc[busid].usbd_msc_mq);
122 }
123 if (g_usbd_msc[busid].usbd_msc_thread) {
124 usb_osal_thread_delete(g_usbd_msc[busid].usbd_msc_thread);
125 }
126 #endif
127 break;
128 case USBD_EVENT_RESET:
129 usbd_msc_reset(busid);
130 break;
131 case USBD_EVENT_CONFIGURED:
132 USB_LOG_DBG("Start reading cbw\r\n");
133 usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc[busid].cbw, USB_SIZEOF_MSC_CBW);
134 break;
135
136 default:
137 break;
138 }
139 }
140
usbd_msc_bot_abort(uint8_t busid)141 static void usbd_msc_bot_abort(uint8_t busid)
142 {
143 if ((g_usbd_msc[busid].cbw.bmFlags == 0) && (g_usbd_msc[busid].cbw.dDataLength != 0)) {
144 usbd_ep_set_stall(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr);
145 }
146 usbd_ep_set_stall(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr);
147 usbd_ep_start_read(busid, mass_ep_data[busid][0].ep_addr, (uint8_t *)&g_usbd_msc[busid].cbw, USB_SIZEOF_MSC_CBW);
148 }
149
usbd_msc_send_csw(uint8_t busid,uint8_t CSW_Status)150 static void usbd_msc_send_csw(uint8_t busid, uint8_t CSW_Status)
151 {
152 g_usbd_msc[busid].csw.dSignature = MSC_CSW_Signature;
153 g_usbd_msc[busid].csw.bStatus = CSW_Status;
154
155 /* updating the State Machine , so that we wait CSW when this
156 * transfer is complete, ie when we get a bulk in callback
157 */
158 g_usbd_msc[busid].stage = MSC_WAIT_CSW;
159
160 USB_LOG_DBG("Send csw\r\n");
161 usbd_ep_start_write(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc[busid].csw, sizeof(struct CSW));
162 }
163
usbd_msc_send_info(uint8_t busid,uint8_t * buffer,uint8_t size)164 static void usbd_msc_send_info(uint8_t busid, uint8_t *buffer, uint8_t size)
165 {
166 size = MIN(size, g_usbd_msc[busid].cbw.dDataLength);
167
168 /* updating the State Machine , so that we send CSW when this
169 * transfer is complete, ie when we get a bulk in callback
170 */
171 g_usbd_msc[busid].stage = MSC_SEND_CSW;
172
173 usbd_ep_start_write(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr, buffer, size);
174
175 g_usbd_msc[busid].csw.dDataResidue -= size;
176 g_usbd_msc[busid].csw.bStatus = CSW_STATUS_CMD_PASSED;
177 }
178
179 static bool SCSI_processWrite(uint8_t busid, uint32_t nbytes);
180 static bool SCSI_processRead(uint8_t busid);
181
182 /**
183 * @brief SCSI_SetSenseData
184 * Load the last error code in the error list
185 * @param sKey: Sense Key
186 * @param ASC: Additional Sense Code
187 * @retval none
188
189 */
SCSI_SetSenseData(uint8_t busid,uint32_t KCQ)190 static void SCSI_SetSenseData(uint8_t busid, uint32_t KCQ)
191 {
192 g_usbd_msc[busid].sKey = (uint8_t)(KCQ >> 16);
193 g_usbd_msc[busid].ASC = (uint8_t)(KCQ >> 8);
194 g_usbd_msc[busid].ASQ = (uint8_t)(KCQ);
195 }
196
197 /**
198 * @brief SCSI Command list
199 *
200 */
201
SCSI_testUnitReady(uint8_t busid,uint8_t ** data,uint32_t * len)202 static bool SCSI_testUnitReady(uint8_t busid, uint8_t **data, uint32_t *len)
203 {
204 if (g_usbd_msc[busid].cbw.dDataLength != 0U) {
205 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
206 return false;
207 }
208 *data = NULL;
209 *len = 0;
210 return true;
211 }
212
SCSI_requestSense(uint8_t busid,uint8_t ** data,uint32_t * len)213 static bool SCSI_requestSense(uint8_t busid, uint8_t **data, uint32_t *len)
214 {
215 uint8_t data_len = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
216 if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
217 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
218 return false;
219 }
220
221 if (g_usbd_msc[busid].cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
222 data_len = g_usbd_msc[busid].cbw.CB[4];
223 }
224
225 uint8_t request_sense[SCSIRESP_FIXEDSENSEDATA_SIZEOF] = {
226 0x70,
227 0x00,
228 0x00, /* Sense Key */
229 0x00,
230 0x00,
231 0x00,
232 0x00,
233 SCSIRESP_FIXEDSENSEDATA_SIZEOF - 8,
234 0x00,
235 0x00,
236 0x00,
237 0x00,
238 0x00, /* Additional Sense Code */
239 0x00, /* Additional Sense Request */
240 0x00,
241 0x00,
242 0x00,
243 0x00,
244 };
245
246 request_sense[2] = g_usbd_msc[busid].sKey;
247 request_sense[12] = g_usbd_msc[busid].ASC;
248 request_sense[13] = g_usbd_msc[busid].ASQ;
249 #if 0
250 request_sense[ 2] = 0x06; /* UNIT ATTENTION */
251 request_sense[12] = 0x28; /* Additional Sense Code: Not ready to ready transition */
252 request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
253 #endif
254 #if 0
255 request_sense[ 2] = 0x02; /* NOT READY */
256 request_sense[12] = 0x3A; /* Additional Sense Code: Medium not present */
257 request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
258 #endif
259 #if 0
260 request_sense[ 2] = 0x05; /* ILLEGAL REQUEST */
261 request_sense[12] = 0x20; /* Additional Sense Code: Invalid command */
262 request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
263 #endif
264 #if 0
265 request_sense[ 2] = 0x00; /* NO SENSE */
266 request_sense[12] = 0x00; /* Additional Sense Code: No additional code */
267 request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
268 #endif
269
270 memcpy(*data, (uint8_t *)request_sense, data_len);
271 *len = data_len;
272 return true;
273 }
274
SCSI_inquiry(uint8_t busid,uint8_t ** data,uint32_t * len)275 static bool SCSI_inquiry(uint8_t busid, uint8_t **data, uint32_t *len)
276 {
277 uint8_t data_len = SCSIRESP_INQUIRY_SIZEOF;
278
279 uint8_t inquiry00[6] = {
280 0x00,
281 0x00,
282 0x00,
283 (0x06 - 4U),
284 0x00,
285 0x80
286 };
287
288 /* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
289 uint8_t inquiry80[8] = {
290 0x00,
291 0x80,
292 0x00,
293 0x08,
294 0x20, /* Put Product Serial number */
295 0x20,
296 0x20,
297 0x20
298 };
299
300 uint8_t inquiry[SCSIRESP_INQUIRY_SIZEOF] = {
301 /* 36 */
302
303 /* LUN 0 */
304 0x00,
305 0x80,
306 0x02,
307 0x02,
308 (SCSIRESP_INQUIRY_SIZEOF - 5),
309 0x00,
310 0x00,
311 0x00,
312 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
313 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* Product : 16 Bytes */
314 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
315 ' ', ' ', ' ', ' ' /* Version : 4 Bytes */
316 };
317
318 memcpy(&inquiry[8], CONFIG_USBDEV_MSC_MANUFACTURER_STRING, strlen(CONFIG_USBDEV_MSC_MANUFACTURER_STRING));
319 memcpy(&inquiry[16], CONFIG_USBDEV_MSC_PRODUCT_STRING, strlen(CONFIG_USBDEV_MSC_PRODUCT_STRING));
320 memcpy(&inquiry[32], CONFIG_USBDEV_MSC_VERSION_STRING, strlen(CONFIG_USBDEV_MSC_VERSION_STRING));
321
322 if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
323 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
324 return false;
325 }
326
327 if ((g_usbd_msc[busid].cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
328 if (g_usbd_msc[busid].cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
329 data_len = 0x06;
330 memcpy(*data, (uint8_t *)inquiry00, data_len);
331 } else if (g_usbd_msc[busid].cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
332 data_len = 0x08;
333 memcpy(*data, (uint8_t *)inquiry80, data_len);
334 } else { /* Request Not supported */
335 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDFIELDINCBA);
336 return false;
337 }
338 } else {
339 if (g_usbd_msc[busid].cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
340 data_len = g_usbd_msc[busid].cbw.CB[4];
341 }
342 memcpy(*data, (uint8_t *)inquiry, data_len);
343 }
344
345 *len = data_len;
346 return true;
347 }
348
SCSI_startStopUnit(uint8_t busid,uint8_t ** data,uint32_t * len)349 static bool SCSI_startStopUnit(uint8_t busid, uint8_t **data, uint32_t *len)
350 {
351 if (g_usbd_msc[busid].cbw.dDataLength != 0U) {
352 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
353 return false;
354 }
355
356 if ((g_usbd_msc[busid].cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
357 {
358 //SCSI_MEDIUM_UNLOCKED;
359 } else if ((g_usbd_msc[busid].cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
360 {
361 //SCSI_MEDIUM_EJECTED;
362 g_usbd_msc[busid].popup = true;
363 } else if ((g_usbd_msc[busid].cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
364 {
365 //SCSI_MEDIUM_UNLOCKED;
366 } else {
367 }
368
369 *data = NULL;
370 *len = 0;
371 return true;
372 }
373
SCSI_preventAllowMediaRemoval(uint8_t busid,uint8_t ** data,uint32_t * len)374 static bool SCSI_preventAllowMediaRemoval(uint8_t busid, uint8_t **data, uint32_t *len)
375 {
376 if (g_usbd_msc[busid].cbw.dDataLength != 0U) {
377 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
378 return false;
379 }
380 if (g_usbd_msc[busid].cbw.CB[4] == 0U) {
381 //SCSI_MEDIUM_UNLOCKED;
382 } else {
383 //SCSI_MEDIUM_LOCKED;
384 }
385 *data = NULL;
386 *len = 0;
387 return true;
388 }
389
SCSI_modeSense6(uint8_t busid,uint8_t ** data,uint32_t * len)390 static bool SCSI_modeSense6(uint8_t busid, uint8_t **data, uint32_t *len)
391 {
392 uint8_t data_len = 4;
393 if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
394 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
395 return false;
396 }
397 if (g_usbd_msc[busid].cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
398 data_len = g_usbd_msc[busid].cbw.CB[4];
399 }
400
401 uint8_t sense6[SCSIRESP_MODEPARAMETERHDR6_SIZEOF] = { 0x03, 0x00, 0x00, 0x00 };
402
403 if (g_usbd_msc[busid].readonly) {
404 sense6[2] = 0x80;
405 }
406 memcpy(*data, (uint8_t *)sense6, data_len);
407 *len = data_len;
408 return true;
409 }
410
SCSI_modeSense10(uint8_t busid,uint8_t ** data,uint32_t * len)411 static bool SCSI_modeSense10(uint8_t busid, uint8_t **data, uint32_t *len)
412 {
413 uint8_t data_len = 27;
414 if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
415 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
416 return false;
417 }
418
419 if (g_usbd_msc[busid].cbw.CB[8] < 27) {
420 data_len = g_usbd_msc[busid].cbw.CB[8];
421 }
422
423 uint8_t sense10[27] = {
424 0x00,
425 0x26,
426 0x00,
427 0x00,
428 0x00,
429 0x00,
430 0x00,
431 0x00,
432 0x08,
433 0x12,
434 0x00,
435 0x00,
436 0x00,
437 0x00,
438 0x00,
439 0x00,
440 0x00,
441 0x00,
442 0x00,
443 0x00,
444 0x00,
445 0x00,
446 0x00,
447 0x00,
448 0x00,
449 0x00,
450 0x00
451 };
452
453 memcpy(*data, (uint8_t *)sense10, data_len);
454 *len = data_len;
455 return true;
456 }
457
SCSI_readFormatCapacity(uint8_t busid,uint8_t ** data,uint32_t * len)458 static bool SCSI_readFormatCapacity(uint8_t busid, uint8_t **data, uint32_t *len)
459 {
460 if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
461 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
462 return false;
463 }
464 uint8_t format_capacity[SCSIRESP_READFORMATCAPACITIES_SIZEOF] = {
465 0x00,
466 0x00,
467 0x00,
468 0x08, /* Capacity List Length */
469 (uint8_t)((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] >> 24) & 0xff),
470 (uint8_t)((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] >> 16) & 0xff),
471 (uint8_t)((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] >> 8) & 0xff),
472 (uint8_t)((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] >> 0) & 0xff),
473
474 0x02, /* Descriptor Code: Formatted Media */
475 0x00,
476 (uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 8) & 0xff),
477 (uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 0) & 0xff),
478 };
479
480 memcpy(*data, (uint8_t *)format_capacity, SCSIRESP_READFORMATCAPACITIES_SIZEOF);
481 *len = SCSIRESP_READFORMATCAPACITIES_SIZEOF;
482 return true;
483 }
484
SCSI_readCapacity10(uint8_t busid,uint8_t ** data,uint32_t * len)485 static bool SCSI_readCapacity10(uint8_t busid, uint8_t **data, uint32_t *len)
486 {
487 if (g_usbd_msc[busid].cbw.dDataLength == 0U) {
488 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
489 return false;
490 }
491
492 uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = {
493 (uint8_t)(((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] - 1) >> 24) & 0xff),
494 (uint8_t)(((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] - 1) >> 16) & 0xff),
495 (uint8_t)(((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] - 1) >> 8) & 0xff),
496 (uint8_t)(((g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN] - 1) >> 0) & 0xff),
497
498 (uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 24) & 0xff),
499 (uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 16) & 0xff),
500 (uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 8) & 0xff),
501 (uint8_t)((g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN] >> 0) & 0xff),
502 };
503
504 memcpy(*data, (uint8_t *)capacity10, SCSIRESP_READCAPACITY10_SIZEOF);
505 *len = SCSIRESP_READCAPACITY10_SIZEOF;
506 return true;
507 }
508
SCSI_read10(uint8_t busid,uint8_t ** data,uint32_t * len)509 static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
510 {
511 (void)data;
512 (void)len;
513
514 if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
515 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
516 return false;
517 }
518
519 g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
520 g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */
521
522 if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
523 SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE);
524 return false;
525 }
526
527 if (g_usbd_msc[busid].cbw.dDataLength != (g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN])) {
528 return false;
529 }
530 g_usbd_msc[busid].stage = MSC_DATA_IN;
531 #if defined(CONFIG_USBDEV_MSC_THREAD)
532 usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
533 return true;
534 #elif defined(CONFIG_USBDEV_MSC_POLLING)
535 g_usbd_msc[busid].event = MSC_DATA_IN;
536 return true;
537 #else
538 return SCSI_processRead(busid);
539 #endif
540 }
541
SCSI_read12(uint8_t busid,uint8_t ** data,uint32_t * len)542 static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
543 {
544 (void)data;
545 (void)len;
546
547 if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x80U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
548 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
549 return false;
550 }
551
552 g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
553 g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */
554
555 if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
556 SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE);
557 return false;
558 }
559
560 if (g_usbd_msc[busid].cbw.dDataLength != (g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN])) {
561 return false;
562 }
563 g_usbd_msc[busid].stage = MSC_DATA_IN;
564 #if defined(CONFIG_USBDEV_MSC_THREAD)
565 usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
566 return true;
567 #elif defined(CONFIG_USBDEV_MSC_POLLING)
568 g_usbd_msc[busid].event = MSC_DATA_IN;
569 return true;
570 #else
571 return SCSI_processRead(busid);
572 #endif
573 }
574
SCSI_write10(uint8_t busid,uint8_t ** data,uint32_t * len)575 static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
576 {
577 uint32_t data_len = 0;
578
579 (void)data;
580 (void)len;
581
582 if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
583 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
584 return false;
585 }
586
587 g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
588 g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */
589
590 data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
591 if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
592 return false;
593 }
594
595 if (g_usbd_msc[busid].cbw.dDataLength != data_len) {
596 return false;
597 }
598 g_usbd_msc[busid].stage = MSC_DATA_OUT;
599 data_len = MIN(data_len, CONFIG_USBDEV_MSC_MAX_BUFSIZE);
600 usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, g_usbd_msc[busid].block_buffer, data_len);
601 return true;
602 }
603
SCSI_write12(uint8_t busid,uint8_t ** data,uint32_t * len)604 static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len)
605 {
606 uint32_t data_len = 0;
607
608 (void)data;
609 (void)len;
610
611 if (((g_usbd_msc[busid].cbw.bmFlags & 0x80U) != 0x00U) || (g_usbd_msc[busid].cbw.dDataLength == 0U)) {
612 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
613 return false;
614 }
615
616 g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
617 g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */
618
619 data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
620 if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
621 return false;
622 }
623
624 if (g_usbd_msc[busid].cbw.dDataLength != data_len) {
625 return false;
626 }
627 g_usbd_msc[busid].stage = MSC_DATA_OUT;
628 data_len = MIN(data_len, CONFIG_USBDEV_MSC_MAX_BUFSIZE);
629 usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, g_usbd_msc[busid].block_buffer, data_len);
630 return true;
631 }
632
SCSI_processRead(uint8_t busid)633 static bool SCSI_processRead(uint8_t busid)
634 {
635 uint32_t transfer_len;
636
637 USB_LOG_DBG("read lba:%d\r\n", g_usbd_msc[busid].start_sector);
638
639 transfer_len = MIN(g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN], CONFIG_USBDEV_MSC_MAX_BUFSIZE);
640
641 if (usbd_msc_sector_read(busid, g_usbd_msc[busid].cbw.bLUN, g_usbd_msc[busid].start_sector, g_usbd_msc[busid].block_buffer, transfer_len) != 0) {
642 SCSI_SetSenseData(busid, SCSI_KCQHE_UREINRESERVEDAREA);
643 return false;
644 }
645
646 g_usbd_msc[busid].start_sector += (transfer_len / g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]);
647 g_usbd_msc[busid].nsectors -= (transfer_len / g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]);
648 g_usbd_msc[busid].csw.dDataResidue -= transfer_len;
649
650 if (g_usbd_msc[busid].nsectors == 0) {
651 g_usbd_msc[busid].stage = MSC_SEND_CSW;
652 }
653
654 usbd_ep_start_write(busid, mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr, g_usbd_msc[busid].block_buffer, transfer_len);
655
656 return true;
657 }
658
SCSI_processWrite(uint8_t busid,uint32_t nbytes)659 static bool SCSI_processWrite(uint8_t busid, uint32_t nbytes)
660 {
661 uint32_t data_len = 0;
662
663 USB_LOG_DBG("write lba:%d\r\n", g_usbd_msc[busid].start_sector);
664
665 if (usbd_msc_sector_write(busid, g_usbd_msc[busid].cbw.bLUN, g_usbd_msc[busid].start_sector, g_usbd_msc[busid].block_buffer, nbytes) != 0) {
666 SCSI_SetSenseData(busid, SCSI_KCQHE_WRITEFAULT);
667 return false;
668 }
669
670 g_usbd_msc[busid].start_sector += (nbytes / g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]);
671 g_usbd_msc[busid].nsectors -= (nbytes / g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN]);
672 g_usbd_msc[busid].csw.dDataResidue -= nbytes;
673
674 if (g_usbd_msc[busid].nsectors == 0) {
675 usbd_msc_send_csw(busid, CSW_STATUS_CMD_PASSED);
676 } else {
677 data_len = MIN(g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN], CONFIG_USBDEV_MSC_MAX_BUFSIZE);
678 usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, g_usbd_msc[busid].block_buffer, data_len);
679 }
680
681 return true;
682 }
683
SCSI_CBWDecode(uint8_t busid,uint32_t nbytes)684 static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes)
685 {
686 uint8_t *buf2send = g_usbd_msc[busid].block_buffer;
687 uint32_t len2send = 0;
688 bool ret = false;
689
690 if (nbytes != sizeof(struct CBW)) {
691 USB_LOG_ERR("size != sizeof(cbw)\r\n");
692 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
693 return false;
694 }
695
696 g_usbd_msc[busid].csw.dTag = g_usbd_msc[busid].cbw.dTag;
697 g_usbd_msc[busid].csw.dDataResidue = g_usbd_msc[busid].cbw.dDataLength;
698
699 if ((g_usbd_msc[busid].cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc[busid].cbw.bCBLength < 1) || (g_usbd_msc[busid].cbw.bCBLength > 16)) {
700 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
701 return false;
702 } else {
703 USB_LOG_DBG("Decode CB:0x%02x\r\n", g_usbd_msc[busid].cbw.CB[0]);
704 switch (g_usbd_msc[busid].cbw.CB[0]) {
705 case SCSI_CMD_TESTUNITREADY:
706 ret = SCSI_testUnitReady(busid, &buf2send, &len2send);
707 break;
708 case SCSI_CMD_REQUESTSENSE:
709 ret = SCSI_requestSense(busid, &buf2send, &len2send);
710 break;
711 case SCSI_CMD_INQUIRY:
712 ret = SCSI_inquiry(busid, &buf2send, &len2send);
713 break;
714 case SCSI_CMD_STARTSTOPUNIT:
715 ret = SCSI_startStopUnit(busid, &buf2send, &len2send);
716 break;
717 case SCSI_CMD_PREVENTMEDIAREMOVAL:
718 ret = SCSI_preventAllowMediaRemoval(busid, &buf2send, &len2send);
719 break;
720 case SCSI_CMD_MODESENSE6:
721 ret = SCSI_modeSense6(busid, &buf2send, &len2send);
722 break;
723 case SCSI_CMD_MODESENSE10:
724 ret = SCSI_modeSense10(busid, &buf2send, &len2send);
725 break;
726 case SCSI_CMD_READFORMATCAPACITIES:
727 ret = SCSI_readFormatCapacity(busid, &buf2send, &len2send);
728 break;
729 case SCSI_CMD_READCAPACITY10:
730 ret = SCSI_readCapacity10(busid, &buf2send, &len2send);
731 break;
732 case SCSI_CMD_READ10:
733 ret = SCSI_read10(busid, NULL, 0);
734 break;
735 case SCSI_CMD_READ12:
736 ret = SCSI_read12(busid, NULL, 0);
737 break;
738 case SCSI_CMD_WRITE10:
739 ret = SCSI_write10(busid, NULL, 0);
740 break;
741 case SCSI_CMD_WRITE12:
742 ret = SCSI_write12(busid, NULL, 0);
743 break;
744 case SCSI_CMD_VERIFY10:
745 ret = false;
746 break;
747 case SCSI_CMD_SYNCHCACHE10:
748 ret = true;
749 break;
750 default:
751 SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
752 ret = false;
753 break;
754 }
755 }
756 if (ret) {
757 if (g_usbd_msc[busid].stage == MSC_READ_CBW) {
758 if (len2send) {
759 USB_LOG_DBG("Send info len: %d\r\n", len2send);
760 usbd_msc_send_info(busid, buf2send, len2send);
761 } else {
762 usbd_msc_send_csw(busid, CSW_STATUS_CMD_PASSED);
763 }
764 }
765 }
766 return ret;
767 }
768
mass_storage_bulk_out(uint8_t busid,uint8_t ep,uint32_t nbytes)769 void mass_storage_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
770 {
771 (void)ep;
772
773 switch (g_usbd_msc[busid].stage) {
774 case MSC_READ_CBW:
775 if (SCSI_CBWDecode(busid, nbytes) == false) {
776 USB_LOG_ERR("Command: 0x%02x decode err\r\n", g_usbd_msc[busid].cbw.CB[0]);
777 usbd_msc_bot_abort(busid);
778 return;
779 }
780 break;
781 case MSC_DATA_OUT:
782 switch (g_usbd_msc[busid].cbw.CB[0]) {
783 case SCSI_CMD_WRITE10:
784 case SCSI_CMD_WRITE12:
785 #if defined(CONFIG_USBDEV_MSC_THREAD)
786 g_usbd_msc[busid].nbytes = nbytes;
787 usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_OUT);
788 #elif defined(CONFIG_USBDEV_MSC_POLLING)
789 g_usbd_msc[busid].nbytes = nbytes;
790 g_usbd_msc[busid].event = MSC_DATA_OUT;
791 #else
792 if (SCSI_processWrite(busid, nbytes) == false) {
793 usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
794 }
795 #endif
796 break;
797 default:
798 break;
799 }
800 break;
801 default:
802 break;
803 }
804 }
805
mass_storage_bulk_in(uint8_t busid,uint8_t ep,uint32_t nbytes)806 void mass_storage_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
807 {
808 (void)ep;
809 (void)nbytes;
810
811 switch (g_usbd_msc[busid].stage) {
812 case MSC_DATA_IN:
813 switch (g_usbd_msc[busid].cbw.CB[0]) {
814 case SCSI_CMD_READ10:
815 case SCSI_CMD_READ12:
816 #if defined(CONFIG_USBDEV_MSC_THREAD)
817 usb_osal_mq_send(g_usbd_msc[busid].usbd_msc_mq, MSC_DATA_IN);
818 #elif defined(CONFIG_USBDEV_MSC_POLLING)
819 g_usbd_msc[busid].event = MSC_DATA_IN;
820 #else
821 if (SCSI_processRead(busid) == false) {
822 usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
823 return;
824 }
825 #endif
826 break;
827 default:
828 break;
829 }
830 break;
831 /*the device has to send a CSW*/
832 case MSC_SEND_CSW:
833 usbd_msc_send_csw(busid, CSW_STATUS_CMD_PASSED);
834 break;
835
836 /*the host has received the CSW*/
837 case MSC_WAIT_CSW:
838 g_usbd_msc[busid].stage = MSC_READ_CBW;
839 USB_LOG_DBG("Start reading cbw\r\n");
840 usbd_ep_start_read(busid, mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&g_usbd_msc[busid].cbw, USB_SIZEOF_MSC_CBW);
841 break;
842
843 default:
844 break;
845 }
846 }
847
848 #if defined(CONFIG_USBDEV_MSC_THREAD)
usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)849 static void usbdev_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
850 {
851 uintptr_t event;
852 int ret;
853 uint8_t busid = (uint8_t)CONFIG_USB_OSAL_THREAD_GET_ARGV;
854
855 while (1) {
856 ret = usb_osal_mq_recv(g_usbd_msc[busid].usbd_msc_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER);
857 if (ret < 0) {
858 continue;
859 }
860 if (event == MSC_DATA_OUT) {
861 if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
862 usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
863 }
864 } else if (event == MSC_DATA_IN) {
865 if (SCSI_processRead(busid) == false) {
866 usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
867 }
868 } else {
869 }
870 }
871 }
872 #elif defined(CONFIG_USBDEV_MSC_POLLING)
usbd_msc_polling(uint8_t busid)873 void usbd_msc_polling(uint8_t busid)
874 {
875 uint8_t event;
876
877 event = g_usbd_msc[busid].event;
878
879 if (event != 0) {
880 g_usbd_msc[busid].event = 0;
881 if (event == MSC_DATA_OUT) {
882 if (SCSI_processWrite(busid, g_usbd_msc[busid].nbytes) == false) {
883 usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
884 }
885 } else if (event == MSC_DATA_IN) {
886 if (SCSI_processRead(busid) == false) {
887 usbd_msc_send_csw(busid, CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
888 }
889 } else {
890 }
891 }
892 }
893 #endif
894
usbd_msc_init_intf(uint8_t busid,struct usbd_interface * intf,const uint8_t out_ep,const uint8_t in_ep)895 struct usbd_interface *usbd_msc_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t out_ep, const uint8_t in_ep)
896 {
897 intf->class_interface_handler = msc_storage_class_interface_request_handler;
898 intf->class_endpoint_handler = NULL;
899 intf->vendor_handler = NULL;
900 intf->notify_handler = msc_storage_notify_handler;
901
902 mass_ep_data[busid][MSD_OUT_EP_IDX].ep_addr = out_ep;
903 mass_ep_data[busid][MSD_OUT_EP_IDX].ep_cb = mass_storage_bulk_out;
904 mass_ep_data[busid][MSD_IN_EP_IDX].ep_addr = in_ep;
905 mass_ep_data[busid][MSD_IN_EP_IDX].ep_cb = mass_storage_bulk_in;
906
907 usbd_add_endpoint(busid, &mass_ep_data[busid][MSD_OUT_EP_IDX]);
908 usbd_add_endpoint(busid, &mass_ep_data[busid][MSD_IN_EP_IDX]);
909
910 memset((uint8_t *)&g_usbd_msc[busid], 0, sizeof(struct usbd_msc_priv));
911
912 usdb_msc_set_max_lun(busid);
913 for (uint8_t i = 0u; i <= g_usbd_msc[busid].max_lun; i++) {
914 usbd_msc_get_cap(busid, i, &g_usbd_msc[busid].scsi_blk_nbr[i], &g_usbd_msc[busid].scsi_blk_size[i]);
915
916 if (CONFIG_USBDEV_MSC_MAX_BUFSIZE % g_usbd_msc[busid].scsi_blk_size[i]) {
917 USB_LOG_ERR("CONFIG_USBDEV_MSC_MAX_BUFSIZE must be a multiple of block size\r\n");
918 while (1) {
919 }
920 }
921 }
922
923 return intf;
924 }
925
usbd_msc_set_readonly(uint8_t busid,bool readonly)926 void usbd_msc_set_readonly(uint8_t busid, bool readonly)
927 {
928 g_usbd_msc[busid].readonly = readonly;
929 }
930
usbd_msc_get_popup(uint8_t busid)931 bool usbd_msc_get_popup(uint8_t busid)
932 {
933 return g_usbd_msc[busid].popup;
934 }
935
usbd_msc_get_cap(uint8_t busid,uint8_t lun,uint32_t * block_num,uint32_t * block_size)936 __WEAK void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint32_t *block_size)
937 {
938 (void)busid;
939 (void)lun;
940
941 *block_num = 0;
942 *block_size = 0;
943 }
944
usbd_msc_sector_read(uint8_t busid,uint8_t lun,uint32_t sector,uint8_t * buffer,uint32_t length)945 __WEAK int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
946 {
947 (void)busid;
948 (void)lun;
949 (void)sector;
950 (void)buffer;
951 (void)length;
952
953 return 0;
954 }
955
usbd_msc_sector_write(uint8_t busid,uint8_t lun,uint32_t sector,uint8_t * buffer,uint32_t length)956 __WEAK int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length)
957 {
958 (void)busid;
959 (void)lun;
960 (void)sector;
961 (void)buffer;
962 (void)length;
963
964 return 0;
965 }