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