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