xref: /nrf52832-nimble/rt-thread/components/drivers/usb/usbdevice/class/mstorage.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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 
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 
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 
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 
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
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 
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
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 
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 
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 
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 
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  */
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  */
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  */
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  */
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 };
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  */
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 
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