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