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