1 /**************************************************************************//**
2 *
3 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Change Logs:
8 * Date            Author           Notes
9 * 2020-09-17      CHChen           First version
10 * 2023-10-11     ChuShicheng       change rt_size_t to rt_ssize_t
11 *
12 ******************************************************************************/
13 
14 #include <rtconfig.h>
15 
16 #ifdef BSP_USING_USBD
17 #include <rtthread.h>
18 #include <rtdevice.h>
19 #include <string.h>
20 #include "NuMicro.h"
21 
22 #define LOG_TAG         "drv.usbd"
23 #define DBG_ENABLE
24 #define DBG_SECTION_NAME "drv.usbd"
25 #define DBG_LEVEL DBG_ERROR
26 #define DBG_COLOR
27 #include <rtdbg.h>
28 
29 /* Private define ---------------------------------------------------------------*/
30 /* Define EP maximum packet size */
31 #define EP0_MAX_PKT_SIZE    64
32 #define EP1_MAX_PKT_SIZE    EP0_MAX_PKT_SIZE /* EP0 and EP1 are assigned the same size for control endpoint */
33 #define EP2_MAX_PKT_SIZE    64
34 #define EP3_MAX_PKT_SIZE    64
35 #define EP4_MAX_PKT_SIZE    64
36 #define EP5_MAX_PKT_SIZE    64
37 #define EP6_MAX_PKT_SIZE    64
38 #define EP7_MAX_PKT_SIZE    64
39 #define EP8_MAX_PKT_SIZE    64
40 #define EP9_MAX_PKT_SIZE    64
41 #define EP10_MAX_PKT_SIZE   64
42 #define EP11_MAX_PKT_SIZE   64
43 
44 #define SETUP_BUF_BASE  0
45 #define SETUP_BUF_LEN   8
46 #define EP0_BUF_BASE    (SETUP_BUF_BASE + SETUP_BUF_LEN)
47 #define EP0_BUF_LEN     EP0_MAX_PKT_SIZE
48 
49 #define EP1_BUF_BASE    (SETUP_BUF_BASE + SETUP_BUF_LEN)
50 #define EP1_BUF_LEN     EP1_MAX_PKT_SIZE
51 #define EP2_BUF_BASE    (EP1_BUF_BASE + EP1_BUF_LEN)
52 #define EP2_BUF_LEN     EP2_MAX_PKT_SIZE
53 #define EP3_BUF_BASE    (EP2_BUF_BASE + EP2_BUF_LEN)
54 #define EP3_BUF_LEN     EP3_MAX_PKT_SIZE
55 #define EP4_BUF_BASE    (EP3_BUF_BASE + EP3_BUF_LEN)
56 #define EP4_BUF_LEN     EP4_MAX_PKT_SIZE
57 #define EP5_BUF_BASE    (EP4_BUF_BASE + EP4_BUF_LEN)
58 #define EP5_BUF_LEN     EP5_MAX_PKT_SIZE
59 #define EP6_BUF_BASE    (EP5_BUF_BASE + EP5_BUF_LEN)
60 #define EP6_BUF_LEN     EP6_MAX_PKT_SIZE
61 #define EP7_BUF_BASE    (EP6_BUF_BASE + EP6_BUF_LEN)
62 #define EP7_BUF_LEN     EP7_MAX_PKT_SIZE
63 #define EP8_BUF_BASE    (EP7_BUF_BASE + EP7_BUF_LEN)
64 #define EP8_BUF_LEN     EP8_MAX_PKT_SIZE
65 #define EP9_BUF_BASE    (EP8_BUF_BASE + EP8_BUF_LEN)
66 #define EP9_BUF_LEN     EP9_MAX_PKT_SIZE
67 #define EP10_BUF_BASE   (EP9_BUF_BASE + EP9_BUF_LEN)
68 #define EP10_BUF_LEN    EP10_MAX_PKT_SIZE
69 #define EP11_BUF_BASE   (EP10_BUF_BASE + EP10_BUF_LEN)
70 #define EP11_BUF_LEN    EP11_MAX_PKT_SIZE
71 
72 #define EPADR_SW2HW(address) ((((address & USB_EPNO_MASK) * 2) +  (!(address & USB_DIR_IN))))
73 #define EPADR_HW2SW(address) ((address & USB_EPNO_MASK) / 2)
74 /* Private typedef --------------------------------------------------------------*/
75 typedef struct _nu_usbd_t
76 {
77     USBD_T *Instance;       /* REG base */
78     uint8_t address_tmp;    /* Keep assigned address for flow control */
79 } nu_usbd_t;
80 
81 
82 /* Private variables ------------------------------------------------------------*/
83 static nu_usbd_t nu_usbd =
84 {
85     .Instance       = USBD,
86     .address_tmp    = 0,
87 };
88 
89 static struct udcd _rt_obj_udc;
90 
91 static struct ep_id _ep_pool[] =
92 {
93     {EPADR_HW2SW(EP0),  USB_EP_ATTR_CONTROL,     USB_DIR_INOUT,  EP0_MAX_PKT_SIZE, ID_ASSIGNED  },
94     {EPADR_HW2SW(EP2),  USB_EP_ATTR_BULK,        USB_DIR_IN,     EP2_MAX_PKT_SIZE, ID_UNASSIGNED},
95     {EPADR_HW2SW(EP3),  USB_EP_ATTR_BULK,        USB_DIR_OUT,    EP3_MAX_PKT_SIZE, ID_UNASSIGNED},
96     {EPADR_HW2SW(EP4),  USB_EP_ATTR_INT,         USB_DIR_IN,     EP4_MAX_PKT_SIZE, ID_UNASSIGNED},
97     {EPADR_HW2SW(EP5),  USB_EP_ATTR_INT,         USB_DIR_OUT,    EP5_MAX_PKT_SIZE, ID_UNASSIGNED},
98     {EPADR_HW2SW(EP6),  USB_EP_ATTR_BULK,        USB_DIR_IN,     EP6_MAX_PKT_SIZE, ID_UNASSIGNED},
99     {EPADR_HW2SW(EP7),  USB_EP_ATTR_BULK,        USB_DIR_OUT,    EP7_MAX_PKT_SIZE, ID_UNASSIGNED},
100     {EPADR_HW2SW(EP8),  USB_EP_ATTR_INT,         USB_DIR_IN,     EP8_MAX_PKT_SIZE, ID_UNASSIGNED},
101     {EPADR_HW2SW(EP9),  USB_EP_ATTR_INT,         USB_DIR_OUT,    EP9_MAX_PKT_SIZE, ID_UNASSIGNED},
102     {EPADR_HW2SW(EP10), USB_EP_ATTR_BULK,        USB_DIR_IN,     EP6_MAX_PKT_SIZE, ID_UNASSIGNED},
103     {EPADR_HW2SW(EP11), USB_EP_ATTR_BULK,        USB_DIR_OUT,    EP7_MAX_PKT_SIZE, ID_UNASSIGNED},
104     {0xFF,              USB_EP_ATTR_TYPE_MASK,   USB_DIR_MASK,   0,                ID_ASSIGNED  },
105 };
106 
_nu_ep_partition(void)107 static void _nu_ep_partition(void)
108 {
109     /* Init setup packet buffer */
110     /* Buffer range for setup packet -> [0 ~ 0x7] */
111     USBD->STBUFSEG = SETUP_BUF_BASE;
112 
113     /*****************************************************/
114     /* EP0 ==> control IN endpoint, address 0 */
115     USBD_CONFIG_EP(EP0, USBD_CFG_CSTALL | USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP0));
116     /* Buffer range for EP0 */
117     USBD_SET_EP_BUF_ADDR(EP0, EP0_BUF_BASE);
118 
119     /* EP1 ==> control OUT endpoint, address 0 */
120     USBD_CONFIG_EP(EP1, USBD_CFG_CSTALL | USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP1));
121     /* Buffer range for EP1 */
122     USBD_SET_EP_BUF_ADDR(EP1, EP1_BUF_BASE);
123 
124     /*****************************************************/
125     /* EP2 ==> Bulk IN endpoint, address 1 */
126     USBD_CONFIG_EP(EP2, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP2));
127     /* Buffer range for EP2 */
128     USBD_SET_EP_BUF_ADDR(EP2, EP2_BUF_BASE);
129 
130     /* EP3 ==> Bulk OUT endpoint, address 1 */
131     USBD_CONFIG_EP(EP3, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP3));
132     /* Buffer range for EP3 */
133     USBD_SET_EP_BUF_ADDR(EP3, EP3_BUF_BASE);
134 
135     /*****************************************************/
136     /* EP4 ==> Interrupt IN endpoint, address 2 */
137     USBD_CONFIG_EP(EP4, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP4));
138     /* Buffer range for EP4 */
139     USBD_SET_EP_BUF_ADDR(EP4, EP4_BUF_BASE);
140 
141     /* EP5 ==> Interrupt Out endpoint, address 2 */
142     USBD_CONFIG_EP(EP5, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP5));
143     /* Buffer range for EP5 */
144     USBD_SET_EP_BUF_ADDR(EP5, EP5_BUF_BASE);
145 
146     /*****************************************************/
147     /* EP6 ==> Bulk IN endpoint, address 3 */
148     USBD_CONFIG_EP(EP6, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP6));
149     /* Buffer range for EP4 */
150     USBD_SET_EP_BUF_ADDR(EP6, EP6_BUF_BASE);
151 
152     /* EP7 ==> Bulk Out endpoint, address 3 */
153     USBD_CONFIG_EP(EP7, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP7));
154     /* Buffer range for EP5 */
155     USBD_SET_EP_BUF_ADDR(EP7, EP7_BUF_BASE);
156 
157     /*****************************************************/
158     /* EP8 ==> Interrupt IN endpoint, address 4 */
159     USBD_CONFIG_EP(EP8, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP8));
160     /* Buffer range for EP4 */
161     USBD_SET_EP_BUF_ADDR(EP8, EP8_BUF_BASE);
162 
163     /* EP9 ==> Interrupt Out endpoint, address 4 */
164     USBD_CONFIG_EP(EP9, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP9));
165     /* Buffer range for EP9 */
166     USBD_SET_EP_BUF_ADDR(EP9, EP9_BUF_BASE);
167 
168     /*****************************************************/
169     /* EP10 ==> Bulk IN endpoint, address 5 */
170     USBD_CONFIG_EP(EP10, USBD_CFG_EPMODE_IN | EPADR_HW2SW(EP10));
171     /* Buffer range for EP10 */
172     USBD_SET_EP_BUF_ADDR(EP10, EP10_BUF_BASE);
173 
174     /* EP11 ==> Bulk Out endpoint, address 5 */
175     USBD_CONFIG_EP(EP11, USBD_CFG_EPMODE_OUT | EPADR_HW2SW(EP11));
176     /* Buffer range for EP11 */
177     USBD_SET_EP_BUF_ADDR(EP11, EP11_BUF_BASE);
178 
179 }
180 
_ep_set_stall(rt_uint8_t address)181 static rt_err_t _ep_set_stall(rt_uint8_t address)
182 {
183     USBD_SET_EP_STALL(EPADR_SW2HW(address));
184     return RT_EOK;
185 }
186 
_ep_clear_stall(rt_uint8_t address)187 static rt_err_t _ep_clear_stall(rt_uint8_t address)
188 {
189     USBD_ClearStall(EPADR_SW2HW(address));
190 
191     return RT_EOK;
192 }
193 
194 
_set_address(rt_uint8_t address)195 static rt_err_t _set_address(rt_uint8_t address)
196 {
197     if (0 != address)
198     {
199         nu_usbd.address_tmp = address;
200     }
201 
202     return RT_EOK;
203 }
204 
_set_config(rt_uint8_t address)205 static rt_err_t _set_config(rt_uint8_t address)
206 {
207     return RT_EOK;
208 }
209 
_ep_enable(uep_t ep)210 static rt_err_t _ep_enable(uep_t ep)
211 {
212     RT_ASSERT(ep != RT_NULL);
213     RT_ASSERT(ep->ep_desc != RT_NULL);
214 
215     USBD_CONFIG_EP(EPADR_SW2HW(EP_ADDRESS(ep)),
216                    USBD_CFG_CSTALL
217                    | ((EP_ADDRESS(ep) & USB_DIR_IN) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT)
218                    | (EP_ADDRESS(ep) & USB_EPNO_MASK));
219 
220     return RT_EOK;
221 }
222 
_ep_disable(uep_t ep)223 static rt_err_t _ep_disable(uep_t ep)
224 {
225     RT_ASSERT(ep != RT_NULL);
226     RT_ASSERT(ep->ep_desc != RT_NULL);
227 
228     USBD_CONFIG_EP(EPADR_SW2HW(EP_ADDRESS(ep)),  USBD_CFG_EPMODE_DISABLE);
229 
230     return RT_EOK;
231 }
232 
_ep_read(rt_uint8_t address,void * buffer)233 static rt_ssize_t _ep_read(rt_uint8_t address, void *buffer)
234 {
235     rt_size_t size = 0;
236     rt_uint8_t *buf;
237     rt_uint32_t hw_ep_num = EPADR_SW2HW(address);
238 
239     RT_ASSERT(!(address & USB_DIR_IN));
240     RT_ASSERT(buffer != RT_NULL);
241 
242     size = USBD_GET_PAYLOAD_LEN(hw_ep_num);
243     buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(hw_ep_num));
244     USBD_MemCopy(buffer, (uint8_t *)buf, size);
245 
246     return size;
247 }
248 
_ep_read_prepare(rt_uint8_t address,void * buffer,rt_size_t size)249 static rt_ssize_t _ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size)
250 {
251     RT_ASSERT(!(address & USB_DIR_IN));
252 
253     USBD_SET_PAYLOAD_LEN(EPADR_SW2HW(address), size);
254 
255     return size;
256 }
257 
_ep_write(rt_uint8_t address,void * buffer,rt_size_t size)258 static rt_ssize_t _ep_write(rt_uint8_t address, void *buffer, rt_size_t size)
259 {
260     RT_ASSERT((address & USB_DIR_IN));
261 
262     /* even number is for IN endpoint */
263     rt_uint32_t hw_ep_num = EPADR_SW2HW(address);
264     uint8_t *buf;
265     buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(hw_ep_num));
266 
267     USBD_MemCopy(buf, (uint8_t *)buffer, size);
268 
269     USBD_SET_PAYLOAD_LEN(hw_ep_num, size);
270 
271     return size;
272 }
273 
_ep0_send_status(void)274 static rt_err_t _ep0_send_status(void)
275 {
276     /* Status stage */
277     USBD_SET_DATA1(EP0);
278     USBD_SET_PAYLOAD_LEN(EP0, 0);
279     return RT_EOK;
280 }
281 
_suspend(void)282 static rt_err_t _suspend(void)
283 {
284     return RT_EOK;
285 }
286 
_wakeup(void)287 static rt_err_t _wakeup(void)
288 {
289     return RT_EOK;
290 }
291 
_USBD_IRQHandler(void)292 __STATIC_INLINE void _USBD_IRQHandler(void)
293 {
294     rt_uint32_t u32IntSts   = USBD_GET_INT_FLAG();
295     rt_uint32_t u32State    = USBD_GET_BUS_STATE();
296 
297 //------------------------------------------------------------------
298     if (u32IntSts & USBD_INTSTS_VBDETIF_Msk)
299     {
300         // Floating detect
301         USBD_CLR_INT_FLAG(USBD_INTSTS_VBDETIF_Msk);
302 
303         if (USBD_IS_ATTACHED())
304         {
305             /* USB Plug In */
306             USBD_ENABLE_USB();
307             rt_usbd_connect_handler(&_rt_obj_udc);
308         }
309         else
310         {
311             /* USB Unplug */
312             USBD_DISABLE_USB();
313             rt_usbd_disconnect_handler(&_rt_obj_udc);
314         }
315     }
316 
317     if (u32IntSts & USBD_INTSTS_SOFIF_Msk)
318     {
319         USBD_CLR_INT_FLAG(USBD_INTSTS_SOFIF_Msk);
320         rt_usbd_sof_handler(&_rt_obj_udc);
321     }
322 //------------------------------------------------------------------
323     if (u32IntSts & USBD_INTSTS_BUSIF_Msk)
324     {
325         /* Clear event flag */
326         USBD_CLR_INT_FLAG(USBD_INTSTS_BUSIF_Msk);
327 
328         if (u32State & USBD_ATTR_USBRST_Msk)
329         {
330             USBD_ENABLE_USB();
331 
332             /* Reset PID DATA0 */
333             for (rt_uint32_t i = 0ul; i < USBD_MAX_EP; i++)
334             {
335                 nu_usbd.Instance->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk;
336             }
337 
338             /* Reset USB device address */
339             USBD_SET_ADDR(0ul);
340 
341             /* Bus reset */
342             rt_usbd_reset_handler(&_rt_obj_udc);
343         }
344         if (u32State & USBD_ATTR_SUSPEND_Msk)
345         {
346             /* Enable USB but disable PHY */
347             USBD_DISABLE_PHY();
348         }
349         if (u32State & USBD_ATTR_RESUME_Msk)
350         {
351             /* Enable USB and enable PHY */
352             USBD_ENABLE_USB();
353         }
354     }
355 
356 //------------------------------------------------------------------
357     if (u32IntSts & USBD_INTSTS_WAKEUP)
358     {
359         /* Clear event flag */
360         USBD_CLR_INT_FLAG(USBD_INTSTS_WAKEUP);
361         USBD_ENABLE_USB();
362     }
363 
364     if (u32IntSts & USBD_INTSTS_USBIF_Msk)
365     {
366         // USB event
367         if (u32IntSts & USBD_INTSTS_SETUP_Msk)
368         {
369             // Setup packet
370             /* Clear event flag */
371             USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP_Msk);
372 
373             /* Clear the data IN/OUT ready flag of control end-points */
374             USBD_STOP_TRANSACTION(EP0);
375             USBD_STOP_TRANSACTION(EP1);
376 
377             USBD_SET_DATA1(EP0);
378             rt_usbd_ep0_setup_handler(&_rt_obj_udc, (struct urequest *)USBD_BUF_BASE);
379         }
380 
381         // EP events
382         if (u32IntSts & USBD_INTSTS_EP0)
383         {
384             /* Clear event flag */
385             USBD_CLR_INT_FLAG(USBD_INTSTS_EP0);
386 
387             if ((USBD_GET_ADDR() == 0)
388                     && (nu_usbd.address_tmp)
389                )
390             {
391                 USBD_SET_ADDR(nu_usbd.address_tmp);
392                 LOG_I("SET ADDR: 0x%02x", nu_usbd.address_tmp);
393                 nu_usbd.address_tmp = 0;
394             }
395 
396             rt_usbd_ep0_in_handler(&_rt_obj_udc);
397         }
398 
399         if (u32IntSts & USBD_INTSTS_EP1)
400         {
401             /* Clear event flag */
402             USBD_CLR_INT_FLAG(USBD_INTSTS_EP1);
403             rt_usbd_ep0_out_handler(&_rt_obj_udc, 0);
404         }
405 
406         if (u32IntSts & USBD_INTSTS_EP2)
407         {
408             /* Clear event flag */
409             USBD_CLR_INT_FLAG(USBD_INTSTS_EP2);
410             rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP2), 0);
411         }
412 
413         if (u32IntSts & USBD_INTSTS_EP3)
414         {
415             /* Clear event flag */
416             USBD_CLR_INT_FLAG(USBD_INTSTS_EP3);
417             rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP3), 0);
418         }
419 
420         if (u32IntSts & USBD_INTSTS_EP4)
421         {
422             /* Clear event flag */
423             USBD_CLR_INT_FLAG(USBD_INTSTS_EP4);
424             rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP4), 0);
425         }
426 
427         if (u32IntSts & USBD_INTSTS_EP5)
428         {
429             /* Clear event flag */
430             USBD_CLR_INT_FLAG(USBD_INTSTS_EP5);
431             rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP5), 0);
432         }
433 
434         if (u32IntSts & USBD_INTSTS_EP6)
435         {
436             /* Clear event flag */
437             USBD_CLR_INT_FLAG(USBD_INTSTS_EP6);
438             rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP6), 0);
439         }
440 
441         if (u32IntSts & USBD_INTSTS_EP7)
442         {
443             /* Clear event flag */
444             USBD_CLR_INT_FLAG(USBD_INTSTS_EP7);
445             rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP7), 0);
446         }
447 
448         if (u32IntSts & USBD_INTSTS_EP8)
449         {
450             /* Clear event flag */
451             USBD_CLR_INT_FLAG(USBD_INTSTS_EP8);
452             rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP8), 0);
453         }
454 
455         if (u32IntSts & USBD_INTSTS_EP9)
456         {
457             /* Clear event flag */
458             USBD_CLR_INT_FLAG(USBD_INTSTS_EP9);
459             rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP9), 0);
460         }
461 
462         if (u32IntSts & USBD_INTSTS_EP10)
463         {
464             /* Clear event flag */
465             USBD_CLR_INT_FLAG(USBD_INTSTS_EP10);
466             rt_usbd_ep_in_handler(&_rt_obj_udc, USB_DIR_IN | EPADR_HW2SW(EP10), 0);
467         }
468 
469         if (u32IntSts & USBD_INTSTS_EP11)
470         {
471             /* Clear event flag */
472             USBD_CLR_INT_FLAG(USBD_INTSTS_EP11);
473             rt_usbd_ep_out_handler(&_rt_obj_udc, USB_DIR_OUT | EPADR_HW2SW(EP11), 0);
474         }
475 
476     }
477 }
478 
USBD_IRQHandler(void)479 void USBD_IRQHandler(void)
480 {
481     rt_interrupt_enter();
482 
483     _USBD_IRQHandler();
484 
485     rt_interrupt_leave();
486 }
487 
_init(rt_device_t device)488 static rt_err_t _init(rt_device_t device)
489 {
490     nu_usbd_t *nu_usbd = (nu_usbd_t *)device->user_data;
491 
492 #if !defined(BSP_USING_OTG)
493 
494     /* Initialize USB PHY */
495     SYS_UnlockReg();
496     /* Select USBD */
497     SYS->USBPHY = (SYS->USBPHY & ~SYS_USBPHY_USBROLE_Msk) | SYS_USBPHY_OTGPHYEN_Msk | SYS_USBPHY_SBO_Msk;
498     SYS_ResetModule(USBD_RST);
499     SYS_LockReg();
500 #endif
501 
502     _nu_ep_partition();
503 
504     /* Initial USB engine */
505     nu_usbd->Instance->ATTR = 0x6D0ul;
506 
507     /* Force SE0 */
508     USBD_SET_SE0();
509 
510     NVIC_EnableIRQ(USBD_IRQn);
511 
512     USBD_Start();
513     return RT_EOK;
514 }
515 
516 const static struct udcd_ops _udc_ops =
517 {
518     _set_address,
519     _set_config,
520     _ep_set_stall,
521     _ep_clear_stall,
522     _ep_enable,
523     _ep_disable,
524     _ep_read_prepare,
525     _ep_read,
526     _ep_write,
527     _ep0_send_status,
528     _suspend,
529     _wakeup,
530 };
531 
532 #ifdef RT_USING_DEVICE_OPS
533 const static struct rt_device_ops _ops =
534 {
535     _init,
536     RT_NULL,
537     RT_NULL,
538     RT_NULL,
539     RT_NULL,
540     RT_NULL,
541 };
542 #endif
543 
nu_usbd_register(void)544 int nu_usbd_register(void)
545 {
546     if (RT_NULL != rt_device_find("usbd"))
547     {
548         LOG_E("\nUSBD Register failed. Another USBD device registered\n");
549         return -RT_ERROR;
550     }
551 
552     rt_memset((void *)&_rt_obj_udc, 0, sizeof(struct udcd));
553     _rt_obj_udc.parent.type = RT_Device_Class_USBDevice;
554 
555 #ifdef RT_USING_DEVICE_OPS
556     _rt_obj_udc.parent.ops = &_ops;
557 #else
558     _rt_obj_udc.parent.init = _init;
559 #endif
560 
561     _rt_obj_udc.parent.user_data = &nu_usbd;
562     _rt_obj_udc.ops = &_udc_ops;
563     /* Register endpoint information */
564     _rt_obj_udc.ep_pool = _ep_pool;
565     _rt_obj_udc.ep0.id = &_ep_pool[0];
566 
567     _rt_obj_udc.device_is_hs = RT_FALSE; /* Support Full-Speed only */
568 
569     rt_device_register((rt_device_t)&_rt_obj_udc, "usbd", 0);
570     rt_usb_device_init();
571     return RT_EOK;
572 }
573 INIT_DEVICE_EXPORT(nu_usbd_register);
574 #endif
575