1 /**
2 ******************************************************************************
3 * @file stm32f7xx_hal_hcd.c
4 * @author MCD Application Team
5 * @brief HCD HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the USB Peripheral Controller:
8 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
12 *
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2017 STMicroelectronics.
17 * All rights reserved.
18 *
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
22 *
23 ******************************************************************************
24 @verbatim
25 ==============================================================================
26 ##### How to use this driver #####
27 ==============================================================================
28 [..]
29 (#)Declare a HCD_HandleTypeDef handle structure, for example:
30 HCD_HandleTypeDef hhcd;
31
32 (#)Fill parameters of Init structure in HCD handle
33
34 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
35
36 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
37 (##) Enable the HCD/USB Low Level interface clock using the following macros
38 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
39 (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
40 (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
41
42 (##) Initialize the related GPIO clocks
43 (##) Configure HCD pin-out
44 (##) Configure HCD NVIC interrupt
45
46 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
47 (##) hhcd.pData = phost;
48
49 (#)Enable HCD transmission and reception:
50 (##) HAL_HCD_Start();
51
52 @endverbatim
53 ******************************************************************************
54 */
55
56 /* Includes ------------------------------------------------------------------*/
57 #include "stm32f7xx_hal.h"
58
59 /** @addtogroup STM32F7xx_HAL_Driver
60 * @{
61 */
62
63 #ifdef HAL_HCD_MODULE_ENABLED
64 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
65
66 /** @defgroup HCD HCD
67 * @brief HCD HAL module driver
68 * @{
69 */
70
71 /* Private typedef -----------------------------------------------------------*/
72 /* Private define ------------------------------------------------------------*/
73 /* Private macro -------------------------------------------------------------*/
74 /* Private variables ---------------------------------------------------------*/
75 /* Private function prototypes -----------------------------------------------*/
76 /** @defgroup HCD_Private_Functions HCD Private Functions
77 * @{
78 */
79 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
80 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
81 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
82 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
83 /**
84 * @}
85 */
86
87 /* Exported functions --------------------------------------------------------*/
88 /** @defgroup HCD_Exported_Functions HCD Exported Functions
89 * @{
90 */
91
92 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
93 * @brief Initialization and Configuration functions
94 *
95 @verbatim
96 ===============================================================================
97 ##### Initialization and de-initialization functions #####
98 ===============================================================================
99 [..] This section provides functions allowing to:
100
101 @endverbatim
102 * @{
103 */
104
105 /**
106 * @brief Initialize the host driver.
107 * @param hhcd HCD handle
108 * @retval HAL status
109 */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)110 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
111 {
112 USB_OTG_GlobalTypeDef *USBx;
113
114 /* Check the HCD handle allocation */
115 if (hhcd == NULL)
116 {
117 return HAL_ERROR;
118 }
119
120 /* Check the parameters */
121 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
122
123 USBx = hhcd->Instance;
124
125 if (hhcd->State == HAL_HCD_STATE_RESET)
126 {
127 /* Allocate lock resource and initialize it */
128 hhcd->Lock = HAL_UNLOCKED;
129
130 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
131 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
132 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
133 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
134 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
135 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
136 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
137
138 if (hhcd->MspInitCallback == NULL)
139 {
140 hhcd->MspInitCallback = HAL_HCD_MspInit;
141 }
142
143 /* Init the low level hardware */
144 hhcd->MspInitCallback(hhcd);
145 #else
146 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
147 HAL_HCD_MspInit(hhcd);
148 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
149 }
150
151 hhcd->State = HAL_HCD_STATE_BUSY;
152
153 /* Disable DMA mode for FS instance */
154 if ((USBx->CID & (0x1U << 8)) == 0U)
155 {
156 hhcd->Init.dma_enable = 0U;
157 }
158
159 /* Disable the Interrupts */
160 __HAL_HCD_DISABLE(hhcd);
161
162 /* Init the Core (common init.) */
163 (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
164
165 /* Force Host Mode*/
166 (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
167
168 /* Init Host */
169 (void)USB_HostInit(hhcd->Instance, hhcd->Init);
170
171 hhcd->State = HAL_HCD_STATE_READY;
172
173 return HAL_OK;
174 }
175
176 /**
177 * @brief Initialize a host channel.
178 * @param hhcd HCD handle
179 * @param ch_num Channel number.
180 * This parameter can be a value from 1 to 15
181 * @param epnum Endpoint number.
182 * This parameter can be a value from 1 to 15
183 * @param dev_address Current device address
184 * This parameter can be a value from 0 to 255
185 * @param speed Current device speed.
186 * This parameter can be one of these values:
187 * HCD_DEVICE_SPEED_HIGH: High speed mode,
188 * HCD_DEVICE_SPEED_FULL: Full speed mode,
189 * HCD_DEVICE_SPEED_LOW: Low speed mode
190 * @param ep_type Endpoint Type.
191 * This parameter can be one of these values:
192 * EP_TYPE_CTRL: Control type,
193 * EP_TYPE_ISOC: Isochronous type,
194 * EP_TYPE_BULK: Bulk type,
195 * EP_TYPE_INTR: Interrupt type
196 * @param mps Max Packet Size.
197 * This parameter can be a value from 0 to32K
198 * @retval HAL status
199 */
HAL_HCD_HC_Init(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t epnum,uint8_t dev_address,uint8_t speed,uint8_t ep_type,uint16_t mps)200 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum,
201 uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
202 {
203 HAL_StatusTypeDef status;
204
205 __HAL_LOCK(hhcd);
206 hhcd->hc[ch_num].do_ping = 0U;
207 hhcd->hc[ch_num].dev_addr = dev_address;
208 hhcd->hc[ch_num].max_packet = mps;
209 hhcd->hc[ch_num].ch_num = ch_num;
210 hhcd->hc[ch_num].ep_type = ep_type;
211 hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
212
213 if ((epnum & 0x80U) == 0x80U)
214 {
215 hhcd->hc[ch_num].ep_is_in = 1U;
216 }
217 else
218 {
219 hhcd->hc[ch_num].ep_is_in = 0U;
220 }
221
222 hhcd->hc[ch_num].speed = speed;
223
224 status = USB_HC_Init(hhcd->Instance, ch_num, epnum,
225 dev_address, speed, ep_type, mps);
226
227 __HAL_UNLOCK(hhcd);
228
229 return status;
230 }
231
232 /**
233 * @brief Halt a host channel.
234 * @param hhcd HCD handle
235 * @param ch_num Channel number.
236 * This parameter can be a value from 1 to 15
237 * @retval HAL status
238 */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)239 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
240 {
241 HAL_StatusTypeDef status = HAL_OK;
242
243 __HAL_LOCK(hhcd);
244 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
245 __HAL_UNLOCK(hhcd);
246
247 return status;
248 }
249
250 /**
251 * @brief DeInitialize the host driver.
252 * @param hhcd HCD handle
253 * @retval HAL status
254 */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)255 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
256 {
257 /* Check the HCD handle allocation */
258 if (hhcd == NULL)
259 {
260 return HAL_ERROR;
261 }
262
263 hhcd->State = HAL_HCD_STATE_BUSY;
264
265 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
266 if (hhcd->MspDeInitCallback == NULL)
267 {
268 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
269 }
270
271 /* DeInit the low level hardware */
272 hhcd->MspDeInitCallback(hhcd);
273 #else
274 /* DeInit the low level hardware: CLOCK, NVIC.*/
275 HAL_HCD_MspDeInit(hhcd);
276 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
277
278 __HAL_HCD_DISABLE(hhcd);
279
280 hhcd->State = HAL_HCD_STATE_RESET;
281
282 return HAL_OK;
283 }
284
285 /**
286 * @brief Initialize the HCD MSP.
287 * @param hhcd HCD handle
288 * @retval None
289 */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)290 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
291 {
292 /* Prevent unused argument(s) compilation warning */
293 UNUSED(hhcd);
294
295 /* NOTE : This function should not be modified, when the callback is needed,
296 the HAL_HCD_MspInit could be implemented in the user file
297 */
298 }
299
300 /**
301 * @brief DeInitialize the HCD MSP.
302 * @param hhcd HCD handle
303 * @retval None
304 */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)305 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
306 {
307 /* Prevent unused argument(s) compilation warning */
308 UNUSED(hhcd);
309
310 /* NOTE : This function should not be modified, when the callback is needed,
311 the HAL_HCD_MspDeInit could be implemented in the user file
312 */
313 }
314
315 /**
316 * @}
317 */
318
319 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
320 * @brief HCD IO operation functions
321 *
322 @verbatim
323 ===============================================================================
324 ##### IO operation functions #####
325 ===============================================================================
326 [..] This subsection provides a set of functions allowing to manage the USB Host Data
327 Transfer
328
329 @endverbatim
330 * @{
331 */
332
333 /**
334 * @brief Submit a new URB for processing.
335 * @param hhcd HCD handle
336 * @param ch_num Channel number.
337 * This parameter can be a value from 1 to 15
338 * @param direction Channel number.
339 * This parameter can be one of these values:
340 * 0 : Output / 1 : Input
341 * @param ep_type Endpoint Type.
342 * This parameter can be one of these values:
343 * EP_TYPE_CTRL: Control type/
344 * EP_TYPE_ISOC: Isochronous type/
345 * EP_TYPE_BULK: Bulk type/
346 * EP_TYPE_INTR: Interrupt type/
347 * @param token Endpoint Type.
348 * This parameter can be one of these values:
349 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
350 * @param pbuff pointer to URB data
351 * @param length Length of URB data
352 * @param do_ping activate do ping protocol (for high speed only).
353 * This parameter can be one of these values:
354 * 0 : do ping inactive / 1 : do ping active
355 * @retval HAL status
356 */
HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t direction,uint8_t ep_type,uint8_t token,uint8_t * pbuff,uint16_t length,uint8_t do_ping)357 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
358 uint8_t ch_num,
359 uint8_t direction,
360 uint8_t ep_type,
361 uint8_t token,
362 uint8_t *pbuff,
363 uint16_t length,
364 uint8_t do_ping)
365 {
366 hhcd->hc[ch_num].ep_is_in = direction;
367 hhcd->hc[ch_num].ep_type = ep_type;
368
369 if (token == 0U)
370 {
371 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
372 hhcd->hc[ch_num].do_ping = do_ping;
373 }
374 else
375 {
376 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
377 }
378
379 /* Manage Data Toggle */
380 switch (ep_type)
381 {
382 case EP_TYPE_CTRL:
383 if ((token == 1U) && (direction == 0U)) /*send data */
384 {
385 if (length == 0U)
386 {
387 /* For Status OUT stage, Length==0, Status Out PID = 1 */
388 hhcd->hc[ch_num].toggle_out = 1U;
389 }
390
391 /* Set the Data Toggle bit as per the Flag */
392 if (hhcd->hc[ch_num].toggle_out == 0U)
393 {
394 /* Put the PID 0 */
395 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
396 }
397 else
398 {
399 /* Put the PID 1 */
400 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
401 }
402 }
403 break;
404
405 case EP_TYPE_BULK:
406 if (direction == 0U)
407 {
408 /* Set the Data Toggle bit as per the Flag */
409 if (hhcd->hc[ch_num].toggle_out == 0U)
410 {
411 /* Put the PID 0 */
412 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
413 }
414 else
415 {
416 /* Put the PID 1 */
417 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
418 }
419 }
420 else
421 {
422 if (hhcd->hc[ch_num].toggle_in == 0U)
423 {
424 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
425 }
426 else
427 {
428 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
429 }
430 }
431
432 break;
433 case EP_TYPE_INTR:
434 if (direction == 0U)
435 {
436 /* Set the Data Toggle bit as per the Flag */
437 if (hhcd->hc[ch_num].toggle_out == 0U)
438 {
439 /* Put the PID 0 */
440 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
441 }
442 else
443 {
444 /* Put the PID 1 */
445 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
446 }
447 }
448 else
449 {
450 if (hhcd->hc[ch_num].toggle_in == 0U)
451 {
452 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
453 }
454 else
455 {
456 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
457 }
458 }
459 break;
460
461 case EP_TYPE_ISOC:
462 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
463 break;
464
465 default:
466 break;
467 }
468
469 hhcd->hc[ch_num].xfer_buff = pbuff;
470 hhcd->hc[ch_num].xfer_len = length;
471 hhcd->hc[ch_num].urb_state = URB_IDLE;
472 hhcd->hc[ch_num].xfer_count = 0U;
473 hhcd->hc[ch_num].ch_num = ch_num;
474 hhcd->hc[ch_num].state = HC_IDLE;
475
476 return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable);
477 }
478
479 /**
480 * @brief Handle HCD interrupt request.
481 * @param hhcd HCD handle
482 * @retval None
483 */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)484 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
485 {
486 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
487 uint32_t USBx_BASE = (uint32_t)USBx;
488 uint32_t i;
489 uint32_t interrupt;
490
491 /* Ensure that we are in device mode */
492 if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
493 {
494 /* Avoid spurious interrupt */
495 if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
496 {
497 return;
498 }
499
500 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
501 {
502 /* Incorrect mode, acknowledge the interrupt */
503 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
504 }
505
506 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
507 {
508 /* Incorrect mode, acknowledge the interrupt */
509 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
510 }
511
512 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
513 {
514 /* Incorrect mode, acknowledge the interrupt */
515 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
516 }
517
518 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
519 {
520 /* Incorrect mode, acknowledge the interrupt */
521 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
522 }
523
524 /* Handle Host Disconnect Interrupts */
525 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
526 {
527 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
528
529 if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
530 {
531 /* Flush USB Fifo */
532 (void)USB_FlushTxFifo(USBx, 0x10U);
533 (void)USB_FlushRxFifo(USBx);
534
535 /* Restore FS Clock */
536 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
537
538 /* Handle Host Port Disconnect Interrupt */
539 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
540 hhcd->DisconnectCallback(hhcd);
541 #else
542 HAL_HCD_Disconnect_Callback(hhcd);
543 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
544 }
545 }
546
547 /* Handle Host Port Interrupts */
548 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
549 {
550 HCD_Port_IRQHandler(hhcd);
551 }
552
553 /* Handle Host SOF Interrupt */
554 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
555 {
556 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
557 hhcd->SOFCallback(hhcd);
558 #else
559 HAL_HCD_SOF_Callback(hhcd);
560 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
561
562 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
563 }
564
565 /* Handle Rx Queue Level Interrupts */
566 if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
567 {
568 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
569
570 HCD_RXQLVL_IRQHandler(hhcd);
571
572 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
573 }
574
575 /* Handle Host channel Interrupt */
576 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
577 {
578 interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
579 for (i = 0U; i < hhcd->Init.Host_channels; i++)
580 {
581 if ((interrupt & (1UL << (i & 0xFU))) != 0U)
582 {
583 if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
584 {
585 HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
586 }
587 else
588 {
589 HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
590 }
591 }
592 }
593 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
594 }
595 }
596 }
597
598
599 /**
600 * @brief Handles HCD Wakeup interrupt request.
601 * @param hhcd HCD handle
602 * @retval HAL status
603 */
HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef * hhcd)604 void HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef *hhcd)
605 {
606 UNUSED(hhcd);
607 }
608
609
610 /**
611 * @brief SOF callback.
612 * @param hhcd HCD handle
613 * @retval None
614 */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)615 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
616 {
617 /* Prevent unused argument(s) compilation warning */
618 UNUSED(hhcd);
619
620 /* NOTE : This function should not be modified, when the callback is needed,
621 the HAL_HCD_SOF_Callback could be implemented in the user file
622 */
623 }
624
625 /**
626 * @brief Connection Event callback.
627 * @param hhcd HCD handle
628 * @retval None
629 */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)630 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
631 {
632 /* Prevent unused argument(s) compilation warning */
633 UNUSED(hhcd);
634
635 /* NOTE : This function should not be modified, when the callback is needed,
636 the HAL_HCD_Connect_Callback could be implemented in the user file
637 */
638 }
639
640 /**
641 * @brief Disconnection Event callback.
642 * @param hhcd HCD handle
643 * @retval None
644 */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)645 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
646 {
647 /* Prevent unused argument(s) compilation warning */
648 UNUSED(hhcd);
649
650 /* NOTE : This function should not be modified, when the callback is needed,
651 the HAL_HCD_Disconnect_Callback could be implemented in the user file
652 */
653 }
654
655 /**
656 * @brief Port Enabled Event callback.
657 * @param hhcd HCD handle
658 * @retval None
659 */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)660 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
661 {
662 /* Prevent unused argument(s) compilation warning */
663 UNUSED(hhcd);
664
665 /* NOTE : This function should not be modified, when the callback is needed,
666 the HAL_HCD_Disconnect_Callback could be implemented in the user file
667 */
668 }
669
670 /**
671 * @brief Port Disabled Event callback.
672 * @param hhcd HCD handle
673 * @retval None
674 */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)675 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
676 {
677 /* Prevent unused argument(s) compilation warning */
678 UNUSED(hhcd);
679
680 /* NOTE : This function should not be modified, when the callback is needed,
681 the HAL_HCD_Disconnect_Callback could be implemented in the user file
682 */
683 }
684
685 /**
686 * @brief Notify URB state change callback.
687 * @param hhcd HCD handle
688 * @param chnum Channel number.
689 * This parameter can be a value from 1 to 15
690 * @param urb_state:
691 * This parameter can be one of these values:
692 * URB_IDLE/
693 * URB_DONE/
694 * URB_NOTREADY/
695 * URB_NYET/
696 * URB_ERROR/
697 * URB_STALL/
698 * @retval None
699 */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)700 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
701 {
702 /* Prevent unused argument(s) compilation warning */
703 UNUSED(hhcd);
704 UNUSED(chnum);
705 UNUSED(urb_state);
706
707 /* NOTE : This function should not be modified, when the callback is needed,
708 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
709 */
710 }
711
712 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
713 /**
714 * @brief Register a User USB HCD Callback
715 * To be used instead of the weak predefined callback
716 * @param hhcd USB HCD handle
717 * @param CallbackID ID of the callback to be registered
718 * This parameter can be one of the following values:
719 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
720 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
721 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
722 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
723 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
724 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
725 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
726 * @param pCallback pointer to the Callback function
727 * @retval HAL status
728 */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)729 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
730 HAL_HCD_CallbackIDTypeDef CallbackID,
731 pHCD_CallbackTypeDef pCallback)
732 {
733 HAL_StatusTypeDef status = HAL_OK;
734
735 if (pCallback == NULL)
736 {
737 /* Update the error code */
738 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
739 return HAL_ERROR;
740 }
741 /* Process locked */
742 __HAL_LOCK(hhcd);
743
744 if (hhcd->State == HAL_HCD_STATE_READY)
745 {
746 switch (CallbackID)
747 {
748 case HAL_HCD_SOF_CB_ID :
749 hhcd->SOFCallback = pCallback;
750 break;
751
752 case HAL_HCD_CONNECT_CB_ID :
753 hhcd->ConnectCallback = pCallback;
754 break;
755
756 case HAL_HCD_DISCONNECT_CB_ID :
757 hhcd->DisconnectCallback = pCallback;
758 break;
759
760 case HAL_HCD_PORT_ENABLED_CB_ID :
761 hhcd->PortEnabledCallback = pCallback;
762 break;
763
764 case HAL_HCD_PORT_DISABLED_CB_ID :
765 hhcd->PortDisabledCallback = pCallback;
766 break;
767
768 case HAL_HCD_MSPINIT_CB_ID :
769 hhcd->MspInitCallback = pCallback;
770 break;
771
772 case HAL_HCD_MSPDEINIT_CB_ID :
773 hhcd->MspDeInitCallback = pCallback;
774 break;
775
776 default :
777 /* Update the error code */
778 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
779 /* Return error status */
780 status = HAL_ERROR;
781 break;
782 }
783 }
784 else if (hhcd->State == HAL_HCD_STATE_RESET)
785 {
786 switch (CallbackID)
787 {
788 case HAL_HCD_MSPINIT_CB_ID :
789 hhcd->MspInitCallback = pCallback;
790 break;
791
792 case HAL_HCD_MSPDEINIT_CB_ID :
793 hhcd->MspDeInitCallback = pCallback;
794 break;
795
796 default :
797 /* Update the error code */
798 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
799 /* Return error status */
800 status = HAL_ERROR;
801 break;
802 }
803 }
804 else
805 {
806 /* Update the error code */
807 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
808 /* Return error status */
809 status = HAL_ERROR;
810 }
811
812 /* Release Lock */
813 __HAL_UNLOCK(hhcd);
814 return status;
815 }
816
817 /**
818 * @brief Unregister an USB HCD Callback
819 * USB HCD callback is redirected to the weak predefined callback
820 * @param hhcd USB HCD handle
821 * @param CallbackID ID of the callback to be unregistered
822 * This parameter can be one of the following values:
823 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
824 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
825 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
826 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
827 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
828 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
829 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
830 * @retval HAL status
831 */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)832 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
833 {
834 HAL_StatusTypeDef status = HAL_OK;
835
836 /* Process locked */
837 __HAL_LOCK(hhcd);
838
839 /* Setup Legacy weak Callbacks */
840 if (hhcd->State == HAL_HCD_STATE_READY)
841 {
842 switch (CallbackID)
843 {
844 case HAL_HCD_SOF_CB_ID :
845 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
846 break;
847
848 case HAL_HCD_CONNECT_CB_ID :
849 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
850 break;
851
852 case HAL_HCD_DISCONNECT_CB_ID :
853 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
854 break;
855
856 case HAL_HCD_PORT_ENABLED_CB_ID :
857 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
858 break;
859
860 case HAL_HCD_PORT_DISABLED_CB_ID :
861 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
862 break;
863
864 case HAL_HCD_MSPINIT_CB_ID :
865 hhcd->MspInitCallback = HAL_HCD_MspInit;
866 break;
867
868 case HAL_HCD_MSPDEINIT_CB_ID :
869 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
870 break;
871
872 default :
873 /* Update the error code */
874 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
875
876 /* Return error status */
877 status = HAL_ERROR;
878 break;
879 }
880 }
881 else if (hhcd->State == HAL_HCD_STATE_RESET)
882 {
883 switch (CallbackID)
884 {
885 case HAL_HCD_MSPINIT_CB_ID :
886 hhcd->MspInitCallback = HAL_HCD_MspInit;
887 break;
888
889 case HAL_HCD_MSPDEINIT_CB_ID :
890 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
891 break;
892
893 default :
894 /* Update the error code */
895 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
896
897 /* Return error status */
898 status = HAL_ERROR;
899 break;
900 }
901 }
902 else
903 {
904 /* Update the error code */
905 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
906
907 /* Return error status */
908 status = HAL_ERROR;
909 }
910
911 /* Release Lock */
912 __HAL_UNLOCK(hhcd);
913 return status;
914 }
915
916 /**
917 * @brief Register USB HCD Host Channel Notify URB Change Callback
918 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
919 * @param hhcd HCD handle
920 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
921 * @retval HAL status
922 */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)923 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
924 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
925 {
926 HAL_StatusTypeDef status = HAL_OK;
927
928 if (pCallback == NULL)
929 {
930 /* Update the error code */
931 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
932
933 return HAL_ERROR;
934 }
935
936 /* Process locked */
937 __HAL_LOCK(hhcd);
938
939 if (hhcd->State == HAL_HCD_STATE_READY)
940 {
941 hhcd->HC_NotifyURBChangeCallback = pCallback;
942 }
943 else
944 {
945 /* Update the error code */
946 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
947
948 /* Return error status */
949 status = HAL_ERROR;
950 }
951
952 /* Release Lock */
953 __HAL_UNLOCK(hhcd);
954
955 return status;
956 }
957
958 /**
959 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
960 * USB HCD Host Channel Notify URB Change Callback is redirected
961 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
962 * @param hhcd HCD handle
963 * @retval HAL status
964 */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)965 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
966 {
967 HAL_StatusTypeDef status = HAL_OK;
968
969 /* Process locked */
970 __HAL_LOCK(hhcd);
971
972 if (hhcd->State == HAL_HCD_STATE_READY)
973 {
974 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
975 }
976 else
977 {
978 /* Update the error code */
979 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
980
981 /* Return error status */
982 status = HAL_ERROR;
983 }
984
985 /* Release Lock */
986 __HAL_UNLOCK(hhcd);
987
988 return status;
989 }
990 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
991
992 /**
993 * @}
994 */
995
996 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
997 * @brief Management functions
998 *
999 @verbatim
1000 ===============================================================================
1001 ##### Peripheral Control functions #####
1002 ===============================================================================
1003 [..]
1004 This subsection provides a set of functions allowing to control the HCD data
1005 transfers.
1006
1007 @endverbatim
1008 * @{
1009 */
1010
1011 /**
1012 * @brief Start the host driver.
1013 * @param hhcd HCD handle
1014 * @retval HAL status
1015 */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1016 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1017 {
1018 __HAL_LOCK(hhcd);
1019 /* Enable port power */
1020 (void)USB_DriveVbus(hhcd->Instance, 1U);
1021
1022 /* Enable global interrupt */
1023 __HAL_HCD_ENABLE(hhcd);
1024 __HAL_UNLOCK(hhcd);
1025
1026 return HAL_OK;
1027 }
1028
1029 /**
1030 * @brief Stop the host driver.
1031 * @param hhcd HCD handle
1032 * @retval HAL status
1033 */
1034
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1035 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1036 {
1037 __HAL_LOCK(hhcd);
1038 (void)USB_StopHost(hhcd->Instance);
1039 __HAL_UNLOCK(hhcd);
1040
1041 return HAL_OK;
1042 }
1043
1044 /**
1045 * @brief Reset the host port.
1046 * @param hhcd HCD handle
1047 * @retval HAL status
1048 */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1049 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1050 {
1051 return (USB_ResetPort(hhcd->Instance));
1052 }
1053
1054 /**
1055 * @}
1056 */
1057
1058 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1059 * @brief Peripheral State functions
1060 *
1061 @verbatim
1062 ===============================================================================
1063 ##### Peripheral State functions #####
1064 ===============================================================================
1065 [..]
1066 This subsection permits to get in run-time the status of the peripheral
1067 and the data flow.
1068
1069 @endverbatim
1070 * @{
1071 */
1072
1073 /**
1074 * @brief Return the HCD handle state.
1075 * @param hhcd HCD handle
1076 * @retval HAL state
1077 */
HAL_HCD_GetState(HCD_HandleTypeDef * hhcd)1078 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
1079 {
1080 return hhcd->State;
1081 }
1082
1083 /**
1084 * @brief Return URB state for a channel.
1085 * @param hhcd HCD handle
1086 * @param chnum Channel number.
1087 * This parameter can be a value from 1 to 15
1088 * @retval URB state.
1089 * This parameter can be one of these values:
1090 * URB_IDLE/
1091 * URB_DONE/
1092 * URB_NOTREADY/
1093 * URB_NYET/
1094 * URB_ERROR/
1095 * URB_STALL
1096 */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef * hhcd,uint8_t chnum)1097 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1098 {
1099 return hhcd->hc[chnum].urb_state;
1100 }
1101
1102
1103 /**
1104 * @brief Return the last host transfer size.
1105 * @param hhcd HCD handle
1106 * @param chnum Channel number.
1107 * This parameter can be a value from 1 to 15
1108 * @retval last transfer size in byte
1109 */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef * hhcd,uint8_t chnum)1110 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1111 {
1112 return hhcd->hc[chnum].xfer_count;
1113 }
1114
1115 /**
1116 * @brief Return the Host Channel state.
1117 * @param hhcd HCD handle
1118 * @param chnum Channel number.
1119 * This parameter can be a value from 1 to 15
1120 * @retval Host channel state
1121 * This parameter can be one of these values:
1122 * HC_IDLE/
1123 * HC_XFRC/
1124 * HC_HALTED/
1125 * HC_NYET/
1126 * HC_NAK/
1127 * HC_STALL/
1128 * HC_XACTERR/
1129 * HC_BBLERR/
1130 * HC_DATATGLERR
1131 */
HAL_HCD_HC_GetState(HCD_HandleTypeDef * hhcd,uint8_t chnum)1132 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1133 {
1134 return hhcd->hc[chnum].state;
1135 }
1136
1137 /**
1138 * @brief Return the current Host frame number.
1139 * @param hhcd HCD handle
1140 * @retval Current Host frame number
1141 */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1142 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1143 {
1144 return (USB_GetCurrentFrame(hhcd->Instance));
1145 }
1146
1147 /**
1148 * @brief Return the Host enumeration speed.
1149 * @param hhcd HCD handle
1150 * @retval Enumeration speed
1151 */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1152 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1153 {
1154 return (USB_GetHostSpeed(hhcd->Instance));
1155 }
1156
1157 /**
1158 * @}
1159 */
1160
1161 /**
1162 * @}
1163 */
1164
1165 /** @addtogroup HCD_Private_Functions
1166 * @{
1167 */
1168 /**
1169 * @brief Handle Host Channel IN interrupt requests.
1170 * @param hhcd HCD handle
1171 * @param chnum Channel number.
1172 * This parameter can be a value from 1 to 15
1173 * @retval none
1174 */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1175 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1176 {
1177 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1178 uint32_t USBx_BASE = (uint32_t)USBx;
1179 uint32_t ch_num = (uint32_t)chnum;
1180
1181 uint32_t tmpreg;
1182
1183 if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_AHBERR))
1184 {
1185 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
1186 hhcd->hc[ch_num].state = HC_XACTERR;
1187 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1188 }
1189 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_BBERR))
1190 {
1191 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
1192 hhcd->hc[ch_num].state = HC_BBLERR;
1193 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1194 }
1195 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_STALL))
1196 {
1197 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
1198 hhcd->hc[ch_num].state = HC_STALL;
1199 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1200 }
1201 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_DTERR))
1202 {
1203 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
1204 hhcd->hc[ch_num].state = HC_DATATGLERR;
1205 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1206 }
1207 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_TXERR))
1208 {
1209 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
1210 hhcd->hc[ch_num].state = HC_XACTERR;
1211 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1212 }
1213 else
1214 {
1215 /* ... */
1216 }
1217
1218 if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_FRMOR))
1219 {
1220 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1221 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
1222 }
1223 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_XFRC))
1224 {
1225 /* Clear any pending ACK IT */
1226 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
1227
1228 if (hhcd->Init.dma_enable != 0U)
1229 {
1230 hhcd->hc[ch_num].xfer_count = hhcd->hc[ch_num].XferSize - \
1231 (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
1232 }
1233
1234 hhcd->hc[ch_num].state = HC_XFRC;
1235 hhcd->hc[ch_num].ErrCnt = 0U;
1236 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
1237
1238 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
1239 (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
1240 {
1241 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1242 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1243 }
1244 else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_INTR) ||
1245 (hhcd->hc[ch_num].ep_type == EP_TYPE_ISOC))
1246 {
1247 USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1248 hhcd->hc[ch_num].urb_state = URB_DONE;
1249
1250 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1251 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1252 #else
1253 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1254 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1255 }
1256 else
1257 {
1258 /* ... */
1259 }
1260
1261 if (hhcd->Init.dma_enable == 1U)
1262 {
1263 if (((hhcd->hc[ch_num].XferSize / hhcd->hc[ch_num].max_packet) & 1U) != 0U)
1264 {
1265 hhcd->hc[ch_num].toggle_in ^= 1U;
1266 }
1267 }
1268 else
1269 {
1270 hhcd->hc[ch_num].toggle_in ^= 1U;
1271 }
1272 }
1273 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_ACK))
1274 {
1275 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
1276 }
1277 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_CHH))
1278 {
1279 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
1280 if (hhcd->hc[ch_num].state == HC_XFRC)
1281 {
1282 hhcd->hc[ch_num].state = HC_HALTED;
1283 hhcd->hc[ch_num].urb_state = URB_DONE;
1284 }
1285 else if (hhcd->hc[ch_num].state == HC_STALL)
1286 {
1287 hhcd->hc[ch_num].state = HC_HALTED;
1288 hhcd->hc[ch_num].urb_state = URB_STALL;
1289 }
1290 else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
1291 (hhcd->hc[ch_num].state == HC_DATATGLERR))
1292 {
1293 hhcd->hc[ch_num].state = HC_HALTED;
1294 hhcd->hc[ch_num].ErrCnt++;
1295 if (hhcd->hc[ch_num].ErrCnt > 2U)
1296 {
1297 hhcd->hc[ch_num].ErrCnt = 0U;
1298 hhcd->hc[ch_num].urb_state = URB_ERROR;
1299 }
1300 else
1301 {
1302 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1303
1304 /* re-activate the channel */
1305 tmpreg = USBx_HC(ch_num)->HCCHAR;
1306 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1307 tmpreg |= USB_OTG_HCCHAR_CHENA;
1308 USBx_HC(ch_num)->HCCHAR = tmpreg;
1309 }
1310 }
1311 else if (hhcd->hc[ch_num].state == HC_NYET)
1312 {
1313 hhcd->hc[ch_num].state = HC_HALTED;
1314 }
1315 else if (hhcd->hc[ch_num].state == HC_ACK)
1316 {
1317 hhcd->hc[ch_num].state = HC_HALTED;
1318 }
1319 else if (hhcd->hc[ch_num].state == HC_NAK)
1320 {
1321 hhcd->hc[ch_num].state = HC_HALTED;
1322 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1323
1324 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
1325 (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
1326 {
1327 /* re-activate the channel */
1328 tmpreg = USBx_HC(ch_num)->HCCHAR;
1329 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1330 tmpreg |= USB_OTG_HCCHAR_CHENA;
1331 USBx_HC(ch_num)->HCCHAR = tmpreg;
1332 }
1333 }
1334 else if (hhcd->hc[ch_num].state == HC_BBLERR)
1335 {
1336 hhcd->hc[ch_num].state = HC_HALTED;
1337 hhcd->hc[ch_num].ErrCnt++;
1338 hhcd->hc[ch_num].urb_state = URB_ERROR;
1339 }
1340 else
1341 {
1342 if (hhcd->hc[ch_num].state == HC_HALTED)
1343 {
1344 return;
1345 }
1346 }
1347
1348 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1349 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1350 #else
1351 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1352 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1353 }
1354 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_NYET))
1355 {
1356 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
1357 hhcd->hc[ch_num].state = HC_NYET;
1358 hhcd->hc[ch_num].ErrCnt = 0U;
1359
1360 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1361 }
1362 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_NAK))
1363 {
1364 if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
1365 {
1366 hhcd->hc[ch_num].ErrCnt = 0U;
1367 hhcd->hc[ch_num].state = HC_NAK;
1368 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1369 }
1370 else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
1371 (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
1372 {
1373 hhcd->hc[ch_num].ErrCnt = 0U;
1374
1375 if (hhcd->Init.dma_enable == 0U)
1376 {
1377 hhcd->hc[ch_num].state = HC_NAK;
1378 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1379 }
1380 }
1381 else
1382 {
1383 /* ... */
1384 }
1385 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1386 }
1387 else
1388 {
1389 /* ... */
1390 }
1391 }
1392
1393 /**
1394 * @brief Handle Host Channel OUT interrupt requests.
1395 * @param hhcd HCD handle
1396 * @param chnum Channel number.
1397 * This parameter can be a value from 1 to 15
1398 * @retval none
1399 */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1400 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1401 {
1402 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1403 uint32_t USBx_BASE = (uint32_t)USBx;
1404 uint32_t ch_num = (uint32_t)chnum;
1405 uint32_t tmpreg;
1406 uint32_t num_packets;
1407
1408 if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_AHBERR))
1409 {
1410 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
1411 hhcd->hc[ch_num].state = HC_XACTERR;
1412 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1413 }
1414 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_ACK))
1415 {
1416 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
1417
1418 if (hhcd->hc[ch_num].do_ping == 1U)
1419 {
1420 hhcd->hc[ch_num].do_ping = 0U;
1421 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1422 hhcd->hc[ch_num].state = HC_ACK;
1423 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1424 }
1425 }
1426 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_FRMOR))
1427 {
1428 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
1429 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1430 }
1431 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_XFRC))
1432 {
1433 hhcd->hc[ch_num].ErrCnt = 0U;
1434
1435 /* transaction completed with NYET state, update do ping state */
1436 if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_NYET))
1437 {
1438 hhcd->hc[ch_num].do_ping = 1U;
1439 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
1440 }
1441 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
1442 hhcd->hc[ch_num].state = HC_XFRC;
1443 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1444 }
1445 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_NYET))
1446 {
1447 hhcd->hc[ch_num].state = HC_NYET;
1448 hhcd->hc[ch_num].do_ping = 1U;
1449 hhcd->hc[ch_num].ErrCnt = 0U;
1450 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1451 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
1452 }
1453 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_STALL))
1454 {
1455 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
1456 hhcd->hc[ch_num].state = HC_STALL;
1457 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1458 }
1459 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_NAK))
1460 {
1461 hhcd->hc[ch_num].ErrCnt = 0U;
1462 hhcd->hc[ch_num].state = HC_NAK;
1463
1464 if (hhcd->hc[ch_num].do_ping == 0U)
1465 {
1466 if (hhcd->hc[ch_num].speed == HCD_DEVICE_SPEED_HIGH)
1467 {
1468 hhcd->hc[ch_num].do_ping = 1U;
1469 }
1470 }
1471
1472 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1473 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1474 }
1475 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_TXERR))
1476 {
1477 if (hhcd->Init.dma_enable == 0U)
1478 {
1479 hhcd->hc[ch_num].state = HC_XACTERR;
1480 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1481 }
1482 else
1483 {
1484 hhcd->hc[ch_num].ErrCnt++;
1485 if (hhcd->hc[ch_num].ErrCnt > 2U)
1486 {
1487 hhcd->hc[ch_num].ErrCnt = 0U;
1488 hhcd->hc[ch_num].urb_state = URB_ERROR;
1489
1490 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1491 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1492 #else
1493 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1494 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1495 }
1496 else
1497 {
1498 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1499 }
1500 }
1501 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
1502 }
1503 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_DTERR))
1504 {
1505 hhcd->hc[ch_num].state = HC_DATATGLERR;
1506 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1507 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
1508 }
1509 else if (__HAL_HCD_GET_CH_FLAG(hhcd, ch_num, USB_OTG_HCINT_CHH))
1510 {
1511 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
1512 if (hhcd->hc[ch_num].state == HC_XFRC)
1513 {
1514 hhcd->hc[ch_num].state = HC_HALTED;
1515 hhcd->hc[ch_num].urb_state = URB_DONE;
1516 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_BULK) ||
1517 (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR))
1518 {
1519 if (hhcd->Init.dma_enable == 0U)
1520 {
1521 hhcd->hc[ch_num].toggle_out ^= 1U;
1522 }
1523
1524 if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[ch_num].xfer_len > 0U))
1525 {
1526 num_packets = (hhcd->hc[ch_num].xfer_len + hhcd->hc[ch_num].max_packet - 1U) / hhcd->hc[ch_num].max_packet;
1527
1528 if ((num_packets & 1U) != 0U)
1529 {
1530 hhcd->hc[ch_num].toggle_out ^= 1U;
1531 }
1532 }
1533 }
1534 }
1535 else if (hhcd->hc[ch_num].state == HC_ACK)
1536 {
1537 hhcd->hc[ch_num].state = HC_HALTED;
1538 }
1539 else if (hhcd->hc[ch_num].state == HC_NAK)
1540 {
1541 hhcd->hc[ch_num].state = HC_HALTED;
1542 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1543 }
1544 else if (hhcd->hc[ch_num].state == HC_NYET)
1545 {
1546 hhcd->hc[ch_num].state = HC_HALTED;
1547 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1548 }
1549 else if (hhcd->hc[ch_num].state == HC_STALL)
1550 {
1551 hhcd->hc[ch_num].state = HC_HALTED;
1552 hhcd->hc[ch_num].urb_state = URB_STALL;
1553 }
1554 else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
1555 (hhcd->hc[ch_num].state == HC_DATATGLERR))
1556 {
1557 hhcd->hc[ch_num].state = HC_HALTED;
1558 hhcd->hc[ch_num].ErrCnt++;
1559 if (hhcd->hc[ch_num].ErrCnt > 2U)
1560 {
1561 hhcd->hc[ch_num].ErrCnt = 0U;
1562 hhcd->hc[ch_num].urb_state = URB_ERROR;
1563 }
1564 else
1565 {
1566 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1567
1568 /* re-activate the channel */
1569 tmpreg = USBx_HC(ch_num)->HCCHAR;
1570 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1571 tmpreg |= USB_OTG_HCCHAR_CHENA;
1572 USBx_HC(ch_num)->HCCHAR = tmpreg;
1573 }
1574 }
1575 else
1576 {
1577 return;
1578 }
1579
1580 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1581 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1582 #else
1583 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1584 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1585 }
1586 else
1587 {
1588 /* ... */
1589 }
1590 }
1591
1592 /**
1593 * @brief Handle Rx Queue Level interrupt requests.
1594 * @param hhcd HCD handle
1595 * @retval none
1596 */
HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef * hhcd)1597 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1598 {
1599 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1600 uint32_t USBx_BASE = (uint32_t)USBx;
1601 uint32_t pktsts;
1602 uint32_t pktcnt;
1603 uint32_t GrxstspReg;
1604 uint32_t xferSizePktCnt;
1605 uint32_t tmpreg;
1606 uint32_t ch_num;
1607
1608 GrxstspReg = hhcd->Instance->GRXSTSP;
1609 ch_num = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
1610 pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1611 pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
1612
1613 switch (pktsts)
1614 {
1615 case GRXSTS_PKTSTS_IN:
1616 /* Read the data into the host buffer. */
1617 if ((pktcnt > 0U) && (hhcd->hc[ch_num].xfer_buff != (void *)0))
1618 {
1619 if ((hhcd->hc[ch_num].xfer_count + pktcnt) <= hhcd->hc[ch_num].xfer_len)
1620 {
1621 (void)USB_ReadPacket(hhcd->Instance,
1622 hhcd->hc[ch_num].xfer_buff, (uint16_t)pktcnt);
1623
1624 /* manage multiple Xfer */
1625 hhcd->hc[ch_num].xfer_buff += pktcnt;
1626 hhcd->hc[ch_num].xfer_count += pktcnt;
1627
1628 /* get transfer size packet count */
1629 xferSizePktCnt = (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
1630
1631 if ((hhcd->hc[ch_num].max_packet == pktcnt) && (xferSizePktCnt > 0U))
1632 {
1633 /* re-activate the channel when more packets are expected */
1634 tmpreg = USBx_HC(ch_num)->HCCHAR;
1635 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1636 tmpreg |= USB_OTG_HCCHAR_CHENA;
1637 USBx_HC(ch_num)->HCCHAR = tmpreg;
1638 hhcd->hc[ch_num].toggle_in ^= 1U;
1639 }
1640 }
1641 else
1642 {
1643 hhcd->hc[ch_num].urb_state = URB_ERROR;
1644 }
1645 }
1646 break;
1647
1648 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1649 break;
1650
1651 case GRXSTS_PKTSTS_IN_XFER_COMP:
1652 case GRXSTS_PKTSTS_CH_HALTED:
1653 default:
1654 break;
1655 }
1656 }
1657
1658 /**
1659 * @brief Handle Host Port interrupt requests.
1660 * @param hhcd HCD handle
1661 * @retval None
1662 */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)1663 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1664 {
1665 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1666 uint32_t USBx_BASE = (uint32_t)USBx;
1667 __IO uint32_t hprt0;
1668 __IO uint32_t hprt0_dup;
1669
1670 /* Handle Host Port Interrupts */
1671 hprt0 = USBx_HPRT0;
1672 hprt0_dup = USBx_HPRT0;
1673
1674 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1675 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1676
1677 /* Check whether Port Connect detected */
1678 if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1679 {
1680 if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1681 {
1682 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1683 hhcd->ConnectCallback(hhcd);
1684 #else
1685 HAL_HCD_Connect_Callback(hhcd);
1686 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1687 }
1688 hprt0_dup |= USB_OTG_HPRT_PCDET;
1689 }
1690
1691 /* Check whether Port Enable Changed */
1692 if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1693 {
1694 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1695
1696 if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1697 {
1698 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1699 {
1700 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1701 {
1702 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1703 }
1704 else
1705 {
1706 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1707 }
1708 }
1709 else
1710 {
1711 if (hhcd->Init.speed == HCD_SPEED_FULL)
1712 {
1713 USBx_HOST->HFIR = 60000U;
1714 }
1715 }
1716 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1717 hhcd->PortEnabledCallback(hhcd);
1718 #else
1719 HAL_HCD_PortEnabled_Callback(hhcd);
1720 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1721
1722 }
1723 else
1724 {
1725 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1726 hhcd->PortDisabledCallback(hhcd);
1727 #else
1728 HAL_HCD_PortDisabled_Callback(hhcd);
1729 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1730 }
1731 }
1732
1733 /* Check for an overcurrent */
1734 if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1735 {
1736 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1737 }
1738
1739 /* Clear Port Interrupts */
1740 USBx_HPRT0 = hprt0_dup;
1741 }
1742
1743 /**
1744 * @}
1745 */
1746
1747 /**
1748 * @}
1749 */
1750
1751 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1752 #endif /* HAL_HCD_MODULE_ENABLED */
1753
1754 /**
1755 * @}
1756 */
1757
1758 /**
1759 * @}
1760 */
1761