NUC472_NUC442_BSP V3.03.004
The Board Support Package for NUC472/NUC442
usbd.c
Go to the documentation of this file.
1/**************************************************************************/
12#include "NUC472_442.h"
13
27/*--------------------------------------------------------------------------*/
29S_USBD_CMD_T gUsbCmd;
30S_USBD_INFO_T *g_usbd_sInfo;
31
32VENDOR_REQ g_usbd_pfnVendorRequest = NULL;
33CLASS_REQ g_usbd_pfnClassRequest = NULL;
34SET_INTERFACE_REQ g_usbd_pfnSetInterface = NULL;
35uint32_t g_u32EpStallLock = 0;
37static uint8_t *g_usbd_CtrlInPointer = 0;
38static uint32_t g_usbd_CtrlMaxPktSize = 64;
39static uint8_t g_usbd_UsbConfig = 0;
40static uint8_t g_usbd_UsbAltInterface = 0;
41static uint8_t g_usbd_EnableTestMode = 0;
42static uint8_t g_usbd_TestSelector = 0;
43
44#ifdef __ICCARM__
45#pragma data_alignment=4
46static uint8_t g_usbd_buf[12];
47#else
48static uint8_t g_usbd_buf[12] __attribute__((aligned(4)));
49#endif
50
51
52uint8_t g_usbd_Configured = 0;
53uint8_t g_usbd_CtrlZero = 0;
54uint8_t g_usbd_UsbAddr = 0;
55uint8_t g_usbd_ShortPacket = 0;
56uint32_t volatile g_usbd_DmaDone = 0;
57uint32_t g_usbd_CtrlInSize = 0;
59
70void USBD_Open(S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
71{
72 g_usbd_sInfo = param;
73 g_usbd_pfnClassRequest = pfnClassReq;
74 g_usbd_pfnSetInterface = pfnSetInterface;
75
76 /* get EP0 maximum packet size */
77 g_usbd_CtrlMaxPktSize = g_usbd_sInfo->gu8DevDesc[7];
78
79 /* Initial USB engine */
80 /* Enable PHY */
82 /* wait PHY clock ready */
83 while (1)
84 {
85 USBD->EP[EPA].EPMPS = 0x20;
86 if (USBD->EP[EPA].EPMPS == 0x20)
87 break;
88 }
89 /* Force SE0, and then clear it to connect*/
91}
92
102void USBD_Start(void)
103{
104 USBD_CLR_SE0();
105}
106
117{
118 // Setup packet process
119 gUsbCmd.bmRequestType = (uint8_t)(USBD->SETUP1_0 & 0xff);
120 gUsbCmd.bRequest = (int8_t)(USBD->SETUP1_0 >> 8) & 0xff;
121 gUsbCmd.wValue = (uint16_t)USBD->SETUP3_2;
122 gUsbCmd.wIndex = (uint16_t)USBD->SETUP5_4;
123 gUsbCmd.wLength = (uint16_t)USBD->SETUP7_6;
124
125 /* USB device request in setup packet: offset 0, D[6..5]: 0=Standard, 1=Class, 2=Vendor, 3=Reserved */
126 switch (gUsbCmd.bmRequestType & 0x60)
127 {
128 case REQ_STANDARD: // Standard
129 {
131 break;
132 }
133 case REQ_CLASS: // Class
134 {
135 if (g_usbd_pfnClassRequest != NULL)
136 {
137 g_usbd_pfnClassRequest();
138 }
139 break;
140 }
141 case REQ_VENDOR: // Vendor
142 {
143 if (g_usbd_pfnVendorRequest != NULL)
144 {
145 g_usbd_pfnVendorRequest();
146 }
147 break;
148 }
149 default: // reserved
150 {
151 /* Setup error, stall the device */
153 break;
154 }
155 }
156}
157
168{
169 uint32_t u32Len;
170
171 u32Len = gUsbCmd.wLength;
172 g_usbd_CtrlZero = 0;
173
174 switch ((gUsbCmd.wValue & 0xff00) >> 8)
175 {
176 // Get Device Descriptor
177 case DESC_DEVICE:
178 {
179 u32Len = Minimum(u32Len, LEN_DEVICE);
180 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8DevDesc, u32Len);
181 break;
182 }
183 // Get Configuration Descriptor
184 case DESC_CONFIG:
185 {
186 uint32_t u32TotalLen;
187
188 u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[3];
189 u32TotalLen = g_usbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);
190
191 u32Len = Minimum(u32Len, u32TotalLen);
192 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0)
193 g_usbd_CtrlZero = 1;
194
195 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8ConfigDesc, u32Len);
196 break;
197 }
198 // Get Qualifier Descriptor
199 case DESC_QUALIFIER:
200 {
201 u32Len = Minimum(u32Len, LEN_QUALIFIER);
202 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8QualDesc, u32Len);
203 break;
204 }
205 // Get Other Speed Descriptor - Full speed
206 case DESC_OTHERSPEED:
207 {
208 uint32_t u32TotalLen;
209
210 u32TotalLen = g_usbd_sInfo->gu8OtherConfigDesc[3];
211 u32TotalLen = g_usbd_sInfo->gu8OtherConfigDesc[2] + (u32TotalLen << 8);
212
213 u32Len = Minimum(u32Len, u32TotalLen);
214 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0)
215 g_usbd_CtrlZero = 1;
216
217 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8OtherConfigDesc, u32Len);
218 break;
219 }
220 // Get HID Descriptor
221 case DESC_HID:
222 {
223 u32Len = Minimum(u32Len, LEN_HID);
224 USBD_MemCopy(g_usbd_buf, (uint8_t *)&g_usbd_sInfo->gu8ConfigDesc[LEN_CONFIG+LEN_INTERFACE], u32Len);
225 USBD_PrepareCtrlIn(g_usbd_buf, u32Len);
226 break;
227 }
228 // Get Report Descriptor
229 case DESC_HID_RPT:
230 {
231 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0)
232 g_usbd_CtrlZero = 1;
233
234 u32Len = Minimum(u32Len, g_usbd_sInfo->gu32HidReportSize[gUsbCmd.wIndex & 0xff]);
235 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8HidReportDesc[gUsbCmd.wIndex & 0xff], u32Len);
236 break;
237 }
238 // Get String Descriptor
239 case DESC_STRING:
240 {
241 // Get String Descriptor
242 if((gUsbCmd.wValue & 0xff) < 4)
243 {
244 u32Len = Minimum(u32Len, g_usbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xff][0]);
245 if ((u32Len % g_usbd_CtrlMaxPktSize) == 0)
246 g_usbd_CtrlZero = 1;
247 USBD_PrepareCtrlIn((uint8_t *)g_usbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xff], u32Len);
248 }
249 else
250 {
252 return 1;
253 }
254 break;
255 }
256 default:
257 // Not support. Reply STALL.
259 return 1;
260 }
261 return 0;
262}
263
264
275{
276 /* clear global variables for new request */
277 g_usbd_CtrlInPointer = 0;
278 g_usbd_CtrlInSize = 0;
279
280 if (gUsbCmd.bmRequestType & 0x80) /* request data transfer direction */
281 {
282 // Device to host
283 switch (gUsbCmd.bRequest)
284 {
285 case GET_CONFIGURATION:
286 {
287 // Return current configuration setting
288 USBD_PrepareCtrlIn((uint8_t *)&g_usbd_UsbConfig, 1);
289
292 break;
293 }
294 case GET_DESCRIPTOR:
295 {
296 if (!USBD_GetDescriptor())
297 {
300 }
301 break;
302 }
303 case GET_INTERFACE:
304 {
305 // Return current interface setting
306 USBD_PrepareCtrlIn((uint8_t *)&g_usbd_UsbAltInterface, 1);
307
310 break;
311 }
312 case GET_STATUS:
313 {
314 // Device
315 if (gUsbCmd.bmRequestType == 0x80)
316 {
317 if (g_usbd_sInfo->gu8ConfigDesc[7] & 0x40)
318 g_usbd_buf[0] = 1; // Self-Powered
319 else
320 g_usbd_buf[0] = 0; // bus-Powered
321 }
322 // Interface
323 else if (gUsbCmd.bmRequestType == 0x81)
324 g_usbd_buf[0] = 0;
325 // Endpoint
326 else if (gUsbCmd.bmRequestType == 0x82)
327 {
328 uint8_t ep = gUsbCmd.wIndex & 0xF;
329 g_usbd_buf[0] = USBD_GetStall(ep)? 1 : 0;
330 }
331 g_usbd_buf[1] = 0;
332 USBD_PrepareCtrlIn(g_usbd_buf, 2);
335 break;
336 }
337 default:
338 {
339 /* Setup error, stall the device */
341 break;
342 }
343 }
344 }
345 else
346 {
347 // Host to device
348 switch (gUsbCmd.bRequest)
349 {
350 case CLEAR_FEATURE:
351 {
352 if((gUsbCmd.wValue & 0xff) == FEATURE_ENDPOINT_HALT)
353 {
354
355 int32_t epNum, i;
356
357 /* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
358 a flag: g_u32EpStallLock is added to support it */
359 epNum = gUsbCmd.wIndex & 0xF;
360 for (i=0; i<USBD_MAX_EP; i++)
361 {
362 if ((((USBD->EP[i].EPCFG & 0xf0) >> 4) == epNum) && ((g_u32EpStallLock & (1 << i)) == 0))
363 {
364 USBD->EP[i].EPRSPCTL = (USBD->EP[i].EPRSPCTL & 0xef) | USB_EP_RSPCTL_TOGGLE;
365 }
366 }
367 }
368 /* Status stage */
372 break;
373 }
374 case SET_ADDRESS:
375 {
376 g_usbd_UsbAddr = (uint8_t)gUsbCmd.wValue;
377
378 // DATA IN for end of setup
379 /* Status Stage */
383 break;
384 }
385 case SET_CONFIGURATION:
386 {
387 g_usbd_UsbConfig = (uint8_t)gUsbCmd.wValue;
388 g_usbd_Configured = 1;
389 // DATA IN for end of setup
390 /* Status stage */
394 break;
395 }
396 case SET_FEATURE:
397 {
398 if ((gUsbCmd.wValue & 0x3) == 2) /* TEST_MODE*/
399 {
400 g_usbd_EnableTestMode = 1;
401 g_usbd_TestSelector = gUsbCmd.wIndex >> 8;
402 }
403 /* Status stage */
407 break;
408 }
409 case SET_INTERFACE:
410 {
411 g_usbd_UsbAltInterface = (uint8_t)gUsbCmd.wValue;
412 if (g_usbd_pfnSetInterface != NULL)
413 g_usbd_pfnSetInterface(g_usbd_UsbAltInterface);
414 /* Status stage */
418 break;
419 }
420 default:
421 {
422 /* Setup error, stall the device */
424 break;
425 }
426 }
427 }
428}
429
440#define TEST_J 0x01
441#define TEST_K 0x02
442#define TEST_SE0_NAK 0x03
443#define TEST_PACKET 0x04
444#define TEST_FORCE_ENABLE 0x05
447{
448 switch (gUsbCmd.bRequest)
449 {
450 case SET_ADDRESS:
451 {
452 USBD_SET_ADDR(g_usbd_UsbAddr);
453 break;
454 }
455 case SET_CONFIGURATION:
456 {
457 if (g_usbd_UsbConfig == 0)
458 {
459 int volatile i;
460 /* Reset PID DATA0 */
461 for (i=0; i<USBD_MAX_EP; i++)
462 {
463 if (USBD->EP[i].EPCFG & 0x1)
464 {
465 USBD->EP[i].EPRSPCTL = USB_EP_RSPCTL_TOGGLE;
466 }
467 }
468 }
469 break;
470 }
471 case SET_FEATURE:
472 {
473 if(gUsbCmd.wValue == FEATURE_ENDPOINT_HALT)
474 USBD_SetStall(gUsbCmd.wIndex & 0xF);
475 else if (g_usbd_EnableTestMode)
476 {
477 g_usbd_EnableTestMode = 0;
478 if (g_usbd_TestSelector == TEST_J)
479 USBD->TEST = TEST_J;
480 else if (g_usbd_TestSelector == TEST_K)
481 USBD->TEST = TEST_K;
482 else if (g_usbd_TestSelector == TEST_SE0_NAK)
483 USBD->TEST = TEST_SE0_NAK;
484 else if (g_usbd_TestSelector == TEST_PACKET)
485 USBD->TEST = TEST_PACKET;
486 else if (g_usbd_TestSelector == TEST_FORCE_ENABLE)
487 USBD->TEST = TEST_FORCE_ENABLE;
488 }
489 break;
490 }
491 case CLEAR_FEATURE:
492 {
493 if(gUsbCmd.wValue == FEATURE_ENDPOINT_HALT)
494 USBD_ClearStall(gUsbCmd.wIndex & 0xF);
495 break;
496 }
497 default:
498 ;
499 }
500}
501
502
513void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size)
514{
515 g_usbd_CtrlInPointer = pu8Buf;
516 g_usbd_CtrlInSize = u32Size;
517}
518
519
520
530void USBD_CtrlIn(void)
531{
532 int volatile i;
533 uint32_t volatile count;
534
535 // Process remained data
536 if(g_usbd_CtrlInSize >= g_usbd_CtrlMaxPktSize)
537 {
538 // Data size > MXPLD
539 for (i=0; i<(g_usbd_CtrlMaxPktSize >> 2); i++, g_usbd_CtrlInPointer+=4)
540 USBD->CEPDAT = *(uint32_t *)g_usbd_CtrlInPointer;
541 USBD_START_CEP_IN(g_usbd_CtrlMaxPktSize);
542 g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
543 }
544 else
545 {
546 // Data size <= MXPLD
547 for (i=0; i<(g_usbd_CtrlInSize >> 2); i++, g_usbd_CtrlInPointer+=4)
548 USBD->CEPDAT = *(uint32_t *)g_usbd_CtrlInPointer;
549
550 count = g_usbd_CtrlInSize % 4;
551 for (i=0; i<count; i++)
552 USBD->CEPDAT_BYTE = *(uint8_t *)(g_usbd_CtrlInPointer + i);
553
554 USBD_START_CEP_IN(g_usbd_CtrlInSize);
555 g_usbd_CtrlInPointer = 0;
556 g_usbd_CtrlInSize = 0;
557 }
558}
559
570void USBD_CtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
571{
572 int volatile i;
573
574 while(1)
575 {
576 if (USBD->CEPINTSTS & USBD_CEPINTSTS_RXPKIF_Msk)
577 {
578 for (i=0; i<u32Size; i++)
579 *(uint8_t *)(pu8Buf + i) = USBD->CEPDAT_BYTE;
580 USBD->CEPINTSTS = USBD_CEPINTSTS_RXPKIF_Msk;
581 break;
582 }
583 }
584}
585
595void USBD_SwReset(void)
596{
597 // Reset all variables for protocol
598 g_usbd_UsbAddr = 0;
599 g_usbd_DmaDone = 0;
600 g_usbd_ShortPacket = 0;
601 g_usbd_Configured = 0;
602
603 // Reset USB device address
604 USBD_SET_ADDR(0);
605}
606
617{
618 g_usbd_pfnVendorRequest = pfnVendorReq;
619}
620
621 /* end of group NUC472_442_GPIO_EXPORTED_FUNCTIONS */
623 /* end of group NUC472_442_GPIO_Driver */
625 /* end of group NUC472_442_Device_Driver */
627
628/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
void *__dso_handle __attribute__((weak))
Definition: _syscalls.c:35
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
#define USBD_CEPINTSTS_RXPKIF_Msk
Definition: NUC472_442.h:28200
#define USBD_CEPCTL_STALLEN_Msk
Definition: NUC472_442.h:28134
#define USBD_CEPINTSTS_INTKIF_Msk
Definition: NUC472_442.h:28191
#define USBD_CEPINTEN_STSDONEIEN_Msk
Definition: NUC472_442.h:28173
#define USBD_CEPINTSTS_STSDONEIF_Msk
Definition: NUC472_442.h:28212
#define USBD_CEPINTEN_INTKIEN_Msk
Definition: NUC472_442.h:28152
#define USBD
Definition: NUC472_442.h:28835
#define USB_CEPCTL_NAKCLR
Definition: usbd.h:108
#define USB_EP_RSPCTL_TOGGLE
Definition: usbd.h:119
static __INLINE void USBD_ClearStall(uint32_t u32EpNum)
Clear USB endpoint stall state.
Definition: usbd.h:344
void USBD_StandardRequest(void)
Process USB standard request.
Definition: usbd.c:274
void(* VENDOR_REQ)(void)
Definition: usbd.h:394
void USBD_UpdateDeviceState(void)
Update Device State.
Definition: usbd.c:446
uint8_t bmRequestType
Definition: usbd.h:144
uint8_t ** gu8StringDesc
Definition: usbd.h:159
uint8_t ** gu8HidReportDesc
Definition: usbd.h:162
uint32_t * gu32HidReportSize
Definition: usbd.h:163
uint16_t wIndex
Definition: usbd.h:147
static __INLINE uint32_t USBD_GetStall(uint32_t u32EpNum)
Get USB endpoint stall state.
Definition: usbd.h:378
uint8_t * gu8OtherConfigDesc
Definition: usbd.h:161
void(* CLASS_REQ)(void)
Definition: usbd.h:395
void USBD_Start(void)
USBD Start.
Definition: usbd.c:102
void USBD_SwReset(void)
Clear all software flags.
Definition: usbd.c:595
uint16_t wLength
Definition: usbd.h:148
uint8_t bRequest
Definition: usbd.h:145
static __INLINE void USBD_MemCopy(uint8_t *u8Dst, uint8_t *u8Src, int32_t i32Size)
USBD_memcpy, Copy bytes hardware limitation.
Definition: usbd.h:226
void USBD_PrepareCtrlIn(uint8_t *pu8Buf, uint32_t u32Size)
Prepare Control IN transaction.
Definition: usbd.c:513
uint8_t * gu8ConfigDesc
Definition: usbd.h:158
void USBD_CtrlIn(void)
Start Control IN transfer.
Definition: usbd.c:530
static __INLINE void USBD_SetStall(uint32_t u32EpNum)
Set USB endpoint stall state.
Definition: usbd.h:307
void USBD_SetVendorRequest(VENDOR_REQ pfnVendorReq)
USBD Set Vendor Request.
Definition: usbd.c:616
uint8_t * gu8DevDesc
Definition: usbd.h:157
void USBD_ProcessSetupPacket(void)
Process Setup Packet.
Definition: usbd.c:116
uint8_t * gu8QualDesc
Definition: usbd.h:160
void USBD_Open(S_USBD_INFO_T *param, CLASS_REQ pfnClassReq, SET_INTERFACE_REQ pfnSetInterface)
USBD Initial.
Definition: usbd.c:70
void USBD_CtrlOut(uint8_t *pu8Buf, uint32_t u32Size)
Start Control OUT transaction.
Definition: usbd.c:570
void(* SET_INTERFACE_REQ)(uint32_t u32AltInterface)
Definition: usbd.h:396
int USBD_GetDescriptor(void)
Get Descriptor request.
Definition: usbd.c:167
uint16_t wValue
Definition: usbd.h:146
#define USBD_SET_SE0()
Definition: usbd.h:191
#define USBD_ENABLE_CEP_INT(intr)
Definition: usbd.h:199
#define USBD_START_CEP_IN(size)
Definition: usbd.h:202
#define USBD_SET_ADDR(addr)
Definition: usbd.h:193
#define USBD_CLR_SE0()
Definition: usbd.h:192
#define USBD_ENABLE_PHY()
Definition: usbd.h:189
#define USBD_SET_CEP_STATE(flag)
Definition: usbd.h:201
#define USBD_CLR_CEP_INT_FLAG(flag)
Definition: usbd.h:200
#define NULL
NULL pointer.
Definition: NUC472_442.h:29018