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