1 /**************************************************************************//**
\r
4 * @brief M2351 series USBD driver source file
\r
6 * @copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
\r
7 *****************************************************************************/
\r
10 #include "NuMicro.h"
\r
17 /** @addtogroup Standard_Driver Standard Driver
\r
21 /** @addtogroup USBD_Driver USBD Driver
\r
26 /** @addtogroup USBD_EXPORTED_FUNCTIONS USBD Exported Functions
\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
35 * @cond HIDDEN_SYMBOLS
\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
51 const S_USBD_INFO_T *g_USBD_sInfo; /*!< A pointer for USB information structure */
\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
60 * @brief This function makes USBD module to be ready to use
\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
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
70 void USBD_Open(const S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
\r
74 if((__PC() & NS_OFFSET) == NS_OFFSET)
\r
83 g_USBD_sInfo = param;
\r
84 g_USBD_pfnClassRequest = pfnClassReq;
\r
85 g_USBD_pfnSetInterface = pfnSetInterface;
\r
87 /* get EP0 maximum packet size */
\r
88 g_USBD_u32CtrlMaxPktSize = g_USBD_sInfo->gu8DevDesc[7];
\r
90 /* Initial USB engine */
\r
92 pUSBD->ATTR = 0x7D0UL | USBD_LPMACK;
\r
94 pUSBD->ATTR = 0x7D0UL;
\r
101 * @brief This function makes USB host to recognize the device
\r
107 * @details Enable WAKEUP, FLDET, USB and BUS interrupts. Disable software-disconnect function after 100ms delay with SysTick timer.
\r
109 void USBD_Start(void)
\r
111 /* Disable software-disconnect function */
\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
117 /* Enable USB-related interrupts. */
\r
118 USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
\r
122 * @brief Get the received SETUP packet
\r
124 * @param[in] buf A buffer pointer used to store 8-byte SETUP packet.
\r
128 * @details Store SETUP packet to a user-specified buffer.
\r
131 void USBD_GetSetupPacket(uint8_t *buf)
\r
133 USBD_MemCopy(buf, g_USBD_au8SetupPacket, 8UL);
\r
137 * @brief Process SETUP packet
\r
143 * @details Parse SETUP packet and perform the corresponding action.
\r
146 void USBD_ProcessSetupPacket(void)
\r
148 /* Get SETUP packet from USB buffer */
\r
149 USBD_MemCopy(g_USBD_au8SetupPacket, (uint8_t *)USBD_BUF_BASE, 8UL);
\r
151 /* Check the request type */
\r
152 switch(g_USBD_au8SetupPacket[0] & 0x60UL)
\r
154 case REQ_STANDARD: /* Standard */
\r
156 USBD_StandardRequest();
\r
159 case REQ_CLASS: /* Class */
\r
161 if(g_USBD_pfnClassRequest != NULL)
\r
163 g_USBD_pfnClassRequest();
\r
167 case REQ_VENDOR: /* Vendor */
\r
169 if(g_USBD_pfnVendorRequest != NULL)
\r
171 g_USBD_pfnVendorRequest();
\r
175 default: /* reserved */
\r
177 /* Setup error, stall the device */
\r
178 USBD_SET_EP_STALL(EP0);
\r
179 USBD_SET_EP_STALL(EP1);
\r
186 * @brief Process GetDescriptor request
\r
192 * @details Parse GetDescriptor request and perform the corresponding action.
\r
195 void USBD_GetDescriptor(void)
\r
199 g_USBD_u8CtrlInZeroFlag = (uint8_t)0UL;
\r
201 u32Len = g_USBD_au8SetupPacket[7];
\r
203 u32Len += g_USBD_au8SetupPacket[6];
\r
205 switch(g_USBD_au8SetupPacket[3])
\r
207 /* Get Device Descriptor */
\r
210 u32Len = USBD_Minimum(u32Len, (uint32_t)LEN_DEVICE);
\r
211 USBD_PrepareCtrlIn((uint8_t *)g_USBD_sInfo->gu8DevDesc, u32Len);
\r
214 /* Get Configuration Descriptor */
\r
217 uint32_t u32TotalLen;
\r
219 u32TotalLen = g_USBD_sInfo->gu8ConfigDesc[3];
\r
220 u32TotalLen = g_USBD_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8UL);
\r
222 if(u32Len > u32TotalLen)
\r
224 u32Len = u32TotalLen;
\r
225 if((u32Len % g_USBD_u32CtrlMaxPktSize) == 0UL)
\r
227 g_USBD_u8CtrlInZeroFlag = (uint8_t)1UL;
\r
230 USBD_PrepareCtrlIn((uint8_t *)g_USBD_sInfo->gu8ConfigDesc, u32Len);
\r
233 /* Get BOS Descriptor */
\r
236 uint32_t u32TotalLen;
\r
238 u32TotalLen = g_USBD_sInfo->gu8BosDesc[3];
\r
239 u32TotalLen = g_USBD_sInfo->gu8BosDesc[2] + (u32TotalLen << 8UL);
\r
241 u32Len = USBD_Minimum(u32Len, u32TotalLen);
\r
242 USBD_PrepareCtrlIn((uint8_t *)g_USBD_sInfo->gu8BosDesc, u32Len);
\r
245 /* Get HID Descriptor */
\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
256 /* Get Report Descriptor */
\r
259 if(u32Len > g_USBD_sInfo->gu32HidReportSize[g_USBD_au8SetupPacket[4]])
\r
261 u32Len = g_USBD_sInfo->gu32HidReportSize[g_USBD_au8SetupPacket[4]];
\r
262 if((u32Len % g_USBD_u32CtrlMaxPktSize) == 0UL)
\r
264 g_USBD_u8CtrlInZeroFlag = (uint8_t)1UL;
\r
267 USBD_PrepareCtrlIn((uint8_t *)g_USBD_sInfo->gu8HidReportDesc[g_USBD_au8SetupPacket[4]], u32Len);
\r
270 /* Get String Descriptor */
\r
273 /* Get String Descriptor */
\r
274 if(g_USBD_au8SetupPacket[2] < 4UL)
\r
276 if(u32Len > g_USBD_sInfo->gu8StringDesc[g_USBD_au8SetupPacket[2]][0])
\r
278 u32Len = g_USBD_sInfo->gu8StringDesc[g_USBD_au8SetupPacket[2]][0];
\r
279 if((u32Len % g_USBD_u32CtrlMaxPktSize) == 0UL)
\r
281 g_USBD_u8CtrlInZeroFlag = (uint8_t)1UL;
\r
284 USBD_PrepareCtrlIn((uint8_t *)g_USBD_sInfo->gu8StringDesc[g_USBD_au8SetupPacket[2]], u32Len);
\r
289 /* Not support. Reply STALL. */
\r
290 USBD_SET_EP_STALL(EP0);
\r
291 USBD_SET_EP_STALL(EP1);
\r
296 /* Not support. Reply STALL. */
\r
297 USBD_SET_EP_STALL(EP0);
\r
298 USBD_SET_EP_STALL(EP1);
\r
304 * @brief Process standard request
\r
310 * @details Parse standard request and perform the corresponding action.
\r
313 void USBD_StandardRequest(void)
\r
319 if((__PC() & NS_OFFSET) == NS_OFFSET)
\r
330 /* clear global variables for new request */
\r
331 g_USBD_pu8CtrlInPointer = 0;
\r
332 g_USBD_u32CtrlInSize = 0UL;
\r
334 if((g_USBD_au8SetupPacket[0] & 0x80UL) == 0x80UL) /* request data transfer direction */
\r
336 /* Device to host */
\r
337 switch(g_USBD_au8SetupPacket[1])
\r
339 case GET_CONFIGURATION:
\r
341 /* Return current configuration setting */
\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
348 USBD_PrepareCtrlOut(0, 0UL);
\r
351 case GET_DESCRIPTOR:
\r
353 USBD_GetDescriptor();
\r
354 USBD_PrepareCtrlOut(0, 0UL); /* For status stage */
\r
357 case GET_INTERFACE:
\r
359 /* Return current interface setting */
\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
366 USBD_PrepareCtrlOut(0, 0UL);
\r
372 if(g_USBD_au8SetupPacket[0] == 0x80UL)
\r
376 u8Tmp = (uint8_t)0UL;
\r
377 if((g_USBD_sInfo->gu8ConfigDesc[7] & 0x40UL) == 0x40UL)
\r
379 u8Tmp |= (uint8_t)1UL; /* Self-Powered/Bus-Powered. */
\r
381 if((g_USBD_sInfo->gu8ConfigDesc[7] & 0x20UL) == 0x20UL)
\r
383 u8Tmp |= (uint8_t)(g_USBD_u8RemoteWakeupEn << 1UL); /* Remote wake up */
\r
386 u32Addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
\r
387 M8(u32Addr) = u8Tmp;
\r
391 else if(g_USBD_au8SetupPacket[0] == 0x81UL)
\r
393 u32Addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0);
\r
394 M8(u32Addr) = (uint8_t)0UL;
\r
397 else if(g_USBD_au8SetupPacket[0] == 0x82UL)
\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
404 u32Addr = USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0) + 1UL;
\r
405 M8(u32Addr) = (uint8_t)0UL;
\r
407 USBD_SET_DATA1(EP0);
\r
408 USBD_SET_PAYLOAD_LEN(EP0, 2UL);
\r
410 USBD_PrepareCtrlOut(0, 0UL);
\r
415 /* Setup error, stall the device */
\r
416 USBD_SET_EP_STALL(EP0);
\r
417 USBD_SET_EP_STALL(EP1);
\r
424 /* Host to device */
\r
425 switch(g_USBD_au8SetupPacket[1])
\r
427 case CLEAR_FEATURE:
\r
429 if(g_USBD_au8SetupPacket[2] == FEATURE_ENDPOINT_HALT)
\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
438 if(((pUSBD->EP[i].CFG & 0xFUL) == epNum) && ((g_USBD_u32EpStallLock & (1UL << i)) == 0UL))
\r
440 pUSBD->EP[i].CFGP &= ~USBD_CFGP_SSTALL_Msk;
\r
441 pUSBD->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk;
\r
445 else if(g_USBD_au8SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
\r
447 g_USBD_u8RemoteWakeupEn = (uint8_t)0UL;
\r
451 USBD_SET_DATA1(EP0);
\r
452 USBD_SET_PAYLOAD_LEN(EP0, 0UL);
\r
457 g_USBD_u32UsbAddr = g_USBD_au8SetupPacket[2];
\r
459 /* DATA IN for end of setup */
\r
461 USBD_SET_DATA1(EP0);
\r
462 USBD_SET_PAYLOAD_LEN(EP0, 0UL);
\r
465 case SET_CONFIGURATION:
\r
467 g_USBD_u32UsbConfig = g_USBD_au8SetupPacket[2];
\r
469 if(g_USBD_pfnSetConfigCallback)
\r
471 g_USBD_pfnSetConfigCallback();
\r
474 /* DATA IN for end of setup */
\r
476 USBD_SET_DATA1(EP0);
\r
477 USBD_SET_PAYLOAD_LEN(EP0, 0UL);
\r
482 if((g_USBD_au8SetupPacket[0] & 0xFUL) == 0UL) /* 0: device */
\r
484 if((g_USBD_au8SetupPacket[2] == 3UL) && (g_USBD_au8SetupPacket[3] == 0UL)) /* 3: HNP enable */
\r
486 pOTG->CTL |= (OTG_CTL_HNPREQEN_Msk | OTG_CTL_BUSREQ_Msk);
\r
489 if(g_USBD_au8SetupPacket[2] == FEATURE_ENDPOINT_HALT)
\r
491 USBD_SetStall((uint8_t)(g_USBD_au8SetupPacket[4] & 0xFUL));
\r
493 else if(g_USBD_au8SetupPacket[2] == FEATURE_DEVICE_REMOTE_WAKEUP)
\r
495 g_USBD_u8RemoteWakeupEn = (uint8_t)1UL;
\r
499 USBD_SET_DATA1(EP0);
\r
500 USBD_SET_PAYLOAD_LEN(EP0, 0UL);
\r
503 case SET_INTERFACE:
\r
505 g_USBD_u32UsbAltInterface = g_USBD_au8SetupPacket[2];
\r
506 if(g_USBD_pfnSetInterface != NULL)
\r
508 g_USBD_pfnSetInterface(g_USBD_u32UsbAltInterface);
\r
512 USBD_SET_DATA1(EP0);
\r
513 USBD_SET_PAYLOAD_LEN(EP0, 0UL);
\r
518 /* Setup error, stall the device */
\r
519 USBD_SET_EP_STALL(EP0);
\r
520 USBD_SET_EP_STALL(EP1);
\r
528 * @brief Prepare the first Control IN pipe
\r
530 * @param[in] pu8Buf The pointer of data sent to USB host.
\r
531 * @param[in] u32Size The IN transfer size.
\r
535 * @details Prepare data for Control IN transfer.
\r
538 void USBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size)
\r
542 if(u32Size > g_USBD_u32CtrlMaxPktSize)
\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
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
565 * @brief Repeat Control IN pipe
\r
571 * @details This function processes the remained data of Control IN transfer.
\r
574 void USBD_CtrlIn(void)
\r
578 if(g_USBD_u32CtrlInSize)
\r
580 /* Process remained data */
\r
581 if(g_USBD_u32CtrlInSize > g_USBD_u32CtrlMaxPktSize)
\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
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
600 else /* No more data for IN token */
\r
602 /* In ACK for Set address */
\r
603 if((g_USBD_au8SetupPacket[0] == REQ_STANDARD) && (g_USBD_au8SetupPacket[1] == SET_ADDRESS))
\r
605 u32Addr = USBD_GET_ADDR();
\r
606 if((u32Addr != g_USBD_u32UsbAddr) && (u32Addr == 0UL))
\r
608 USBD_SET_ADDR(g_USBD_u32UsbAddr);
\r
612 /* For the case of data size is integral times maximum packet size */
\r
613 if(g_USBD_u8CtrlInZeroFlag)
\r
615 USBD_SET_PAYLOAD_LEN(EP0, 0UL);
\r
616 g_USBD_u8CtrlInZeroFlag = (uint8_t)0UL;
\r
622 * @brief Prepare the first Control OUT pipe
\r
624 * @param[in] pu8Buf The pointer of data received from USB host.
\r
625 * @param[in] u32Size The OUT transfer size.
\r
629 * @details This function is used to prepare the first Control OUT transfer.
\r
632 void USBD_PrepareCtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
\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
641 * @brief Repeat Control OUT pipe
\r
647 * @details This function processes the successive Control OUT transfer.
\r
650 void USBD_CtrlOut(void)
\r
655 if(g_USBD_u32CtrlOutSize < g_USBD_u32CtrlOutSizeLimit)
\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
663 if(g_USBD_u32CtrlOutSize < g_USBD_u32CtrlOutSizeLimit)
\r
665 USBD_SET_PAYLOAD_LEN(EP1, g_USBD_u32CtrlMaxPktSize);
\r
671 * @brief Reset software flags
\r
677 * @details This function resets all variables for protocol and resets USB device address to 0.
\r
680 void USBD_SwReset(void)
\r
685 if((__PC() & NS_OFFSET) == NS_OFFSET)
\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
703 /* Reset PID DATA0 */
\r
704 for(i = 0UL; i < USBD_MAX_EP; i++)
\r
706 pUSBD->EP[i].CFG &= ~USBD_CFG_DSQSYNC_Msk;
\r
709 /* Reset USB device address */
\r
710 USBD_SET_ADDR(0UL);
\r
714 * @brief USBD Set Vendor Request
\r
716 * @param[in] pfnVendorReq Vendor Request Callback Function
\r
720 * @details This function is used to set USBD vendor request callback function
\r
722 void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)
\r
724 g_USBD_pfnVendorRequest = pfnVendorReq;
\r
728 * @brief The callback function which called when get SET CONFIGURATION request
\r
730 * @param[in] pfnSetConfigCallback Callback function pointer for SET CONFIGURATION request
\r
734 * @details This function is used to set the callback function which will be called at SET CONFIGURATION request.
\r
736 void USBD_SetConfigCallback(SET_CONFIG_CB pfnSetConfigCallback)
\r
738 g_USBD_pfnSetConfigCallback = pfnSetConfigCallback;
\r
743 * @brief EP stall lock function to avoid stall clear by USB SET FEATURE request.
\r
745 * @param[in] u32EpBitmap Use bitmap to select which endpoints will be locked
\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
752 void USBD_LockEpStall(uint32_t u32EpBitmap)
\r
754 g_USBD_u32EpStallLock = u32EpBitmap;
\r
757 /*@}*/ /* end of group USBD_EXPORTED_FUNCTIONS */
\r
759 /*@}*/ /* end of group USBD_Driver */
\r
761 /*@}*/ /* end of group Standard_Driver */
\r
767 /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/
\r