1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2012-10-01 Yi Qiu first version
9 * 2012-11-25 Heyuanjie87 reduce the memory consumption
10 * 2012-12-09 Heyuanjie87 change function and endpoint handler
11 * 2013-07-25 Yi Qiu update for USB CV test
12 */
13
14 #include <rtthread.h>
15 #include <rtservice.h>
16 #include "drivers/usb_device.h"
17 #include "mstorage.h"
18
19 #ifdef RT_USB_DEVICE_MSTORAGE
20
21 enum STAT
22 {
23 STAT_CBW,
24 STAT_CMD,
25 STAT_CSW,
26 STAT_RECEIVE,
27 STAT_SEND,
28 };
29
30 typedef enum
31 {
32 FIXED,
33 COUNT,
34 BLOCK_COUNT,
35 }CB_SIZE_TYPE;
36
37 typedef enum
38 {
39 DIR_IN,
40 DIR_OUT,
41 DIR_NONE,
42 }CB_DIR;
43
44 typedef rt_size_t (*cbw_handler)(ufunction_t func, ustorage_cbw_t cbw);
45
46 struct scsi_cmd
47 {
48 rt_uint16_t cmd;
49 cbw_handler handler;
50 rt_size_t cmd_len;
51 CB_SIZE_TYPE type;
52 rt_size_t data_size;
53 CB_DIR dir;
54 };
55
56 struct mstorage
57 {
58 struct ustorage_csw csw_response;
59 uep_t ep_in;
60 uep_t ep_out;
61 int status;
62 rt_uint32_t cb_data_size;
63 rt_device_t disk;
64 rt_uint32_t block;
65 rt_int32_t count;
66 rt_int32_t size;
67 struct scsi_cmd* processing;
68 struct rt_device_blk_geometry geometry;
69 };
70
71 ALIGN(4)
72 static struct udevice_descriptor dev_desc =
73 {
74 USB_DESC_LENGTH_DEVICE, //bLength;
75 USB_DESC_TYPE_DEVICE, //type;
76 USB_BCD_VERSION, //bcdUSB;
77 USB_CLASS_MASS_STORAGE, //bDeviceClass;
78 0x06, //bDeviceSubClass;
79 0x50, //bDeviceProtocol;
80 0x40, //bMaxPacketSize0;
81 _VENDOR_ID, //idVendor;
82 _PRODUCT_ID, //idProduct;
83 USB_BCD_DEVICE, //bcdDevice;
84 USB_STRING_MANU_INDEX, //iManufacturer;
85 USB_STRING_PRODUCT_INDEX, //iProduct;
86 USB_STRING_SERIAL_INDEX, //iSerialNumber;
87 USB_DYNAMIC, //bNumConfigurations;
88 };
89
90 //FS and HS needed
91 ALIGN(4)
92 static struct usb_qualifier_descriptor dev_qualifier =
93 {
94 sizeof(dev_qualifier), //bLength
95 USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType
96 0x0200, //bcdUSB
97 USB_CLASS_MASS_STORAGE, //bDeviceClass
98 0x06, //bDeviceSubClass
99 0x50, //bDeviceProtocol
100 64, //bMaxPacketSize0
101 0x01, //bNumConfigurations
102 0,
103 };
104
105
106 ALIGN(4)
107 const static struct umass_descriptor _mass_desc =
108 {
109 #ifdef RT_USB_DEVICE_COMPOSITE
110 /* Interface Association Descriptor */
111 {
112 USB_DESC_LENGTH_IAD,
113 USB_DESC_TYPE_IAD,
114 USB_DYNAMIC,
115 0x01,
116 USB_CLASS_MASS_STORAGE,
117 0x06,
118 0x50,
119 0x00,
120 },
121 #endif
122 {
123 USB_DESC_LENGTH_INTERFACE, //bLength;
124 USB_DESC_TYPE_INTERFACE, //type;
125 USB_DYNAMIC, //bInterfaceNumber;
126 0x00, //bAlternateSetting;
127 0x02, //bNumEndpoints
128 USB_CLASS_MASS_STORAGE, //bInterfaceClass;
129 0x06, //bInterfaceSubClass;
130 0x50, //bInterfaceProtocol;
131 0x00, //iInterface;
132 },
133
134 {
135 USB_DESC_LENGTH_ENDPOINT, //bLength;
136 USB_DESC_TYPE_ENDPOINT, //type;
137 USB_DYNAMIC | USB_DIR_OUT, //bEndpointAddress;
138 USB_EP_ATTR_BULK, //bmAttributes;
139 USB_DYNAMIC, //wMaxPacketSize;
140 0x00, //bInterval;
141 },
142
143 {
144 USB_DESC_LENGTH_ENDPOINT, //bLength;
145 USB_DESC_TYPE_ENDPOINT, //type;
146 USB_DYNAMIC | USB_DIR_IN, //bEndpointAddress;
147 USB_EP_ATTR_BULK, //bmAttributes;
148 USB_DYNAMIC, //wMaxPacketSize;
149 0x00, //bInterval;
150 },
151 };
152
153 ALIGN(4)
154 const static char* _ustring[] =
155 {
156 "Language",
157 "RT-Thread Team.",
158 "RTT Mass Storage",
159 "320219198301",
160 "Configuration",
161 "Interface",
162 };
163
164 static rt_size_t _test_unit_ready(ufunction_t func, ustorage_cbw_t cbw);
165 static rt_size_t _request_sense(ufunction_t func, ustorage_cbw_t cbw);
166 static rt_size_t _inquiry_cmd(ufunction_t func, ustorage_cbw_t cbw);
167 static rt_size_t _allow_removal(ufunction_t func, ustorage_cbw_t cbw);
168 static rt_size_t _start_stop(ufunction_t func, ustorage_cbw_t cbw);
169 static rt_size_t _mode_sense_6(ufunction_t func, ustorage_cbw_t cbw);
170 static rt_size_t _read_capacities(ufunction_t func, ustorage_cbw_t cbw);
171 static rt_size_t _read_capacity(ufunction_t func, ustorage_cbw_t cbw);
172 static rt_size_t _read_10(ufunction_t func, ustorage_cbw_t cbw);
173 static rt_size_t _write_10(ufunction_t func, ustorage_cbw_t cbw);
174 static rt_size_t _verify_10(ufunction_t func, ustorage_cbw_t cbw);
175
176 ALIGN(4)
177 static struct scsi_cmd cmd_data[] =
178 {
179 {SCSI_TEST_UNIT_READY, _test_unit_ready, 6, FIXED, 0, DIR_NONE},
180 {SCSI_REQUEST_SENSE, _request_sense, 6, COUNT, 0, DIR_IN},
181 {SCSI_INQUIRY_CMD, _inquiry_cmd, 6, COUNT, 0, DIR_IN},
182 {SCSI_ALLOW_REMOVAL, _allow_removal, 6, FIXED, 0, DIR_NONE},
183 {SCSI_MODE_SENSE_6, _mode_sense_6, 6, COUNT, 0, DIR_IN},
184 {SCSI_START_STOP, _start_stop, 6, FIXED, 0, DIR_NONE},
185 {SCSI_READ_CAPACITIES, _read_capacities, 10, COUNT, 0, DIR_NONE},
186 {SCSI_READ_CAPACITY, _read_capacity, 10, FIXED, 8, DIR_IN},
187 {SCSI_READ_10, _read_10, 10, BLOCK_COUNT, 0, DIR_IN},
188 {SCSI_WRITE_10, _write_10, 10, BLOCK_COUNT, 0, DIR_OUT},
189 {SCSI_VERIFY_10, _verify_10, 10, FIXED, 0, DIR_NONE},
190 };
191
_send_status(ufunction_t func)192 static void _send_status(ufunction_t func)
193 {
194 struct mstorage *data;
195
196 RT_ASSERT(func != RT_NULL);
197
198 RT_DEBUG_LOG(RT_DEBUG_USB, ("_send_status\n"));
199
200 data = (struct mstorage*)func->user_data;
201 data->ep_in->request.buffer = (rt_uint8_t*)&data->csw_response;
202 data->ep_in->request.size = SIZEOF_CSW;
203 data->ep_in->request.req_type = UIO_REQUEST_WRITE;
204 rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
205 data->status = STAT_CSW;
206 }
207
_test_unit_ready(ufunction_t func,ustorage_cbw_t cbw)208 static rt_size_t _test_unit_ready(ufunction_t func, ustorage_cbw_t cbw)
209 {
210 struct mstorage *data;
211
212 RT_ASSERT(func != RT_NULL);
213 RT_ASSERT(func->device != RT_NULL);
214
215 RT_DEBUG_LOG(RT_DEBUG_USB, ("_test_unit_ready\n"));
216
217 data = (struct mstorage*)func->user_data;
218 data->csw_response.status = 0;
219
220 return 0;
221 }
222
_allow_removal(ufunction_t func,ustorage_cbw_t cbw)223 static rt_size_t _allow_removal(ufunction_t func, ustorage_cbw_t cbw)
224 {
225 struct mstorage *data;
226
227 RT_ASSERT(func != RT_NULL);
228 RT_ASSERT(func->device != RT_NULL);
229
230 RT_DEBUG_LOG(RT_DEBUG_USB, ("_allow_removal\n"));
231
232 data = (struct mstorage*)func->user_data;
233 data->csw_response.status = 0;
234
235 return 0;
236 }
237
238 /**
239 * This function will handle inquiry command request.
240 *
241 * @param func the usb function object.
242 * @param cbw the command block wrapper.
243 *
244 * @return RT_EOK on successful.
245 */
246
_inquiry_cmd(ufunction_t func,ustorage_cbw_t cbw)247 static rt_size_t _inquiry_cmd(ufunction_t func, ustorage_cbw_t cbw)
248 {
249 struct mstorage *data;
250 rt_uint8_t *buf;
251
252 RT_ASSERT(func != RT_NULL);
253 RT_ASSERT(func->device != RT_NULL);
254 RT_ASSERT(cbw != RT_NULL);
255
256 RT_DEBUG_LOG(RT_DEBUG_USB, ("_inquiry_cmd\n"));
257
258 data = (struct mstorage*)func->user_data;
259 buf = data->ep_in->buffer;
260
261 *(rt_uint32_t*)&buf[0] = 0x0 | (0x80 << 8);
262 *(rt_uint32_t*)&buf[4] = 31;
263
264 rt_memset(&buf[8], 0x20, 28);
265 rt_memcpy(&buf[8], "RTT", 3);
266 rt_memcpy(&buf[16], "USB Disk", 8);
267
268 data->cb_data_size = MIN(data->cb_data_size, SIZEOF_INQUIRY_CMD);
269 data->ep_in->request.buffer = buf;
270 data->ep_in->request.size = data->cb_data_size;
271 data->ep_in->request.req_type = UIO_REQUEST_WRITE;
272 rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
273 data->status = STAT_CMD;
274
275 return data->cb_data_size;
276 }
277
278 /**
279 * This function will handle sense request.
280 *
281 * @param func the usb function object.
282 * @param cbw the command block wrapper.
283 *
284 * @return RT_EOK on successful.
285 */
_request_sense(ufunction_t func,ustorage_cbw_t cbw)286 static rt_size_t _request_sense(ufunction_t func, ustorage_cbw_t cbw)
287 {
288 struct mstorage *data;
289 struct request_sense_data *buf;
290
291 RT_ASSERT(func != RT_NULL);
292 RT_ASSERT(func->device != RT_NULL);
293 RT_ASSERT(cbw != RT_NULL);
294
295 RT_DEBUG_LOG(RT_DEBUG_USB, ("_request_sense\n"));
296
297 data = (struct mstorage*)func->user_data;
298 buf = (struct request_sense_data *)data->ep_in->buffer;
299
300 buf->ErrorCode = 0x70;
301 buf->Valid = 0;
302 buf->SenseKey = 2;
303 buf->Information[0] = 0;
304 buf->Information[1] = 0;
305 buf->Information[2] = 0;
306 buf->Information[3] = 0;
307 buf->AdditionalSenseLength = 0x0a;
308 buf->AdditionalSenseCode = 0x3a;
309 buf->AdditionalSenseCodeQualifier = 0;
310
311 data->cb_data_size = MIN(data->cb_data_size, SIZEOF_REQUEST_SENSE);
312 data->ep_in->request.buffer = (rt_uint8_t*)data->ep_in->buffer;
313 data->ep_in->request.size = data->cb_data_size;
314 data->ep_in->request.req_type = UIO_REQUEST_WRITE;
315 rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
316 data->status = STAT_CMD;
317
318 return data->cb_data_size;
319 }
320
321 /**
322 * This function will handle mode_sense_6 request.
323 *
324 * @param func the usb function object.
325 * @param cbw the command block wrapper.
326 *
327 * @return RT_EOK on successful.
328 */
_mode_sense_6(ufunction_t func,ustorage_cbw_t cbw)329 static rt_size_t _mode_sense_6(ufunction_t func, ustorage_cbw_t cbw)
330 {
331 struct mstorage *data;
332 rt_uint8_t *buf;
333
334 RT_ASSERT(func != RT_NULL);
335 RT_ASSERT(func->device != RT_NULL);
336 RT_ASSERT(cbw != RT_NULL);
337
338 RT_DEBUG_LOG(RT_DEBUG_USB, ("_mode_sense_6\n"));
339
340 data = (struct mstorage*)func->user_data;
341 buf = data->ep_in->buffer;
342 buf[0] = 3;
343 buf[1] = 0;
344 buf[2] = 0;
345 buf[3] = 0;
346
347 data->cb_data_size = MIN(data->cb_data_size, SIZEOF_MODE_SENSE_6);
348 data->ep_in->request.buffer = buf;
349 data->ep_in->request.size = data->cb_data_size;
350 data->ep_in->request.req_type = UIO_REQUEST_WRITE;
351 rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
352 data->status = STAT_CMD;
353
354 return data->cb_data_size;
355 }
356
357 /**
358 * This function will handle read_capacities request.
359 *
360 * @param func the usb function object.
361 * @param cbw the command block wrapper.
362 *
363 * @return RT_EOK on successful.
364 */
_read_capacities(ufunction_t func,ustorage_cbw_t cbw)365 static rt_size_t _read_capacities(ufunction_t func, ustorage_cbw_t cbw)
366 {
367 struct mstorage *data;
368 rt_uint8_t *buf;
369 rt_uint32_t sector_count, sector_size;
370
371 RT_ASSERT(func != RT_NULL);
372 RT_ASSERT(func->device != RT_NULL);
373 RT_ASSERT(cbw != RT_NULL);
374
375 RT_DEBUG_LOG(RT_DEBUG_USB, ("_read_capacities\n"));
376
377 data = (struct mstorage*)func->user_data;
378 buf = data->ep_in->buffer;
379 sector_count = data->geometry.sector_count;
380 sector_size = data->geometry.bytes_per_sector;
381
382 *(rt_uint32_t*)&buf[0] = 0x08000000;
383 buf[4] = sector_count >> 24;
384 buf[5] = 0xff & (sector_count >> 16);
385 buf[6] = 0xff & (sector_count >> 8);
386 buf[7] = 0xff & (sector_count);
387 buf[8] = 0x02;
388 buf[9] = 0xff & (sector_size >> 16);
389 buf[10] = 0xff & (sector_size >> 8);
390 buf[11] = 0xff & sector_size;
391
392 data->cb_data_size = MIN(data->cb_data_size, SIZEOF_READ_CAPACITIES);
393 data->ep_in->request.buffer = buf;
394 data->ep_in->request.size = data->cb_data_size;
395 data->ep_in->request.req_type = UIO_REQUEST_WRITE;
396 rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
397 data->status = STAT_CMD;
398
399 return data->cb_data_size;
400 }
401
402 /**
403 * This function will handle read_capacity request.
404 *
405 * @param func the usb function object.
406 * @param cbw the command block wapper.
407 *
408 * @return RT_EOK on successful.
409 */
_read_capacity(ufunction_t func,ustorage_cbw_t cbw)410 static rt_size_t _read_capacity(ufunction_t func, ustorage_cbw_t cbw)
411 {
412 struct mstorage *data;
413
414 rt_uint8_t *buf;
415 rt_uint32_t sector_count, sector_size;
416
417 RT_ASSERT(func != RT_NULL);
418 RT_ASSERT(func->device != RT_NULL);
419 RT_ASSERT(cbw != RT_NULL);
420
421 RT_DEBUG_LOG(RT_DEBUG_USB, ("_read_capacity\n"));
422
423 data = (struct mstorage*)func->user_data;
424 buf = data->ep_in->buffer;
425 sector_count = data->geometry.sector_count;
426 sector_size = data->geometry.bytes_per_sector;
427
428 buf[0] = sector_count >> 24;
429 buf[1] = 0xff & (sector_count >> 16);
430 buf[2] = 0xff & (sector_count >> 8);
431 buf[3] = 0xff & (sector_count);
432 buf[4] = 0x0;
433 buf[5] = 0xff & (sector_size >> 16);
434 buf[6] = 0xff & (sector_size >> 8);
435 buf[7] = 0xff & sector_size;
436
437 data->cb_data_size = MIN(data->cb_data_size, SIZEOF_READ_CAPACITY);
438 data->ep_in->request.buffer = buf;
439 data->ep_in->request.size = data->cb_data_size;
440 data->ep_in->request.req_type = UIO_REQUEST_WRITE;
441 rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
442 data->status = STAT_CMD;
443
444 return data->cb_data_size;
445 }
446
447 /**
448 * This function will handle read_10 request.
449 *
450 * @param func the usb function object.
451 * @param cbw the command block wrapper.
452 *
453 * @return RT_EOK on successful.
454 */
_read_10(ufunction_t func,ustorage_cbw_t cbw)455 static rt_size_t _read_10(ufunction_t func, ustorage_cbw_t cbw)
456 {
457 struct mstorage *data;
458 rt_size_t size;
459
460 RT_ASSERT(func != RT_NULL);
461 RT_ASSERT(func->device != RT_NULL);
462 RT_ASSERT(cbw != RT_NULL);
463
464 data = (struct mstorage*)func->user_data;
465 data->block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
466 cbw->cb[5]<<0;
467 data->count = cbw->cb[7]<<8 | cbw->cb[8]<<0;
468
469 RT_ASSERT(data->count < data->geometry.sector_count);
470
471 data->csw_response.data_reside = data->cb_data_size;
472 size = rt_device_read(data->disk, data->block, data->ep_in->buffer, 1);
473 if(size == 0)
474 {
475 rt_kprintf("read data error\n");
476 }
477
478 data->ep_in->request.buffer = data->ep_in->buffer;
479 data->ep_in->request.size = data->geometry.bytes_per_sector;
480 data->ep_in->request.req_type = UIO_REQUEST_WRITE;
481 rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
482 data->status = STAT_SEND;
483
484 return data->geometry.bytes_per_sector;
485 }
486
487 /**
488 * This function will handle write_10 request.
489 *
490 * @param func the usb function object.
491 * @param cbw the command block wrapper.
492 *
493 * @return RT_EOK on successful.
494 */
_write_10(ufunction_t func,ustorage_cbw_t cbw)495 static rt_size_t _write_10(ufunction_t func, ustorage_cbw_t cbw)
496 {
497 struct mstorage *data;
498
499 RT_ASSERT(func != RT_NULL);
500 RT_ASSERT(func->device != RT_NULL);
501 RT_ASSERT(cbw != RT_NULL);
502
503 data = (struct mstorage*)func->user_data;
504
505 data->block = cbw->cb[2]<<24 | cbw->cb[3]<<16 | cbw->cb[4]<<8 |
506 cbw->cb[5]<<0;
507 data->count = cbw->cb[7]<<8 | cbw->cb[8];
508 data->csw_response.data_reside = cbw->xfer_len;
509 data->size = data->count * data->geometry.bytes_per_sector;
510
511 RT_DEBUG_LOG(RT_DEBUG_USB, ("_write_10 count 0x%x block 0x%x 0x%x\n",
512 data->count, data->block, data->geometry.sector_count));
513
514 data->csw_response.data_reside = data->cb_data_size;
515
516 data->ep_out->request.buffer = data->ep_out->buffer;
517 data->ep_out->request.size = data->geometry.bytes_per_sector;
518 data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
519 rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
520 data->status = STAT_RECEIVE;
521
522 return data->geometry.bytes_per_sector;
523 }
524
525 /**
526 * This function will handle verify_10 request.
527 *
528 * @param func the usb function object.
529 *
530 * @return RT_EOK on successful.
531 */
_verify_10(ufunction_t func,ustorage_cbw_t cbw)532 static rt_size_t _verify_10(ufunction_t func, ustorage_cbw_t cbw)
533 {
534 struct mstorage *data;
535
536 RT_ASSERT(func != RT_NULL);
537 RT_ASSERT(func->device != RT_NULL);
538
539 RT_DEBUG_LOG(RT_DEBUG_USB, ("_verify_10\n"));
540
541 data = (struct mstorage*)func->user_data;
542 data->csw_response.status = 0;
543
544 return 0;
545 }
546
_start_stop(ufunction_t func,ustorage_cbw_t cbw)547 static rt_size_t _start_stop(ufunction_t func,
548 ustorage_cbw_t cbw)
549 {
550 struct mstorage *data;
551
552 RT_ASSERT(func != RT_NULL);
553 RT_ASSERT(func->device != RT_NULL);
554
555 RT_DEBUG_LOG(RT_DEBUG_USB, ("_start_stop\n"));
556
557 data = (struct mstorage*)func->user_data;
558 data->csw_response.status = 0;
559
560 return 0;
561 }
562
_ep_in_handler(ufunction_t func,rt_size_t size)563 static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size)
564 {
565 struct mstorage *data;
566
567 RT_ASSERT(func != RT_NULL);
568 RT_ASSERT(func->device != RT_NULL);
569
570 RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_in_handler\n"));
571
572 data = (struct mstorage*)func->user_data;
573
574 switch(data->status)
575 {
576 case STAT_CSW:
577 if(data->ep_in->request.size != SIZEOF_CSW)
578 {
579 rt_kprintf("Size of csw command error\n");
580 rt_usbd_ep_set_stall(func->device, data->ep_in);
581 }
582 else
583 {
584 RT_DEBUG_LOG(RT_DEBUG_USB, ("return to cbw status\n"));
585 data->ep_out->request.buffer = data->ep_out->buffer;
586 data->ep_out->request.size = SIZEOF_CBW;
587 data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
588 rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
589 data->status = STAT_CBW;
590 }
591 break;
592 case STAT_CMD:
593 if(data->csw_response.data_reside == 0xFF)
594 {
595 data->csw_response.data_reside = 0;
596 }
597 else
598 {
599 data->csw_response.data_reside -= data->ep_in->request.size;
600 if(data->csw_response.data_reside != 0)
601 {
602 RT_DEBUG_LOG(RT_DEBUG_USB, ("data_reside %d, request %d\n",
603 data->csw_response.data_reside, data->ep_in->request.size));
604 if(data->processing->dir == DIR_OUT)
605 {
606 rt_usbd_ep_set_stall(func->device, data->ep_out);
607 }
608 else
609 {
610 rt_usbd_ep_set_stall(func->device, data->ep_in);
611 }
612 data->csw_response.data_reside = 0;
613 }
614 }
615 _send_status(func);
616 break;
617 case STAT_SEND:
618 data->csw_response.data_reside -= data->ep_in->request.size;
619 data->count--;
620 data->block++;
621 if(data->count > 0 && data->csw_response.data_reside > 0)
622 {
623 if(rt_device_read(data->disk, data->block, data->ep_in->buffer, 1) == 0)
624 {
625 rt_kprintf("disk read error\n");
626 rt_usbd_ep_set_stall(func->device, data->ep_in);
627 return -RT_ERROR;
628 }
629
630 data->ep_in->request.buffer = data->ep_in->buffer;
631 data->ep_in->request.size = data->geometry.bytes_per_sector;
632 data->ep_in->request.req_type = UIO_REQUEST_WRITE;
633 rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request);
634 }
635 else
636 {
637 _send_status(func);
638 }
639 break;
640 }
641
642 return RT_EOK;
643 }
644
645 #ifdef MASS_CBW_DUMP
cbw_dump(struct ustorage_cbw * cbw)646 static void cbw_dump(struct ustorage_cbw* cbw)
647 {
648 RT_ASSERT(cbw != RT_NULL);
649
650 RT_DEBUG_LOG(RT_DEBUG_USB, ("signature 0x%x\n", cbw->signature));
651 RT_DEBUG_LOG(RT_DEBUG_USB, ("tag 0x%x\n", cbw->tag));
652 RT_DEBUG_LOG(RT_DEBUG_USB, ("xfer_len 0x%x\n", cbw->xfer_len));
653 RT_DEBUG_LOG(RT_DEBUG_USB, ("dflags 0x%x\n", cbw->dflags));
654 RT_DEBUG_LOG(RT_DEBUG_USB, ("lun 0x%x\n", cbw->lun));
655 RT_DEBUG_LOG(RT_DEBUG_USB, ("cb_len 0x%x\n", cbw->cb_len));
656 RT_DEBUG_LOG(RT_DEBUG_USB, ("cb[0] 0x%x\n", cbw->cb[0]));
657 }
658 #endif
659
_find_cbw_command(rt_uint16_t cmd)660 static struct scsi_cmd* _find_cbw_command(rt_uint16_t cmd)
661 {
662 int i;
663
664 for(i=0; i<sizeof(cmd_data)/sizeof(struct scsi_cmd); i++)
665 {
666 if(cmd_data[i].cmd == cmd)
667 return &cmd_data[i];
668 }
669
670 return RT_NULL;
671 }
672
_cb_len_calc(ufunction_t func,struct scsi_cmd * cmd,ustorage_cbw_t cbw)673 static void _cb_len_calc(ufunction_t func, struct scsi_cmd* cmd,
674 ustorage_cbw_t cbw)
675 {
676 struct mstorage *data;
677
678 RT_ASSERT(func != RT_NULL);
679 RT_ASSERT(cmd != RT_NULL);
680 RT_ASSERT(cbw != RT_NULL);
681
682 data = (struct mstorage*)func->user_data;
683 if(cmd->cmd_len == 6)
684 {
685 switch(cmd->type)
686 {
687 case COUNT:
688 data->cb_data_size = cbw->cb[4];
689 break;
690 case BLOCK_COUNT:
691 data->cb_data_size = cbw->cb[4] * data->geometry.bytes_per_sector;
692 break;
693 case FIXED:
694 data->cb_data_size = cmd->data_size;
695 break;
696 default:
697 break;
698 }
699 }
700 else if(cmd->cmd_len == 10)
701 {
702 switch(cmd->type)
703 {
704 case COUNT:
705 data->cb_data_size = cbw->cb[7]<<8 | cbw->cb[8];
706 break;
707 case BLOCK_COUNT:
708 data->cb_data_size = (cbw->cb[7]<<8 | cbw->cb[8]) *
709 data->geometry.bytes_per_sector;
710 break;
711 case FIXED:
712 data->cb_data_size = cmd->data_size;
713 break;
714 default:
715 break;
716 }
717 }
718 else
719 {
720 // rt_kprintf("cmd_len error %d\n", cmd->cmd_len);
721 }
722 }
723
_cbw_verify(ufunction_t func,struct scsi_cmd * cmd,ustorage_cbw_t cbw)724 static rt_bool_t _cbw_verify(ufunction_t func, struct scsi_cmd* cmd,
725 ustorage_cbw_t cbw)
726 {
727 struct mstorage *data;
728
729 RT_ASSERT(cmd != RT_NULL);
730 RT_ASSERT(cbw != RT_NULL);
731 RT_ASSERT(func != RT_NULL);
732
733 data = (struct mstorage*)func->user_data;
734 if(cmd->cmd_len != cbw->cb_len)
735 {
736 // rt_kprintf("cb_len error\n");
737 cmd->cmd_len = cbw->cb_len;
738 }
739
740 if(cbw->xfer_len > 0 && data->cb_data_size == 0)
741 {
742 rt_kprintf("xfer_len > 0 && data_size == 0\n");
743 return RT_FALSE;
744 }
745
746 if(cbw->xfer_len == 0 && data->cb_data_size > 0)
747 {
748 rt_kprintf("xfer_len == 0 && data_size > 0");
749 return RT_FALSE;
750 }
751
752 if(((cbw->dflags & USB_DIR_IN) && (cmd->dir == DIR_OUT)) ||
753 (!(cbw->dflags & USB_DIR_IN) && (cmd->dir == DIR_IN)))
754 {
755 rt_kprintf("dir error\n");
756 return RT_FALSE;
757 }
758
759 if(cbw->xfer_len > data->cb_data_size)
760 {
761 rt_kprintf("xfer_len > data_size\n");
762 return RT_FALSE;
763 }
764
765 if(cbw->xfer_len < data->cb_data_size)
766 {
767 // rt_kprintf("xfer_len < data_size\n");
768 data->cb_data_size = cbw->xfer_len;
769 data->csw_response.status = 1;
770 }
771
772 return RT_TRUE;
773 }
774
_cbw_handler(ufunction_t func,struct scsi_cmd * cmd,ustorage_cbw_t cbw)775 static rt_size_t _cbw_handler(ufunction_t func, struct scsi_cmd* cmd,
776 ustorage_cbw_t cbw)
777 {
778 struct mstorage *data;
779
780 RT_ASSERT(func != RT_NULL);
781 RT_ASSERT(cbw != RT_NULL);
782 RT_ASSERT(cmd->handler != RT_NULL);
783
784 data = (struct mstorage*)func->user_data;
785 data->processing = cmd;
786 return cmd->handler(func, cbw);
787 }
788
789 /**
790 * This function will handle mass storage bulk out endpoint request.
791 *
792 * @param func the usb function object.
793 * @param size request size.
794 *
795 * @return RT_EOK.
796 */
_ep_out_handler(ufunction_t func,rt_size_t size)797 static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size)
798 {
799 struct mstorage *data;
800 struct scsi_cmd* cmd;
801 rt_size_t len;
802 struct ustorage_cbw* cbw;
803
804 RT_ASSERT(func != RT_NULL);
805 RT_ASSERT(func->device != RT_NULL);
806
807 RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_out_handler %d\n", size));
808
809 data = (struct mstorage*)func->user_data;
810 cbw = (struct ustorage_cbw*)data->ep_out->buffer;
811 if(data->status == STAT_CBW)
812 {
813 /* dump cbw information */
814 if(cbw->signature != CBW_SIGNATURE || size != SIZEOF_CBW)
815 {
816 goto exit;
817 }
818
819 data->csw_response.signature = CSW_SIGNATURE;
820 data->csw_response.tag = cbw->tag;
821 data->csw_response.data_reside = cbw->xfer_len;
822 data->csw_response.status = 0;
823
824 RT_DEBUG_LOG(RT_DEBUG_USB, ("ep_out reside %d\n", data->csw_response.data_reside));
825
826 cmd = _find_cbw_command(cbw->cb[0]);
827 if(cmd == RT_NULL)
828 {
829 rt_kprintf("can't find cbw command\n");
830 goto exit;
831 }
832
833 _cb_len_calc(func, cmd, cbw);
834 if(!_cbw_verify(func, cmd, cbw))
835 {
836 goto exit;
837 }
838
839 len = _cbw_handler(func, cmd, cbw);
840 if(len == 0)
841 {
842 _send_status(func);
843 }
844
845 return RT_EOK;
846 }
847 else if(data->status == STAT_RECEIVE)
848 {
849 RT_DEBUG_LOG(RT_DEBUG_USB, ("\nwrite size %d block 0x%x oount 0x%x\n",
850 size, data->block, data->size));
851
852 data->size -= size;
853 data->csw_response.data_reside -= size;
854
855 rt_device_write(data->disk, data->block, data->ep_out->buffer, 1);
856
857 if(data->csw_response.data_reside != 0)
858 {
859 data->ep_out->request.buffer = data->ep_out->buffer;
860 data->ep_out->request.size = data->geometry.bytes_per_sector;
861 data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
862 rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
863 data->block ++;
864 }
865 else
866 {
867 _send_status(func);
868 }
869
870 return RT_EOK;
871 }
872
873 exit:
874 if(data->csw_response.data_reside)
875 {
876 if(cbw->dflags & USB_DIR_IN)
877 {
878 rt_usbd_ep_set_stall(func->device, data->ep_in);
879 }
880 else
881 {
882 rt_usbd_ep_set_stall(func->device, data->ep_in);
883 rt_usbd_ep_set_stall(func->device, data->ep_out);
884 }
885 }
886 data->csw_response.status = 1;
887 _send_status(func);
888
889 return -RT_ERROR;
890 }
891
892 /**
893 * This function will handle mass storage interface request.
894 *
895 * @param func the usb function object.
896 * @param setup the setup request.
897 *
898 * @return RT_EOK on successful.
899 */
_interface_handler(ufunction_t func,ureq_t setup)900 static rt_err_t _interface_handler(ufunction_t func, ureq_t setup)
901 {
902 rt_uint8_t lun = 0;
903
904 RT_ASSERT(func != RT_NULL);
905 RT_ASSERT(func->device != RT_NULL);
906 RT_ASSERT(setup != RT_NULL);
907
908 RT_DEBUG_LOG(RT_DEBUG_USB, ("mstorage_interface_handler\n"));
909
910 switch(setup->bRequest)
911 {
912 case USBREQ_GET_MAX_LUN:
913
914 RT_DEBUG_LOG(RT_DEBUG_USB, ("USBREQ_GET_MAX_LUN\n"));
915
916 if(setup->wValue || setup->wLength != 1)
917 {
918 rt_usbd_ep0_set_stall(func->device);
919 }
920 else
921 {
922 rt_usbd_ep0_write(func->device, &lun, setup->wLength);
923 }
924 break;
925 case USBREQ_MASS_STORAGE_RESET:
926
927 RT_DEBUG_LOG(RT_DEBUG_USB, ("USBREQ_MASS_STORAGE_RESET\n"));
928
929 if(setup->wValue || setup->wLength != 0)
930 {
931 rt_usbd_ep0_set_stall(func->device);
932 }
933 else
934 {
935 dcd_ep0_send_status(func->device->dcd);
936 }
937 break;
938 default:
939 rt_kprintf("unknown interface request\n");
940 break;
941 }
942
943 return RT_EOK;
944 }
945
946 /**
947 * This function will run mass storage function, it will be called on handle set configuration request.
948 *
949 * @param func the usb function object.
950 *
951 * @return RT_EOK on successful.
952 */
_function_enable(ufunction_t func)953 static rt_err_t _function_enable(ufunction_t func)
954 {
955 struct mstorage *data;
956 RT_ASSERT(func != RT_NULL);
957 RT_DEBUG_LOG(RT_DEBUG_USB, ("Mass storage function enabled\n"));
958 data = (struct mstorage*)func->user_data;
959
960 data->disk = rt_device_find(RT_USB_MSTORAGE_DISK_NAME);
961 if(data->disk == RT_NULL)
962 {
963 rt_kprintf("no data->disk named %s\n", RT_USB_MSTORAGE_DISK_NAME);
964 return -RT_ERROR;
965 }
966
967 if(rt_device_open(data->disk, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
968 {
969 rt_kprintf("disk open error\n");
970 return -RT_ERROR;
971 }
972
973 if(rt_device_control(data->disk, RT_DEVICE_CTRL_BLK_GETGEOME,
974 (void*)&data->geometry) != RT_EOK)
975 {
976 rt_kprintf("get disk info error\n");
977 return -RT_ERROR;
978 }
979
980 data->ep_in->buffer = (rt_uint8_t*)rt_malloc(data->geometry.bytes_per_sector);
981 if(data->ep_in->buffer == RT_NULL)
982 {
983 rt_kprintf("no memory\n");
984 return -RT_ENOMEM;
985 }
986 data->ep_out->buffer = (rt_uint8_t*)rt_malloc(data->geometry.bytes_per_sector);
987 if(data->ep_out->buffer == RT_NULL)
988 {
989 rt_free(data->ep_in->buffer);
990 rt_kprintf("no memory\n");
991 return -RT_ENOMEM;
992 }
993
994 /* prepare to read CBW request */
995 data->ep_out->request.buffer = data->ep_out->buffer;
996 data->ep_out->request.size = SIZEOF_CBW;
997 data->ep_out->request.req_type = UIO_REQUEST_READ_FULL;
998 rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request);
999
1000 return RT_EOK;
1001 }
1002
1003 /**
1004 * This function will stop mass storage function, it will be called on handle set configuration request.
1005 *
1006 * @param device the usb device object.
1007 *
1008 * @return RT_EOK on successful.
1009 */
_function_disable(ufunction_t func)1010 static rt_err_t _function_disable(ufunction_t func)
1011 {
1012 struct mstorage *data;
1013 RT_ASSERT(func != RT_NULL);
1014
1015 RT_DEBUG_LOG(RT_DEBUG_USB, ("Mass storage function disabled\n"));
1016
1017 data = (struct mstorage*)func->user_data;
1018 if(data->ep_in->buffer != RT_NULL)
1019 {
1020 rt_free(data->ep_in->buffer);
1021 data->ep_in->buffer = RT_NULL;
1022 }
1023
1024 if(data->ep_out->buffer != RT_NULL)
1025 {
1026 rt_free(data->ep_out->buffer);
1027 data->ep_out->buffer = RT_NULL;
1028 }
1029 if(data->disk != RT_NULL)
1030 {
1031 rt_device_close(data->disk);
1032 data->disk = RT_NULL;
1033 }
1034
1035 data->status = STAT_CBW;
1036
1037 return RT_EOK;
1038 }
1039
1040 static struct ufunction_ops ops =
1041 {
1042 _function_enable,
1043 _function_disable,
1044 RT_NULL,
1045 };
_mstorage_descriptor_config(umass_desc_t desc,rt_uint8_t cintf_nr,rt_uint8_t device_is_hs)1046 static rt_err_t _mstorage_descriptor_config(umass_desc_t desc, rt_uint8_t cintf_nr, rt_uint8_t device_is_hs)
1047 {
1048 #ifdef RT_USB_DEVICE_COMPOSITE
1049 desc->iad_desc.bFirstInterface = cintf_nr;
1050 #endif
1051 desc->ep_out_desc.wMaxPacketSize = device_is_hs ? 512 : 64;
1052 desc->ep_in_desc.wMaxPacketSize = device_is_hs ? 512 : 64;
1053 return RT_EOK;
1054 }
1055 /**
1056 * This function will create a mass storage function instance.
1057 *
1058 * @param device the usb device object.
1059 *
1060 * @return RT_EOK on successful.
1061 */
rt_usbd_function_mstorage_create(udevice_t device)1062 ufunction_t rt_usbd_function_mstorage_create(udevice_t device)
1063 {
1064 uintf_t intf;
1065 struct mstorage *data;
1066 ufunction_t func;
1067 ualtsetting_t setting;
1068 umass_desc_t mass_desc;
1069
1070 /* parameter check */
1071 RT_ASSERT(device != RT_NULL);
1072
1073 /* set usb device string description */
1074 rt_usbd_device_set_string(device, _ustring);
1075
1076 /* create a mass storage function */
1077 func = rt_usbd_function_new(device, &dev_desc, &ops);
1078 device->dev_qualifier = &dev_qualifier;
1079
1080 /* allocate memory for mass storage function data */
1081 data = (struct mstorage*)rt_malloc(sizeof(struct mstorage));
1082 rt_memset(data, 0, sizeof(struct mstorage));
1083 func->user_data = (void*)data;
1084
1085 /* create an interface object */
1086 intf = rt_usbd_interface_new(device, _interface_handler);
1087
1088 /* create an alternate setting object */
1089 setting = rt_usbd_altsetting_new(sizeof(struct umass_descriptor));
1090
1091 /* config desc in alternate setting */
1092 rt_usbd_altsetting_config_descriptor(setting, &_mass_desc, (rt_off_t)&((umass_desc_t)0)->intf_desc);
1093
1094 /* configure the msc interface descriptor */
1095 _mstorage_descriptor_config(setting->desc, intf->intf_num, device->dcd->device_is_hs);
1096
1097 /* create a bulk out and a bulk in endpoint */
1098 mass_desc = (umass_desc_t)setting->desc;
1099 data->ep_in = rt_usbd_endpoint_new(&mass_desc->ep_in_desc, _ep_in_handler);
1100 data->ep_out = rt_usbd_endpoint_new(&mass_desc->ep_out_desc, _ep_out_handler);
1101
1102 /* add the bulk out and bulk in endpoint to the alternate setting */
1103 rt_usbd_altsetting_add_endpoint(setting, data->ep_out);
1104 rt_usbd_altsetting_add_endpoint(setting, data->ep_in);
1105
1106 /* add the alternate setting to the interface, then set default setting */
1107 rt_usbd_interface_add_altsetting(intf, setting);
1108 rt_usbd_set_altsetting(intf, 0);
1109
1110 /* add the interface to the mass storage function */
1111 rt_usbd_function_add_interface(func, intf);
1112
1113 return func;
1114 }
1115 struct udclass msc_class =
1116 {
1117 .rt_usbd_function_create = rt_usbd_function_mstorage_create
1118 };
1119
rt_usbd_msc_class_register(void)1120 int rt_usbd_msc_class_register(void)
1121 {
1122 rt_usbd_class_register(&msc_class);
1123 return 0;
1124 }
1125 INIT_PREV_EXPORT(rt_usbd_msc_class_register);
1126
1127 #endif
1128