1 /**************************************************************************//**
2 * @file hsusbd.c
3 * @version V1.00
4 * @brief M480 HSUSBD driver source file
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include <stdio.h>
10 #include "NuMicro.h"
11
12 /** @addtogroup Standard_Driver Standard Driver
13 @{
14 */
15
16 /** @addtogroup HSUSBD_Driver HSUSBD Driver
17 @{
18 */
19
20
21 /** @addtogroup HSUSBD_EXPORTED_FUNCTIONS HSUSBD Exported Functions
22 @{
23 */
24 /*--------------------------------------------------------------------------*/
25 /** @cond HIDDEN_SYMBOLS */
26 /* Global variables for Control Pipe */
27 S_HSUSBD_CMD_T gUsbCmd;
28 S_HSUSBD_INFO_T *g_hsusbd_sInfo;
29
30 HSUSBD_VENDOR_REQ g_hsusbd_pfnVendorRequest = NULL;
31 HSUSBD_CLASS_REQ g_hsusbd_pfnClassRequest = NULL;
32 HSUSBD_SET_INTERFACE_REQ g_hsusbd_pfnSetInterface = NULL;
33 uint32_t g_u32HsEpStallLock = 0ul; /* Bit map flag to lock specified EP when SET_FEATURE */
34
35 static uint8_t *g_hsusbd_CtrlInPointer = 0;
36 static uint32_t g_hsusbd_CtrlMaxPktSize = 64ul;
37 static uint8_t g_hsusbd_UsbConfig = 0ul;
38 static uint8_t g_hsusbd_UsbAltInterface = 0ul;
39 static uint8_t g_hsusbd_EnableTestMode = 0ul;
40 static uint8_t g_hsusbd_TestSelector = 0ul;
41
42 #ifdef __ICCARM__
43 #pragma data_alignment=4
44 static uint8_t g_hsusbd_buf[12];
45 #else
46 static uint8_t g_hsusbd_buf[12] __attribute__((aligned(4)));
47 #endif
48
49 uint8_t volatile g_hsusbd_Configured = 0ul;
50 uint8_t g_hsusbd_CtrlZero = 0ul;
51 uint8_t g_hsusbd_UsbAddr = 0ul;
52 uint8_t g_hsusbd_ShortPacket = 0ul;
53 uint32_t volatile g_hsusbd_DmaDone = 0ul;
54 uint32_t g_hsusbd_CtrlInSize = 0ul;
55 /** @endcond HIDDEN_SYMBOLS */
56
57 /**
58 * @brief HSUSBD Initial
59 *
60 * @param[in] param Descriptor
61 * @param[in] pfnClassReq Class Request Callback Function
62 * @param[in] pfnSetInterface SetInterface Request Callback Function
63 *
64 * @return None
65 *
66 * @details This function is used to initial HSUSBD.
67 */
HSUSBD_Open(S_HSUSBD_INFO_T * param,HSUSBD_CLASS_REQ pfnClassReq,HSUSBD_SET_INTERFACE_REQ pfnSetInterface)68 void HSUSBD_Open(S_HSUSBD_INFO_T *param, HSUSBD_CLASS_REQ pfnClassReq, HSUSBD_SET_INTERFACE_REQ pfnSetInterface)
69 {
70 g_hsusbd_sInfo = param;
71 g_hsusbd_pfnClassRequest = pfnClassReq;
72 g_hsusbd_pfnSetInterface = pfnSetInterface;
73
74 /* get EP0 maximum packet size */
75 g_hsusbd_CtrlMaxPktSize = g_hsusbd_sInfo->gu8DevDesc[7];
76
77 /* Initial USB engine */
78 HSUSBD->PHYCTL |= (HSUSBD_PHYCTL_PHYEN_Msk | HSUSBD_PHYCTL_DPPUEN_Msk);
79 /* wait PHY clock ready */
80 while (1)
81 {
82 HSUSBD->EP[EPA].EPMPS = 0x20ul;
83 if (HSUSBD->EP[EPA].EPMPS == 0x20ul)
84 {
85 break;
86 }
87 }
88 /* Force SE0, and then clear it to connect*/
89 HSUSBD_SET_SE0();
90 }
91
92 /**
93 * @brief HSUSBD Start
94 *
95 * @param[in] None
96 *
97 * @return None
98 *
99 * @details This function is used to start transfer
100 */
HSUSBD_Start(void)101 void HSUSBD_Start(void)
102 {
103 HSUSBD_CLR_SE0();
104 }
105
106 /**
107 * @brief Process Setup Packet
108 *
109 * @param[in] None
110 *
111 * @return None
112 *
113 * @details This function is used to process Setup packet.
114 */
HSUSBD_ProcessSetupPacket(void)115 void HSUSBD_ProcessSetupPacket(void)
116 {
117 /* Setup packet process */
118 gUsbCmd.bmRequestType = (uint8_t)(HSUSBD->SETUP1_0 & 0xfful);
119 gUsbCmd.bRequest = (uint8_t)((HSUSBD->SETUP1_0 >> 8) & 0xfful);
120 gUsbCmd.wValue = (uint16_t)HSUSBD->SETUP3_2;
121 gUsbCmd.wIndex = (uint16_t)HSUSBD->SETUP5_4;
122 gUsbCmd.wLength = (uint16_t)HSUSBD->SETUP7_6;
123
124 /* USB device request in setup packet: offset 0, D[6..5]: 0=Standard, 1=Class, 2=Vendor, 3=Reserved */
125 switch (gUsbCmd.bmRequestType & 0x60ul)
126 {
127 case REQ_STANDARD:
128 {
129 HSUSBD_StandardRequest();
130 break;
131 }
132 case REQ_CLASS:
133 {
134 if (g_hsusbd_pfnClassRequest != NULL)
135 {
136 g_hsusbd_pfnClassRequest();
137 }
138 break;
139 }
140 case REQ_VENDOR:
141 {
142 if (g_hsusbd_pfnVendorRequest != NULL)
143 {
144 g_hsusbd_pfnVendorRequest();
145 }
146 break;
147 }
148 default:
149 {
150 /* Setup error, stall the device */
151 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
152 break;
153 }
154 }
155 }
156
157 /**
158 * @brief Get Descriptor request
159 *
160 * @param[in] None
161 *
162 * @return None
163 *
164 * @details This function is used to process GetDescriptor request.
165 */
HSUSBD_GetDescriptor(void)166 int HSUSBD_GetDescriptor(void)
167 {
168 uint32_t u32Len;
169 int val = 0;
170
171 u32Len = gUsbCmd.wLength;
172 g_hsusbd_CtrlZero = (uint8_t)0ul;
173
174 switch ((gUsbCmd.wValue & 0xff00ul) >> 8)
175 {
176 /* Get Device Descriptor */
177 case DESC_DEVICE:
178 {
179 u32Len = Minimum(u32Len, LEN_DEVICE);
180 HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8DevDesc, u32Len);
181 break;
182 }
183 /* Get Configuration Descriptor */
184 case DESC_CONFIG:
185 {
186 uint32_t u32TotalLen;
187 if ((HSUSBD->OPER & 0x04ul) == 0x04ul)
188 {
189 u32TotalLen = g_hsusbd_sInfo->gu8ConfigDesc[3];
190 u32TotalLen = g_hsusbd_sInfo->gu8ConfigDesc[2] + (u32TotalLen << 8);
191
192 if (u32Len > u32TotalLen)
193 {
194 u32Len = u32TotalLen;
195 if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul)
196 {
197 g_hsusbd_CtrlZero = (uint8_t)1ul;
198 }
199 }
200 HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8ConfigDesc, u32Len);
201 }
202 else
203 {
204 u32TotalLen = g_hsusbd_sInfo->gu8FullConfigDesc[3];
205 u32TotalLen = g_hsusbd_sInfo->gu8FullConfigDesc[2] + (u32TotalLen << 8);
206
207 if (u32Len > u32TotalLen)
208 {
209 u32Len = u32TotalLen;
210 if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul)
211 {
212 g_hsusbd_CtrlZero = (uint8_t)1ul;
213 }
214 }
215 HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8FullConfigDesc, u32Len);
216 }
217
218 break;
219 }
220 /* Get Qualifier Descriptor */
221 case DESC_QUALIFIER:
222 {
223 u32Len = Minimum(u32Len, LEN_QUALIFIER);
224 HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8QualDesc, u32Len);
225 break;
226 }
227 /* Get Other Speed Descriptor - Full speed */
228 case DESC_OTHERSPEED:
229 {
230 uint32_t u32TotalLen;
231 if ((HSUSBD->OPER & 0x04ul) == 0x04ul)
232 {
233 u32TotalLen = g_hsusbd_sInfo->gu8HSOtherConfigDesc[3];
234 u32TotalLen = g_hsusbd_sInfo->gu8HSOtherConfigDesc[2] + (u32TotalLen << 8);
235
236 if (u32Len > u32TotalLen)
237 {
238 u32Len = u32TotalLen;
239 if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul)
240 {
241 g_hsusbd_CtrlZero = (uint8_t)1ul;
242 }
243 }
244 HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8HSOtherConfigDesc, u32Len);
245 }
246 else
247 {
248 u32TotalLen = g_hsusbd_sInfo->gu8FSOtherConfigDesc[3];
249 u32TotalLen = g_hsusbd_sInfo->gu8FSOtherConfigDesc[2] + (u32TotalLen << 8);
250
251 if (u32Len > u32TotalLen)
252 {
253 u32Len = u32TotalLen;
254 if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul)
255 {
256 g_hsusbd_CtrlZero = (uint8_t)1ul;
257 }
258 }
259 HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8FSOtherConfigDesc, u32Len);
260 }
261
262 break;
263 }
264 /* Get HID Descriptor */
265 case DESC_HID:
266 {
267 uint32_t u32ConfigDescOffset; /* u32ConfigDescOffset is configuration descriptor offset (HID descriptor start index) */
268 u32Len = Minimum(u32Len, LEN_HID);
269 u32ConfigDescOffset = g_hsusbd_sInfo->gu32ConfigHidDescIdx[gUsbCmd.wIndex & 0xfful];
270 HSUSBD_PrepareCtrlIn((uint8_t *)&g_hsusbd_sInfo->gu8ConfigDesc[u32ConfigDescOffset], u32Len);
271 break;
272 }
273 /* Get Report Descriptor */
274 case DESC_HID_RPT:
275 {
276 if (u32Len > g_hsusbd_sInfo->gu32HidReportSize[gUsbCmd.wIndex & 0xfful])
277 {
278 u32Len = g_hsusbd_sInfo->gu32HidReportSize[gUsbCmd.wIndex & 0xfful];
279 if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul)
280 {
281 g_hsusbd_CtrlZero = (uint8_t)1ul;
282 }
283 }
284 HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8HidReportDesc[gUsbCmd.wIndex & 0xfful], u32Len);
285 break;
286 }
287 /* Get String Descriptor */
288 case DESC_STRING:
289 {
290 if((gUsbCmd.wValue & 0xfful) < 8ul)
291 {
292 if (u32Len > g_hsusbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xfful][0])
293 {
294 u32Len = g_hsusbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xfful][0];
295 if ((u32Len % g_hsusbd_CtrlMaxPktSize) == 0ul)
296 {
297 g_hsusbd_CtrlZero = (uint8_t)1ul;
298 }
299 }
300 HSUSBD_PrepareCtrlIn((uint8_t *)g_hsusbd_sInfo->gu8StringDesc[gUsbCmd.wValue & 0xfful], u32Len);
301 }
302 else
303 {
304 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
305 val = 1;
306 }
307 break;
308 }
309 default:
310 /* Not support. Reply STALL. */
311 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
312 val = 1;
313 break;
314 }
315 return val;
316 }
317
318
319 /**
320 * @brief Process USB standard request
321 *
322 * @param[in] None
323 *
324 * @return None
325 *
326 * @details This function is used to process USB Standard Request.
327 */
HSUSBD_StandardRequest(void)328 void HSUSBD_StandardRequest(void)
329 {
330 /* clear global variables for new request */
331 g_hsusbd_CtrlInPointer = 0;
332 g_hsusbd_CtrlInSize = 0ul;
333
334 if ((gUsbCmd.bmRequestType & 0x80ul) == 0x80ul) /* request data transfer direction */
335 {
336 /* Device to host */
337 switch (gUsbCmd.bRequest)
338 {
339 case GET_CONFIGURATION:
340 {
341 /* Return current configuration setting */
342 HSUSBD_PrepareCtrlIn((uint8_t *)&g_hsusbd_UsbConfig, 1ul);
343
344 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
345 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
346 break;
347 }
348 case GET_DESCRIPTOR:
349 {
350 if (!HSUSBD_GetDescriptor())
351 {
352 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
353 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
354 }
355 break;
356 }
357 case GET_INTERFACE:
358 {
359 /* Return current interface setting */
360 HSUSBD_PrepareCtrlIn((uint8_t *)&g_hsusbd_UsbAltInterface, 1ul);
361
362 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
363 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
364 break;
365 }
366 case GET_STATUS:
367 {
368 /* Device */
369 if (gUsbCmd.bmRequestType == 0x80ul)
370 {
371 if ((g_hsusbd_sInfo->gu8ConfigDesc[7] & 0x40ul) == 0x40ul)
372 {
373 g_hsusbd_buf[0] = (uint8_t)1ul; /* Self-Powered */
374 }
375 else
376 {
377 g_hsusbd_buf[0] = (uint8_t)0ul; /* bus-Powered */
378 }
379 }
380 /* Interface */
381 else if (gUsbCmd.bmRequestType == 0x81ul)
382 {
383 g_hsusbd_buf[0] = (uint8_t)0ul;
384 }
385 /* Endpoint */
386 else if (gUsbCmd.bmRequestType == 0x82ul)
387 {
388 uint8_t ep = (uint8_t)(gUsbCmd.wIndex & 0xFul);
389 g_hsusbd_buf[0] = (uint8_t)HSUSBD_GetStall((uint32_t)ep)? (uint8_t)1 : (uint8_t)0;
390 }
391 g_hsusbd_buf[1] = (uint8_t)0ul;
392 HSUSBD_PrepareCtrlIn(g_hsusbd_buf, 2ul);
393 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk);
394 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk);
395 break;
396 }
397 default:
398 {
399 /* Setup error, stall the device */
400 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
401 break;
402 }
403 }
404 }
405 else
406 {
407 /* Host to device */
408 switch (gUsbCmd.bRequest)
409 {
410 case CLEAR_FEATURE:
411 {
412 if((gUsbCmd.wValue & 0xfful) == FEATURE_ENDPOINT_HALT)
413 {
414
415 uint32_t epNum, i;
416
417 /* EP number stall is not allow to be clear in MSC class "Error Recovery Test".
418 a flag: g_u32HsEpStallLock is added to support it */
419 epNum = (uint32_t)(gUsbCmd.wIndex & 0xFul);
420 for (i=0ul; i<HSUSBD_MAX_EP; i++)
421 {
422 if ((((HSUSBD->EP[i].EPCFG & 0xf0ul) >> 4) == epNum) && ((g_u32HsEpStallLock & (1ul << i)) == 0ul))
423 {
424 HSUSBD->EP[i].EPRSPCTL = (HSUSBD->EP[i].EPRSPCTL & 0xeful) | HSUSBD_EP_RSPCTL_TOGGLE;
425 }
426 }
427 }
428 /* Status stage */
429 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
430 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
431 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
432 break;
433 }
434 case SET_ADDRESS:
435 {
436 g_hsusbd_UsbAddr = (uint8_t)gUsbCmd.wValue;
437 /* Status Stage */
438 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
439 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
440 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
441 break;
442 }
443 case SET_CONFIGURATION:
444 {
445 g_hsusbd_UsbConfig = (uint8_t)gUsbCmd.wValue;
446 g_hsusbd_Configured = (uint8_t)1ul;
447 /* Status stage */
448 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
449 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
450 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
451 break;
452 }
453 case SET_FEATURE:
454 {
455 if ((gUsbCmd.wValue & 0x3ul) == 2ul) /* TEST_MODE */
456 {
457 g_hsusbd_EnableTestMode = (uint8_t)1ul;
458 g_hsusbd_TestSelector = (uint8_t)(gUsbCmd.wIndex >> 8);
459 }
460 if ((gUsbCmd.wValue & 0x3ul) == 3ul) /* HNP ebable */
461 {
462 HSOTG->CTL |= (HSOTG_CTL_HNPREQEN_Msk | HSOTG_CTL_BUSREQ_Msk);
463 }
464
465 /* Status stage */
466 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
467 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
468 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
469 break;
470 }
471 case SET_INTERFACE:
472 {
473 g_hsusbd_UsbAltInterface = (uint8_t)gUsbCmd.wValue;
474 if (g_hsusbd_pfnSetInterface != NULL)
475 {
476 g_hsusbd_pfnSetInterface((uint32_t)g_hsusbd_UsbAltInterface);
477 }
478 /* Status stage */
479 HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk);
480 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR);
481 HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk);
482 break;
483 }
484 default:
485 {
486 /* Setup error, stall the device */
487 HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_STALLEN_Msk);
488 break;
489 }
490 }
491 }
492 }
493
494 /**
495 * @brief Update Device State
496 *
497 * @param[in] None
498 *
499 * @return None
500 *
501 * @details This function is used to update Device state when Setup packet complete
502 */
503 /** @cond HIDDEN_SYMBOLS */
504 #define TEST_J 0x01ul
505 #define TEST_K 0x02ul
506 #define TEST_SE0_NAK 0x03ul
507 #define TEST_PACKET 0x04ul
508 #define TEST_FORCE_ENABLE 0x05ul
509 /** @endcond HIDDEN_SYMBOLS */
510
HSUSBD_UpdateDeviceState(void)511 void HSUSBD_UpdateDeviceState(void)
512 {
513 switch (gUsbCmd.bRequest)
514 {
515 case SET_ADDRESS:
516 {
517 HSUSBD_SET_ADDR(g_hsusbd_UsbAddr);
518 break;
519 }
520 case SET_CONFIGURATION:
521 {
522 if (g_hsusbd_UsbConfig == 0ul)
523 {
524 uint32_t volatile i;
525 /* Reset PID DATA0 */
526 for (i=0ul; i<HSUSBD_MAX_EP; i++)
527 {
528 if ((HSUSBD->EP[i].EPCFG & 0x1ul) == 0x1ul)
529 {
530 HSUSBD->EP[i].EPRSPCTL = HSUSBD_EP_RSPCTL_TOGGLE;
531 }
532 }
533 }
534 break;
535 }
536 case SET_FEATURE:
537 {
538 if(gUsbCmd.wValue == FEATURE_ENDPOINT_HALT)
539 {
540 uint32_t idx;
541 idx = (uint32_t)(gUsbCmd.wIndex & 0xFul);
542 HSUSBD_SetStall(idx);
543 }
544 else if (g_hsusbd_EnableTestMode)
545 {
546 g_hsusbd_EnableTestMode = (uint8_t)0ul;
547 if (g_hsusbd_TestSelector == TEST_J)
548 {
549 HSUSBD->TEST = TEST_J;
550 }
551 else if (g_hsusbd_TestSelector == TEST_K)
552 {
553 HSUSBD->TEST = TEST_K;
554 }
555 else if (g_hsusbd_TestSelector == TEST_SE0_NAK)
556 {
557 HSUSBD->TEST = TEST_SE0_NAK;
558 }
559 else if (g_hsusbd_TestSelector == TEST_PACKET)
560 {
561 HSUSBD->TEST = TEST_PACKET;
562 }
563 else if (g_hsusbd_TestSelector == TEST_FORCE_ENABLE)
564 {
565 HSUSBD->TEST = TEST_FORCE_ENABLE;
566 }
567 }
568 break;
569 }
570 case CLEAR_FEATURE:
571 {
572 if(gUsbCmd.wValue == FEATURE_ENDPOINT_HALT)
573 {
574 uint32_t idx;
575 idx = (uint32_t)(gUsbCmd.wIndex & 0xFul);
576 HSUSBD_ClearStall(idx);
577 }
578 break;
579 }
580 default:
581 break;
582 }
583 }
584
585
586 /**
587 * @brief Prepare Control IN transaction
588 *
589 * @param[in] pu8Buf Control IN data pointer
590 * @param[in] u32Size IN transfer size
591 *
592 * @return None
593 *
594 * @details This function is used to prepare Control IN transfer
595 */
HSUSBD_PrepareCtrlIn(uint8_t pu8Buf[],uint32_t u32Size)596 void HSUSBD_PrepareCtrlIn(uint8_t pu8Buf[], uint32_t u32Size)
597 {
598 g_hsusbd_CtrlInPointer = pu8Buf;
599 g_hsusbd_CtrlInSize = u32Size;
600 }
601
602
603
604 /**
605 * @brief Start Control IN transfer
606 *
607 * @param[in] None
608 *
609 * @return None
610 *
611 * @details This function is used to start Control IN
612 */
HSUSBD_CtrlIn(void)613 void HSUSBD_CtrlIn(void)
614 {
615 uint32_t volatile i, cnt;
616 uint8_t u8Value;
617 if(g_hsusbd_CtrlInSize >= g_hsusbd_CtrlMaxPktSize)
618 {
619 /* Data size > MXPLD */
620 cnt = g_hsusbd_CtrlMaxPktSize >> 2;
621 for (i=0ul; i<cnt; i++)
622 {
623 HSUSBD->CEPDAT = *(uint32_t *)g_hsusbd_CtrlInPointer;
624 g_hsusbd_CtrlInPointer = (uint8_t *)(g_hsusbd_CtrlInPointer + 4ul);
625 }
626 HSUSBD_START_CEP_IN(g_hsusbd_CtrlMaxPktSize);
627 g_hsusbd_CtrlInSize -= g_hsusbd_CtrlMaxPktSize;
628 }
629 else
630 {
631 /* Data size <= MXPLD */
632 cnt = g_hsusbd_CtrlInSize >> 2;
633 for (i=0ul; i<cnt; i++)
634 {
635 HSUSBD->CEPDAT = *(uint32_t *)g_hsusbd_CtrlInPointer;
636 g_hsusbd_CtrlInPointer += 4ul;
637 }
638
639 for (i=0ul; i<(g_hsusbd_CtrlInSize % 4ul); i++)
640 {
641 u8Value = *(uint8_t *)(g_hsusbd_CtrlInPointer+i);
642 outpb(&HSUSBD->CEPDAT, u8Value);
643 }
644
645 HSUSBD_START_CEP_IN(g_hsusbd_CtrlInSize);
646 g_hsusbd_CtrlInPointer = 0;
647 g_hsusbd_CtrlInSize = 0ul;
648 }
649 }
650
651 /**
652 * @brief Start Control OUT transaction
653 *
654 * @param[in] pu8Buf Control OUT data pointer
655 * @param[in] u32Size OUT transfer size
656 *
657 * @return None
658 *
659 * @details This function is used to start Control OUT transfer
660 */
HSUSBD_CtrlOut(uint8_t pu8Buf[],uint32_t u32Size)661 void HSUSBD_CtrlOut(uint8_t pu8Buf[], uint32_t u32Size)
662 {
663 uint32_t volatile i;
664 while(1)
665 {
666 if ((HSUSBD->CEPINTSTS & HSUSBD_CEPINTSTS_RXPKIF_Msk) == HSUSBD_CEPINTSTS_RXPKIF_Msk)
667 {
668 for (i=0ul; i<u32Size; i++)
669 {
670 pu8Buf[i] = inpb(&HSUSBD->CEPDAT);
671 }
672 HSUSBD->CEPINTSTS = HSUSBD_CEPINTSTS_RXPKIF_Msk;
673 break;
674 }
675 }
676 }
677
678 /**
679 * @brief Clear all software flags
680 *
681 * @param[in] None
682 *
683 * @return None
684 *
685 * @details This function is used to clear all software control flag
686 */
HSUSBD_SwReset(void)687 void HSUSBD_SwReset(void)
688 {
689 /* Reset all variables for protocol */
690 g_hsusbd_UsbAddr = (uint8_t)0ul;
691 g_hsusbd_DmaDone = 0ul;
692 g_hsusbd_ShortPacket = (uint8_t)0ul;
693 g_hsusbd_Configured = (uint8_t)0ul;
694
695 /* Reset USB device address */
696 HSUSBD_SET_ADDR(0ul);
697 }
698
699 /**
700 * @brief HSUSBD Set Vendor Request
701 *
702 * @param[in] pfnVendorReq Vendor Request Callback Function
703 *
704 * @return None
705 *
706 * @details This function is used to set HSUSBD vendor request callback function
707 */
HSUSBD_SetVendorRequest(HSUSBD_VENDOR_REQ pfnVendorReq)708 void HSUSBD_SetVendorRequest(HSUSBD_VENDOR_REQ pfnVendorReq)
709 {
710 g_hsusbd_pfnVendorRequest = pfnVendorReq;
711 }
712
713
714 /*@}*/ /* end of group HSUSBD_EXPORTED_FUNCTIONS */
715
716 /*@}*/ /* end of group HSUSBD_Driver */
717
718 /*@}*/ /* end of group Standard_Driver */
719
720 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
721