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