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