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