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