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