1 /**************************************************************************//**
2 * @file usbd.c
3 * @version V1.00
4 * @brief M2L31 USBD driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9
10 #include <string.h>
11 #include "NuMicro.h"
12
13 #ifdef __cplusplus
14 extern "C"
15 {
16 #endif
17
18 /** @addtogroup Standard_Driver Standard Driver
19 @{
20 */
21
22 /** @addtogroup USBD_Driver USBD Driver
23 @{
24 */
25
26
27 /** @addtogroup USBD_EXPORTED_FUNCTIONS USBD Exported Functions
28 @{
29 */
30
31 /* Global variables for Control Pipe */
32 uint8_t g_usbd_SetupPacket[8] = {0ul}; /*!< Setup packet buffer */
33 volatile uint8_t g_usbd_RemoteWakeupEn = 0ul; /*!< Remote wake up function enable flag */
34
35 /**
36 * @cond HIDDEN_SYMBOLS
37 */
38 static uint8_t *g_usbd_CtrlInPointer = 0;
39 static uint8_t *g_usbd_CtrlOutPointer = 0;
40 static volatile uint32_t g_usbd_CtrlInSize = 0ul;
41 static volatile uint32_t g_usbd_CtrlOutSize = 0ul;
42 static volatile uint32_t g_usbd_CtrlOutSizeLimit = 0ul;
43 static volatile uint32_t g_usbd_UsbAddr = 0ul;
44 static volatile uint32_t g_usbd_UsbConfig = 0ul;
45 static volatile uint32_t g_usbd_CtrlMaxPktSize = 8ul;
46 static volatile uint32_t g_usbd_UsbAltInterface = 0ul;
47 static volatile uint32_t g_usbd_CtrlOutToggle = 0;
48 static volatile uint8_t g_usbd_CtrlInZeroFlag = 0ul;
49 /**
50 * @endcond
51 */
52
53 const S_USBD_INFO_T *g_usbd_sInfo; /*!< A pointer for USB information structure */
54
55 VENDOR_REQ g_usbd_pfnVendorRequest = NULL; /*!< USB Vendor Request Functional Pointer */
56 CLASS_REQ g_usbd_pfnClassRequest = NULL; /*!< USB Class Request Functional Pointer */
57 SET_INTERFACE_REQ g_usbd_pfnSetInterface = NULL; /*!< USB Set Interface Functional Pointer */
58 SET_CONFIG_CB g_usbd_pfnSetConfigCallback = NULL; /*!< USB Set configuration callback function pointer */
59 uint32_t g_u32EpStallLock = 0ul; /*!< Bit map flag to lock specified EP when SET_FEATURE */
60
61 /**
62 * @brief This function makes USBD module to be ready to use
63 *
64 * @param[in] param The structure of USBD information.
65 * @param[in] pfnClassReq USB Class request callback function.
66 * @param[in] pfnSetInterface USB Set Interface request callback function.
67 *
68 * @return None
69 *
70 * @details This function will enable USB controller, USB PHY transceiver and pull-up resistor of USB_D+ pin. USB PHY will drive SE0 to bus.
71 */
USBD_Open(const S_USBD_INFO_T * param,CLASS_REQ pfnClassReq,SET_INTERFACE_REQ pfnSetInterface)72 void USBD_Open(const S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
73 {
74 g_usbd_sInfo = param;
75 g_usbd_pfnClassRequest = pfnClassReq;
76 g_usbd_pfnSetInterface = pfnSetInterface;
77
78 /* get EP0 maximum packet size */
79 g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7];
80
81 /* Initial USB engine */
82 #ifdef SUPPORT_LPM
83 USBD->ATTR = 0x7D0 | USBD_LPMACK;
84 #else
85 USBD->ATTR = 0x6D0ul;
86 #endif
87 /* Force SE0 */
88 USBD_SET_SE0();
89 }
90
91 /**
92 * @brief This function makes USB host to recognize the device
93 *
94 * @param None
95 *
96 * @return None
97 *
98 * @details Enable WAKEUP, FLDET, USB and BUS interrupts. Disable software-disconnect function after 100ms delay with SysTick timer.
99 */
USBD_Start(void)100 void USBD_Start(void)
101 {
102 /* Disable software-disconnect function */
103 USBD_CLR_SE0();
104
105 /* Clear USB-related interrupts before enable interrupt */
106 USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
107
108 /* Enable USB-related interrupts. */
109 USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
110 }
111
112 /**
113 * @brief Get the received SETUP packet
114 *
115 * @param[in] buf A buffer pointer used to store 8-byte SETUP packet.
116 *
117 * @return None
118 *
119 * @details Store SETUP packet to a user-specified buffer.
120 *
121 */
USBD_GetSetupPacket(uint8_t * buf)122 void USBD_GetSetupPacket(uint8_t *buf)
123 {
124 USBD_MemCopy(buf, g_usbd_SetupPacket, 8ul);
125 }
126
127 /**
128 * @brief Process SETUP packet
129 *
130 * @param None
131 *
132 * @return None
133 *
134 * @details Parse SETUP packet and perform the corresponding action.
135 *
136 */
USBD_ProcessSetupPacket(void)137 void USBD_ProcessSetupPacket(void)
138 {
139 g_usbd_CtrlOutToggle = 0;
140 /* Get SETUP packet from USB buffer */
141 USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8ul);
142
143 /* Check the request type */
144 switch(g_usbd_SetupPacket[0] & 0x60ul)
145 {
146 case REQ_STANDARD:
147 {
148 USBD_StandardRequest();
149 break;
150 }
151 case REQ_CLASS:
152 {
153 if(g_usbd_pfnClassRequest != NULL)
154 {
155 g_usbd_pfnClassRequest();
156 }
157 break;
158 }
159 case REQ_VENDOR:
160 {
161 if(g_usbd_pfnVendorRequest != NULL)
162 {
163 g_usbd_pfnVendorRequest();
164 }
165 break;
166 }
167 default:
168 {
169 /* Setup error, stall the device */
170 USBD_SET_EP_STALL(EP0);
171 USBD_SET_EP_STALL(EP1);
172 break;
173 }
174 }
175 }
176
177 /**
178 * @brief Process GetDescriptor request
179 *
180 * @param None
181 *
182 * @return None
183 *
184 * @details Parse GetDescriptor request and perform the corresponding action.
185 *
186 */
USBD_GetDescriptor(void)187 void USBD_GetDescriptor(void)
188 {
189 uint32_t u32Len;
190
191 g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
192 u32Len = 0ul;
193 u32Len = g_usbd_SetupPacket[7];
194 u32Len <<= 8ul;
195 u32Len += g_usbd_SetupPacket[6];
196
197 switch(g_usbd_SetupPacket[3])
198 {
199 /* Get Device Descriptor */
200 case DESC_DEVICE:
201 {
202 u32Len = USBD_Minimum(u32Len, (uint32_t)LEN_DEVICE);
203 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len);
204
205 break;
206 }
207 /* Get Configuration Descriptor */
208 case DESC_CONFIG:
209 {
210 uint32_t u32TotalLen;
211
212 u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3];
213 u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);
214
215 if (u32Len > u32TotalLen)
216 {
217 u32Len = u32TotalLen;
218 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
219 {
220 g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
221 }
222 }
223 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len);
224
225 break;
226 }
227
228 /* Get BOS Descriptor */
229 case DESC_BOS:
230 {
231 if (g_usbd_sInfo->gu8BosDesc == 0)
232 {
233 USBD_SET_EP_STALL(EP0);
234 USBD_SET_EP_STALL(EP1);
235 }
236 else
237 {
238 u32Len = USBD_Minimum(u32Len, LEN_BOS+LEN_BOSCAP);
239 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8BosDesc, u32Len);
240 }
241 break;
242 }
243 /* Get HID Descriptor */
244 case DESC_HID:
245 {
246 /* CV3.0 HID Class Descriptor Test,
247 Need to indicate index of the HID Descriptor within gu8ConfigDescriptor, specifically HID Composite device. */
248 uint32_t u32ConfigDescOffset; /* u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index) */
249 u32Len = USBD_Minimum(u32Len, LEN_HID);
250 u32ConfigDescOffset = g_usbd_sInfo->gu32ConfigHidDescIdx[g_usbd_SetupPacket[4]];
251 USBD_PrepareCtrlIn((uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len);
252
253 break;
254 }
255 /* Get Report Descriptor */
256 case DESC_HID_RPT:
257 {
258 if (u32Len > g_usbd_sInfo->gu32HidReportSize[g_usbd_SetupPacket[4]])
259 {
260 u32Len = g_usbd_sInfo->gu32HidReportSize[g_usbd_SetupPacket[4]];
261 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
262 {
263 g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
264 }
265 }
266 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8HidReportDesc[g_usbd_SetupPacket[4]], u32Len);
267 break;
268 }
269 /* Get String Descriptor */
270 case DESC_STRING:
271 {
272 /* Get String Descriptor */
273 if(g_usbd_SetupPacket[2] < 4ul)
274 {
275 if (u32Len > g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0])
276 {
277 u32Len = g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]][0];
278 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0ul)
279 {
280 g_usbd_CtrlInZeroFlag = (uint8_t)1ul;
281 }
282 }
283 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[g_usbd_SetupPacket[2]], u32Len);
284 break;
285 }
286 else
287 {
288 /* Not support. Reply STALL. */
289 USBD_SET_EP_STALL(EP0);
290 USBD_SET_EP_STALL(EP1);
291 break;
292 }
293 }
294 default:
295 /* Not support. Reply STALL.*/
296 USBD_SET_EP_STALL(EP0);
297 USBD_SET_EP_STALL(EP1);
298 break;
299 }
300 }
301
302 /**
303 * @brief Process standard request
304 *
305 * @param None
306 *
307 * @return None
308 *
309 * @details Parse standard request and perform the corresponding action.
310 *
311 */
USBD_StandardRequest(void)312 void USBD_StandardRequest(void)
313 {
314 uint32_t addr;
315 /* clear global variables for new request */
316 g_usbd_CtrlInPointer = 0;
317 g_usbd_CtrlInSize = 0ul;
318
319 if((g_usbd_SetupPacket[0] & 0x80ul) == 0x80ul) /* request data transfer direction */
320 {
321 /* Device to host */
322 switch(g_usbd_SetupPacket[1])
323 {
324 case GET_CONFIGURATION:
325 {
326 /* Return current configuration setting */
327 /* Data stage */
328 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
329 M8(addr) = (uint8_t)g_usbd_UsbConfig;
330 USBD_SET_DATA1(EP0);
331 USBD_SET_PAYLOAD_LEN(EP0, 1ul);
332 /* Status stage */
333 USBD_PrepareCtrlOut(0, 0ul);
334 break;
335 }
336 case GET_DESCRIPTOR:
337 {
338 USBD_GetDescriptor();
339 USBD_PrepareCtrlOut(0, 0ul); /* For status stage */
340 break;
341 }
342 case GET_INTERFACE:
343 {
344 /* Return current interface setting */
345 /* Data stage */
346 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
347 M8(addr) = (uint8_t)g_usbd_UsbAltInterface;
348 USBD_SET_DATA1(EP0);
349 USBD_SET_PAYLOAD_LEN(EP0, 1ul);
350 /* Status stage */
351 USBD_PrepareCtrlOut(0, 0ul);
352 break;
353 }
354 case GET_STATUS:
355 {
356 /* Device */
357 if(g_usbd_SetupPacket[0] == 0x80ul)
358 {
359 uint8_t u8Tmp;
360
361 u8Tmp = (uint8_t)0ul;
362 if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x40ul) == 0x40ul)
363 {
364 u8Tmp |= (uint8_t)1ul; /* Self-Powered/Bus-Powered.*/
365 }
366 if ((g_usbd_sInfo->gu8ConfigDesc[7] & 0x20ul) == 0x20ul)
367 {
368 u8Tmp |= (uint8_t)(g_usbd_RemoteWakeupEn << 1ul); /* Remote wake up */
369 }
370
371 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
372 M8(addr) = u8Tmp;
373 }
374 /* Interface */
375 else if(g_usbd_SetupPacket[0] == 0x81ul)
376 {
377 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
378 M8(addr) = (uint8_t)0ul;
379 }
380 /* Endpoint */
381 else if(g_usbd_SetupPacket[0] == 0x82ul)
382 {
383 uint8_t ep = (uint8_t)(g_usbd_SetupPacket[4] & 0xFul);
384 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
385 M8(addr) = (uint8_t)(USBD_GetStall(ep) ? 1ul : 0ul);
386 }
387
388 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0) + 1ul;
389 M8(addr) = (uint8_t)0ul;
390 /* Data stage */
391 USBD_SET_DATA1(EP0);
392 USBD_SET_PAYLOAD_LEN(EP0, 2ul);
393 /* Status stage */
394 USBD_PrepareCtrlOut(0, 0ul);
395 break;
396 }
397 default:
398 {
399 /* Setup error, stall the device */
400 USBD_SET_EP_STALL(EP0);
401 USBD_SET_EP_STALL(EP1);
402 break;
403 }
404 }
405 }
406 else
407 {
408 /* Host to device */
409 switch(g_usbd_SetupPacket[1])
410 {
411 case CLEAR_FEATURE:
412 {
413 if(g_usbd_SetupPacket[2] == 3)
414 {
415 USBD_SET_EP_STALL(0);
416 USBD_SET_EP_STALL(1);
417 }
418 if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
419 {
420 uint32_t epNum, i;
421
422 /* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
423 a flag: g_u32EpStallLock is added to support it */
424 epNum = (uint8_t)(g_usbd_SetupPacket[4] & 0xFul);
425 for(i = 0ul; i < USBD_MAX_EP; i++)
426 {
427 if(((USBD->EP[i].CFG & 0xFul) == epNum) && ((g_u32EpStallLock & (1ul << i)) == 0ul))
428 {
429 USBD->EP[i].CFGP &= ~USBD_CFGP_SSTALL_Msk;
430 USBD->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk;
431 }
432 }
433 }
434 else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
435 {
436 g_usbd_RemoteWakeupEn = (uint8_t)0;
437 }
438
439 /* Status stage */
440 USBD_SET_DATA1(EP0);
441 USBD_SET_PAYLOAD_LEN(EP0, 0ul);
442 break;
443 }
444 case SET_ADDRESS:
445 {
446 g_usbd_UsbAddr = g_usbd_SetupPacket[2];
447 /* Status Stage */
448 USBD_SET_DATA1(EP0);
449 USBD_SET_PAYLOAD_LEN(EP0, 0ul);
450
451 break;
452 }
453 case SET_CONFIGURATION:
454 {
455 g_usbd_UsbConfig = g_usbd_SetupPacket[2];
456
457 if(g_usbd_pfnSetConfigCallback)
458 {
459 g_usbd_pfnSetConfigCallback();
460 }
461
462 /* Status stage */
463 USBD_SET_DATA1(EP0);
464 USBD_SET_PAYLOAD_LEN(EP0, 0ul);
465 break;
466 }
467 case SET_FEATURE:
468 {
469 if( (g_usbd_SetupPacket[0] & 0xFul) == 0ul ) /* 0: device */
470 {
471 if((g_usbd_SetupPacket[2] == 2) && (g_usbd_SetupPacket[3] == 0)) /* 2:test mode */
472 {
473 OTG->CTL |= (OTG_CTL_HNPREQEN_Msk | OTG_CTL_BUSREQ_Msk);
474 }
475 }
476 if(g_usbd_SetupPacket[2] == FEATURE_ENDPOINT_HALT)
477 {
478 USBD_SetStall((uint8_t)(g_usbd_SetupPacket[4] & 0xFul));
479 }
480 else if(g_usbd_SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
481 {
482 g_usbd_RemoteWakeupEn = (uint8_t)1ul;
483 }
484
485 /* Status stage */
486 USBD_SET_DATA1(EP0);
487 USBD_SET_PAYLOAD_LEN(EP0, 0ul);
488
489 break;
490 }
491 case SET_INTERFACE:
492 {
493 g_usbd_UsbAltInterface = g_usbd_SetupPacket[2];
494 if(g_usbd_pfnSetInterface != NULL)
495 {
496 g_usbd_pfnSetInterface(g_usbd_UsbAltInterface);
497 }
498 /* Status stage */
499 USBD_SET_DATA1(EP0);
500 USBD_SET_PAYLOAD_LEN(EP0, 0ul);
501 break;
502 }
503 default:
504 {
505 /* Setup error, stall the device */
506 USBD_SET_EP_STALL(EP0);
507 USBD_SET_EP_STALL(EP1);
508 break;
509 }
510 }
511 }
512 }
513
514 /**
515 * @brief Prepare the first Control IN pipe
516 *
517 * @param[in] pu8Buf The pointer of data sent to USB host.
518 * @param[in] u32Size The IN transfer size.
519 *
520 * @return None
521 *
522 * @details Prepare data for Control IN transfer.
523 *
524 */
USBD_PrepareCtrlIn(uint8_t pu8Buf[],uint32_t u32Size)525 void USBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size)
526 {
527 uint32_t addr;
528 if(u32Size > g_usbd_CtrlMaxPktSize)
529 {
530 /* Data size > MXPLD */
531 g_usbd_CtrlInPointer = pu8Buf + g_usbd_CtrlMaxPktSize;
532 g_usbd_CtrlInSize = u32Size - g_usbd_CtrlMaxPktSize;
533 USBD_SET_DATA1(EP0);
534 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
535 USBD_MemCopy((uint8_t *)addr, pu8Buf, g_usbd_CtrlMaxPktSize);
536 USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
537 }
538 else
539 {
540 /* Data size <= MXPLD */
541 g_usbd_CtrlInPointer = 0;
542 g_usbd_CtrlInSize = 0ul;
543 USBD_SET_DATA1(EP0);
544 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
545 USBD_MemCopy((uint8_t *)addr, pu8Buf, u32Size);
546 USBD_SET_PAYLOAD_LEN(EP0, u32Size);
547 }
548 }
549
550 /**
551 * @brief Repeat Control IN pipe
552 *
553 * @param None
554 *
555 * @return None
556 *
557 * @details This function processes the remained data of Control IN transfer.
558 *
559 */
USBD_CtrlIn(void)560 void USBD_CtrlIn(void)
561 {
562 uint32_t addr;
563
564 if(g_usbd_CtrlInSize)
565 {
566 /* Process remained data */
567 if(g_usbd_CtrlInSize > g_usbd_CtrlMaxPktSize)
568 {
569 /* Data size > MXPLD */
570 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
571 USBD_MemCopy((uint8_t *)addr, (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlMaxPktSize);
572 USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlMaxPktSize);
573 g_usbd_CtrlInPointer += g_usbd_CtrlMaxPktSize;
574 g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
575 }
576 else
577 {
578 /* Data size <= MXPLD */
579 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
580 USBD_MemCopy((uint8_t *)addr, (uint8_t *)g_usbd_CtrlInPointer, g_usbd_CtrlInSize);
581 USBD_SET_PAYLOAD_LEN(EP0, g_usbd_CtrlInSize);
582 g_usbd_CtrlInPointer = 0;
583 g_usbd_CtrlInSize = 0ul;
584 }
585 }
586 else
587 {
588 /* In ACK for Set address */
589 if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == SET_ADDRESS))
590 {
591 addr = USBD_GET_ADDR();
592 if((addr != g_usbd_UsbAddr) && (addr == 0ul))
593 {
594 USBD_SET_ADDR(g_usbd_UsbAddr);
595 }
596 }
597
598 /* For the case of data size is integral times maximum packet size */
599 if(g_usbd_CtrlInZeroFlag)
600 {
601 USBD_SET_PAYLOAD_LEN(EP0, 0ul);
602 g_usbd_CtrlInZeroFlag = (uint8_t)0ul;
603 }
604 }
605 }
606
607 /**
608 * @brief Prepare the first Control OUT pipe
609 *
610 * @param[in] pu8Buf The pointer of data received from USB host.
611 * @param[in] u32Size The OUT transfer size.
612 *
613 * @return None
614 *
615 * @details This function is used to prepare the first Control OUT transfer.
616 *
617 */
USBD_PrepareCtrlOut(uint8_t * pu8Buf,uint32_t u32Size)618 void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
619 {
620 g_usbd_CtrlOutPointer = pu8Buf;
621 g_usbd_CtrlOutSize = 0ul;
622 g_usbd_CtrlOutSizeLimit = u32Size;
623 USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
624 }
625
626 /**
627 * @brief Repeat Control OUT pipe
628 *
629 * @param None
630 *
631 * @return None
632 *
633 * @details This function processes the successive Control OUT transfer.
634 *
635 */
USBD_CtrlOut(void)636 void USBD_CtrlOut(void)
637 {
638 uint32_t u32Size;
639 uint32_t addr;
640
641 if (g_usbd_CtrlOutToggle != (USBD->EPSTS0 & USBD_EPSTS0_EPSTS1_Msk))
642 {
643 g_usbd_CtrlOutToggle = USBD->EPSTS0 & USBD_EPSTS0_EPSTS1_Msk;
644 if (g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
645 {
646 u32Size = USBD_GET_PAYLOAD_LEN(EP1);
647 addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1);
648 USBD_MemCopy((uint8_t *)g_usbd_CtrlOutPointer, (uint8_t *)addr, u32Size);
649 g_usbd_CtrlOutPointer += u32Size;
650 g_usbd_CtrlOutSize += u32Size;
651
652 if(g_usbd_CtrlOutSize < g_usbd_CtrlOutSizeLimit)
653 {
654 USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
655 }
656 }
657 }
658 else
659 {
660 USBD_SET_PAYLOAD_LEN(EP1, g_usbd_CtrlMaxPktSize);
661 }
662 }
663
664 /**
665 * @brief Reset software flags
666 *
667 * @param None
668 *
669 * @return None
670 *
671 * @details This function resets all variables for protocol and resets USB device address to 0.
672 *
673 */
USBD_SwReset(void)674 void USBD_SwReset(void)
675 {
676 uint32_t i, u32CFG;
677
678 /* Reset all variables for protocol */
679 g_usbd_CtrlInPointer = 0;
680 g_usbd_CtrlInSize = 0ul;
681 g_usbd_CtrlOutPointer = 0;
682 g_usbd_CtrlOutSize = 0ul;
683 g_usbd_CtrlOutSizeLimit = 0ul;
684 g_u32EpStallLock = 0ul;
685 memset(g_usbd_SetupPacket, 0, 8ul);
686
687 /* Reset PID DATA0 */
688 for(i = 0ul; i < USBD_MAX_EP; i++)
689 {
690 if(!USBD_IS_DB_MODE(i))
691 {
692 USBD->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk;
693 }
694 else
695 {
696 /* Reset double buffer setting */
697 u32CFG = USBD->EP[i].CFG;
698 USBD->EP[i].CFG = u32CFG;
699 }
700 }
701
702 /* Reset USB device address */
703 USBD_SET_ADDR(0ul);
704 }
705
706 /**
707 * @brief USBD Set Vendor Request
708 *
709 * @param[in] pfnVendorReq Vendor Request Callback Function
710 *
711 * @return None
712 *
713 * @details This function is used to set USBD vendor request callback function
714 */
USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)715 void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)
716 {
717 g_usbd_pfnVendorRequest = pfnVendorReq;
718 }
719
720 /**
721 * @brief The callback function which called when get SET CONFIGURATION request
722 *
723 * @param[in] pfnSetConfigCallback Callback function pointer for SET CONFIGURATION request
724 *
725 * @return None
726 *
727 * @details This function is used to set the callback function which will be called at SET CONFIGURATION request.
728 */
USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)729 void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
730 {
731 g_usbd_pfnSetConfigCallback = pfnSetConfigCallback;
732 }
733
734
735 /**
736 * @brief EP stall lock function to avoid stall clear by USB SET FEATURE request.
737 *
738 * @param[in] u32EpBitmap Use bitmap to select which endpoints will be locked
739 *
740 * @return None
741 *
742 * @details This function is used to lock relative endpoint to avoid stall clear by SET FEATURE request.
743 * If ep stall locked, user needs to reset USB device or re-configure device to clear it.
744 */
USBD_LockEpStall(uint32_t u32EpBitmap)745 void USBD_LockEpStall(uint32_t u32EpBitmap)
746 {
747 g_u32EpStallLock = u32EpBitmap;
748 }
749
750
751 /*@}*/ /* end of group USBD_EXPORTED_FUNCTIONS */
752
753 /*@}*/ /* end of group USBD_Driver */
754
755 /*@}*/ /* end of group Standard_Driver */
756
757 #ifdef __cplusplus
758 }
759 #endif
760
761 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
762