1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2011-12-12 Yi Qiu first version
9 */
10
11 #include <rtthread.h>
12 #include <dfs_fs.h>
13 #include <drivers/usb_host.h>
14 #include "mass.h"
15
16 #ifdef RT_USBH_MSTORAGE
17
18 #define UDISK_MAX_COUNT 8
19 static rt_uint8_t _udisk_idset = 0;
20
udisk_get_id(void)21 static int udisk_get_id(void)
22 {
23 int i;
24
25 for(i=0; i< UDISK_MAX_COUNT; i++)
26 {
27 if((_udisk_idset & (1 << i)) != 0) continue;
28 else break;
29 }
30
31 /* it should not happen */
32 if(i == UDISK_MAX_COUNT) RT_ASSERT(0);
33
34 _udisk_idset |= (1 << i);
35 return i;
36 }
37
udisk_free_id(int id)38 static void udisk_free_id(int id)
39 {
40 RT_ASSERT(id < UDISK_MAX_COUNT)
41
42 _udisk_idset &= ~(1 << id);
43 }
44
45 /**
46 * This function will initialize the udisk device
47 *
48 * @param dev the pointer of device driver structure
49 *
50 * @return RT_EOK
51 */
rt_udisk_init(rt_device_t dev)52 static rt_err_t rt_udisk_init(rt_device_t dev)
53 {
54 return RT_EOK;
55 }
56
57 /**
58 * This function will read some data from a device.
59 *
60 * @param dev the pointer of device driver structure
61 * @param pos the position of reading
62 * @param buffer the data buffer to save read data
63 * @param size the size of buffer
64 *
65 * @return the actually read size on successful, otherwise negative returned.
66 */
rt_udisk_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)67 static rt_size_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void* buffer,
68 rt_size_t size)
69 {
70 rt_err_t ret;
71 struct uhintf* intf;
72 struct ustor_data* data;
73 int timeout = USB_TIMEOUT_LONG;
74
75 /* check parameter */
76 RT_ASSERT(dev != RT_NULL);
77 RT_ASSERT(buffer != RT_NULL);
78
79 if(size > 4096) timeout *= 2;
80
81 data = (struct ustor_data*)dev->user_data;
82 intf = data->intf;
83
84 ret = rt_usbh_storage_read10(intf, (rt_uint8_t*)buffer, pos, size, timeout);
85
86 if (ret != RT_EOK)
87 {
88 rt_kprintf("usb mass_storage read failed\n");
89 return 0;
90 }
91
92 return size;
93 }
94
95 /**
96 * This function will write some data to a device.
97 *
98 * @param dev the pointer of device driver structure
99 * @param pos the position of written
100 * @param buffer the data buffer to be written to device
101 * @param size the size of buffer
102 *
103 * @return the actually written size on successful, otherwise negative returned.
104 */
rt_udisk_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)105 static rt_size_t rt_udisk_write (rt_device_t dev, rt_off_t pos, const void* buffer,
106 rt_size_t size)
107 {
108 rt_err_t ret;
109 struct uhintf* intf;
110 struct ustor_data* data;
111 int timeout = USB_TIMEOUT_LONG;
112
113 /* check parameter */
114 RT_ASSERT(dev != RT_NULL);
115 RT_ASSERT(buffer != RT_NULL);
116
117 if(size * SECTOR_SIZE > 4096) timeout *= 2;
118
119 data = (struct ustor_data*)dev->user_data;
120 intf = data->intf;
121
122 ret = rt_usbh_storage_write10(intf, (rt_uint8_t*)buffer, pos, size, timeout);
123 if (ret != RT_EOK)
124 {
125 rt_kprintf("usb mass_storage write %d sector failed\n", size);
126 return 0;
127 }
128
129 return size;
130 }
131
132 /**
133 * This function will execute SCSI_INQUIRY_CMD command to get inquiry data.
134 *
135 * @param intf the interface instance.
136 * @param buffer the data buffer to save inquiry data
137 *
138 * @return the error code, RT_EOK on successfully.
139 */
rt_udisk_control(rt_device_t dev,int cmd,void * args)140 static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args)
141 {
142 ustor_t stor;
143 struct ustor_data* data;
144
145 /* check parameter */
146 RT_ASSERT(dev != RT_NULL);
147
148 data = (struct ustor_data*)dev->user_data;
149 stor = (ustor_t)data->intf->user_data;
150
151 if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
152 {
153 struct rt_device_blk_geometry *geometry;
154
155 geometry = (struct rt_device_blk_geometry *)args;
156 if (geometry == RT_NULL) return -RT_ERROR;
157
158 geometry->bytes_per_sector = SECTOR_SIZE;
159 geometry->block_size = stor->capicity[1];
160 geometry->sector_count = stor->capicity[0];
161 }
162
163 return RT_EOK;
164 }
165
166 #ifdef RT_USING_DEVICE_OPS
167 const static struct rt_device_ops udisk_device_ops =
168 {
169 rt_udisk_init,
170 RT_NULL,
171 RT_NULL,
172 rt_udisk_read,
173 rt_udisk_write,
174 rt_udisk_control
175 };
176 #endif
177
178 /**
179 * This function will run udisk driver when usb disk is detected.
180 *
181 * @param intf the usb interface instance.
182 *
183 * @return the error code, RT_EOK on successfully.
184 */
rt_udisk_run(struct uhintf * intf)185 rt_err_t rt_udisk_run(struct uhintf* intf)
186 {
187 int i = 0;
188 rt_err_t ret;
189 char dname[4];
190 char sname[8];
191 rt_uint8_t max_lun, *sector, sense[18], inquiry[36];
192 struct dfs_partition part[MAX_PARTITION_COUNT];
193 ustor_t stor;
194
195 /* check parameter */
196 RT_ASSERT(intf != RT_NULL);
197
198 /* set interface */
199 // ret = rt_usbh_set_interface(intf->device, intf->intf_desc->bInterfaceNumber);
200 // if(ret != RT_EOK)
201 // rt_usbh_clear_feature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT);
202 /* reset mass storage class device */
203 ret = rt_usbh_storage_reset(intf);
204 if(ret != RT_EOK) return ret;
205
206 stor = (ustor_t)intf->user_data;
207
208 /* get max logic unit number */
209 ret = rt_usbh_storage_get_max_lun(intf, &max_lun);
210 if(ret != RT_EOK)
211 rt_usbh_clear_feature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT);
212
213 /* reset pipe in endpoint */
214 if(stor->pipe_in->status == UPIPE_STATUS_STALL)
215 {
216 ret = rt_usbh_clear_feature(intf->device,
217 stor->pipe_in->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT);
218 if(ret != RT_EOK) return ret;
219 }
220
221
222 /* reset pipe out endpoint */
223 if(stor->pipe_out->status == UPIPE_STATUS_STALL)
224 {
225 ret = rt_usbh_clear_feature(intf->device,
226 stor->pipe_out->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT);
227 if(ret != RT_EOK) return ret;
228 }
229
230 while((ret = rt_usbh_storage_inquiry(intf, inquiry)) != RT_EOK)
231 {
232 if(ret == -RT_EIO) return ret;
233
234 rt_thread_delay(5);
235 if(i++ < 10) continue;
236 rt_kprintf("rt_usbh_storage_inquiry error\n");
237 return -RT_ERROR;
238 }
239
240 i = 0;
241
242 /* wait device ready */
243 while((ret = rt_usbh_storage_test_unit_ready(intf)) != RT_EOK)
244 {
245 if(ret == -RT_EIO) return ret;
246
247 ret = rt_usbh_storage_request_sense(intf, sense);
248 if(ret == -RT_EIO) return ret;
249
250 rt_thread_delay(10);
251 if(i++ < 10) continue;
252
253 rt_kprintf("rt_usbh_storage_test_unit_ready error\n");
254 return -RT_ERROR;
255 }
256
257 i = 0;
258 rt_memset(stor->capicity, 0, sizeof(stor->capicity));
259
260 /* get storage capacity */
261 while((ret = rt_usbh_storage_get_capacity(intf,
262 (rt_uint8_t*)stor->capicity)) != RT_EOK)
263 {
264 if(ret == -RT_EIO) return ret;
265
266 rt_thread_delay(50);
267 if(i++ < 10) continue;
268
269 stor->capicity[0] = 2880;
270 stor->capicity[1] = 0x200;
271
272 rt_kprintf("rt_usbh_storage_get_capacity error\n");
273 break;
274 }
275
276 stor->capicity[0] = uswap_32(stor->capicity[0]);
277 stor->capicity[1] = uswap_32(stor->capicity[1]);
278 stor->capicity[0] += 1;
279
280 RT_DEBUG_LOG(RT_DEBUG_USB, ("capicity %d, block size %d\n",
281 stor->capicity[0], stor->capicity[1]));
282
283 /* get the first sector to read partition table */
284 sector = (rt_uint8_t*) rt_malloc (SECTOR_SIZE);
285 if (sector == RT_NULL)
286 {
287 rt_kprintf("allocate partition sector buffer failed\n");
288 return -RT_ERROR;
289 }
290
291 rt_memset(sector, 0, SECTOR_SIZE);
292
293 RT_DEBUG_LOG(RT_DEBUG_USB, ("read partition table\n"));
294
295 /* get the partition table */
296 ret = rt_usbh_storage_read10(intf, sector, 0, 1, USB_TIMEOUT_LONG);
297 if(ret != RT_EOK)
298 {
299 rt_kprintf("read parition table error\n");
300
301 rt_free(sector);
302 return -RT_ERROR;
303 }
304
305 RT_DEBUG_LOG(RT_DEBUG_USB, ("finished reading partition\n"));
306
307 for(i=0; i<MAX_PARTITION_COUNT; i++)
308 {
309 /* get the first partition */
310 ret = dfs_filesystem_get_partition(&part[i], sector, i);
311 if (ret == RT_EOK)
312 {
313 struct ustor_data* data = rt_malloc(sizeof(struct ustor_data));
314 rt_memset(data, 0, sizeof(struct ustor_data));
315 data->intf = intf;
316 data->udisk_id = udisk_get_id();
317 rt_snprintf(dname, 6, "ud%d-%d", data->udisk_id, i);
318 rt_snprintf(sname, 8, "sem_ud%d", i);
319 data->part.lock = rt_sem_create(sname, 1, RT_IPC_FLAG_FIFO);
320
321 /* register sdcard device */
322 stor->dev[i].type = RT_Device_Class_Block;
323 #ifdef RT_USING_DEVICE_OPS
324 stor->dev[i].ops = &udisk_device_ops;
325 #else
326 stor->dev[i].init = rt_udisk_init;
327 stor->dev[i].read = rt_udisk_read;
328 stor->dev[i].write = rt_udisk_write;
329 stor->dev[i].control = rt_udisk_control;
330 #endif
331 stor->dev[i].user_data = (void*)data;
332
333 rt_device_register(&stor->dev[i], dname, RT_DEVICE_FLAG_RDWR |
334 RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
335
336 stor->dev_cnt++;
337 if (dfs_mount(stor->dev[i].parent.name, UDISK_MOUNTPOINT, "elm",
338 0, 0) == 0)
339 {
340 RT_DEBUG_LOG(RT_DEBUG_USB, ("udisk part %d mount successfully\n", i));
341 }
342 else
343 {
344 RT_DEBUG_LOG(RT_DEBUG_USB, ("udisk part %d mount failed\n", i));
345 }
346 }
347 else
348 {
349 if(i == 0)
350 {
351 struct ustor_data* data = rt_malloc(sizeof(struct ustor_data));
352 rt_memset(data, 0, sizeof(struct ustor_data));
353 data->udisk_id = udisk_get_id();
354
355 /* there is no partition table */
356 data->part.offset = 0;
357 data->part.size = 0;
358 data->intf = intf;
359 data->part.lock = rt_sem_create("sem_ud", 1, RT_IPC_FLAG_FIFO);
360
361 rt_snprintf(dname, 7, "udisk%d", data->udisk_id);
362
363 /* register sdcard device */
364 stor->dev[0].type = RT_Device_Class_Block;
365 #ifdef RT_USING_DEVICE_OPS
366 stor->dev[i].ops = &udisk_device_ops;
367 #else
368 stor->dev[0].init = rt_udisk_init;
369 stor->dev[0].read = rt_udisk_read;
370 stor->dev[0].write = rt_udisk_write;
371 stor->dev[0].control = rt_udisk_control;
372 #endif
373 stor->dev[0].user_data = (void*)data;
374
375 rt_device_register(&stor->dev[0], dname,
376 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE
377 | RT_DEVICE_FLAG_STANDALONE);
378
379 stor->dev_cnt++;
380 if (dfs_mount(stor->dev[0].parent.name, UDISK_MOUNTPOINT,
381 "elm", 0, 0) == 0)
382 {
383 rt_kprintf("Mount FAT on Udisk successful.\n");
384 }
385 else
386 {
387 rt_kprintf("Mount FAT on Udisk failed.\n");
388 }
389 }
390
391 break;
392 }
393 }
394
395 rt_free(sector);
396
397 return RT_EOK;
398 }
399
400 /**
401 * This function will be invoked when usb disk plug out is detected and it would clean
402 * and release all udisk related resources.
403 *
404 * @param intf the usb interface instance.
405 *
406 * @return the error code, RT_EOK on successfully.
407 */
rt_udisk_stop(struct uhintf * intf)408 rt_err_t rt_udisk_stop(struct uhintf* intf)
409 {
410 int i;
411 ustor_t stor;
412 struct ustor_data* data;
413
414 /* check parameter */
415 RT_ASSERT(intf != RT_NULL);
416 RT_ASSERT(intf->device != RT_NULL);
417
418 stor = (ustor_t)intf->user_data;
419 RT_ASSERT(stor != RT_NULL);
420
421 for(i=0; i<stor->dev_cnt; i++)
422 {
423 rt_device_t dev = &stor->dev[i];
424 data = (struct ustor_data*)dev->user_data;
425
426 /* unmount filesystem */
427 dfs_unmount(UDISK_MOUNTPOINT);
428
429 /* delete semaphore */
430 rt_sem_delete(data->part.lock);
431 udisk_free_id(data->udisk_id);
432 rt_free(data);
433
434 /* unregister device */
435 rt_device_unregister(&stor->dev[i]);
436 }
437
438 return RT_EOK;
439 }
440
441 #endif
442
443