1 /*
2 * Copyright (c) 2022 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <rthw.h>
9 #include <rtdevice.h>
10 #include <rtdbg.h>
11 #include "tusb.h"
12
13 /* Definition of logic unit number for each drive */
14 #define LUN_USB (0U) /* lun 0 of usb drive */
15
16 static rt_ssize_t hpm_usb_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
17 static rt_ssize_t hpm_usb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
18 rt_err_t hpm_usb_control(rt_device_t dev, int cmd, void *args);
19
20 rt_uint8_t usb_dev_addr;
21
22 static struct rt_device hpm_usb = {
23 .read = hpm_usb_read,
24 .write = hpm_usb_write,
25 .control = hpm_usb_control,
26 };
27
usb_disk_wait_for_complete(uint8_t usb_addr)28 static bool usb_disk_wait_for_complete(uint8_t usb_addr)
29 {
30 #if CFG_TUSB_OS != OPT_OS_NONE
31 int32_t retry_cnt = 200;
32 #else
33 int32_t retry_cnt = 5000000;
34 #endif
35
36 while (!tuh_msc_idle(usb_addr) && retry_cnt--)
37 {
38 #if CFG_TUSB_OS != OPT_OS_NONE
39 osal_task_delay(5);
40 #else
41 tuh_task();
42 #endif
43 }
44
45 return retry_cnt > 0 ? true : false;
46 }
47
hpm_usb_set_addr(uint8_t dev_addr)48 void hpm_usb_set_addr(uint8_t dev_addr)
49 {
50 usb_dev_addr = dev_addr;
51 }
52
hpm_usb_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)53 static rt_ssize_t hpm_usb_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
54 {
55 rt_bool_t result;
56
57 result = tuh_msc_read10(usb_dev_addr, LUN_USB, buffer, pos, size, NULL);
58
59 if (result) {
60 result = usb_disk_wait_for_complete(usb_dev_addr);
61 }
62
63 return result ? size : 0;
64 }
65
hpm_usb_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)66 static rt_ssize_t hpm_usb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
67 {
68 bool result;
69
70 result = tuh_msc_write10(usb_dev_addr, LUN_USB, buffer, pos, size, NULL);
71
72 if (result) {
73 result = usb_disk_wait_for_complete(usb_dev_addr);
74 }
75
76 return result ? size : 0;
77 }
78
hpm_usb_control(rt_device_t dev,int cmd,void * args)79 rt_err_t hpm_usb_control(rt_device_t dev, int cmd, void *args)
80 {
81 rt_err_t ret = RT_EOK;
82
83 switch (cmd)
84 {
85 case RT_DEVICE_CTRL_BLK_GETGEOME:
86 struct rt_device_blk_geometry *geometry = (struct rt_device_blk_geometry *)args;
87 geometry->sector_count = tuh_msc_get_block_count(usb_dev_addr, LUN_USB);
88 geometry->bytes_per_sector = tuh_msc_get_block_size(usb_dev_addr, LUN_USB);
89 break;
90 case RT_DEVICE_CTRL_BLK_SYNC:
91 break;
92 case RT_DEVICE_CTRL_BLK_ERASE:
93 break;
94
95 default:
96 ret = RT_EINVAL;
97 break;
98 }
99
100 return RT_EOK;
101 }
102
rt_hw_usb_init(void)103 int rt_hw_usb_init(void)
104 {
105 rt_err_t err = RT_EOK;
106
107 hpm_usb.type = RT_Device_Class_Block;
108
109 err = rt_device_register(&hpm_usb, "usb0", RT_DEVICE_FLAG_RDWR);
110
111 if (err != RT_EOK) {
112 LOG_E("rt device %s failed, status=%d\n", "usb", err);
113 return err;
114 }
115
116 return err;
117 }
118
119 INIT_BOARD_EXPORT(rt_hw_usb_init);
120