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