1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-02-28 leo first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "drv_common.h"
14
15 #if defined(BSP_USING_USBD)
16 #include "usbd_int.h"
17 #include "drv_usbd.h"
18 #include "drv_config.h"
19
20 static struct at32_usbd *p_usbd_instance = RT_NULL;
21 static struct ep_id endpoint_pool[] =
22 {
23 {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED },
24 {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 64, ID_UNASSIGNED},
25 {0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 64, ID_UNASSIGNED},
26 {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 64, ID_UNASSIGNED},
27 {0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 64, ID_UNASSIGNED},
28 {0x3, USB_EP_ATTR_ISOC, USB_DIR_IN, 64, ID_UNASSIGNED},
29 {0x3, USB_EP_ATTR_ISOC, USB_DIR_OUT, 64, ID_UNASSIGNED},
30 {0xFF, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED },
31 };
32
33 enum
34 {
35 #ifdef BSP_USING_USBD
36 USBD1_INDEX,
37 #endif
38 };
39
40 static struct at32_usbd usbd_config[] = {
41 #ifdef BSP_USING_USBD
42 USBD_CONFIG,
43 #endif
44 };
45
USB_IRQHandler(void)46 void USB_IRQHandler(void)
47 {
48 /* enter interrupt */
49 rt_interrupt_enter();
50
51 usbd_irq_handler(p_usbd_instance->p_usbd_core);
52
53 /* leave interrupt */
54 rt_interrupt_leave();
55 }
56
usbd_reset_callback(usbd_core_type * udev)57 void usbd_reset_callback(usbd_core_type *udev)
58 {
59 udcd_t udcd = (udcd_t)udev->pdata;
60 rt_usbd_reset_handler(udcd);
61 }
62
usbd_connectCallback(usbd_core_type * udev)63 void usbd_connectCallback(usbd_core_type *udev)
64 {
65 udcd_t udcd = (udcd_t)udev->pdata;
66 rt_usbd_connect_handler(udcd);
67 }
68
usbd_disconnectCallback(usbd_core_type * udev)69 void usbd_disconnectCallback(usbd_core_type *udev)
70 {
71 udcd_t udcd = (udcd_t)udev->pdata;
72 rt_usbd_disconnect_handler(udcd);
73 }
74
usbd_setup_phase_done_callback(usbd_core_type * udev)75 void usbd_setup_phase_done_callback(usbd_core_type *udev)
76 {
77 udcd_t udcd = (udcd_t)udev->pdata;
78 rt_usbd_ep0_setup_handler(udcd, (struct urequest*)udev->setup_buffer);
79 }
80
usbd_data_in_stage_callback(usbd_core_type * udev,uint32_t ept_num)81 void usbd_data_in_stage_callback(usbd_core_type *udev, uint32_t ept_num)
82 {
83 udcd_t udcd = (udcd_t)udev->pdata;
84
85 if (ept_num == 0)
86 {
87 rt_usbd_ep0_in_handler(udcd);
88 }
89 else
90 {
91 rt_usbd_ep_in_handler(udcd, 0x80 | ept_num, udev->ept_in[ept_num].trans_len);
92 }
93 }
94
usbd_sof_callback(usbd_core_type * udev)95 void usbd_sof_callback(usbd_core_type *udev)
96 {
97 udcd_t udcd = (udcd_t)udev->pdata;
98 rt_usbd_sof_handler(udcd);
99 }
100
usbd_data_out_stage_callback(usbd_core_type * udev,uint32_t ept_num)101 void usbd_data_out_stage_callback(usbd_core_type *udev, uint32_t ept_num)
102 {
103 udcd_t udcd = (udcd_t)udev->pdata;
104
105 if (ept_num != 0)
106 {
107 rt_usbd_ep_out_handler(udcd, ept_num, udev->ept_out[ept_num].trans_len);
108 }
109 else
110 {
111 rt_usbd_ep0_out_handler(udcd, udev->ept_out[0].trans_len);
112 }
113 }
114
_ep_set_stall(rt_uint8_t address)115 static rt_err_t _ep_set_stall(rt_uint8_t address)
116 {
117 usbd_set_stall(p_usbd_instance->p_usbd_core, address);
118 return RT_EOK;
119 }
120
_ep_clear_stall(rt_uint8_t address)121 static rt_err_t _ep_clear_stall(rt_uint8_t address)
122 {
123 usbd_clear_stall(p_usbd_instance->p_usbd_core, address);
124 return RT_EOK;
125 }
126
_set_address(rt_uint8_t address)127 static rt_err_t _set_address(rt_uint8_t address)
128 {
129 usbd_set_device_addr(p_usbd_instance->p_usbd_core, address);
130 return RT_EOK;
131 }
132
_set_config(rt_uint8_t address)133 static rt_err_t _set_config(rt_uint8_t address)
134 {
135 return RT_EOK;
136 }
137
_ep_enable(uep_t ep)138 static rt_err_t _ep_enable(uep_t ep)
139 {
140 RT_ASSERT(ep != RT_NULL);
141 RT_ASSERT(ep->ep_desc != RT_NULL);
142
143 usbd_ept_open(p_usbd_instance->p_usbd_core, ep->ep_desc->bEndpointAddress, ep->ep_desc->bmAttributes, ep->ep_desc->wMaxPacketSize);
144 return RT_EOK;
145 }
146
_ep_disable(uep_t ep)147 static rt_err_t _ep_disable(uep_t ep)
148 {
149 RT_ASSERT(ep != RT_NULL);
150 RT_ASSERT(ep->ep_desc != RT_NULL);
151 usbd_ept_close(p_usbd_instance->p_usbd_core, ep->ep_desc->bEndpointAddress);
152 return RT_EOK;
153 }
154
_ep_read(rt_uint8_t address,void * buffer)155 static rt_ssize_t _ep_read(rt_uint8_t address, void *buffer)
156 {
157 rt_size_t size = 0;
158 RT_ASSERT(buffer != RT_NULL);
159 return size;
160 }
161
_ep_read_prepare(rt_uint8_t address,void * buffer,rt_size_t size)162 static rt_ssize_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
163 {
164 usbd_ept_recv(p_usbd_instance->p_usbd_core, address, buffer, size);
165 return size;
166 }
167
_ep_write(rt_uint8_t address,void * buffer,rt_size_t size)168 static rt_ssize_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
169 {
170 usbd_ept_send(p_usbd_instance->p_usbd_core, address, buffer, size);
171 return size;
172 }
173
_ep0_send_status(void)174 static rt_err_t _ep0_send_status(void)
175 {
176 usbd_ctrl_send_status(p_usbd_instance->p_usbd_core);
177 return RT_EOK;
178 }
179
_suspend(void)180 static rt_err_t _suspend(void)
181 {
182 return RT_EOK;
183 }
184
_wakeup(void)185 static rt_err_t _wakeup(void)
186 {
187 return RT_EOK;
188 }
189
at32_dcd_init(rt_device_t device)190 static rt_err_t at32_dcd_init(rt_device_t device)
191 {
192 /* usb gpio config */
193 at32_msp_usb_init(device);
194
195 /* enable usb interrupt */
196 nvic_irq_enable(p_usbd_instance->irqn, 2, 0);
197
198 /* usb core init */
199 usbd_core_init(p_usbd_instance->p_usbd_core, USB, 0);
200
201 /* enable usb pull-up */
202 usbd_connect(p_usbd_instance->p_usbd_core);
203
204 return RT_EOK;
205 }
206
207 const static struct udcd_ops _udc_ops =
208 {
209 _set_address,
210 _set_config,
211 _ep_set_stall,
212 _ep_clear_stall,
213 _ep_enable,
214 _ep_disable,
215 _ep_read_prepare,
216 _ep_read,
217 _ep_write,
218 _ep0_send_status,
219 _suspend,
220 _wakeup,
221 };
222
at32_usbd_register(void)223 int at32_usbd_register(void)
224 {
225 rt_size_t obj_num;
226 rt_err_t result = 0;
227 int index;
228
229 obj_num = sizeof(usbd_config) / sizeof(struct at32_usbd);
230
231 for (index = 0; index < obj_num; index++) {
232 udcd_t udcd = (udcd_t)rt_malloc(sizeof(struct udcd));
233 if (udcd == RT_NULL)
234 {
235 rt_kprintf("udcd malloc failed\r\n");
236 return -RT_ERROR;
237 }
238 rt_memset((void *)udcd, 0, sizeof(struct udcd));
239
240 usbd_core_type *p_usbd_core = (usbd_core_type *)rt_malloc(sizeof(usbd_core_type));
241 if (p_usbd_core == RT_NULL)
242 {
243 rt_kprintf("usbd_core malloc failed\r\n");
244 return -RT_ERROR;
245 }
246 rt_memset((void *)p_usbd_core, 0, sizeof(usbd_core_type));
247
248 udcd->parent.type = RT_Device_Class_USBDevice;
249 udcd->parent.init = at32_dcd_init;
250
251 udcd->parent.user_data = p_usbd_core;
252 udcd->ops = &_udc_ops;
253 p_usbd_core->pdata = udcd;
254 usbd_config[index].p_usbd_core = p_usbd_core;
255
256 /* register endpoint infomation */
257 udcd->ep_pool = endpoint_pool;
258 udcd->ep0.id = &endpoint_pool[0];
259
260 result = rt_device_register((rt_device_t)udcd, usbd_config[index].name, 0);
261 RT_ASSERT(result == RT_EOK);
262
263 p_usbd_instance = &usbd_config[index];
264
265 result = rt_usb_device_init();
266 RT_ASSERT(result == RT_EOK);
267 }
268
269 return result;
270 }
271
272 INIT_DEVICE_EXPORT(at32_usbd_register);
273
274 #endif
275