1 /**
2   ******************************************************************************
3   * @file    stm32h7xx_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 "stm32h7xx_hal.h"
58 
59 /** @addtogroup STM32H7xx_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, 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         if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
536         {
537           /* Restore FS Clock */
538           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
539         }
540 
541         /* Handle Host Port Disconnect Interrupt */
542 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
543         hhcd->DisconnectCallback(hhcd);
544 #else
545         HAL_HCD_Disconnect_Callback(hhcd);
546 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
547       }
548     }
549 
550     /* Handle Host Port Interrupts */
551     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
552     {
553       HCD_Port_IRQHandler(hhcd);
554     }
555 
556     /* Handle Host SOF Interrupt */
557     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
558     {
559 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
560       hhcd->SOFCallback(hhcd);
561 #else
562       HAL_HCD_SOF_Callback(hhcd);
563 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
564 
565       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
566     }
567 
568     /* Handle Rx Queue Level Interrupts */
569     if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
570     {
571       USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
572 
573       HCD_RXQLVL_IRQHandler(hhcd);
574 
575       USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
576     }
577 
578     /* Handle Host channel Interrupt */
579     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
580     {
581       interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
582       for (i = 0U; i < hhcd->Init.Host_channels; i++)
583       {
584         if ((interrupt & (1UL << (i & 0xFU))) != 0U)
585         {
586           if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
587           {
588             HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
589           }
590           else
591           {
592             HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
593           }
594         }
595       }
596       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
597     }
598   }
599 }
600 
601 
602 /**
603   * @brief  SOF callback.
604   * @param  hhcd HCD handle
605   * @retval None
606   */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)607 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
608 {
609   /* Prevent unused argument(s) compilation warning */
610   UNUSED(hhcd);
611 
612   /* NOTE : This function should not be modified, when the callback is needed,
613             the HAL_HCD_SOF_Callback could be implemented in the user file
614    */
615 }
616 
617 /**
618   * @brief Connection Event callback.
619   * @param  hhcd HCD handle
620   * @retval None
621   */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)622 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
623 {
624   /* Prevent unused argument(s) compilation warning */
625   UNUSED(hhcd);
626 
627   /* NOTE : This function should not be modified, when the callback is needed,
628             the HAL_HCD_Connect_Callback could be implemented in the user file
629    */
630 }
631 
632 /**
633   * @brief  Disconnection Event callback.
634   * @param  hhcd HCD handle
635   * @retval None
636   */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)637 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
638 {
639   /* Prevent unused argument(s) compilation warning */
640   UNUSED(hhcd);
641 
642   /* NOTE : This function should not be modified, when the callback is needed,
643             the HAL_HCD_Disconnect_Callback could be implemented in the user file
644    */
645 }
646 
647 /**
648   * @brief  Port Enabled  Event callback.
649   * @param  hhcd HCD handle
650   * @retval None
651   */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)652 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
653 {
654   /* Prevent unused argument(s) compilation warning */
655   UNUSED(hhcd);
656 
657   /* NOTE : This function should not be modified, when the callback is needed,
658             the HAL_HCD_Disconnect_Callback could be implemented in the user file
659    */
660 }
661 
662 /**
663   * @brief  Port Disabled  Event callback.
664   * @param  hhcd HCD handle
665   * @retval None
666   */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)667 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
668 {
669   /* Prevent unused argument(s) compilation warning */
670   UNUSED(hhcd);
671 
672   /* NOTE : This function should not be modified, when the callback is needed,
673             the HAL_HCD_Disconnect_Callback could be implemented in the user file
674    */
675 }
676 
677 /**
678   * @brief  Notify URB state change callback.
679   * @param  hhcd HCD handle
680   * @param  chnum Channel number.
681   *         This parameter can be a value from 1 to 15
682   * @param  urb_state:
683   *          This parameter can be one of these values:
684   *            URB_IDLE/
685   *            URB_DONE/
686   *            URB_NOTREADY/
687   *            URB_NYET/
688   *            URB_ERROR/
689   *            URB_STALL/
690   * @retval None
691   */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)692 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
693 {
694   /* Prevent unused argument(s) compilation warning */
695   UNUSED(hhcd);
696   UNUSED(chnum);
697   UNUSED(urb_state);
698 
699   /* NOTE : This function should not be modified, when the callback is needed,
700             the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
701    */
702 }
703 
704 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
705 /**
706   * @brief  Register a User USB HCD Callback
707   *         To be used instead of the weak predefined callback
708   * @param  hhcd USB HCD handle
709   * @param  CallbackID ID of the callback to be registered
710   *         This parameter can be one of the following values:
711   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
712   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
713   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
714   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
715   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
716   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
717   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
718   * @param  pCallback pointer to the Callback function
719   * @retval HAL status
720   */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)721 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
722                                            HAL_HCD_CallbackIDTypeDef CallbackID,
723                                            pHCD_CallbackTypeDef pCallback)
724 {
725   HAL_StatusTypeDef status = HAL_OK;
726 
727   if (pCallback == NULL)
728   {
729     /* Update the error code */
730     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
731     return HAL_ERROR;
732   }
733   /* Process locked */
734   __HAL_LOCK(hhcd);
735 
736   if (hhcd->State == HAL_HCD_STATE_READY)
737   {
738     switch (CallbackID)
739     {
740       case HAL_HCD_SOF_CB_ID :
741         hhcd->SOFCallback = pCallback;
742         break;
743 
744       case HAL_HCD_CONNECT_CB_ID :
745         hhcd->ConnectCallback = pCallback;
746         break;
747 
748       case HAL_HCD_DISCONNECT_CB_ID :
749         hhcd->DisconnectCallback = pCallback;
750         break;
751 
752       case HAL_HCD_PORT_ENABLED_CB_ID :
753         hhcd->PortEnabledCallback = pCallback;
754         break;
755 
756       case HAL_HCD_PORT_DISABLED_CB_ID :
757         hhcd->PortDisabledCallback = pCallback;
758         break;
759 
760       case HAL_HCD_MSPINIT_CB_ID :
761         hhcd->MspInitCallback = pCallback;
762         break;
763 
764       case HAL_HCD_MSPDEINIT_CB_ID :
765         hhcd->MspDeInitCallback = pCallback;
766         break;
767 
768       default :
769         /* Update the error code */
770         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
771         /* Return error status */
772         status =  HAL_ERROR;
773         break;
774     }
775   }
776   else if (hhcd->State == HAL_HCD_STATE_RESET)
777   {
778     switch (CallbackID)
779     {
780       case HAL_HCD_MSPINIT_CB_ID :
781         hhcd->MspInitCallback = pCallback;
782         break;
783 
784       case HAL_HCD_MSPDEINIT_CB_ID :
785         hhcd->MspDeInitCallback = pCallback;
786         break;
787 
788       default :
789         /* Update the error code */
790         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
791         /* Return error status */
792         status =  HAL_ERROR;
793         break;
794     }
795   }
796   else
797   {
798     /* Update the error code */
799     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
800     /* Return error status */
801     status =  HAL_ERROR;
802   }
803 
804   /* Release Lock */
805   __HAL_UNLOCK(hhcd);
806   return status;
807 }
808 
809 /**
810   * @brief  Unregister an USB HCD Callback
811   *         USB HCD callback is redirected to the weak predefined callback
812   * @param  hhcd USB HCD handle
813   * @param  CallbackID ID of the callback to be unregistered
814   *         This parameter can be one of the following values:
815   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
816   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
817   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
818   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
819   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
820   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
821   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
822   * @retval HAL status
823   */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)824 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
825 {
826   HAL_StatusTypeDef status = HAL_OK;
827 
828   /* Process locked */
829   __HAL_LOCK(hhcd);
830 
831   /* Setup Legacy weak Callbacks  */
832   if (hhcd->State == HAL_HCD_STATE_READY)
833   {
834     switch (CallbackID)
835     {
836       case HAL_HCD_SOF_CB_ID :
837         hhcd->SOFCallback = HAL_HCD_SOF_Callback;
838         break;
839 
840       case HAL_HCD_CONNECT_CB_ID :
841         hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
842         break;
843 
844       case HAL_HCD_DISCONNECT_CB_ID :
845         hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
846         break;
847 
848       case HAL_HCD_PORT_ENABLED_CB_ID :
849         hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
850         break;
851 
852       case HAL_HCD_PORT_DISABLED_CB_ID :
853         hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
854         break;
855 
856       case HAL_HCD_MSPINIT_CB_ID :
857         hhcd->MspInitCallback = HAL_HCD_MspInit;
858         break;
859 
860       case HAL_HCD_MSPDEINIT_CB_ID :
861         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
862         break;
863 
864       default :
865         /* Update the error code */
866         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
867 
868         /* Return error status */
869         status =  HAL_ERROR;
870         break;
871     }
872   }
873   else if (hhcd->State == HAL_HCD_STATE_RESET)
874   {
875     switch (CallbackID)
876     {
877       case HAL_HCD_MSPINIT_CB_ID :
878         hhcd->MspInitCallback = HAL_HCD_MspInit;
879         break;
880 
881       case HAL_HCD_MSPDEINIT_CB_ID :
882         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
883         break;
884 
885       default :
886         /* Update the error code */
887         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
888 
889         /* Return error status */
890         status =  HAL_ERROR;
891         break;
892     }
893   }
894   else
895   {
896     /* Update the error code */
897     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
898 
899     /* Return error status */
900     status =  HAL_ERROR;
901   }
902 
903   /* Release Lock */
904   __HAL_UNLOCK(hhcd);
905   return status;
906 }
907 
908 /**
909   * @brief  Register USB HCD Host Channel Notify URB Change Callback
910   *         To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
911   * @param  hhcd HCD handle
912   * @param  pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
913   * @retval HAL status
914   */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)915 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
916                                                              pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
917 {
918   HAL_StatusTypeDef status = HAL_OK;
919 
920   if (pCallback == NULL)
921   {
922     /* Update the error code */
923     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
924 
925     return HAL_ERROR;
926   }
927 
928   /* Process locked */
929   __HAL_LOCK(hhcd);
930 
931   if (hhcd->State == HAL_HCD_STATE_READY)
932   {
933     hhcd->HC_NotifyURBChangeCallback = pCallback;
934   }
935   else
936   {
937     /* Update the error code */
938     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
939 
940     /* Return error status */
941     status =  HAL_ERROR;
942   }
943 
944   /* Release Lock */
945   __HAL_UNLOCK(hhcd);
946 
947   return status;
948 }
949 
950 /**
951   * @brief  Unregister the USB HCD Host Channel Notify URB Change Callback
952   *         USB HCD Host Channel Notify URB Change Callback is redirected
953   *         to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
954   * @param  hhcd HCD handle
955   * @retval HAL status
956   */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)957 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
958 {
959   HAL_StatusTypeDef status = HAL_OK;
960 
961   /* Process locked */
962   __HAL_LOCK(hhcd);
963 
964   if (hhcd->State == HAL_HCD_STATE_READY)
965   {
966     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback  */
967   }
968   else
969   {
970     /* Update the error code */
971     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
972 
973     /* Return error status */
974     status =  HAL_ERROR;
975   }
976 
977   /* Release Lock */
978   __HAL_UNLOCK(hhcd);
979 
980   return status;
981 }
982 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
983 
984 /**
985   * @}
986   */
987 
988 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
989   *  @brief   Management functions
990   *
991 @verbatim
992  ===============================================================================
993                       ##### Peripheral Control functions #####
994  ===============================================================================
995     [..]
996     This subsection provides a set of functions allowing to control the HCD data
997     transfers.
998 
999 @endverbatim
1000   * @{
1001   */
1002 
1003 /**
1004   * @brief  Start the host driver.
1005   * @param  hhcd HCD handle
1006   * @retval HAL status
1007   */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1008 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1009 {
1010   __HAL_LOCK(hhcd);
1011   /* Enable port power */
1012   (void)USB_DriveVbus(hhcd->Instance, 1U);
1013 
1014   /* Enable global interrupt */
1015   __HAL_HCD_ENABLE(hhcd);
1016   __HAL_UNLOCK(hhcd);
1017 
1018   return HAL_OK;
1019 }
1020 
1021 /**
1022   * @brief  Stop the host driver.
1023   * @param  hhcd HCD handle
1024   * @retval HAL status
1025   */
1026 
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1027 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1028 {
1029   __HAL_LOCK(hhcd);
1030   (void)USB_StopHost(hhcd->Instance);
1031   __HAL_UNLOCK(hhcd);
1032 
1033   return HAL_OK;
1034 }
1035 
1036 /**
1037   * @brief  Reset the host port.
1038   * @param  hhcd HCD handle
1039   * @retval HAL status
1040   */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1041 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1042 {
1043   return (USB_ResetPort(hhcd->Instance));
1044 }
1045 
1046 /**
1047   * @}
1048   */
1049 
1050 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1051   *  @brief   Peripheral State functions
1052   *
1053 @verbatim
1054  ===============================================================================
1055                       ##### Peripheral State functions #####
1056  ===============================================================================
1057     [..]
1058     This subsection permits to get in run-time the status of the peripheral
1059     and the data flow.
1060 
1061 @endverbatim
1062   * @{
1063   */
1064 
1065 /**
1066   * @brief  Return the HCD handle state.
1067   * @param  hhcd HCD handle
1068   * @retval HAL state
1069   */
HAL_HCD_GetState(HCD_HandleTypeDef * hhcd)1070 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
1071 {
1072   return hhcd->State;
1073 }
1074 
1075 /**
1076   * @brief  Return  URB state for a channel.
1077   * @param  hhcd HCD handle
1078   * @param  chnum Channel number.
1079   *         This parameter can be a value from 1 to 15
1080   * @retval URB state.
1081   *          This parameter can be one of these values:
1082   *            URB_IDLE/
1083   *            URB_DONE/
1084   *            URB_NOTREADY/
1085   *            URB_NYET/
1086   *            URB_ERROR/
1087   *            URB_STALL
1088   */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef * hhcd,uint8_t chnum)1089 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1090 {
1091   return hhcd->hc[chnum].urb_state;
1092 }
1093 
1094 
1095 /**
1096   * @brief  Return the last host transfer size.
1097   * @param  hhcd HCD handle
1098   * @param  chnum Channel number.
1099   *         This parameter can be a value from 1 to 15
1100   * @retval last transfer size in byte
1101   */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef * hhcd,uint8_t chnum)1102 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1103 {
1104   return hhcd->hc[chnum].xfer_count;
1105 }
1106 
1107 /**
1108   * @brief  Return the Host Channel state.
1109   * @param  hhcd HCD handle
1110   * @param  chnum Channel number.
1111   *         This parameter can be a value from 1 to 15
1112   * @retval Host channel state
1113   *          This parameter can be one of these values:
1114   *            HC_IDLE/
1115   *            HC_XFRC/
1116   *            HC_HALTED/
1117   *            HC_NYET/
1118   *            HC_NAK/
1119   *            HC_STALL/
1120   *            HC_XACTERR/
1121   *            HC_BBLERR/
1122   *            HC_DATATGLERR
1123   */
HAL_HCD_HC_GetState(HCD_HandleTypeDef * hhcd,uint8_t chnum)1124 HCD_HCStateTypeDef  HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1125 {
1126   return hhcd->hc[chnum].state;
1127 }
1128 
1129 /**
1130   * @brief  Return the current Host frame number.
1131   * @param  hhcd HCD handle
1132   * @retval Current Host frame number
1133   */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1134 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1135 {
1136   return (USB_GetCurrentFrame(hhcd->Instance));
1137 }
1138 
1139 /**
1140   * @brief  Return the Host enumeration speed.
1141   * @param  hhcd HCD handle
1142   * @retval Enumeration speed
1143   */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1144 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1145 {
1146   return (USB_GetHostSpeed(hhcd->Instance));
1147 }
1148 
1149 /**
1150   * @}
1151   */
1152 
1153 /**
1154   * @}
1155   */
1156 
1157 /** @addtogroup HCD_Private_Functions
1158   * @{
1159   */
1160 /**
1161   * @brief  Handle Host Channel IN interrupt requests.
1162   * @param  hhcd HCD handle
1163   * @param  chnum Channel number.
1164   *         This parameter can be a value from 1 to 15
1165   * @retval none
1166   */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1167 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1168 {
1169   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1170   uint32_t USBx_BASE = (uint32_t)USBx;
1171   uint32_t tmpreg;
1172 
1173   if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1174   {
1175     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1176     hhcd->hc[chnum].state = HC_XACTERR;
1177     (void)USB_HC_Halt(hhcd->Instance, chnum);
1178   }
1179   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_BBERR))
1180   {
1181     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_BBERR);
1182     hhcd->hc[chnum].state = HC_BBLERR;
1183     (void)USB_HC_Halt(hhcd->Instance, chnum);
1184   }
1185   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1186   {
1187     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1188     hhcd->hc[chnum].state = HC_STALL;
1189     (void)USB_HC_Halt(hhcd->Instance, chnum);
1190   }
1191   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1192   {
1193     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1194     hhcd->hc[chnum].state = HC_DATATGLERR;
1195     (void)USB_HC_Halt(hhcd->Instance, chnum);
1196   }
1197   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1198   {
1199     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1200     hhcd->hc[chnum].state = HC_XACTERR;
1201     (void)USB_HC_Halt(hhcd->Instance, chnum);
1202   }
1203   else
1204   {
1205     /* ... */
1206   }
1207 
1208   if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1209   {
1210     (void)USB_HC_Halt(hhcd->Instance, chnum);
1211     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1212   }
1213   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1214   {
1215     /* Clear any pending ACK IT */
1216     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1217 
1218     if (hhcd->Init.dma_enable != 0U)
1219     {
1220       hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].XferSize - (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
1221     }
1222 
1223     hhcd->hc[chnum].state = HC_XFRC;
1224     hhcd->hc[chnum].ErrCnt = 0U;
1225     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1226 
1227     if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1228         (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1229     {
1230       (void)USB_HC_Halt(hhcd->Instance, chnum);
1231       __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1232     }
1233     else if ((hhcd->hc[chnum].ep_type == EP_TYPE_INTR) ||
1234              (hhcd->hc[chnum].ep_type == EP_TYPE_ISOC))
1235     {
1236       USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1237       hhcd->hc[chnum].urb_state = URB_DONE;
1238 
1239 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1240       hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1241 #else
1242       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1243 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1244     }
1245     else
1246     {
1247       /* ... */
1248     }
1249 
1250     if (hhcd->Init.dma_enable == 1U)
1251     {
1252       if ((((hhcd->hc[chnum].xfer_count + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet) & 1U) != 0U)
1253       {
1254         hhcd->hc[chnum].toggle_in ^= 1U;
1255       }
1256     }
1257     else
1258     {
1259       hhcd->hc[chnum].toggle_in ^= 1U;
1260     }
1261   }
1262   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1263   {
1264     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1265   }
1266   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1267   {
1268     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1269     if (hhcd->hc[chnum].state == HC_XFRC)
1270     {
1271       hhcd->hc[chnum].state = HC_HALTED;
1272       hhcd->hc[chnum].urb_state = URB_DONE;
1273     }
1274     else if (hhcd->hc[chnum].state == HC_STALL)
1275     {
1276       hhcd->hc[chnum].state = HC_HALTED;
1277       hhcd->hc[chnum].urb_state = URB_STALL;
1278     }
1279     else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1280              (hhcd->hc[chnum].state == HC_DATATGLERR))
1281     {
1282       hhcd->hc[chnum].state = HC_HALTED;
1283       hhcd->hc[chnum].ErrCnt++;
1284       if (hhcd->hc[chnum].ErrCnt > 2U)
1285       {
1286         hhcd->hc[chnum].ErrCnt = 0U;
1287         hhcd->hc[chnum].urb_state = URB_ERROR;
1288       }
1289       else
1290       {
1291         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1292 
1293         /* re-activate the channel */
1294         tmpreg = USBx_HC(chnum)->HCCHAR;
1295         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1296         tmpreg |= USB_OTG_HCCHAR_CHENA;
1297         USBx_HC(chnum)->HCCHAR = tmpreg;
1298       }
1299     }
1300     else if (hhcd->hc[chnum].state == HC_NYET)
1301     {
1302       hhcd->hc[chnum].state = HC_HALTED;
1303     }
1304     else if (hhcd->hc[chnum].state == HC_ACK)
1305     {
1306       hhcd->hc[chnum].state = HC_HALTED;
1307     }
1308     else if (hhcd->hc[chnum].state == HC_NAK)
1309     {
1310       hhcd->hc[chnum].state = HC_HALTED;
1311       hhcd->hc[chnum].urb_state = URB_NOTREADY;
1312 
1313       if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1314           (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1315       {
1316         /* re-activate the channel */
1317         tmpreg = USBx_HC(chnum)->HCCHAR;
1318         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1319         tmpreg |= USB_OTG_HCCHAR_CHENA;
1320         USBx_HC(chnum)->HCCHAR = tmpreg;
1321       }
1322     }
1323     else if (hhcd->hc[chnum].state == HC_BBLERR)
1324     {
1325       hhcd->hc[chnum].state = HC_HALTED;
1326       hhcd->hc[chnum].ErrCnt++;
1327       hhcd->hc[chnum].urb_state = URB_ERROR;
1328     }
1329     else
1330     {
1331       if (hhcd->hc[chnum].state == HC_HALTED)
1332       {
1333         return;
1334       }
1335     }
1336 
1337 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1338     hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1339 #else
1340     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1341 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1342   }
1343   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1344   {
1345     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1346     hhcd->hc[chnum].state = HC_NYET;
1347     hhcd->hc[chnum].ErrCnt = 0U;
1348 
1349     (void)USB_HC_Halt(hhcd->Instance, chnum);
1350   }
1351   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1352   {
1353     if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1354     {
1355       hhcd->hc[chnum].ErrCnt = 0U;
1356       hhcd->hc[chnum].state = HC_NAK;
1357       (void)USB_HC_Halt(hhcd->Instance, chnum);
1358     }
1359     else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1360              (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1361     {
1362       hhcd->hc[chnum].ErrCnt = 0U;
1363 
1364       if (hhcd->Init.dma_enable == 0U)
1365       {
1366         hhcd->hc[chnum].state = HC_NAK;
1367         (void)USB_HC_Halt(hhcd->Instance, chnum);
1368       }
1369     }
1370     else
1371     {
1372       /* ... */
1373     }
1374     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1375   }
1376   else
1377   {
1378     /* ... */
1379   }
1380 }
1381 
1382 /**
1383   * @brief  Handle Host Channel OUT interrupt requests.
1384   * @param  hhcd HCD handle
1385   * @param  chnum Channel number.
1386   *         This parameter can be a value from 1 to 15
1387   * @retval none
1388   */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1389 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1390 {
1391   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1392   uint32_t USBx_BASE = (uint32_t)USBx;
1393   uint32_t tmpreg;
1394   uint32_t num_packets;
1395 
1396   if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1397   {
1398     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1399     hhcd->hc[chnum].state = HC_XACTERR;
1400     (void)USB_HC_Halt(hhcd->Instance, chnum);
1401   }
1402   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1403   {
1404     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1405 
1406     if (hhcd->hc[chnum].do_ping == 1U)
1407     {
1408       hhcd->hc[chnum].do_ping = 0U;
1409       hhcd->hc[chnum].urb_state = URB_NOTREADY;
1410       hhcd->hc[chnum].state = HC_ACK;
1411       (void)USB_HC_Halt(hhcd->Instance, chnum);
1412     }
1413   }
1414   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1415   {
1416     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1417     (void)USB_HC_Halt(hhcd->Instance, chnum);
1418   }
1419   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1420   {
1421     hhcd->hc[chnum].ErrCnt = 0U;
1422 
1423     /* transaction completed with NYET state, update do ping state */
1424     if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1425     {
1426       hhcd->hc[chnum].do_ping = 1U;
1427       __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1428     }
1429     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1430     hhcd->hc[chnum].state = HC_XFRC;
1431     (void)USB_HC_Halt(hhcd->Instance, chnum);
1432   }
1433   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1434   {
1435     hhcd->hc[chnum].state = HC_NYET;
1436     hhcd->hc[chnum].do_ping = 1U;
1437     hhcd->hc[chnum].ErrCnt = 0U;
1438     (void)USB_HC_Halt(hhcd->Instance, chnum);
1439     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1440   }
1441   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1442   {
1443     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1444     hhcd->hc[chnum].state = HC_STALL;
1445     (void)USB_HC_Halt(hhcd->Instance, chnum);
1446   }
1447   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1448   {
1449     hhcd->hc[chnum].ErrCnt = 0U;
1450     hhcd->hc[chnum].state = HC_NAK;
1451 
1452     if (hhcd->hc[chnum].do_ping == 0U)
1453     {
1454       if (hhcd->hc[chnum].speed == HCD_DEVICE_SPEED_HIGH)
1455       {
1456         hhcd->hc[chnum].do_ping = 1U;
1457       }
1458     }
1459 
1460     (void)USB_HC_Halt(hhcd->Instance, chnum);
1461     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1462   }
1463   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1464   {
1465     if (hhcd->Init.dma_enable == 0U)
1466     {
1467       hhcd->hc[chnum].state = HC_XACTERR;
1468       (void)USB_HC_Halt(hhcd->Instance, chnum);
1469     }
1470     else
1471     {
1472       hhcd->hc[chnum].ErrCnt++;
1473       if (hhcd->hc[chnum].ErrCnt > 2U)
1474       {
1475         hhcd->hc[chnum].ErrCnt = 0U;
1476         hhcd->hc[chnum].urb_state = URB_ERROR;
1477 
1478 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1479         hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1480 #else
1481         HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1482 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1483       }
1484       else
1485       {
1486         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1487       }
1488     }
1489     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1490   }
1491   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1492   {
1493     hhcd->hc[chnum].state = HC_DATATGLERR;
1494     (void)USB_HC_Halt(hhcd->Instance, chnum);
1495     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1496   }
1497   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1498   {
1499     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1500     if (hhcd->hc[chnum].state == HC_XFRC)
1501     {
1502       hhcd->hc[chnum].state = HC_HALTED;
1503       hhcd->hc[chnum].urb_state  = URB_DONE;
1504       if ((hhcd->hc[chnum].ep_type == EP_TYPE_BULK) ||
1505           (hhcd->hc[chnum].ep_type == EP_TYPE_INTR))
1506       {
1507         if (hhcd->Init.dma_enable == 0U)
1508         {
1509           hhcd->hc[chnum].toggle_out ^= 1U;
1510         }
1511 
1512         if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[chnum].xfer_len > 0U))
1513         {
1514           num_packets = (hhcd->hc[chnum].xfer_len + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet;
1515 
1516           if ((num_packets & 1U) != 0U)
1517           {
1518             hhcd->hc[chnum].toggle_out ^= 1U;
1519           }
1520         }
1521       }
1522     }
1523     else if (hhcd->hc[chnum].state == HC_ACK)
1524     {
1525       hhcd->hc[chnum].state = HC_HALTED;
1526     }
1527     else if (hhcd->hc[chnum].state == HC_NAK)
1528     {
1529       hhcd->hc[chnum].state = HC_HALTED;
1530       hhcd->hc[chnum].urb_state = URB_NOTREADY;
1531     }
1532     else if (hhcd->hc[chnum].state == HC_NYET)
1533     {
1534       hhcd->hc[chnum].state = HC_HALTED;
1535       hhcd->hc[chnum].urb_state  = URB_NOTREADY;
1536     }
1537     else if (hhcd->hc[chnum].state == HC_STALL)
1538     {
1539       hhcd->hc[chnum].state = HC_HALTED;
1540       hhcd->hc[chnum].urb_state  = URB_STALL;
1541     }
1542     else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1543              (hhcd->hc[chnum].state == HC_DATATGLERR))
1544     {
1545       hhcd->hc[chnum].state = HC_HALTED;
1546       hhcd->hc[chnum].ErrCnt++;
1547       if (hhcd->hc[chnum].ErrCnt > 2U)
1548       {
1549         hhcd->hc[chnum].ErrCnt = 0U;
1550         hhcd->hc[chnum].urb_state = URB_ERROR;
1551       }
1552       else
1553       {
1554         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1555 
1556         /* re-activate the channel  */
1557         tmpreg = USBx_HC(chnum)->HCCHAR;
1558         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1559         tmpreg |= USB_OTG_HCCHAR_CHENA;
1560         USBx_HC(chnum)->HCCHAR = tmpreg;
1561       }
1562     }
1563     else
1564     {
1565       return;
1566     }
1567 
1568 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1569     hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1570 #else
1571     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1572 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1573   }
1574   else
1575   {
1576     /* ... */
1577   }
1578 }
1579 
1580 /**
1581   * @brief  Handle Rx Queue Level interrupt requests.
1582   * @param  hhcd HCD handle
1583   * @retval none
1584   */
HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef * hhcd)1585 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1586 {
1587   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1588   uint32_t USBx_BASE = (uint32_t)USBx;
1589   uint32_t pktsts;
1590   uint32_t pktcnt;
1591   uint32_t GrxstspReg;
1592   uint32_t xferSizePktCnt;
1593   uint32_t tmpreg;
1594   uint32_t chnum;
1595 
1596   GrxstspReg = hhcd->Instance->GRXSTSP;
1597   chnum = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
1598   pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1599   pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
1600 
1601   switch (pktsts)
1602   {
1603     case GRXSTS_PKTSTS_IN:
1604       /* Read the data into the host buffer. */
1605       if ((pktcnt > 0U) && (hhcd->hc[chnum].xfer_buff != (void *)0))
1606       {
1607         if ((hhcd->hc[chnum].xfer_count + pktcnt) <= hhcd->hc[chnum].xfer_len)
1608         {
1609           (void)USB_ReadPacket(hhcd->Instance,
1610                                hhcd->hc[chnum].xfer_buff, (uint16_t)pktcnt);
1611 
1612           /* manage multiple Xfer */
1613           hhcd->hc[chnum].xfer_buff += pktcnt;
1614           hhcd->hc[chnum].xfer_count += pktcnt;
1615 
1616           /* get transfer size packet count */
1617           xferSizePktCnt = (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
1618 
1619           if ((hhcd->hc[chnum].max_packet == pktcnt) && (xferSizePktCnt > 0U))
1620           {
1621             /* re-activate the channel when more packets are expected */
1622             tmpreg = USBx_HC(chnum)->HCCHAR;
1623             tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1624             tmpreg |= USB_OTG_HCCHAR_CHENA;
1625             USBx_HC(chnum)->HCCHAR = tmpreg;
1626             hhcd->hc[chnum].toggle_in ^= 1U;
1627           }
1628         }
1629         else
1630         {
1631           hhcd->hc[chnum].urb_state = URB_ERROR;
1632         }
1633       }
1634       break;
1635 
1636     case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1637       break;
1638 
1639     case GRXSTS_PKTSTS_IN_XFER_COMP:
1640     case GRXSTS_PKTSTS_CH_HALTED:
1641     default:
1642       break;
1643   }
1644 }
1645 
1646 /**
1647   * @brief  Handle Host Port interrupt requests.
1648   * @param  hhcd HCD handle
1649   * @retval None
1650   */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)1651 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1652 {
1653   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1654   uint32_t USBx_BASE = (uint32_t)USBx;
1655   __IO uint32_t hprt0;
1656   __IO uint32_t hprt0_dup;
1657 
1658   /* Handle Host Port Interrupts */
1659   hprt0 = USBx_HPRT0;
1660   hprt0_dup = USBx_HPRT0;
1661 
1662   hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1663                  USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1664 
1665   /* Check whether Port Connect detected */
1666   if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1667   {
1668     if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1669     {
1670 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1671       hhcd->ConnectCallback(hhcd);
1672 #else
1673       HAL_HCD_Connect_Callback(hhcd);
1674 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1675     }
1676     hprt0_dup |= USB_OTG_HPRT_PCDET;
1677   }
1678 
1679   /* Check whether Port Enable Changed */
1680   if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1681   {
1682     hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1683 
1684     if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1685     {
1686       if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1687       {
1688         if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1689         {
1690           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1691         }
1692         else
1693         {
1694           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1695         }
1696       }
1697       else
1698       {
1699         if (hhcd->Init.speed == HCD_SPEED_FULL)
1700         {
1701           USBx_HOST->HFIR = HFIR_60_MHZ;
1702         }
1703       }
1704 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1705       hhcd->PortEnabledCallback(hhcd);
1706 #else
1707       HAL_HCD_PortEnabled_Callback(hhcd);
1708 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1709 
1710     }
1711     else
1712     {
1713 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1714       hhcd->PortDisabledCallback(hhcd);
1715 #else
1716       HAL_HCD_PortDisabled_Callback(hhcd);
1717 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1718     }
1719   }
1720 
1721   /* Check for an overcurrent */
1722   if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1723   {
1724     hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1725   }
1726 
1727   /* Clear Port Interrupts */
1728   USBx_HPRT0 = hprt0_dup;
1729 }
1730 
1731 /**
1732   * @}
1733   */
1734 
1735 /**
1736   * @}
1737   */
1738 
1739 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1740 #endif /* HAL_HCD_MODULE_ENABLED */
1741 
1742 /**
1743   * @}
1744   */
1745 
1746 /**
1747   * @}
1748   */
1749