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