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