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