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