1 /**
2   ******************************************************************************
3   * @file    stm32u5xx_hal_hcd.c
4   * @author  MCD Application Team
5   * @brief   HCD HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the USB Peripheral Controller:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *           + Peripheral Control functions
11   *           + Peripheral State functions
12   *
13   ******************************************************************************
14   * @attention
15   *
16   * Copyright (c) 2021 STMicroelectronics.
17   * All rights reserved.
18   *
19   * This software is licensed under terms that can be found in the LICENSE file
20   * in the root directory of this software component.
21   * If no LICENSE file comes with this software, it is provided AS-IS.
22   *
23   ******************************************************************************
24   @verbatim
25   ==============================================================================
26                     ##### How to use this driver #####
27   ==============================================================================
28   [..]
29     (#)Declare a HCD_HandleTypeDef handle structure, for example:
30        HCD_HandleTypeDef  hhcd;
31 
32     (#)Fill parameters of Init structure in HCD handle
33 
34     (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
35 
36     (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
37         (##) Enable the HCD/USB Low Level interface clock using the following macros
38              (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
39              (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
40              (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
41 
42              (+++) __HAL_RCC_USB_CLK_ENABLE();
43         (##) Initialize the related GPIO clocks
44         (##) Configure HCD pin-out
45         (##) Configure HCD NVIC interrupt
46 
47     (#)Associate the Upper USB Host stack to the HAL HCD Driver:
48         (##) hhcd.pData = phost;
49 
50     (#)Enable HCD transmission and reception:
51         (##) HAL_HCD_Start();
52 
53   @endverbatim
54   ******************************************************************************
55   */
56 
57 /* Includes ------------------------------------------------------------------*/
58 #include "stm32u5xx_hal.h"
59 
60 /** @addtogroup STM32U5xx_HAL_Driver
61   * @{
62   */
63 
64 #ifdef HAL_HCD_MODULE_ENABLED
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 #if defined (STM32U575xx) || defined (STM32U585xx)
114   USB_OTG_GlobalTypeDef *USBx;
115 #endif /* defined (STM32U575xx) || defined (STM32U585xx) */
116 
117   /* Check the HCD handle allocation */
118   if (hhcd == NULL)
119   {
120     return HAL_ERROR;
121   }
122 
123   /* Check the parameters */
124   assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
125 
126 #if defined (STM32U575xx) || defined (STM32U585xx)
127   USBx = hhcd->Instance;
128 #endif /* defined (STM32U575xx) || defined (STM32U585xx) */
129 
130   if (hhcd->State == HAL_HCD_STATE_RESET)
131   {
132     /* Allocate lock resource and initialize it */
133     hhcd->Lock = HAL_UNLOCKED;
134 
135 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
136     hhcd->SOFCallback = HAL_HCD_SOF_Callback;
137     hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
138     hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
139     hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
140     hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
141     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
142 
143     if (hhcd->MspInitCallback == NULL)
144     {
145       hhcd->MspInitCallback = HAL_HCD_MspInit;
146     }
147 
148     /* Init the low level hardware */
149     hhcd->MspInitCallback(hhcd);
150 #else
151     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
152     HAL_HCD_MspInit(hhcd);
153 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
154   }
155 
156   hhcd->State = HAL_HCD_STATE_BUSY;
157 #if defined (STM32U575xx) || defined (STM32U585xx)
158   /* Disable DMA mode for FS instance */
159   if ((USBx->CID & (0x1U << 14)) == 0U)
160   {
161     hhcd->Init.dma_enable = 0U;
162   }
163 #endif /* defined (STM32U575xx) || defined (STM32U585xx) */
164   /* Disable the Interrupts */
165   __HAL_HCD_DISABLE(hhcd);
166 
167   /* Init the Core (common init.) */
168   (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
169 
170   /* Force Host Mode*/
171   (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
172 
173   /* Init Host */
174   (void)USB_HostInit(hhcd->Instance, hhcd->Init);
175 
176   hhcd->State = HAL_HCD_STATE_READY;
177 
178   return HAL_OK;
179 }
180 
181 /**
182   * @brief  Initialize a host channel.
183   * @param  hhcd HCD handle
184   * @param  ch_num Channel number.
185   *         This parameter can be a value from 1 to 15
186   * @param  epnum Endpoint number.
187   *          This parameter can be a value from 1 to 15
188   * @param  dev_address Current device address
189   *          This parameter can be a value from 0 to 255
190   * @param  speed Current device speed.
191   *          This parameter can be one of these values:
192   *            HCD_DEVICE_SPEED_HIGH: High speed mode,
193   *            HCD_DEVICE_SPEED_FULL: Full speed mode,
194   *            HCD_DEVICE_SPEED_LOW: Low speed mode
195   * @param  ep_type Endpoint Type.
196   *          This parameter can be one of these values:
197   *            EP_TYPE_CTRL: Control type,
198   *            EP_TYPE_ISOC: Isochronous type,
199   *            EP_TYPE_BULK: Bulk type,
200   *            EP_TYPE_INTR: Interrupt type
201   * @param  mps Max Packet Size.
202   *          This parameter can be a value from 0 to32K
203   * @retval HAL status
204   */
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)205 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum,
206                                   uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
207 {
208   HAL_StatusTypeDef status;
209   uint32_t HostCoreSpeed;
210   uint32_t HCcharMps = mps;
211 
212   __HAL_LOCK(hhcd);
213   hhcd->hc[ch_num].do_ping = 0U;
214   hhcd->hc[ch_num].dev_addr = dev_address;
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   (void)HAL_HCD_HC_ClearHubInfo(hhcd, ch_num);
220 
221   if ((epnum & 0x80U) == 0x80U)
222   {
223     hhcd->hc[ch_num].ep_is_in = 1U;
224   }
225   else
226   {
227     hhcd->hc[ch_num].ep_is_in = 0U;
228   }
229 
230   HostCoreSpeed = USB_GetHostSpeed(hhcd->Instance);
231 
232   if (ep_type == EP_TYPE_ISOC)
233   {
234     /* FS device plugged to HS HUB */
235     if ((speed == HCD_DEVICE_SPEED_FULL) && (HostCoreSpeed == HPRT0_PRTSPD_HIGH_SPEED))
236     {
237       if (HCcharMps > ISO_SPLT_MPS)
238       {
239         /* ISO Max Packet Size for Split mode */
240         HCcharMps = ISO_SPLT_MPS;
241       }
242     }
243   }
244 
245   hhcd->hc[ch_num].speed = speed;
246   hhcd->hc[ch_num].max_packet = (uint16_t)HCcharMps;
247 
248   status =  USB_HC_Init(hhcd->Instance, ch_num, epnum,
249                         dev_address, speed, ep_type, (uint16_t)HCcharMps);
250 
251   __HAL_UNLOCK(hhcd);
252 
253   return status;
254 }
255 
256 /**
257   * @brief  Halt a host channel.
258   * @param  hhcd HCD handle
259   * @param  ch_num Channel number.
260   *         This parameter can be a value from 1 to 15
261   * @retval HAL status
262   */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)263 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
264 {
265   HAL_StatusTypeDef status = HAL_OK;
266 
267   __HAL_LOCK(hhcd);
268   (void)USB_HC_Halt(hhcd->Instance, ch_num);
269   __HAL_UNLOCK(hhcd);
270 
271   return status;
272 }
273 
274 /**
275   * @brief  DeInitialize the host driver.
276   * @param  hhcd HCD handle
277   * @retval HAL status
278   */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)279 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
280 {
281   /* Check the HCD handle allocation */
282   if (hhcd == NULL)
283   {
284     return HAL_ERROR;
285   }
286 
287   hhcd->State = HAL_HCD_STATE_BUSY;
288 
289 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
290   if (hhcd->MspDeInitCallback == NULL)
291   {
292     hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit  */
293   }
294 
295   /* DeInit the low level hardware */
296   hhcd->MspDeInitCallback(hhcd);
297 #else
298   /* DeInit the low level hardware: CLOCK, NVIC.*/
299   HAL_HCD_MspDeInit(hhcd);
300 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
301 
302   __HAL_HCD_DISABLE(hhcd);
303 
304   hhcd->State = HAL_HCD_STATE_RESET;
305 
306   return HAL_OK;
307 }
308 
309 /**
310   * @brief  Initialize the HCD MSP.
311   * @param  hhcd HCD handle
312   * @retval None
313   */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)314 __weak void  HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
315 {
316   /* Prevent unused argument(s) compilation warning */
317   UNUSED(hhcd);
318 
319   /* NOTE : This function should not be modified, when the callback is needed,
320             the HAL_HCD_MspInit could be implemented in the user file
321    */
322 }
323 
324 /**
325   * @brief  DeInitialize the HCD MSP.
326   * @param  hhcd HCD handle
327   * @retval None
328   */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)329 __weak void  HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
330 {
331   /* Prevent unused argument(s) compilation warning */
332   UNUSED(hhcd);
333 
334   /* NOTE : This function should not be modified, when the callback is needed,
335             the HAL_HCD_MspDeInit could be implemented in the user file
336    */
337 }
338 
339 /**
340   * @}
341   */
342 
343 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
344   *  @brief   HCD IO operation functions
345   *
346 @verbatim
347  ===============================================================================
348                       ##### IO operation functions #####
349  ===============================================================================
350  [..] This subsection provides a set of functions allowing to manage the USB Host Data
351     Transfer
352 
353 @endverbatim
354   * @{
355   */
356 
357 /**
358   * @brief  Submit a new URB for processing.
359   * @param  hhcd HCD handle
360   * @param  ch_num Channel number.
361   *         This parameter can be a value from 1 to 15
362   * @param  direction Channel number.
363   *          This parameter can be one of these values:
364   *           0 : Output / 1 : Input
365   * @param  ep_type Endpoint Type.
366   *          This parameter can be one of these values:
367   *            EP_TYPE_CTRL: Control type/
368   *            EP_TYPE_ISOC: Isochronous type/
369   *            EP_TYPE_BULK: Bulk type/
370   *            EP_TYPE_INTR: Interrupt type/
371   * @param  token Endpoint Type.
372   *          This parameter can be one of these values:
373   *            0: HC_PID_SETUP / 1: HC_PID_DATA1
374   * @param  pbuff pointer to URB data
375   * @param  length Length of URB data
376   * @param  do_ping activate do ping protocol (for high speed only).
377   *          This parameter can be one of these values:
378   *           0 : do ping inactive / 1 : do ping active
379   * @retval HAL status
380   */
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)381 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
382                                            uint8_t ch_num,
383                                            uint8_t direction,
384                                            uint8_t ep_type,
385                                            uint8_t token,
386                                            uint8_t *pbuff,
387                                            uint16_t length,
388                                            uint8_t do_ping)
389 {
390   hhcd->hc[ch_num].ep_is_in = direction;
391   hhcd->hc[ch_num].ep_type  = ep_type;
392 
393   if (token == 0U)
394   {
395     hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
396     hhcd->hc[ch_num].do_ping = do_ping;
397   }
398   else
399   {
400     hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
401   }
402 
403   /* Manage Data Toggle */
404   switch (ep_type)
405   {
406     case EP_TYPE_CTRL:
407       if (token == 1U) /* send data */
408       {
409         if (direction == 0U)
410         {
411           if (length == 0U)
412           {
413             /* For Status OUT stage, Length == 0U, Status Out PID = 1 */
414             hhcd->hc[ch_num].toggle_out = 1U;
415           }
416 
417           /* Set the Data Toggle bit as per the Flag */
418           if (hhcd->hc[ch_num].toggle_out == 0U)
419           {
420             /* Put the PID 0 */
421             hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
422           }
423           else
424           {
425             /* Put the PID 1 */
426             hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
427           }
428         }
429         else
430         {
431           if (hhcd->hc[ch_num].do_ssplit == 1U)
432           {
433             if (hhcd->hc[ch_num].toggle_in == 0U)
434             {
435               hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
436             }
437             else
438             {
439               hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
440             }
441           }
442         }
443       }
444       break;
445 
446     case EP_TYPE_BULK:
447       if (direction == 0U)
448       {
449         /* Set the Data Toggle bit as per the Flag */
450         if (hhcd->hc[ch_num].toggle_out == 0U)
451         {
452           /* Put the PID 0 */
453           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
454         }
455         else
456         {
457           /* Put the PID 1 */
458           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
459         }
460       }
461       else
462       {
463         if (hhcd->hc[ch_num].toggle_in == 0U)
464         {
465           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
466         }
467         else
468         {
469           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
470         }
471       }
472 
473       break;
474     case EP_TYPE_INTR:
475       if (direction == 0U)
476       {
477         /* Set the Data Toggle bit as per the Flag */
478         if (hhcd->hc[ch_num].toggle_out == 0U)
479         {
480           /* Put the PID 0 */
481           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
482         }
483         else
484         {
485           /* Put the PID 1 */
486           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
487         }
488       }
489       else
490       {
491         if (hhcd->hc[ch_num].toggle_in == 0U)
492         {
493           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
494         }
495         else
496         {
497           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
498         }
499       }
500       break;
501 
502     case EP_TYPE_ISOC:
503       hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
504       break;
505 
506     default:
507       break;
508   }
509 
510   hhcd->hc[ch_num].xfer_buff = pbuff;
511   hhcd->hc[ch_num].xfer_len  = length;
512   hhcd->hc[ch_num].urb_state = URB_IDLE;
513   hhcd->hc[ch_num].xfer_count = 0U;
514   hhcd->hc[ch_num].ch_num = ch_num;
515   hhcd->hc[ch_num].state = HC_IDLE;
516 
517   return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable);
518 }
519 
520 /**
521   * @brief  Handle HCD interrupt request.
522   * @param  hhcd HCD handle
523   * @retval None
524   */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)525 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
526 {
527   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
528   uint32_t USBx_BASE = (uint32_t)USBx;
529   uint32_t i;
530   uint32_t interrupt;
531 
532   /* Ensure that we are in device mode */
533   if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
534   {
535     /* Avoid spurious interrupt */
536     if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
537     {
538       return;
539     }
540 
541     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
542     {
543       /* Incorrect mode, acknowledge the interrupt */
544       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
545     }
546 
547     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
548     {
549       /* Incorrect mode, acknowledge the interrupt */
550       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
551     }
552 
553     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
554     {
555       /* Incorrect mode, acknowledge the interrupt */
556       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
557     }
558 
559     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
560     {
561       /* Incorrect mode, acknowledge the interrupt */
562       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
563     }
564 
565     /* Handle Host Disconnect Interrupts */
566     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
567     {
568       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
569 
570       if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
571       {
572         /* Flush USB Fifo */
573         (void)USB_FlushTxFifo(USBx, 0x10U);
574         (void)USB_FlushRxFifo(USBx);
575 
576         if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
577         {
578           /* Restore FS Clock */
579           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
580         }
581 
582         /* Handle Host Port Disconnect Interrupt */
583 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
584         hhcd->DisconnectCallback(hhcd);
585 #else
586         HAL_HCD_Disconnect_Callback(hhcd);
587 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
588       }
589     }
590 
591     /* Handle Host Port Interrupts */
592     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
593     {
594       HCD_Port_IRQHandler(hhcd);
595     }
596 
597     /* Handle Host SOF Interrupt */
598     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
599     {
600 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
601       hhcd->SOFCallback(hhcd);
602 #else
603       HAL_HCD_SOF_Callback(hhcd);
604 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
605 
606       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
607     }
608 
609     /* Handle Host channel Interrupt */
610     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
611     {
612       interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
613       for (i = 0U; i < hhcd->Init.Host_channels; i++)
614       {
615         if ((interrupt & (1UL << (i & 0xFU))) != 0U)
616         {
617           if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
618           {
619             HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
620           }
621           else
622           {
623             HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
624           }
625         }
626       }
627       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
628     }
629 
630     /* Handle Rx Queue Level Interrupts */
631     if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
632     {
633       USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
634 
635       HCD_RXQLVL_IRQHandler(hhcd);
636 
637       USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
638     }
639   }
640 }
641 
642 
643 /**
644   * @brief  SOF callback.
645   * @param  hhcd HCD handle
646   * @retval None
647   */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)648 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
649 {
650   /* Prevent unused argument(s) compilation warning */
651   UNUSED(hhcd);
652 
653   /* NOTE : This function should not be modified, when the callback is needed,
654             the HAL_HCD_SOF_Callback could be implemented in the user file
655    */
656 }
657 
658 /**
659   * @brief Connection Event callback.
660   * @param  hhcd HCD handle
661   * @retval None
662   */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)663 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
664 {
665   /* Prevent unused argument(s) compilation warning */
666   UNUSED(hhcd);
667 
668   /* NOTE : This function should not be modified, when the callback is needed,
669             the HAL_HCD_Connect_Callback could be implemented in the user file
670    */
671 }
672 
673 /**
674   * @brief  Disconnection Event callback.
675   * @param  hhcd HCD handle
676   * @retval None
677   */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)678 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
679 {
680   /* Prevent unused argument(s) compilation warning */
681   UNUSED(hhcd);
682 
683   /* NOTE : This function should not be modified, when the callback is needed,
684             the HAL_HCD_Disconnect_Callback could be implemented in the user file
685    */
686 }
687 
688 /**
689   * @brief  Port Enabled  Event callback.
690   * @param  hhcd HCD handle
691   * @retval None
692   */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)693 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
694 {
695   /* Prevent unused argument(s) compilation warning */
696   UNUSED(hhcd);
697 
698   /* NOTE : This function should not be modified, when the callback is needed,
699             the HAL_HCD_Disconnect_Callback could be implemented in the user file
700    */
701 }
702 
703 /**
704   * @brief  Port Disabled  Event callback.
705   * @param  hhcd HCD handle
706   * @retval None
707   */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)708 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
709 {
710   /* Prevent unused argument(s) compilation warning */
711   UNUSED(hhcd);
712 
713   /* NOTE : This function should not be modified, when the callback is needed,
714             the HAL_HCD_Disconnect_Callback could be implemented in the user file
715    */
716 }
717 
718 /**
719   * @brief  Notify URB state change callback.
720   * @param  hhcd HCD handle
721   * @param  chnum Channel number.
722   *         This parameter can be a value from 1 to 15
723   * @param  urb_state:
724   *          This parameter can be one of these values:
725   *            URB_IDLE/
726   *            URB_DONE/
727   *            URB_NOTREADY/
728   *            URB_NYET/
729   *            URB_ERROR/
730   *            URB_STALL/
731   * @retval None
732   */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)733 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
734 {
735   /* Prevent unused argument(s) compilation warning */
736   UNUSED(hhcd);
737   UNUSED(chnum);
738   UNUSED(urb_state);
739 
740   /* NOTE : This function should not be modified, when the callback is needed,
741             the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
742    */
743 }
744 
745 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
746 /**
747   * @brief  Register a User USB HCD Callback
748   *         To be used instead of the weak predefined callback
749   * @param  hhcd USB HCD handle
750   * @param  CallbackID ID of the callback to be registered
751   *         This parameter can be one of the following values:
752   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
753   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
754   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
755   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
756   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
757   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
758   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
759   * @param  pCallback pointer to the Callback function
760   * @retval HAL status
761   */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)762 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
763                                            HAL_HCD_CallbackIDTypeDef CallbackID,
764                                            pHCD_CallbackTypeDef pCallback)
765 {
766   HAL_StatusTypeDef status = HAL_OK;
767 
768   if (pCallback == NULL)
769   {
770     /* Update the error code */
771     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
772     return HAL_ERROR;
773   }
774   /* Process locked */
775   __HAL_LOCK(hhcd);
776 
777   if (hhcd->State == HAL_HCD_STATE_READY)
778   {
779     switch (CallbackID)
780     {
781       case HAL_HCD_SOF_CB_ID :
782         hhcd->SOFCallback = pCallback;
783         break;
784 
785       case HAL_HCD_CONNECT_CB_ID :
786         hhcd->ConnectCallback = pCallback;
787         break;
788 
789       case HAL_HCD_DISCONNECT_CB_ID :
790         hhcd->DisconnectCallback = pCallback;
791         break;
792 
793       case HAL_HCD_PORT_ENABLED_CB_ID :
794         hhcd->PortEnabledCallback = pCallback;
795         break;
796 
797       case HAL_HCD_PORT_DISABLED_CB_ID :
798         hhcd->PortDisabledCallback = pCallback;
799         break;
800 
801       case HAL_HCD_MSPINIT_CB_ID :
802         hhcd->MspInitCallback = pCallback;
803         break;
804 
805       case HAL_HCD_MSPDEINIT_CB_ID :
806         hhcd->MspDeInitCallback = pCallback;
807         break;
808 
809       default :
810         /* Update the error code */
811         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
812         /* Return error status */
813         status =  HAL_ERROR;
814         break;
815     }
816   }
817   else if (hhcd->State == HAL_HCD_STATE_RESET)
818   {
819     switch (CallbackID)
820     {
821       case HAL_HCD_MSPINIT_CB_ID :
822         hhcd->MspInitCallback = pCallback;
823         break;
824 
825       case HAL_HCD_MSPDEINIT_CB_ID :
826         hhcd->MspDeInitCallback = pCallback;
827         break;
828 
829       default :
830         /* Update the error code */
831         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
832         /* Return error status */
833         status =  HAL_ERROR;
834         break;
835     }
836   }
837   else
838   {
839     /* Update the error code */
840     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
841     /* Return error status */
842     status =  HAL_ERROR;
843   }
844 
845   /* Release Lock */
846   __HAL_UNLOCK(hhcd);
847   return status;
848 }
849 
850 /**
851   * @brief  Unregister an USB HCD Callback
852   *         USB HCD callback is redirected to the weak predefined callback
853   * @param  hhcd USB HCD handle
854   * @param  CallbackID ID of the callback to be unregistered
855   *         This parameter can be one of the following values:
856   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
857   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
858   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
859   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
860   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
861   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
862   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
863   * @retval HAL status
864   */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)865 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
866 {
867   HAL_StatusTypeDef status = HAL_OK;
868 
869   /* Process locked */
870   __HAL_LOCK(hhcd);
871 
872   /* Setup Legacy weak Callbacks  */
873   if (hhcd->State == HAL_HCD_STATE_READY)
874   {
875     switch (CallbackID)
876     {
877       case HAL_HCD_SOF_CB_ID :
878         hhcd->SOFCallback = HAL_HCD_SOF_Callback;
879         break;
880 
881       case HAL_HCD_CONNECT_CB_ID :
882         hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
883         break;
884 
885       case HAL_HCD_DISCONNECT_CB_ID :
886         hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
887         break;
888 
889       case HAL_HCD_PORT_ENABLED_CB_ID :
890         hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
891         break;
892 
893       case HAL_HCD_PORT_DISABLED_CB_ID :
894         hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
895         break;
896 
897       case HAL_HCD_MSPINIT_CB_ID :
898         hhcd->MspInitCallback = HAL_HCD_MspInit;
899         break;
900 
901       case HAL_HCD_MSPDEINIT_CB_ID :
902         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
903         break;
904 
905       default :
906         /* Update the error code */
907         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
908 
909         /* Return error status */
910         status =  HAL_ERROR;
911         break;
912     }
913   }
914   else if (hhcd->State == HAL_HCD_STATE_RESET)
915   {
916     switch (CallbackID)
917     {
918       case HAL_HCD_MSPINIT_CB_ID :
919         hhcd->MspInitCallback = HAL_HCD_MspInit;
920         break;
921 
922       case HAL_HCD_MSPDEINIT_CB_ID :
923         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
924         break;
925 
926       default :
927         /* Update the error code */
928         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
929 
930         /* Return error status */
931         status =  HAL_ERROR;
932         break;
933     }
934   }
935   else
936   {
937     /* Update the error code */
938     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
939 
940     /* Return error status */
941     status =  HAL_ERROR;
942   }
943 
944   /* Release Lock */
945   __HAL_UNLOCK(hhcd);
946   return status;
947 }
948 
949 /**
950   * @brief  Register USB HCD Host Channel Notify URB Change Callback
951   *         To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
952   * @param  hhcd HCD handle
953   * @param  pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
954   * @retval HAL status
955   */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)956 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
957                                                              pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
958 {
959   HAL_StatusTypeDef status = HAL_OK;
960 
961   if (pCallback == NULL)
962   {
963     /* Update the error code */
964     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
965 
966     return HAL_ERROR;
967   }
968 
969   /* Process locked */
970   __HAL_LOCK(hhcd);
971 
972   if (hhcd->State == HAL_HCD_STATE_READY)
973   {
974     hhcd->HC_NotifyURBChangeCallback = pCallback;
975   }
976   else
977   {
978     /* Update the error code */
979     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
980 
981     /* Return error status */
982     status =  HAL_ERROR;
983   }
984 
985   /* Release Lock */
986   __HAL_UNLOCK(hhcd);
987 
988   return status;
989 }
990 
991 /**
992   * @brief  Unregister the USB HCD Host Channel Notify URB Change Callback
993   *         USB HCD Host Channel Notify URB Change Callback is redirected
994   *         to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
995   * @param  hhcd HCD handle
996   * @retval HAL status
997   */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)998 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
999 {
1000   HAL_StatusTypeDef status = HAL_OK;
1001 
1002   /* Process locked */
1003   __HAL_LOCK(hhcd);
1004 
1005   if (hhcd->State == HAL_HCD_STATE_READY)
1006   {
1007     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback  */
1008   }
1009   else
1010   {
1011     /* Update the error code */
1012     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1013 
1014     /* Return error status */
1015     status =  HAL_ERROR;
1016   }
1017 
1018   /* Release Lock */
1019   __HAL_UNLOCK(hhcd);
1020 
1021   return status;
1022 }
1023 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1024 
1025 /**
1026   * @}
1027   */
1028 
1029 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1030   *  @brief   Management functions
1031   *
1032 @verbatim
1033  ===============================================================================
1034                       ##### Peripheral Control functions #####
1035  ===============================================================================
1036     [..]
1037     This subsection provides a set of functions allowing to control the HCD data
1038     transfers.
1039 
1040 @endverbatim
1041   * @{
1042   */
1043 
1044 /**
1045   * @brief  Start the host driver.
1046   * @param  hhcd HCD handle
1047   * @retval HAL status
1048   */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1049 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1050 {
1051   __HAL_LOCK(hhcd);
1052   /* Enable port power */
1053   (void)USB_DriveVbus(hhcd->Instance, 1U);
1054 
1055   /* Enable global interrupt */
1056   __HAL_HCD_ENABLE(hhcd);
1057   __HAL_UNLOCK(hhcd);
1058 
1059   return HAL_OK;
1060 }
1061 
1062 /**
1063   * @brief  Stop the host driver.
1064   * @param  hhcd HCD handle
1065   * @retval HAL status
1066   */
1067 
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1068 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1069 {
1070   __HAL_LOCK(hhcd);
1071   (void)USB_StopHost(hhcd->Instance);
1072   __HAL_UNLOCK(hhcd);
1073 
1074   return HAL_OK;
1075 }
1076 
1077 /**
1078   * @brief  Reset the host port.
1079   * @param  hhcd HCD handle
1080   * @retval HAL status
1081   */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1082 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1083 {
1084   return (USB_ResetPort(hhcd->Instance));
1085 }
1086 
1087 /**
1088   * @}
1089   */
1090 
1091 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1092   *  @brief   Peripheral State functions
1093   *
1094 @verbatim
1095  ===============================================================================
1096                       ##### Peripheral State functions #####
1097  ===============================================================================
1098     [..]
1099     This subsection permits to get in run-time the status of the peripheral
1100     and the data flow.
1101 
1102 @endverbatim
1103   * @{
1104   */
1105 
1106 /**
1107   * @brief  Return the HCD handle state.
1108   * @param  hhcd HCD handle
1109   * @retval HAL state
1110   */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)1111 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
1112 {
1113   return hhcd->State;
1114 }
1115 
1116 /**
1117   * @brief  Return  URB state for a channel.
1118   * @param  hhcd HCD handle
1119   * @param  chnum Channel number.
1120   *         This parameter can be a value from 1 to 15
1121   * @retval URB state.
1122   *          This parameter can be one of these values:
1123   *            URB_IDLE/
1124   *            URB_DONE/
1125   *            URB_NOTREADY/
1126   *            URB_NYET/
1127   *            URB_ERROR/
1128   *            URB_STALL
1129   */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1130 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1131 {
1132   return hhcd->hc[chnum].urb_state;
1133 }
1134 
1135 
1136 /**
1137   * @brief  Return the last host transfer size.
1138   * @param  hhcd HCD handle
1139   * @param  chnum Channel number.
1140   *         This parameter can be a value from 1 to 15
1141   * @retval last transfer size in byte
1142   */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1143 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1144 {
1145   return hhcd->hc[chnum].xfer_count;
1146 }
1147 
1148 /**
1149   * @brief  Return the Host Channel state.
1150   * @param  hhcd HCD handle
1151   * @param  chnum Channel number.
1152   *         This parameter can be a value from 1 to 15
1153   * @retval Host channel state
1154   *          This parameter can be one of these values:
1155   *            HC_IDLE/
1156   *            HC_XFRC/
1157   *            HC_HALTED/
1158   *            HC_NYET/
1159   *            HC_NAK/
1160   *            HC_STALL/
1161   *            HC_XACTERR/
1162   *            HC_BBLERR/
1163   *            HC_DATATGLERR
1164   */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1165 HCD_HCStateTypeDef  HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1166 {
1167   return hhcd->hc[chnum].state;
1168 }
1169 
1170 /**
1171   * @brief  Return the current Host frame number.
1172   * @param  hhcd HCD handle
1173   * @retval Current Host frame number
1174   */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1175 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1176 {
1177   return (USB_GetCurrentFrame(hhcd->Instance));
1178 }
1179 
1180 /**
1181   * @brief  Return the Host enumeration speed.
1182   * @param  hhcd HCD handle
1183   * @retval Enumeration speed
1184   */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1185 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1186 {
1187   return (USB_GetHostSpeed(hhcd->Instance));
1188 }
1189 
1190 /**
1191   * @brief  Set host channel Hub information.
1192   * @param  hhcd HCD handle
1193   * @param  ch_num Channel number.
1194   *         This parameter can be a value from 1 to 15
1195   * @param  addr Hub address
1196   * @param  PortNbr Hub port number
1197   * @retval HAL status
1198   */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)1199 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1200                                         uint8_t addr, uint8_t PortNbr)
1201 {
1202   uint32_t HostCoreSpeed = USB_GetHostSpeed(hhcd->Instance);
1203 
1204   /* LS/FS device plugged to HS HUB */
1205   if ((hhcd->hc[ch_num].speed != HCD_DEVICE_SPEED_HIGH) && (HostCoreSpeed == HPRT0_PRTSPD_HIGH_SPEED))
1206   {
1207     hhcd->hc[ch_num].do_ssplit = 1U;
1208 
1209     if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) && (hhcd->hc[ch_num].ep_is_in != 0U))
1210     {
1211       hhcd->hc[ch_num].toggle_in = 1U;
1212     }
1213   }
1214 
1215   hhcd->hc[ch_num].hub_addr = addr;
1216   hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1217 
1218   return HAL_OK;
1219 }
1220 
1221 
1222 /**
1223   * @brief  Clear host channel hub information.
1224   * @param  hhcd HCD handle
1225   * @param  ch_num Channel number.
1226   *         This parameter can be a value from 1 to 15
1227   * @retval HAL status
1228   */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1229 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1230 {
1231   hhcd->hc[ch_num].do_ssplit = 0U;
1232   hhcd->hc[ch_num].do_csplit = 0U;
1233   hhcd->hc[ch_num].hub_addr = 0U;
1234   hhcd->hc[ch_num].hub_port_nbr = 0U;
1235 
1236   return HAL_OK;
1237 }
1238 /**
1239   * @}
1240   */
1241 
1242 /**
1243   * @}
1244   */
1245 
1246 /** @addtogroup HCD_Private_Functions
1247   * @{
1248   */
1249 /**
1250   * @brief  Handle Host Channel IN interrupt requests.
1251   * @param  hhcd HCD handle
1252   * @param  chnum Channel number.
1253   *         This parameter can be a value from 1 to 15
1254   * @retval none
1255   */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1256 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1257 {
1258   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1259   uint32_t USBx_BASE = (uint32_t)USBx;
1260   uint32_t tmpreg;
1261 
1262   if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1263   {
1264     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1265     hhcd->hc[chnum].state = HC_XACTERR;
1266     (void)USB_HC_Halt(hhcd->Instance, chnum);
1267   }
1268   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_BBERR))
1269   {
1270     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_BBERR);
1271     hhcd->hc[chnum].state = HC_BBLERR;
1272     (void)USB_HC_Halt(hhcd->Instance, chnum);
1273   }
1274   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1275   {
1276     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1277     hhcd->hc[chnum].state = HC_STALL;
1278     (void)USB_HC_Halt(hhcd->Instance, chnum);
1279   }
1280   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1281   {
1282     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1283     hhcd->hc[chnum].state = HC_DATATGLERR;
1284     (void)USB_HC_Halt(hhcd->Instance, chnum);
1285   }
1286   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1287   {
1288     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1289     hhcd->hc[chnum].state = HC_XACTERR;
1290     (void)USB_HC_Halt(hhcd->Instance, chnum);
1291   }
1292   else
1293   {
1294     /* ... */
1295   }
1296 
1297   if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1298   {
1299     (void)USB_HC_Halt(hhcd->Instance, chnum);
1300     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1301   }
1302   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1303   {
1304     /* Clear any pending ACK IT */
1305     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1306 
1307     if (hhcd->hc[chnum].do_csplit == 1U)
1308     {
1309       hhcd->hc[chnum].do_csplit = 0U;
1310       __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1311     }
1312 
1313     if (hhcd->Init.dma_enable != 0U)
1314     {
1315       hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].XferSize - (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
1316     }
1317 
1318     hhcd->hc[chnum].state = HC_XFRC;
1319     hhcd->hc[chnum].ErrCnt = 0U;
1320     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1321 
1322     if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1323         (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1324     {
1325       (void)USB_HC_Halt(hhcd->Instance, chnum);
1326       __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1327     }
1328     else if ((hhcd->hc[chnum].ep_type == EP_TYPE_INTR) ||
1329              (hhcd->hc[chnum].ep_type == EP_TYPE_ISOC))
1330     {
1331       USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1332       hhcd->hc[chnum].urb_state = URB_DONE;
1333 
1334 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1335       hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1336 #else
1337       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1338 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1339     }
1340     else
1341     {
1342       /* ... */
1343     }
1344 
1345     if (hhcd->Init.dma_enable == 1U)
1346     {
1347       if ((((hhcd->hc[chnum].xfer_count + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet) & 1U) != 0U)
1348       {
1349         hhcd->hc[chnum].toggle_in ^= 1U;
1350       }
1351     }
1352     else
1353     {
1354       hhcd->hc[chnum].toggle_in ^= 1U;
1355     }
1356   }
1357   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1358   {
1359     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1360 
1361     if (hhcd->hc[chnum].do_ssplit == 1U)
1362     {
1363       hhcd->hc[chnum].do_csplit = 1U;
1364       hhcd->hc[chnum].state = HC_ACK;
1365 
1366       (void)USB_HC_Halt(hhcd->Instance, chnum);
1367     }
1368   }
1369   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1370   {
1371     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1372 
1373     if (hhcd->hc[chnum].state == HC_XFRC)
1374     {
1375       hhcd->hc[chnum].state = HC_HALTED;
1376       hhcd->hc[chnum].urb_state = URB_DONE;
1377     }
1378     else if (hhcd->hc[chnum].state == HC_STALL)
1379     {
1380       hhcd->hc[chnum].state = HC_HALTED;
1381       hhcd->hc[chnum].urb_state = URB_STALL;
1382     }
1383     else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1384              (hhcd->hc[chnum].state == HC_DATATGLERR))
1385     {
1386       hhcd->hc[chnum].state = HC_HALTED;
1387       hhcd->hc[chnum].ErrCnt++;
1388       if (hhcd->hc[chnum].ErrCnt > 2U)
1389       {
1390         hhcd->hc[chnum].ErrCnt = 0U;
1391 
1392         if (hhcd->hc[chnum].do_ssplit == 1U)
1393         {
1394           hhcd->hc[chnum].do_csplit = 0U;
1395           hhcd->hc[chnum].ep_ss_schedule = 0U;
1396           __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1397         }
1398 
1399         hhcd->hc[chnum].urb_state = URB_ERROR;
1400       }
1401       else
1402       {
1403         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1404 
1405         if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1406             (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1407         {
1408           /* re-activate the channel */
1409           tmpreg = USBx_HC(chnum)->HCCHAR;
1410           tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1411           tmpreg |= USB_OTG_HCCHAR_CHENA;
1412           USBx_HC(chnum)->HCCHAR = tmpreg;
1413         }
1414       }
1415     }
1416     else if (hhcd->hc[chnum].state == HC_NYET)
1417     {
1418       hhcd->hc[chnum].state = HC_HALTED;
1419 
1420       if (hhcd->hc[chnum].do_csplit == 1U)
1421       {
1422         if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1423         {
1424           hhcd->hc[chnum].NyetErrCnt++;
1425           if (hhcd->hc[chnum].NyetErrCnt > 2U)
1426           {
1427             hhcd->hc[chnum].NyetErrCnt = 0U;
1428             hhcd->hc[chnum].do_csplit = 0U;
1429 
1430             if (hhcd->hc[chnum].ErrCnt < 3U)
1431             {
1432               hhcd->hc[chnum].ep_ss_schedule = 1U;
1433             }
1434             __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1435             hhcd->hc[chnum].urb_state = URB_ERROR;
1436           }
1437           else
1438           {
1439             hhcd->hc[chnum].urb_state = URB_NOTREADY;
1440           }
1441         }
1442         else
1443         {
1444           hhcd->hc[chnum].urb_state = URB_NOTREADY;
1445         }
1446 
1447         if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1448             (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1449         {
1450           /* re-activate the channel */
1451           tmpreg = USBx_HC(chnum)->HCCHAR;
1452           tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1453           tmpreg |= USB_OTG_HCCHAR_CHENA;
1454           USBx_HC(chnum)->HCCHAR = tmpreg;
1455         }
1456       }
1457     }
1458     else if (hhcd->hc[chnum].state == HC_ACK)
1459     {
1460       hhcd->hc[chnum].state = HC_HALTED;
1461 
1462       if (hhcd->hc[chnum].do_csplit == 1U)
1463       {
1464         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1465 
1466         /* Set Complete split and re-activate the channel */
1467         USBx_HC(chnum)->HCSPLT |= USB_OTG_HCSPLT_COMPLSPLT;
1468         USBx_HC(chnum)->HCINTMSK |= USB_OTG_HCINTMSK_NYET;
1469         USBx_HC(chnum)->HCINTMSK &= ~USB_OTG_HCINT_ACK;
1470 
1471         if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1472             (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1473         {
1474           /* re-activate the channel */
1475           tmpreg = USBx_HC(chnum)->HCCHAR;
1476           tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1477           tmpreg |= USB_OTG_HCCHAR_CHENA;
1478           USBx_HC(chnum)->HCCHAR = tmpreg;
1479         }
1480       }
1481     }
1482     else if (hhcd->hc[chnum].state == HC_NAK)
1483     {
1484       hhcd->hc[chnum].state = HC_HALTED;
1485       hhcd->hc[chnum].urb_state = URB_NOTREADY;
1486 
1487       if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1488           (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1489       {
1490         /* re-activate the channel */
1491         tmpreg = USBx_HC(chnum)->HCCHAR;
1492         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1493         tmpreg |= USB_OTG_HCCHAR_CHENA;
1494         USBx_HC(chnum)->HCCHAR = tmpreg;
1495       }
1496     }
1497     else if (hhcd->hc[chnum].state == HC_BBLERR)
1498     {
1499       hhcd->hc[chnum].state = HC_HALTED;
1500       hhcd->hc[chnum].ErrCnt++;
1501       hhcd->hc[chnum].urb_state = URB_ERROR;
1502     }
1503     else
1504     {
1505       if (hhcd->hc[chnum].state == HC_HALTED)
1506       {
1507         return;
1508       }
1509     }
1510 
1511 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1512     hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1513 #else
1514     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1515 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1516   }
1517   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1518   {
1519     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1520     hhcd->hc[chnum].state = HC_NYET;
1521 
1522     if (hhcd->hc[chnum].do_ssplit == 0U)
1523     {
1524       hhcd->hc[chnum].ErrCnt = 0U;
1525     }
1526 
1527     (void)USB_HC_Halt(hhcd->Instance, chnum);
1528   }
1529   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1530   {
1531     if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
1532     {
1533       hhcd->hc[chnum].ErrCnt = 0U;
1534       hhcd->hc[chnum].state = HC_NAK;
1535       (void)USB_HC_Halt(hhcd->Instance, chnum);
1536     }
1537     else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
1538              (hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
1539     {
1540       hhcd->hc[chnum].ErrCnt = 0U;
1541 
1542       if ((hhcd->Init.dma_enable == 0U) || (hhcd->hc[chnum].do_csplit == 1U))
1543       {
1544         hhcd->hc[chnum].state = HC_NAK;
1545         (void)USB_HC_Halt(hhcd->Instance, chnum);
1546       }
1547     }
1548     else
1549     {
1550       /* ... */
1551     }
1552 
1553     if (hhcd->hc[chnum].do_csplit == 1U)
1554     {
1555       hhcd->hc[chnum].do_csplit = 0U;
1556       __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1557       __HAL_HCD_UNMASK_ACK_HC_INT(chnum);
1558     }
1559 
1560     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1561   }
1562   else
1563   {
1564     /* ... */
1565   }
1566 }
1567 
1568 /**
1569   * @brief  Handle Host Channel OUT interrupt requests.
1570   * @param  hhcd HCD handle
1571   * @param  chnum Channel number.
1572   *         This parameter can be a value from 1 to 15
1573   * @retval none
1574   */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1575 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1576 {
1577   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1578   uint32_t USBx_BASE = (uint32_t)USBx;
1579   uint32_t tmpreg;
1580   uint32_t num_packets;
1581 
1582   if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
1583   {
1584     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
1585     hhcd->hc[chnum].state = HC_XACTERR;
1586     (void)USB_HC_Halt(hhcd->Instance, chnum);
1587   }
1588   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
1589   {
1590     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
1591 
1592     if (hhcd->hc[chnum].do_ping == 1U)
1593     {
1594       hhcd->hc[chnum].do_ping = 0U;
1595       hhcd->hc[chnum].urb_state = URB_NOTREADY;
1596       hhcd->hc[chnum].state = HC_ACK;
1597       (void)USB_HC_Halt(hhcd->Instance, chnum);
1598     }
1599 
1600     if ((hhcd->hc[chnum].do_ssplit == 1U) && (hhcd->hc[chnum].do_csplit == 0U))
1601     {
1602       if (hhcd->hc[chnum].ep_type != EP_TYPE_ISOC)
1603       {
1604         hhcd->hc[chnum].do_csplit = 1U;
1605       }
1606 
1607       hhcd->hc[chnum].state = HC_ACK;
1608       (void)USB_HC_Halt(hhcd->Instance, chnum);
1609 
1610       /* reset error_count */
1611       hhcd->hc[chnum].ErrCnt = 0U;
1612     }
1613   }
1614   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
1615   {
1616     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
1617     (void)USB_HC_Halt(hhcd->Instance, chnum);
1618   }
1619   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
1620   {
1621     hhcd->hc[chnum].ErrCnt = 0U;
1622 
1623     /* transaction completed with NYET state, update do ping state */
1624     if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1625     {
1626       hhcd->hc[chnum].do_ping = 1U;
1627       __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1628     }
1629 
1630     if (hhcd->hc[chnum].do_csplit != 0U)
1631     {
1632       hhcd->hc[chnum].do_csplit = 0U;
1633       __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1634     }
1635 
1636     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
1637     hhcd->hc[chnum].state = HC_XFRC;
1638     (void)USB_HC_Halt(hhcd->Instance, chnum);
1639   }
1640   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
1641   {
1642     hhcd->hc[chnum].state = HC_NYET;
1643 
1644     if (hhcd->hc[chnum].do_ssplit == 0U)
1645     {
1646       hhcd->hc[chnum].do_ping = 1U;
1647     }
1648 
1649     hhcd->hc[chnum].ErrCnt = 0U;
1650     (void)USB_HC_Halt(hhcd->Instance, chnum);
1651     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
1652   }
1653   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
1654   {
1655     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
1656     hhcd->hc[chnum].state = HC_STALL;
1657     (void)USB_HC_Halt(hhcd->Instance, chnum);
1658   }
1659   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
1660   {
1661     hhcd->hc[chnum].ErrCnt = 0U;
1662     hhcd->hc[chnum].state = HC_NAK;
1663 
1664     if (hhcd->hc[chnum].do_ping == 0U)
1665     {
1666       if (hhcd->hc[chnum].speed == HCD_DEVICE_SPEED_HIGH)
1667       {
1668         hhcd->hc[chnum].do_ping = 1U;
1669       }
1670     }
1671 
1672     (void)USB_HC_Halt(hhcd->Instance, chnum);
1673     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
1674   }
1675   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
1676   {
1677     if (hhcd->Init.dma_enable == 0U)
1678     {
1679       hhcd->hc[chnum].state = HC_XACTERR;
1680       (void)USB_HC_Halt(hhcd->Instance, chnum);
1681     }
1682     else
1683     {
1684       hhcd->hc[chnum].ErrCnt++;
1685       if (hhcd->hc[chnum].ErrCnt > 2U)
1686       {
1687         hhcd->hc[chnum].ErrCnt = 0U;
1688         hhcd->hc[chnum].urb_state = URB_ERROR;
1689 
1690 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1691         hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1692 #else
1693         HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1694 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1695       }
1696       else
1697       {
1698         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1699       }
1700     }
1701     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
1702   }
1703   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
1704   {
1705     hhcd->hc[chnum].state = HC_DATATGLERR;
1706     (void)USB_HC_Halt(hhcd->Instance, chnum);
1707     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
1708   }
1709   else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
1710   {
1711     __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
1712 
1713     if (hhcd->hc[chnum].state == HC_XFRC)
1714     {
1715       hhcd->hc[chnum].state = HC_HALTED;
1716       hhcd->hc[chnum].urb_state = URB_DONE;
1717 
1718       if ((hhcd->hc[chnum].ep_type == EP_TYPE_BULK) ||
1719           (hhcd->hc[chnum].ep_type == EP_TYPE_INTR))
1720       {
1721         if (hhcd->Init.dma_enable == 0U)
1722         {
1723           hhcd->hc[chnum].toggle_out ^= 1U;
1724         }
1725 
1726         if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[chnum].xfer_len > 0U))
1727         {
1728           num_packets = (hhcd->hc[chnum].xfer_len + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet;
1729 
1730           if ((num_packets & 1U) != 0U)
1731           {
1732             hhcd->hc[chnum].toggle_out ^= 1U;
1733           }
1734         }
1735       }
1736     }
1737     else if (hhcd->hc[chnum].state == HC_ACK)
1738     {
1739       hhcd->hc[chnum].state = HC_HALTED;
1740 
1741       if (hhcd->hc[chnum].do_csplit == 1U)
1742       {
1743         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1744       }
1745     }
1746     else if (hhcd->hc[chnum].state == HC_NAK)
1747     {
1748       hhcd->hc[chnum].state = HC_HALTED;
1749       hhcd->hc[chnum].urb_state = URB_NOTREADY;
1750 
1751       if (hhcd->hc[chnum].do_csplit == 1U)
1752       {
1753         hhcd->hc[chnum].do_csplit = 0U;
1754         __HAL_HCD_CLEAR_HC_CSPLT(chnum);
1755       }
1756     }
1757     else if (hhcd->hc[chnum].state == HC_NYET)
1758     {
1759       hhcd->hc[chnum].state = HC_HALTED;
1760       hhcd->hc[chnum].urb_state  = URB_NOTREADY;
1761     }
1762     else if (hhcd->hc[chnum].state == HC_STALL)
1763     {
1764       hhcd->hc[chnum].state = HC_HALTED;
1765       hhcd->hc[chnum].urb_state  = URB_STALL;
1766     }
1767     else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
1768              (hhcd->hc[chnum].state == HC_DATATGLERR))
1769     {
1770       hhcd->hc[chnum].state = HC_HALTED;
1771       hhcd->hc[chnum].ErrCnt++;
1772       if (hhcd->hc[chnum].ErrCnt > 2U)
1773       {
1774         hhcd->hc[chnum].ErrCnt = 0U;
1775         hhcd->hc[chnum].urb_state = URB_ERROR;
1776       }
1777       else
1778       {
1779         hhcd->hc[chnum].urb_state = URB_NOTREADY;
1780 
1781         /* re-activate the channel  */
1782         tmpreg = USBx_HC(chnum)->HCCHAR;
1783         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1784         tmpreg |= USB_OTG_HCCHAR_CHENA;
1785         USBx_HC(chnum)->HCCHAR = tmpreg;
1786       }
1787     }
1788     else
1789     {
1790       return;
1791     }
1792 
1793 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1794     hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1795 #else
1796     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
1797 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1798   }
1799   else
1800   {
1801     return;
1802   }
1803 }
1804 
1805 /**
1806   * @brief  Handle Rx Queue Level interrupt requests.
1807   * @param  hhcd HCD handle
1808   * @retval none
1809   */
HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef * hhcd)1810 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1811 {
1812   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1813   uint32_t USBx_BASE = (uint32_t)USBx;
1814   uint32_t pktsts;
1815   uint32_t pktcnt;
1816   uint32_t GrxstspReg;
1817   uint32_t xferSizePktCnt;
1818   uint32_t tmpreg;
1819   uint32_t chnum;
1820 
1821   GrxstspReg = hhcd->Instance->GRXSTSP;
1822   chnum = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
1823   pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1824   pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
1825 
1826   switch (pktsts)
1827   {
1828     case GRXSTS_PKTSTS_IN:
1829       /* Read the data into the host buffer. */
1830       if ((pktcnt > 0U) && (hhcd->hc[chnum].xfer_buff != (void *)0))
1831       {
1832         if ((hhcd->hc[chnum].xfer_count + pktcnt) <= hhcd->hc[chnum].xfer_len)
1833         {
1834           (void)USB_ReadPacket(hhcd->Instance,
1835                                hhcd->hc[chnum].xfer_buff, (uint16_t)pktcnt);
1836 
1837           /* manage multiple Xfer */
1838           hhcd->hc[chnum].xfer_buff += pktcnt;
1839           hhcd->hc[chnum].xfer_count += pktcnt;
1840 
1841           /* get transfer size packet count */
1842           xferSizePktCnt = (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
1843 
1844           if ((hhcd->hc[chnum].max_packet == pktcnt) && (xferSizePktCnt > 0U))
1845           {
1846             /* re-activate the channel when more packets are expected */
1847             tmpreg = USBx_HC(chnum)->HCCHAR;
1848             tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1849             tmpreg |= USB_OTG_HCCHAR_CHENA;
1850             USBx_HC(chnum)->HCCHAR = tmpreg;
1851             hhcd->hc[chnum].toggle_in ^= 1U;
1852           }
1853         }
1854         else
1855         {
1856           hhcd->hc[chnum].urb_state = URB_ERROR;
1857         }
1858       }
1859       break;
1860 
1861     case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1862       break;
1863 
1864     case GRXSTS_PKTSTS_IN_XFER_COMP:
1865     case GRXSTS_PKTSTS_CH_HALTED:
1866     default:
1867       break;
1868   }
1869 }
1870 
1871 /**
1872   * @brief  Handle Host Port interrupt requests.
1873   * @param  hhcd HCD handle
1874   * @retval None
1875   */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)1876 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1877 {
1878   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1879   uint32_t USBx_BASE = (uint32_t)USBx;
1880   __IO uint32_t hprt0;
1881   __IO uint32_t hprt0_dup;
1882 
1883   /* Handle Host Port Interrupts */
1884   hprt0 = USBx_HPRT0;
1885   hprt0_dup = USBx_HPRT0;
1886 
1887   hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1888                  USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1889 
1890   /* Check whether Port Connect detected */
1891   if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1892   {
1893     if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1894     {
1895 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1896       hhcd->ConnectCallback(hhcd);
1897 #else
1898       HAL_HCD_Connect_Callback(hhcd);
1899 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1900     }
1901     hprt0_dup |= USB_OTG_HPRT_PCDET;
1902   }
1903 
1904   /* Check whether Port Enable Changed */
1905   if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1906   {
1907     hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1908 
1909     if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1910     {
1911       if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1912       {
1913         if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1914         {
1915           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1916         }
1917         else
1918         {
1919           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1920         }
1921       }
1922       else
1923       {
1924         if (hhcd->Init.speed == HCD_SPEED_FULL)
1925         {
1926           USBx_HOST->HFIR = HFIR_60_MHZ;
1927         }
1928       }
1929 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1930       hhcd->PortEnabledCallback(hhcd);
1931 #else
1932       HAL_HCD_PortEnabled_Callback(hhcd);
1933 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1934 
1935     }
1936     else
1937     {
1938 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1939       hhcd->PortDisabledCallback(hhcd);
1940 #else
1941       HAL_HCD_PortDisabled_Callback(hhcd);
1942 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1943     }
1944   }
1945 
1946   /* Check for an overcurrent */
1947   if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1948   {
1949     hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1950   }
1951 
1952   /* Clear Port Interrupts */
1953   USBx_HPRT0 = hprt0_dup;
1954 }
1955 
1956 /**
1957   * @}
1958   */
1959 
1960 /**
1961   * @}
1962   */
1963 
1964 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1965 #if defined (USB_DRD_FS)
1966 
1967 /** @defgroup HCD HCD
1968   * @brief HCD HAL module driver
1969   * @{
1970   */
1971 
1972 /* Private typedef -----------------------------------------------------------*/
1973 /* Private define ------------------------------------------------------------*/
1974 /* Private macro -------------------------------------------------------------*/
1975 /* Private variables ---------------------------------------------------------*/
1976 /* Private function ----------------------------------------------------------*/
1977 /** @defgroup HCD_Private_Functions HCD Private Functions
1978   * @{
1979   */
1980 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
1981 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
1982 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
1983 static void HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd);
1984 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd, uint8_t phy_chnum, uint8_t dir);
1985 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num);
1986 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum, uint8_t ep_type);
1987 
1988 #if (USE_USB_DOUBLE_BUFFER == 1U)
1989 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
1990 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
1991 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1992 
1993 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps);
1994 static HAL_StatusTypeDef  HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps);
1995 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
1996 /**
1997   * @}
1998   */
1999 
2000 /* Exported functions --------------------------------------------------------*/
2001 /** @defgroup HCD_Exported_Functions HCD Exported Functions
2002   * @{
2003   */
2004 
2005 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
2006   *  @brief    Initialization and Configuration functions
2007   *
2008 @verbatim
2009 ===============================================================================
2010 ##### Initialization and de-initialization functions #####
2011 ===============================================================================
2012 [..]  This section provides functions allowing to:
2013 
2014 @endverbatim
2015   * @{
2016   */
2017 
2018 /**
2019   * @brief  Initialize the host driver.
2020   * @param  hhcd HCD handle
2021   * @retval HAL status
2022   */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)2023 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
2024 {
2025   /* Check the HCD handle allocation */
2026   if (hhcd == NULL)
2027   {
2028     return HAL_ERROR;
2029   }
2030 
2031   /* Check the parameters */
2032   assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
2033 
2034   if (hhcd->State == HAL_HCD_STATE_RESET)
2035   {
2036     /* Allocate lock resource and initialize it */
2037     hhcd->Lock = HAL_UNLOCKED;
2038 
2039 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2040     hhcd->SOFCallback = HAL_HCD_SOF_Callback;
2041     hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
2042     hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
2043     hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
2044     hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
2045     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
2046 
2047     if (hhcd->MspInitCallback == NULL)
2048     {
2049       hhcd->MspInitCallback = HAL_HCD_MspInit;
2050     }
2051 
2052     /* Init the low level hardware */
2053     hhcd->MspInitCallback(hhcd);
2054 #else
2055     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
2056     HAL_HCD_MspInit(hhcd);
2057 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
2058   }
2059   hhcd->State = HAL_HCD_STATE_BUSY;
2060 
2061   /* Disable the Interrupts */
2062   (void)__HAL_HCD_DISABLE(hhcd);
2063 
2064   /* Dma not supported, force to zero */
2065   hhcd->Init.dma_enable = 0U;
2066 
2067   /* Init the Core (common init.) */
2068   (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
2069 
2070   /* Force Host Mode */
2071   (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
2072 
2073   /* Init Host */
2074   (void)USB_HostInit(hhcd->Instance, hhcd->Init);
2075 
2076   /* Deactivate the power down */
2077   hhcd->Instance->CNTR &= ~USB_CNTR_PDWN;
2078 
2079   hhcd->State = HAL_HCD_STATE_READY;
2080 
2081   /* Host Port State */
2082   hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2083 
2084   /* Init PMA Address */
2085   (void)HAL_HCD_PMAReset(hhcd);
2086 
2087   hhcd->State = HAL_HCD_STATE_READY;
2088 
2089   return HAL_OK;
2090 }
2091 
2092 /**
2093   * @brief  Initialize a host channel.
2094   * @param  hhcd HCD handle
2095   * @param  ch_num Channel number.
2096   *         This parameter can be a value from 1 to 15
2097   * @param  epnum Endpoint number.
2098   *          This parameter can be a value from 1 to 15
2099   * @param  dev_address Current device address
2100   *          This parameter can be a value from 0 to 255
2101   * @param  speed Current device speed.
2102   *          This parameter can be one of these values:
2103   *            HCD_DEVICE_SPEED_HIGH High speed mode,
2104   *            HCD_DEVICE_SPEED_FULL Full speed mode,
2105   *            HCD_DEVICE_SPEED_LOW Low speed mode
2106   * @param  ep_type Endpoint Type.
2107   *          This parameter can be one of these values:
2108   *            USBH_EP_CONTROL Control type,
2109   *            USBH_EP_ISO Isochronous type,
2110   *            USBH_EP_BULK Bulk type,
2111   *            USBH_EP_INTERRUPT Interrupt type
2112   * @param  mps Max Packet Size.
2113   *          This parameter can be a value from 0 to32K
2114   * @retval HAL status
2115   */
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)2116 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2117                                   uint8_t epnum, uint8_t dev_address,
2118                                   uint8_t speed, uint8_t ep_type, uint16_t mps)
2119 {
2120   HAL_StatusTypeDef status;
2121   uint8_t used_channel;
2122   uint8_t ep0_virtual_channel;
2123 
2124   __HAL_LOCK(hhcd);
2125 
2126   /* Check if the logical channel are already allocated */
2127   used_channel = HAL_HCD_Check_usedChannel(hhcd, ch_num);
2128 
2129   /* Check if the channel is not already opened */
2130   if (used_channel == 0U)
2131   {
2132     /* Allocate New Physical channel */
2133     hhcd->hc[ch_num & 0xFU].phy_ch_num = HAL_HCD_Get_FreePhyChannel(hhcd, ch_num, epnum, ep_type);
2134 
2135     /* No free Channel available, return error */
2136     if (hhcd->hc[ch_num & 0xFU].phy_ch_num == HCD_FREE_CH_NOT_FOUND)
2137     {
2138       return HAL_ERROR;
2139     }
2140   }
2141   /* Channel already opened */
2142   else
2143   {
2144     /* Get Physical Channel number */
2145     hhcd->hc[ch_num & 0xFU].phy_ch_num = (used_channel & 0xF0U) >> 4U;
2146   }
2147 
2148   if ((epnum & 0x80U) != 0U)
2149   {
2150     hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
2151   }
2152   else
2153   {
2154     hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
2155   }
2156 
2157   hhcd->hc[ch_num & 0xFU].dev_addr   = dev_address;
2158   hhcd->hc[ch_num & 0xFU].max_packet = mps;
2159   hhcd->hc[ch_num & 0xFU].ep_type    = ep_type;
2160   hhcd->hc[ch_num & 0xFU].ep_num     = epnum & 0x7FU;
2161   hhcd->hc[ch_num & 0xFU].speed      = speed;
2162 
2163   /* Check if the channel is not already opened */
2164   if (used_channel == 0U)
2165   {
2166     if (((ep_type == EP_TYPE_ISOC) && (hhcd->Init.iso_singlebuffer_enable == 0U)) ||
2167         ((ep_type == EP_TYPE_BULK) && (hhcd->Init.bulk_doublebuffer_enable == 1U)))
2168     {
2169       /* PMA Dynamic Allocation */
2170       status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_DBL_BUF, mps);
2171 
2172       if (status == HAL_ERROR)
2173       {
2174         return HAL_ERROR;
2175       }
2176 
2177       /* Clear Channel DTOG_TX */
2178       HCD_CLEAR_TX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
2179 
2180       /* Clear Channel DTOG RX */
2181       HCD_CLEAR_RX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
2182 
2183     }
2184     else
2185     {
2186       if (hhcd->hc[ch_num & 0xFU].ep_num != 0U)
2187       {
2188         status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, mps);
2189 
2190         if (status == HAL_ERROR)
2191         {
2192           return HAL_ERROR;
2193         }
2194       }
2195       else
2196       {
2197         if (ch_num == 0U)
2198         {
2199           ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
2200 
2201           if ((ep0_virtual_channel != 0U) && (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR))
2202           {
2203             if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_OUT_DIR)
2204             {
2205               status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
2206 
2207               if (status == HAL_ERROR)
2208               {
2209                 return HAL_ERROR;
2210               }
2211             }
2212             else
2213             {
2214               return HAL_ERROR;
2215             }
2216           }
2217           else
2218           {
2219             /* PMA Dynamic Allocation for EP0 OUT direction */
2220             hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
2221             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
2222 
2223             if (status == HAL_ERROR)
2224             {
2225               return HAL_ERROR;
2226             }
2227 
2228             /* PMA Dynamic Allocation for EP0 IN direction */
2229             hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
2230             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
2231 
2232             if (status == HAL_ERROR)
2233             {
2234               return HAL_ERROR;
2235             }
2236           }
2237         }
2238         else
2239         {
2240           if (((hhcd->ep0_PmaAllocState & 0xF00U) >> 8) == 1U)
2241           {
2242             ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
2243 
2244             if (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR)
2245             {
2246               hhcd->hc[ch_num & 0xFU].pmaaddr1 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr1;
2247             }
2248             else
2249             {
2250               hhcd->hc[ch_num & 0xFU].pmaaddr0 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr0;
2251             }
2252           }
2253           else
2254           {
2255             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
2256 
2257             if (status == HAL_ERROR)
2258             {
2259               return HAL_ERROR;
2260             }
2261           }
2262         }
2263       }
2264     }
2265   }
2266 
2267   if ((epnum & 0x80U) != 0U)
2268   {
2269     hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
2270 
2271     if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
2272     {
2273       hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr1;
2274     }
2275   }
2276   else
2277   {
2278     hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
2279 
2280     if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
2281     {
2282       hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr0;
2283     }
2284   }
2285 
2286   /* Init the USB Channel CHEPRx */
2287   status =  USB_HC_Init(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
2288                         epnum, dev_address, speed, ep_type, mps);
2289 
2290   /* check single buffer for isochronous channel */
2291   if (ep_type == EP_TYPE_ISOC)
2292   {
2293     if (hhcd->Init.iso_singlebuffer_enable == 1U)
2294     {
2295       (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
2296                                 USB_DRD_ISOC_DBUFF_DISABLE);
2297     }
2298   }
2299 
2300   /* Bulk double buffer check */
2301   if (ep_type == EP_TYPE_BULK)
2302   {
2303     if (hhcd->Init.bulk_doublebuffer_enable == 1U)
2304     {
2305       (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
2306                                 USB_DRD_BULK_DBUFF_ENBALE);
2307     }
2308   }
2309 
2310   __HAL_UNLOCK(hhcd);
2311 
2312   return status;
2313 }
2314 
2315 /**
2316   * @brief  HAL_HCD_HC_Close Pipe
2317   * @param  hhcd HCD handle
2318   * @param  ch_num Channel number.
2319   *         This parameter can be a value from 1 to 15
2320   * @retval HAL status
2321   */
HAL_HCD_HC_Close(HCD_HandleTypeDef * hhcd,uint8_t ch_num)2322 HAL_StatusTypeDef HAL_HCD_HC_Close(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
2323 {
2324   /* Stop the channel */
2325   (void) HAL_HCD_HC_Halt(hhcd, ch_num);
2326 
2327   HAL_Delay(3U);
2328 
2329   if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
2330   {
2331     /* Free Allocated Channel */
2332     hhcd->phy_chin_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
2333   }
2334   else
2335   {
2336     /* Free Allocated Channel */
2337     hhcd->phy_chout_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
2338   }
2339 
2340   /* Reset PMA Channel_Allocation */
2341   (void)HAL_HCD_PMADeAlloc(hhcd, ch_num);
2342 
2343   return HAL_OK;
2344 }
2345 
2346 /**
2347   * @brief  Halt a host channel.
2348   * @param  hhcd HCD handle
2349   * @param  ch_num Channel number.
2350   *         This parameter can be a value from 1 to 15
2351   * @retval HAL status
2352   */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)2353 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
2354 {
2355   HAL_StatusTypeDef status = HAL_OK;
2356 
2357   __HAL_LOCK(hhcd);
2358   if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
2359   {
2360     (void)USB_HC_IN_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
2361   }
2362   else
2363   {
2364     (void)USB_HC_OUT_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
2365   }
2366   __HAL_UNLOCK(hhcd);
2367 
2368   return status;
2369 }
2370 
2371 /**
2372   * @brief  DeInitialize the host driver.
2373   * @param  hhcd HCD handle
2374   * @retval HAL status
2375   */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)2376 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
2377 {
2378   uint8_t idx;
2379 
2380   /* Check the HCD handle allocation */
2381   if (hhcd == NULL)
2382   {
2383     return HAL_ERROR;
2384   }
2385 
2386   /* Host Port State */
2387   hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2388 
2389   /* Reset PMA Address */
2390   (void)HAL_HCD_PMAReset(hhcd);
2391 
2392   for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
2393   {
2394     hhcd->phy_chin_state[idx] = 0U;
2395     hhcd->phy_chout_state[idx] = 0U;
2396   }
2397 
2398   /* reset Ep0 Pma allocation state */
2399   hhcd->ep0_PmaAllocState = 0U;
2400 
2401   hhcd->State = HAL_HCD_STATE_BUSY;
2402 
2403 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2404   if (hhcd->MspDeInitCallback == NULL)
2405   {
2406     hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
2407   }
2408 
2409   /* DeInit the low level hardware */
2410   hhcd->MspDeInitCallback(hhcd);
2411 #else
2412   /* DeInit the low level hardware: CLOCK, NVIC. */
2413   HAL_HCD_MspDeInit(hhcd);
2414 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2415 
2416   hhcd->State = HAL_HCD_STATE_RESET;
2417 
2418   return HAL_OK;
2419 }
2420 
2421 /**
2422   * @brief  Initialize the HCD MSP.
2423   * @param  hhcd HCD handle
2424   * @retval None
2425   */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)2426 __weak void  HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
2427 {
2428   /* Prevent unused argument(s) compilation warning */
2429   UNUSED(hhcd);
2430 
2431   /* NOTE : This function Should not be modified, when the callback is needed,
2432   the HAL_HCD_MspInit could be implemented in the user file
2433   */
2434 }
2435 
2436 /**
2437   * @brief  DeInitialize the HCD MSP.
2438   * @param  hhcd HCD handle
2439   * @retval None
2440   */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)2441 __weak void  HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
2442 {
2443   /* Prevent unused argument(s) compilation warning */
2444   UNUSED(hhcd);
2445 
2446   /* NOTE : This function Should not be modified, when the callback is needed,
2447   the HAL_HCD_MspDeInit could be implemented in the user file
2448   */
2449 }
2450 
HAL_HCD_SuspendCallback(HCD_HandleTypeDef * hhcd)2451 __weak void HAL_HCD_SuspendCallback(HCD_HandleTypeDef *hhcd)
2452 {
2453   /* Prevent unused argument(s) compilation warning */
2454   UNUSED(hhcd);
2455 
2456   /* NOTE : This function Should not be modified, when the callback is needed,
2457   the HAL_HCD_SuspendCallback could be implemented in the user file
2458   */
2459 
2460 }
2461 
HAL_HCD_ResumeCallback(HCD_HandleTypeDef * hhcd)2462 __weak void HAL_HCD_ResumeCallback(HCD_HandleTypeDef *hhcd)
2463 {
2464   /* Prevent unused argument(s) compilation warning */
2465   UNUSED(hhcd);
2466 
2467   /* NOTE : This function Should not be modified, when the callback is needed,
2468   the HAL_HCD_ResumeCallback could be implemented in the user file
2469   */
2470 }
2471 
2472 /**
2473   * @}
2474   */
2475 
2476 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
2477   *  @brief   HCD IO operation functions
2478   *
2479 @verbatim
2480 ===============================================================================
2481 ##### IO operation functions #####
2482 ===============================================================================
2483 [..] This subsection provides a set of functions allowing to manage the USB Host Data
2484 Transfer
2485 
2486 @endverbatim
2487   * @{
2488   */
2489 
2490 /**
2491   * @brief  Submit a new URB for processing.
2492   * @param  hhcd HCD handle
2493   * @param  ch_num Channel number.
2494   *         This parameter can be a value from 1 to 15
2495   * @param  direction Channel number.
2496   *          This parameter can be one of these values:
2497   *           0 : Output / 1 : Input
2498   * @param  ep_type Endpoint Type.
2499   *          This parameter can be one of these values:
2500   *            USBH_EP_CONTROL   : Control type/
2501   *            USBH_EP_ISO       : Isochronous type/
2502   *            USBH_EP_BULK      : Bulk type/
2503   *            USBH_EP_INTERRUPT : Interrupt type/
2504   * @param  token Endpoint Type.
2505   *          This parameter can be one of these values:
2506   *            0: HC_PID_SETUP / 1: HC_PID_DATA1
2507   * @param  pbuff pointer to URB data
2508   * @param  length Length of URB data
2509   * @param  do_ping activate do ping protocol (for high speed only).
2510   *          This parameter can be one of these values:
2511   *           0 : do ping inactive / 1 : do ping active
2512   * @retval HAL status
2513   */
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)2514 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2515                                            uint8_t direction, uint8_t ep_type,
2516                                            uint8_t token, uint8_t *pbuff,
2517                                            uint16_t length, uint8_t do_ping)
2518 {
2519   UNUSED(do_ping);
2520 
2521   if (token == 0U)
2522   {
2523     hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_SETUP;
2524   }
2525   else
2526   {
2527     hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2528   }
2529 
2530   /* Manage Data Toggle */
2531   switch (ep_type)
2532   {
2533     case EP_TYPE_CTRL:
2534       if ((token == 1U) && (direction == 0U)) /* send data */
2535       {
2536         if (length == 0U)
2537         {
2538           /* For Status OUT stage, Length==0, Status Out PID = 1 */
2539           hhcd->hc[ch_num & 0xFU].toggle_out = 1U;
2540         }
2541 
2542         /* Set the Data Toggle bit as per the Flag */
2543         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
2544         {
2545           /* Put the PID 0 */
2546           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2547         }
2548         else
2549         {
2550           /* Put the PID 1 */
2551           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2552         }
2553       }
2554       break;
2555 
2556     case EP_TYPE_BULK:
2557       if (direction == 0U)
2558       {
2559         /* Set the Data Toggle bit as per the Flag */
2560         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
2561         {
2562           /* Put the PID 0 */
2563           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2564         }
2565         else
2566         {
2567           /* Put the PID 1 */
2568           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2569         }
2570       }
2571       else
2572       {
2573         if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
2574         {
2575           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2576         }
2577         else
2578         {
2579           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2580         }
2581       }
2582       break;
2583 
2584     case EP_TYPE_INTR:
2585       if (direction == 0U)
2586       {
2587         /* Set the Data Toggle bit as per the Flag */
2588         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
2589         {
2590           /* Put the PID 0 */
2591           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2592         }
2593         else
2594         {
2595           /* Put the PID 1 */
2596           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2597         }
2598       }
2599       else
2600       {
2601         if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
2602         {
2603           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2604         }
2605         else
2606         {
2607           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
2608         }
2609       }
2610       break;
2611 
2612     case EP_TYPE_ISOC:
2613       hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
2614       break;
2615 
2616     default:
2617       break;
2618   }
2619 
2620   hhcd->hc[ch_num & 0xFU].xfer_buff = pbuff;
2621   hhcd->hc[ch_num & 0xFU].xfer_len = length;
2622   hhcd->hc[ch_num & 0xFU].xfer_len_db = length;
2623   hhcd->hc[ch_num & 0xFU].urb_state = URB_IDLE;
2624   hhcd->hc[ch_num & 0xFU].xfer_count = 0U;
2625   hhcd->hc[ch_num & 0xFU].state = HC_IDLE;
2626 
2627   return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num & 0xFU]);
2628 }
2629 /**
2630   * @brief  Handle HCD interrupt request.
2631   * @param  hhcd HCD handle
2632   * @retval None
2633   */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)2634 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
2635 {
2636   uint8_t phy_chnum;
2637   uint8_t chnum;
2638   uint32_t epch_reg;
2639   uint32_t wIstr = USB_ReadInterrupts(hhcd->Instance);
2640 
2641   /* Port Change Detected (Connection/Disconnection) */
2642   if ((wIstr & USB_ISTR_DCON) == USB_ISTR_DCON)
2643   {
2644     /* Clear Flag */
2645     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_DCON);
2646 
2647     /* Call Port IRQHandler */
2648     HCD_Port_IRQHandler(hhcd);
2649 
2650     return;
2651   }
2652 
2653   /* Correct Transaction Detected -------*/
2654   if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
2655   {
2656     /* Handle Host channel Interrupt */
2657     for (phy_chnum = 0U; phy_chnum < hhcd->Init.Host_channels; phy_chnum++)
2658     {
2659       if ((HCD_GET_CHANNEL(hhcd->Instance, phy_chnum) & USB_CH_VTRX) != 0U)
2660       {
2661         /* Get Logical channel to check if the channel is already opened */
2662         chnum = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 1U);
2663 
2664         if (chnum != HCD_LOGICAL_CH_NOT_OPENED)
2665         {
2666           /* Call Channel_IN_IRQ() */
2667           HCD_HC_IN_IRQHandler(hhcd, chnum);
2668         }
2669         else
2670         {
2671           /*Channel was not closed correctly still have interrupt */
2672           epch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
2673           epch_reg = (epch_reg & (USB_CHEP_REG_MASK & (~USB_CH_ERRRX) & (~USB_CH_VTRX))) |
2674                      (USB_CH_VTTX | USB_CH_ERRTX);
2675 
2676           HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, epch_reg);
2677         }
2678       }
2679 
2680       if ((HCD_GET_CHANNEL(hhcd->Instance, phy_chnum) & USB_CH_VTTX) != 0U)
2681       {
2682         /* Get Logical channel to check if the channel is already opened */
2683         chnum = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 0U);
2684 
2685         if (chnum != HCD_LOGICAL_CH_NOT_OPENED)
2686         {
2687           /*Call Channel_OUT_IRQ()*/
2688           HCD_HC_OUT_IRQHandler(hhcd, chnum);
2689         }
2690         else
2691         {
2692           /* Clear Error & unwanted VTTX or Channel was not closed correctly */
2693           epch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
2694           epch_reg = (epch_reg & (USB_CHEP_REG_MASK & (~USB_CH_ERRTX) & (~USB_CH_VTTX))) |
2695                      (USB_CH_VTRX | USB_CH_ERRRX);
2696 
2697           HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, epch_reg);
2698         }
2699       }
2700     }
2701 
2702     return;
2703   }
2704 
2705   /* Wakeup Flag Detected */
2706   if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
2707   {
2708     if (hhcd->HostState == HCD_HCD_STATE_SUSPEND)
2709     {
2710       /* Set The L2Resume bit */
2711       hhcd->Instance->CNTR |= USB_CNTR_L2RES;
2712 
2713       /* Clear the wake-up flag */
2714       __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
2715 
2716       /* Update the USB Software state machine */
2717       HAL_HCD_ResumeCallback(hhcd);
2718       hhcd->HostState = HCD_HCD_STATE_RESUME;
2719     }
2720     else
2721     {
2722       /* Clear the wake-up flag */
2723       __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
2724     }
2725 
2726     return;
2727   }
2728 
2729   /* Global Error Flag Detected */
2730   if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
2731   {
2732     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_ERR);
2733 
2734     return;
2735   }
2736 
2737   /* PMA Overrun detected */
2738   if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
2739   {
2740     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_PMAOVR);
2741 
2742     return;
2743   }
2744 
2745   /* Suspend Detected */
2746   if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
2747   {
2748     /* Set HAL State to Suspend */
2749     hhcd->HostState = HCD_HCD_STATE_SUSPEND;
2750 
2751     /* Force low-power mode in the macrocell */
2752     hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
2753 
2754     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
2755     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SUSP);
2756 
2757     /* Call suspend Callback */
2758     HAL_HCD_SuspendCallback(hhcd);
2759 
2760     return;
2761   }
2762 
2763   /* Start Of Frame Detected */
2764   if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
2765   {
2766 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2767     hhcd->SOFCallback(hhcd);
2768 #else
2769     HAL_HCD_SOF_Callback(hhcd);
2770 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2771 
2772     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SOF);
2773 
2774     /* when first SOF is detected after USB_RESET is asserted */
2775     if (hhcd->HostState == HCD_HCD_STATE_RESETED)
2776     {
2777       /* HAL State */
2778       hhcd->HostState = HCD_HCD_STATE_RUN;
2779 
2780 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2781       hhcd->PortEnabledCallback(hhcd);
2782 #else
2783       HAL_HCD_PortEnabled_Callback(hhcd);
2784 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2785     }
2786 
2787     return;
2788   }
2789 }
2790 
2791 /**
2792   * @brief  SOF callback.
2793   * @param  hhcd HCD handle
2794   * @retval None
2795   */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)2796 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
2797 {
2798   /* Prevent unused argument(s) compilation warning */
2799   UNUSED(hhcd);
2800 
2801   /* NOTE : This function Should not be modified, when the callback is needed,
2802   the HAL_HCD_SOF_Callback could be implemented in the user file
2803   */
2804 }
2805 
2806 /**
2807   * @brief Connection Event callback.
2808   * @param  hhcd HCD handle
2809   * @retval None
2810   */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)2811 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
2812 {
2813   /* Prevent unused argument(s) compilation warning */
2814   UNUSED(hhcd);
2815 
2816   /* NOTE : This function Should not be modified, when the callback is needed,
2817   the HAL_HCD_Connect_Callback could be implemented in the user file
2818   */
2819 }
2820 
2821 /**
2822   * @brief  Disconnection Event callback.
2823   * @param  hhcd HCD handle
2824   * @retval None
2825   */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)2826 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
2827 {
2828   /* Prevent unused argument(s) compilation warning */
2829   UNUSED(hhcd);
2830 
2831   /* NOTE : This function Should not be modified, when the callback is needed,
2832   the HAL_HCD_Disconnect_Callback could be implemented in the user file
2833   */
2834 }
2835 /**
2836   * @brief  Port Enabled  Event callback.
2837   * @param  hhcd HCD handle
2838   * @retval None
2839   */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)2840 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
2841 {
2842   /* Prevent unused argument(s) compilation warning */
2843   UNUSED(hhcd);
2844 
2845   /* NOTE : This function should not be modified, when the callback is needed,
2846             the HAL_HCD_Disconnect_Callback could be implemented in the user file
2847    */
2848 }
2849 /**
2850   * @brief  Port Disabled  Event callback.
2851   * @param  hhcd HCD handle
2852   * @retval None
2853   */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)2854 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
2855 {
2856   /* Prevent unused argument(s) compilation warning */
2857   UNUSED(hhcd);
2858 
2859   /* NOTE : This function should not be modified, when the callback is needed,
2860             the HAL_HCD_Disconnect_Callback could be implemented in the user file
2861    */
2862 }
2863 
2864 /**
2865   * @brief  Notify URB state change callback.
2866   * @param  hhcd HCD handle
2867   * @param  chnum Channel number.
2868   *         This parameter can be a value from 1 to 15
2869   * @param  urb_state
2870   *          This parameter can be one of these values:
2871   *            URB_IDLE/
2872   *            URB_DONE/
2873   *            URB_NOTREADY/
2874   *            URB_NYET/
2875   *            URB_ERROR/
2876   *            URB_STALL/
2877   * @retval None
2878   */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)2879 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd,
2880                                                 uint8_t chnum, HCD_URBStateTypeDef urb_state)
2881 {
2882   /* Prevent unused argument(s) compilation warning */
2883   UNUSED(hhcd);
2884   UNUSED(chnum);
2885   UNUSED(urb_state);
2886 
2887   /* NOTE : This function Should not be modified, when the callback is needed,
2888   the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
2889   */
2890 }
2891 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2892 /**
2893   * @brief  Register a User USB HCD Callback
2894   *         To be used instead of the weak predefined callback
2895   * @param  hhcd USB HCD handle
2896   * @param  CallbackID ID of the callback to be registered
2897   *         This parameter can be one of the following values:
2898   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
2899   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
2900   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID HCD Disconnect callback ID
2901   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
2902   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
2903   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
2904   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
2905   * @param  pCallback pointer to the Callback function
2906   * @retval HAL status
2907   */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)2908 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
2909                                            HAL_HCD_CallbackIDTypeDef CallbackID,
2910                                            pHCD_CallbackTypeDef pCallback)
2911 {
2912   HAL_StatusTypeDef status = HAL_OK;
2913 
2914   if (pCallback == NULL)
2915   {
2916     /* Update the error code */
2917     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
2918     return HAL_ERROR;
2919   }
2920   /* Process locked */
2921   __HAL_LOCK(hhcd);
2922 
2923   if (hhcd->State == HAL_HCD_STATE_READY)
2924   {
2925     switch (CallbackID)
2926     {
2927       case HAL_HCD_SOF_CB_ID :
2928         hhcd->SOFCallback = pCallback;
2929         break;
2930 
2931       case HAL_HCD_CONNECT_CB_ID :
2932         hhcd->ConnectCallback = pCallback;
2933         break;
2934 
2935       case HAL_HCD_DISCONNECT_CB_ID :
2936         hhcd->DisconnectCallback = pCallback;
2937         break;
2938 
2939       case HAL_HCD_PORT_ENABLED_CB_ID :
2940         hhcd->PortEnabledCallback = pCallback;
2941         break;
2942 
2943       case HAL_HCD_PORT_DISABLED_CB_ID :
2944         hhcd->PortDisabledCallback = pCallback;
2945         break;
2946 
2947       case HAL_HCD_MSPINIT_CB_ID :
2948         hhcd->MspInitCallback = pCallback;
2949         break;
2950 
2951       case HAL_HCD_MSPDEINIT_CB_ID :
2952         hhcd->MspDeInitCallback = pCallback;
2953         break;
2954 
2955       default :
2956         /* Update the error code */
2957         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
2958         /* Return error status */
2959         status =  HAL_ERROR;
2960         break;
2961     }
2962   }
2963   else if (hhcd->State == HAL_HCD_STATE_RESET)
2964   {
2965     switch (CallbackID)
2966     {
2967       case HAL_HCD_MSPINIT_CB_ID :
2968         hhcd->MspInitCallback = pCallback;
2969         break;
2970 
2971       case HAL_HCD_MSPDEINIT_CB_ID :
2972         hhcd->MspDeInitCallback = pCallback;
2973         break;
2974 
2975       default :
2976         /* Update the error code */
2977         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
2978         /* Return error status */
2979         status =  HAL_ERROR;
2980         break;
2981     }
2982   }
2983   else
2984   {
2985     /* Update the error code */
2986     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
2987     /* Return error status */
2988     status =  HAL_ERROR;
2989   }
2990 
2991   /* Release Lock */
2992   __HAL_UNLOCK(hhcd);
2993   return status;
2994 }
2995 
2996 /**
2997   * @brief  Unregister an USB HCD Callback
2998   *         USB HCD callback is redirected to the weak predefined callback
2999   * @param  hhcd USB HCD handle
3000   * @param  CallbackID ID of the callback to be unregistered
3001   *         This parameter can be one of the following values:
3002   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
3003   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
3004   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID DRD HCD Disconnect callback ID
3005   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
3006   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
3007   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
3008   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
3009   * @retval HAL status
3010   */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)3011 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd,
3012                                              HAL_HCD_CallbackIDTypeDef CallbackID)
3013 {
3014   HAL_StatusTypeDef status = HAL_OK;
3015 
3016   /* Process locked */
3017   __HAL_LOCK(hhcd);
3018 
3019   /* Setup Legacy weak Callbacks */
3020   if (hhcd->State == HAL_HCD_STATE_READY)
3021   {
3022     switch (CallbackID)
3023     {
3024       case HAL_HCD_SOF_CB_ID :
3025         hhcd->SOFCallback = HAL_HCD_SOF_Callback;
3026         break;
3027 
3028       case HAL_HCD_CONNECT_CB_ID :
3029         hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
3030         break;
3031 
3032       case HAL_HCD_DISCONNECT_CB_ID :
3033         hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
3034         break;
3035 
3036       case HAL_HCD_PORT_ENABLED_CB_ID :
3037         hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
3038         break;
3039 
3040       case HAL_HCD_PORT_DISABLED_CB_ID :
3041         hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
3042         break;
3043 
3044       case HAL_HCD_MSPINIT_CB_ID :
3045         hhcd->MspInitCallback = HAL_HCD_MspInit;
3046         break;
3047 
3048       case HAL_HCD_MSPDEINIT_CB_ID :
3049         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
3050         break;
3051 
3052       default :
3053         /* Update the error code */
3054         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3055 
3056         /* Return error status */
3057         status =  HAL_ERROR;
3058         break;
3059     }
3060   }
3061   else if (hhcd->State == HAL_HCD_STATE_RESET)
3062   {
3063     switch (CallbackID)
3064     {
3065       case HAL_HCD_MSPINIT_CB_ID :
3066         hhcd->MspInitCallback = HAL_HCD_MspInit;
3067         break;
3068 
3069       case HAL_HCD_MSPDEINIT_CB_ID :
3070         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
3071         break;
3072 
3073       default :
3074         /* Update the error code */
3075         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3076 
3077         /* Return error status */
3078         status =  HAL_ERROR;
3079         break;
3080     }
3081   }
3082   else
3083   {
3084     /* Update the error code */
3085     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3086 
3087     /* Return error status */
3088     status =  HAL_ERROR;
3089   }
3090 
3091   /* Release Lock */
3092   __HAL_UNLOCK(hhcd);
3093   return status;
3094 }
3095 
3096 /**
3097   * @brief  Register USB HCD Host Channel Notify URB Change Callback
3098   *         To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
3099   * @param  hhcd HCD handle
3100   * @param  pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
3101   * @retval HAL status
3102   */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)3103 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
3104                                                              pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
3105 {
3106   HAL_StatusTypeDef status = HAL_OK;
3107 
3108   if (pCallback == NULL)
3109   {
3110     /* Update the error code */
3111     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3112 
3113     return HAL_ERROR;
3114   }
3115 
3116   /* Process locked */
3117   __HAL_LOCK(hhcd);
3118 
3119   if (hhcd->State == HAL_HCD_STATE_READY)
3120   {
3121     hhcd->HC_NotifyURBChangeCallback = pCallback;
3122   }
3123   else
3124   {
3125     /* Update the error code */
3126     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3127 
3128     /* Return error status */
3129     status = HAL_ERROR;
3130   }
3131 
3132   /* Release Lock */
3133   __HAL_UNLOCK(hhcd);
3134 
3135   return status;
3136 }
3137 
3138 /**
3139   * @brief  Unregister the USB HCD Host Channel Notify URB Change Callback
3140   *         USB HCD Host Channel Notify URB Change Callback is redirected
3141   *         to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
3142   * @param  hhcd HCD handle
3143   * @retval HAL status
3144   */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)3145 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
3146 {
3147   HAL_StatusTypeDef status = HAL_OK;
3148 
3149   /* Process locked */
3150   __HAL_LOCK(hhcd);
3151 
3152   if (hhcd->State == HAL_HCD_STATE_READY)
3153   {
3154     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
3155   }
3156   else
3157   {
3158     /* Update the error code */
3159     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
3160 
3161     /* Return error status */
3162     status =  HAL_ERROR;
3163   }
3164 
3165   /* Release Lock */
3166   __HAL_UNLOCK(hhcd);
3167 
3168   return status;
3169 }
3170 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
3171 
3172 
3173 /**
3174   * @}
3175   */
3176 
3177 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
3178   *  @brief   Management functions
3179   *
3180 @verbatim
3181 ===============================================================================
3182 ##### Peripheral Control functions #####
3183 ===============================================================================
3184 [..]
3185 This subsection provides a set of functions allowing to control the HCD data
3186 transfers.
3187 
3188 @endverbatim
3189   * @{
3190   */
3191 
3192 /**
3193   * @brief  Start the host driver.
3194   * @param  hhcd HCD handle
3195   * @retval HAL status
3196   */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)3197 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
3198 {
3199   __HAL_LOCK(hhcd);
3200 
3201   /*Set the PullDown on the PHY */
3202   hhcd->Instance->BCDR |= USB_BCDR_DPPD;
3203 
3204   /* Clear Reset  */
3205   hhcd->Instance->CNTR &= ~USB_CNTR_USBRST;
3206 
3207   /*Remove PowerDown */
3208   hhcd->Instance->CNTR &= ~USB_CNTR_PDWN;
3209 
3210   __HAL_UNLOCK(hhcd);
3211 
3212   return HAL_OK;
3213 }
3214 
3215 /**
3216   * @brief  Stop the host driver.
3217   * @param  hhcd HCD handle
3218   * @retval HAL status
3219   */
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)3220 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
3221 {
3222   __HAL_LOCK(hhcd);
3223   /*Stop the Host IP: setting powerdown  */
3224   (void)USB_StopHost(hhcd->Instance);
3225 
3226   /* clear all allocated virtual channel */
3227   HAL_HCD_ClearPhyChannel(hhcd);
3228 
3229   /* Reset the PMA current pointer */
3230   (void)HAL_HCD_PMAReset(hhcd);
3231 
3232   /* reset Ep0 Pma allocation state */
3233   hhcd->ep0_PmaAllocState = 0U;
3234 
3235   __HAL_UNLOCK(hhcd);
3236   return HAL_OK;
3237 }
3238 
3239 /**
3240   * @brief  Put the Device in suspend mode
3241   * @param  hhcd HCD handle
3242   * @retval HAL status
3243   */
HAL_HCD_Suspend(HCD_HandleTypeDef * hhcd)3244 HAL_StatusTypeDef HAL_HCD_Suspend(HCD_HandleTypeDef *hhcd)
3245 {
3246   __IO uint32_t count = 0U;
3247 
3248   /* Set Suspend Mode */
3249   hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
3250 
3251   /* wait for Suspend Ready */
3252   while ((hhcd->Instance->CNTR & USB_CNTR_SUSPRDY) == 0U)
3253   {
3254     if (++count > 0xFFFFFFU)
3255     {
3256       return HAL_TIMEOUT;
3257     }
3258   }
3259 
3260   return HAL_OK;
3261 }
3262 
3263 /**
3264   * @brief  Resume host port
3265   * @param  hhcd HCD handle
3266   * @retval HAL status
3267   */
HAL_HCD_Resume(HCD_HandleTypeDef * hhcd)3268 HAL_StatusTypeDef HAL_HCD_Resume(HCD_HandleTypeDef *hhcd)
3269 {
3270   /* Set Resume bit */
3271   hhcd->Instance->CNTR |= USB_CNTR_L2RES;
3272 
3273   return HAL_OK;
3274 }
3275 
3276 /**
3277   * @brief  Reset the host port.
3278   * @param  hhcd HCD handle
3279   * @retval HAL status
3280   */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)3281 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
3282 {
3283   __HAL_LOCK(hhcd);
3284 
3285   /* Reset the USB Port by inserting an SE0 on the bus */
3286   (void)USB_ResetPort(hhcd->Instance);
3287 
3288   if (hhcd->HostState == HCD_HCD_STATE_CONNECTED)
3289   {
3290     hhcd->HostState = HCD_HCD_STATE_RESETED;
3291   }
3292   __HAL_UNLOCK(hhcd);
3293 
3294   return HAL_OK;
3295 }
3296 
3297 /**
3298   * @brief  Resme the host port.
3299   * @param  hhcd HCD handle
3300   * @retval HAL status
3301   */
HAL_HCD_ResumePort(HCD_HandleTypeDef * hhcd)3302 HAL_StatusTypeDef HAL_HCD_ResumePort(HCD_HandleTypeDef *hhcd)
3303 {
3304   /* Set Resume bit */
3305   hhcd->Instance->CNTR |= USB_CNTR_L2RES;
3306   HAL_Delay(30U);
3307 
3308   /* Clear Resume bit */
3309   hhcd->Instance->CNTR &= ~USB_CNTR_L2RES;
3310 
3311   return HAL_OK;
3312 }
3313 
3314 
3315 /**
3316   * @}
3317   */
3318 
3319 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
3320   *  @brief   Peripheral State functions
3321   *
3322 @verbatim
3323 ===============================================================================
3324 ##### Peripheral State functions #####
3325 ===============================================================================
3326 [..]
3327 This subsection permits to get in run-time the status of the peripheral
3328 and the data flow.
3329 
3330 @endverbatim
3331   * @{
3332   */
3333 
3334 /**
3335   * @brief  Return the HCD handle state.
3336   * @param  hhcd HCD handle
3337   * @retval HAL state
3338   */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)3339 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
3340 {
3341   return hhcd->State;
3342 }
3343 
3344 /**
3345   * @brief  Return  URB state for a channel.
3346   * @param  hhcd HCD handle
3347   * @param  chnum Channel number.
3348   *         This parameter can be a value from 1 to 15
3349   * @retval URB state.
3350   *          This parameter can be one of these values:
3351   *            URB_IDLE/
3352   *            URB_DONE/
3353   *            URB_NOTREADY/
3354   *            URB_NYET/
3355   *            URB_ERROR/
3356   *            URB_STALL
3357   */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)3358 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
3359 {
3360   return hhcd->hc[chnum].urb_state;
3361 }
3362 
3363 
3364 /**
3365   * @brief  Return the last host transfer size.
3366   * @param  hhcd HCD handle
3367   * @param  chnum Channel number.
3368   *         This parameter can be a value from 1 to 15
3369   * @retval last transfer size in byte
3370   */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)3371 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
3372 {
3373   return hhcd->hc[chnum].xfer_count;
3374 }
3375 
3376 /**
3377   * @brief  Return the Host Channel state.
3378   * @param  hhcd HCD handle
3379   * @param  chnum Channel number.
3380   *         This parameter can be a value from 1 to 15
3381   * @retval Host channel state
3382   *          This parameter can be one of these values:
3383   *            HC_IDLE/
3384   *            HC_XFRC/
3385   *            HC_HALTED/
3386   *            HC_NYET/
3387   *            HC_NAK/
3388   *            HC_STALL/
3389   *            HC_XACTERR/
3390   *            HC_BBLERR/
3391   *            HC_DATATGLERR
3392   */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)3393 HCD_HCStateTypeDef  HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
3394 {
3395   return hhcd->hc[chnum].state;
3396 }
3397 
3398 /**
3399   * @brief  Return the current Host frame number.
3400   * @param  hhcd HCD handle
3401   * @retval Current Host frame number
3402   */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)3403 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
3404 {
3405   return (USB_GetCurrentFrame(hhcd->Instance));
3406 }
3407 
3408 /**
3409   * @brief  Return the Host enumeration speed.
3410   * @param  hhcd HCD handle
3411   * @retval speed : Device speed after Host enumeration
3412   *          This parameter can be one of these values:
3413   *            @arg HCD_DEVICE_SPEED_HIGH: High speed mode
3414   *            @arg HCD_DEVICE_SPEED_FULL: Full speed mode
3415   *            @arg HCD_DEVICE_SPEED_LOW: Low speed mode
3416   */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)3417 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
3418 {
3419   return (USB_GetHostSpeed(hhcd->Instance));
3420 }
3421 
3422 /**
3423   * @brief  Set host channel Hub Information.
3424   * @param  hhcd HCD handle
3425   * @param  ch_num Channel number.
3426   *         This parameter can be a value from 1 to 15
3427   * @param  addr Hub address
3428   * @param  PortNbr Hub port number
3429   * @retval HAL status
3430   */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)3431 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
3432                                         uint8_t addr, uint8_t PortNbr)
3433 {
3434   hhcd->hc[ch_num].hub_addr = addr;
3435   hhcd->hc[ch_num].hub_port_nbr = PortNbr;
3436 
3437   return HAL_OK;
3438 }
3439 
3440 
3441 /**
3442   * @brief  Clear host channel hub information.
3443   * @param  hhcd HCD handle
3444   * @param  ch_num Channel number.
3445   *         This parameter can be a value from 1 to 15
3446   * @retval HAL status
3447   */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)3448 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
3449 {
3450   hhcd->hc[ch_num].hub_addr = 0U;
3451   hhcd->hc[ch_num].hub_port_nbr = 0U;
3452 
3453   return HAL_OK;
3454 }
3455 
3456 #if (USE_USB_DOUBLE_BUFFER == 1U)
3457 /**
3458   * @brief  Handle Host Channel OUT Double Buffer Bulk requests.
3459   * @param  hhcd HCD handle
3460   * @param  ch_num Channel number This parameter can be a value from 1 to 15
3461   * @param  phy_chnum Physical Channel number [0..7]
3462   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
3463   * @retval none
3464   */
HCD_HC_OUT_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)3465 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
3466                               uint8_t phy_chnum, uint32_t regvalue)
3467 {
3468   uint16_t data_xfr;
3469   uint16_t len;
3470 
3471   /* Send Buffer0 */
3472   if ((regvalue & USB_CH_DTOG_TX) != 0U)
3473   {
3474     data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
3475 
3476     if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr)
3477     {
3478       hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
3479     }
3480     else
3481     {
3482       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
3483     }
3484 
3485     /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
3486     if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
3487     {
3488       /* manage multiple Xfer */
3489       hhcd->hc[ch_num & 0xFU].xfer_count  += data_xfr;
3490 
3491       /* check if we need to free user buffer */
3492       if ((regvalue & USB_CH_DTOG_RX) != 0U)
3493       {
3494         /* Toggle SwBuff */
3495         HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
3496         HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
3497         HCD_TX_DTOG(hhcd->Instance, phy_chnum);
3498       }
3499 
3500       /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
3501       if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
3502       {
3503         hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
3504 
3505         /* calculate len of new buffer to fill */
3506         if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
3507         {
3508           len = (uint16_t)hhcd->hc[ch_num & 0xFU].max_packet;
3509           hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
3510         }
3511         else
3512         {
3513           len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
3514           hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
3515         }
3516 
3517         /* Write remaining data to Buffer0 */
3518         HCD_SET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
3519         USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3520                      hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)len);
3521       }
3522       /* start a new transfer */
3523       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
3524     }
3525     else
3526     {
3527       /* Transfer complete state */
3528       hhcd->hc[ch_num & 0xFU].xfer_count  += data_xfr;
3529       hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
3530       hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
3531       hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
3532       /* Close the Channel */
3533       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
3534     }
3535   }
3536   else
3537   {
3538     /* Send Buffer1 */
3539     data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->RXBD & 0x03FF0000U) >> 16U);
3540 
3541     if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr) /* updated */
3542     {
3543       hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
3544     }
3545 
3546     /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
3547     if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
3548     {
3549       /* manage multiple Xfer */
3550       hhcd->hc[ch_num & 0xFU].xfer_count  += data_xfr;
3551 
3552       /* check if we need to free user buffer */
3553       if ((regvalue & USB_CH_DTOG_RX) == 0U)
3554       {
3555         /* Toggle SwBuff */
3556         HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
3557         HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
3558         HCD_RX_DTOG(hhcd->Instance, phy_chnum);
3559       }
3560 
3561       /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
3562       if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
3563       {
3564         hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
3565 
3566         /* calculate len of new buffer to fill */
3567         if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
3568         {
3569           len = hhcd->hc[ch_num & 0xFU].max_packet;
3570           hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
3571         }
3572         else
3573         {
3574           len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
3575           hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
3576         }
3577 
3578         /* Write remaining data to Buffer0 */
3579         HCD_SET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
3580 
3581         USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3582                      hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)len);
3583       }
3584 
3585       /* start a new transfer */
3586       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
3587     }
3588     else
3589     {
3590       /* Transfer complete state */
3591       hhcd->hc[ch_num & 0xFU].xfer_count  += data_xfr;
3592       hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
3593       hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
3594       hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
3595 
3596       /* Close the channel */
3597       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
3598     }
3599   }
3600 }
3601 
3602 
3603 /**
3604   * @brief  Handle Host Channel IN Double Buffer Bulk requests.
3605   * @param  hhcd HCD handle
3606   * @param  ch_num Channel number: This parameter can be a value from 1 to 15
3607   * @param  phy_chnum Physical Channel number [0..7]
3608   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
3609   * @retval none
3610   */
HCD_HC_IN_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)3611 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd,
3612                              uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue)
3613 {
3614   uint16_t received_bytes;
3615 
3616   /* Read from Buffer 0 */
3617   if ((regvalue & USB_CH_DTOG_RX) != 0U)
3618   {
3619     received_bytes = (uint16_t)HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
3620 
3621     if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
3622     {
3623       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
3624     }
3625     else
3626     {
3627       hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
3628     }
3629 
3630     /* Check if we Need to free the other buffer for the IP */
3631     if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) != 0U))
3632     {
3633       /* Toggle SwBuff to Allow the IP to submit a new IN */
3634       HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
3635     }
3636 
3637     /* Read the byte from PMA to user Buffer(System Memory) */
3638     USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3639                 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)received_bytes);
3640   }
3641   else
3642   {
3643     /* Read from Buffer 1 */
3644     received_bytes = (uint16_t) HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
3645 
3646     if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
3647     {
3648       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
3649     }
3650     else
3651     {
3652       hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
3653     }
3654 
3655     /* Check if we Need to free the other buffer for the IP */
3656     if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) == 0U))
3657     {
3658       /* Toggle SwBuff */
3659       HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
3660     }
3661 
3662     /* Read the byte from PMA to user Buffer(System Memory) */
3663     USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3664                 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)received_bytes);
3665   }
3666 
3667   /* update the global number of all received bytes */
3668   hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
3669 
3670   /* Transfer complete state */
3671   hhcd->hc[ch_num & 0xFU].state = HC_ACK;
3672   hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
3673 
3674   if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
3675       ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
3676   {
3677     hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
3678     hhcd->hc[ch_num & 0xFU].state  = HC_XFRC;
3679 
3680     /* disable channel */
3681     HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
3682   }
3683   else
3684   {
3685     hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
3686 
3687     /* Reactivate the Channel Submit an other URB since the Transfer is not yet completed */
3688     HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
3689   }
3690 }
3691 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3692 
3693 /**
3694   * @brief  Handle Host Channel IN Isochronous Transaction
3695   * @param  hhcd HCD handle
3696   * @param  ch_num Channel number: This parameter can be a value from 1 to 15
3697   * @param  phy_chnum Physical Channel number [0..7]
3698   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
3699   * @retval none
3700   */
HCD_HC_IN_ISO(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)3701 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
3702                                  uint8_t phy_chnum, uint32_t regvalue)
3703 {
3704   /* Check if Double buffer isochronous */
3705   if ((regvalue & USB_CH_KIND) != 0U)
3706   {
3707     /* Get Data IN Packet */
3708     hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
3709     if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
3710     {
3711       USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3712                   hhcd->hc[ch_num & 0xFU].pmaadress,
3713                   (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
3714 
3715       hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3716     }
3717   }
3718 #if (USE_USB_DOUBLE_BUFFER == 1U)
3719   else  /* double buffer isochronous */
3720   {
3721     /* Read from Buffer0 */
3722     if ((regvalue & USB_CH_DTOG_RX) != 0U)
3723     {
3724       /* Get number of Received byte in buffer0 */
3725       hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
3726 
3727       if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
3728       {
3729         /* Read from Buffer0 */
3730         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3731                     hhcd->hc[ch_num & 0xFU].pmaaddr0,
3732                     (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
3733 
3734         hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
3735       }
3736     }
3737     else
3738     {
3739       /* Get number of Received byte in buffer1 */
3740       hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
3741 
3742       if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
3743       {
3744         /* Read from Buffer1 */
3745         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3746                     hhcd->hc[ch_num & 0xFU].pmaaddr1,
3747                     (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
3748 
3749         hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
3750       }
3751     }
3752   }
3753 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3754 
3755   /* Transfer complete state */
3756   hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
3757 
3758   /* Clear VTRX */
3759   HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
3760 }
3761 
3762 /**
3763   * @brief  Handle Host Channel IN interrupt requests.
3764   * @param  hhcd HCD handle
3765   * @param  ch_num Channel number
3766   *         This parameter can be a value from 1 to 15
3767   * @retval none
3768   */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t ch_num)3769 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
3770 {
3771   uint16_t received_bytes;
3772   uint8_t phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
3773 
3774   /*Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control and status */
3775   uint32_t ch_reg =  HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
3776 
3777   /* Manage Correct Transaction */
3778   if ((ch_reg & USB_CH_ERRRX) == 0U)
3779   {
3780     /* Isochronous Channel */
3781     if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
3782     {
3783       HCD_HC_IN_ISO(hhcd, ch_num, phy_chnum, ch_reg);
3784     }
3785     else
3786     {
3787       /* manage ACK response single buffer */
3788       if (((ch_reg) & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF)
3789       {
3790         /* Get Control Data OUT Packet */
3791         received_bytes = (uint16_t)HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
3792 
3793         /* Read the byte from PMA to user Buffer(System Memory) */
3794         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
3795                     hhcd->hc[ch_num & 0xFU].pmaadress, (uint16_t)received_bytes);
3796 
3797         /* update the global number of all received bytes */
3798         hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
3799 
3800         /* Transfer complete state */
3801         hhcd->hc[ch_num & 0xFU].state = HC_ACK;
3802         hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
3803 
3804         if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
3805         {
3806           hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
3807         }
3808         else
3809         {
3810           hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
3811         }
3812 
3813         if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
3814             ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
3815         {
3816           hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
3817           hhcd->hc[ch_num & 0xFU].state  = HC_XFRC;
3818         }
3819         else
3820         {
3821           hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
3822 
3823           /* Reactivate the Channel to Submit another URB since the Transfer is not yet completed */
3824           HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
3825         }
3826 
3827         if ((hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_BULK) ||
3828             (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR))
3829         {
3830           hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
3831         }
3832       }
3833       /* manage NACK Response */
3834       else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK)
3835                && (hhcd->hc[ch_num & 0xFU].urb_state != URB_DONE))
3836       {
3837         hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
3838         hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
3839         hhcd->hc[ch_num & 0xFU].state = HC_NAK;
3840       }
3841       /* manage STALL Response */
3842       else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL)
3843       {
3844         (void)HAL_HCD_HC_Halt(hhcd, ch_num);
3845         hhcd->hc[ch_num & 0xFU].state = HC_STALL;
3846         hhcd->hc[ch_num & 0xFU].urb_state = URB_STALL;
3847 
3848         /* Close the channel */
3849         HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
3850       }
3851 #if (USE_USB_DOUBLE_BUFFER == 1U)
3852       /* Double Buffer Management in case of Bulk Transaction */
3853       else  if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_DBUF)
3854                 && ((ch_reg & USB_CH_KIND) != 0U))
3855       {
3856         /* Bulk IN Double Buffer ISR */
3857         HCD_HC_IN_BulkDb(hhcd, ch_num, phy_chnum, ch_reg);
3858       }
3859 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3860       else
3861       {
3862         /*....*/
3863         /* not defined state: STRX=11 in single buffer no iso is not defined */
3864       }
3865 
3866 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
3867       hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
3868 #else
3869       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
3870 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
3871 
3872       /*Clear VTRX */
3873       HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
3874     }
3875   }
3876   else   /* Error detected during last transaction */
3877   {
3878     /* Set URB Error State */
3879     hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
3880     hhcd->hc[ch_num & 0xFU].ErrCnt++;
3881     hhcd->hc[ch_num & 0xFU].state = HC_XACTERR;
3882 
3883     /* Clear VTTRX & ERR_RX */
3884     HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
3885 
3886     /* Check Error number */
3887     if (hhcd->hc[ch_num & 0xFU].ErrCnt > 3U)
3888     {
3889       hhcd->hc[ch_num & 0xFU].urb_state = URB_ERROR;
3890       HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
3891 
3892       /* Clear pending err_tx */
3893       HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
3894     }
3895 
3896 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
3897     hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
3898 #else
3899     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
3900 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
3901   }
3902 }
3903 
3904 
3905 /**
3906   * @brief  Handle Host Channel OUT interrupt requests.
3907   * @param  hhcd  HCD handle
3908   * @param  chnum Channel number
3909   *         This parameter can be a value from 1 to 15
3910   * @retval none
3911   */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)3912 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
3913 {
3914   uint16_t data_xfr;
3915   __IO uint32_t WregCh;
3916 
3917   /* Get Physical Channel number */
3918   uint32_t phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
3919 
3920   /* Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control &status */
3921   uint32_t ch_reg =  *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
3922 
3923   /*------ Manage Correct Transaction ------*/
3924   if ((ch_reg & USB_CH_ERRTX) == 0U)
3925   {
3926     /* Handle Isochronous channel */
3927     if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
3928     {
3929       /* correct transaction */
3930       if ((hhcd->Instance->ISTR & USB_ISTR_ERR) == 0U)
3931       {
3932         /* Double buffer isochronous out */
3933         if ((ch_reg & USB_CH_KIND) != 0U)
3934         {
3935           HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
3936         }
3937 #if (USE_USB_DOUBLE_BUFFER == 1U)
3938         else /* double buffer isochronous out */
3939         {
3940           /* Odd Transaction */
3941           if ((ch_reg & USB_CH_DTOG_TX) != 0U)
3942           {
3943             HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
3944           }
3945           /* Even Transaction */
3946           else
3947           {
3948             HCD_SET_CH_RX_CNT(hhcd->Instance, phy_chnum, 0U);
3949           }
3950 
3951           USB_DRD_SET_CHEP_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
3952         }
3953 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3954 
3955         /* Transfer complete state */
3956         hhcd->hc[chnum & 0xFU].state = HC_XFRC;
3957         hhcd->hc[chnum & 0xFU].urb_state = URB_DONE;
3958       }
3959 
3960       /*Clear Correct Transfer */
3961       HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
3962 
3963       /*TX COMPLETE*/
3964 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
3965       hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
3966 #else
3967       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
3968 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
3969 
3970     }
3971     else /* Manage all Non Isochronous Transaction */
3972     {
3973       /* Check ACK response */
3974       if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF)
3975       {
3976         data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
3977 
3978         if (hhcd->hc[chnum & 0xFU].xfer_len >= data_xfr)
3979         {
3980           hhcd->hc[chnum & 0xFU].xfer_len -= data_xfr;
3981         }
3982         else
3983         {
3984           hhcd->hc[chnum & 0xFU].xfer_len = 0U;
3985         }
3986 
3987         /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
3988         if (hhcd->hc[chnum & 0xFU].xfer_len != 0U)
3989         {
3990           /* manage multiple Xfer */
3991           hhcd->hc[chnum & 0xFU].xfer_buff += data_xfr;
3992           hhcd->hc[chnum & 0xFU].xfer_count  += data_xfr;
3993 
3994           /* start a new transfer */
3995           (void) USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[chnum & 0xFU]);
3996         }
3997         else
3998         {
3999           /* Transfer complete */
4000           hhcd->hc[chnum & 0xFU].xfer_count += data_xfr;
4001           hhcd->hc[chnum & 0xFU].state = HC_XFRC;
4002           hhcd->hc[chnum & 0xFU].urb_state = URB_DONE;
4003 
4004           if ((hhcd->hc[chnum & 0xFU].ep_type == EP_TYPE_BULK) ||
4005               (hhcd->hc[chnum & 0xFU].ep_type == EP_TYPE_INTR))
4006           {
4007             hhcd->hc[chnum & 0xFU].toggle_out ^= 1U;
4008           }
4009         }
4010       }
4011       /* Check NACK Response */
4012       else if (((ch_reg & USB_CHEP_NAK) == USB_CHEP_NAK) ||
4013                ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK))
4014       {
4015         /* Update Channel status */
4016         hhcd->hc[chnum & 0xFU].state = HC_NAK;
4017         hhcd->hc[chnum & 0xFU].urb_state = URB_NOTREADY;
4018         hhcd->hc[chnum & 0xFU].ErrCnt = 0U;
4019 
4020         /* Get Channel register value */
4021         WregCh = *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
4022 
4023         /*clear NAK status*/
4024         WregCh &= ~USB_CHEP_NAK & USB_CHEP_REG_MASK;
4025 
4026         /* Update channel register Value */
4027         HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, WregCh);
4028 
4029         if (hhcd->hc[chnum & 0xFU].doublebuffer == 0U)
4030         {
4031 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4032           hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4033 #else
4034           HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4035 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4036         }
4037       }
4038       /* Check STALL Response */
4039       else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL)
4040       {
4041         (void) HAL_HCD_HC_Halt(hhcd, (uint8_t)chnum);
4042         hhcd->hc[chnum & 0xFU].state = HC_STALL;
4043         hhcd->hc[chnum & 0xFU].urb_state = URB_STALL;
4044       }
4045 #if (USE_USB_DOUBLE_BUFFER == 1U)
4046       /* Check double buffer ACK in case of bulk transaction */
4047       else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_DBUF)
4048       {
4049         /* Double buffer management Bulk Out */
4050         (void) HCD_HC_OUT_BulkDb(hhcd, chnum, (uint8_t)phy_chnum, ch_reg);
4051       }
4052 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4053       else
4054       {
4055         /*...*/
4056       }
4057 
4058       if ((ch_reg & USB_CH_TX_STTX) != USB_CH_TX_NAK)
4059       {
4060 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4061         hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4062 #else
4063         HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4064 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4065       }
4066 
4067       HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
4068     }  /* end no isochronous */
4069   }
4070   /*------ Manage Transaction Error------*/
4071   else
4072   {
4073     hhcd->hc[chnum & 0xFU].ErrCnt++;
4074     if (hhcd->hc[chnum & 0xFU].ErrCnt > 3U)
4075     {
4076       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
4077       hhcd->hc[chnum & 0xFU].urb_state = URB_ERROR;
4078     }
4079     else
4080     {
4081       hhcd->hc[chnum & 0xFU].urb_state = URB_NOTREADY;
4082     }
4083 
4084     hhcd->hc[chnum & 0xFU].state = HC_XACTERR;
4085 
4086     /*Clear ERR_TX*/
4087     HCD_CLEAR_TX_CH_ERR(hhcd->Instance, phy_chnum);
4088 
4089 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4090     hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4091 #else
4092     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
4093 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4094   }
4095 }
4096 
4097 
4098 /**
4099   * @brief  Handle Host Port interrupt requests.
4100   * @param  hhcd  HCD handle
4101   * @retval None
4102   */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)4103 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
4104 {
4105   uint32_t FnrReg = hhcd->Instance->FNR;
4106   uint32_t IstrReg = hhcd->Instance->ISTR;
4107 
4108   /* SE0 detected USB Disconnected state */
4109   if ((FnrReg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U)
4110   {
4111     /* Host Port State */
4112     hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
4113 
4114     /* clear all allocated virtual channel */
4115     HAL_HCD_ClearPhyChannel(hhcd);
4116 
4117     /* Reset the PMA current pointer */
4118     (void)HAL_HCD_PMAReset(hhcd);
4119 
4120     /* reset Ep0 Pma allocation state */
4121     hhcd->ep0_PmaAllocState = 0U;
4122 
4123     /* Disconnection Callback */
4124 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4125     hhcd->DisconnectCallback(hhcd);
4126 #else
4127     HAL_HCD_Disconnect_Callback(hhcd);
4128 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4129 
4130     return;
4131   }
4132 
4133   if ((hhcd->HostState == HCD_HCD_STATE_DISCONNECTED) != 0U)
4134   {
4135     /* J-state or K-state detected & LastState=Disconnected */
4136     if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
4137     {
4138       hhcd->HostState = HCD_HCD_STATE_CONNECTED;
4139 
4140 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4141       hhcd->ConnectCallback(hhcd);
4142 #else
4143       HAL_HCD_Connect_Callback(hhcd);
4144 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4145     }
4146   }
4147   else
4148   {
4149     /* J-state or K-state detected & lastState=Connected: a Missed disconnection is detected */
4150     if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
4151     {
4152       /* Host Port State */
4153       hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
4154 
4155       /* clear all allocated virtual channel */
4156       HAL_HCD_ClearPhyChannel(hhcd);
4157 
4158       /* Reset the PMA current pointer */
4159       (void)HAL_HCD_PMAReset(hhcd);
4160 
4161       /* reset Ep0 PMA allocation state */
4162       hhcd->ep0_PmaAllocState = 0U;
4163 
4164       /* Disconnection Callback */
4165 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
4166       hhcd->DisconnectCallback(hhcd);
4167 #else
4168       HAL_HCD_Disconnect_Callback(hhcd);
4169 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
4170     }
4171   }
4172 }
4173 
4174 
4175 /**
4176   * @brief  Check if the ch_num are already reserved to a physical channel
4177   * @param  hhcd  HCD handle
4178   * @param  ch_num  Channel number
4179   *         This parameter can be a value from 1 to 15
4180   * @retval HAL status
4181   */
HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const * hhcd,uint8_t ch_num)4182 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num)
4183 {
4184   uint8_t idx;
4185 
4186   /* Check if the logical channel are already opened  */
4187   for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
4188   {
4189     if ((((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
4190         (hhcd->phy_chin_state[idx] != 0U))
4191     {
4192       return (1U | (idx << 4U));
4193     }
4194 
4195     if ((((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
4196         (hhcd->phy_chout_state[idx] != 0U))
4197     {
4198       return (1U | (idx << 4U));
4199     }
4200   }
4201 
4202   return 0U;
4203 }
4204 
4205 
4206 /**
4207   * @brief  Get a Logical Channel number from  physical Channel
4208   * @param  hhcd  HCD handle
4209   * @param  phy_chnum
4210   *         This parameter can be a value from 1 to 15
4211   * @param  dir  Channel direction
4212   *         -0 OUT_Channel
4213   *         -1 IN_Channel
4214   * @retval HAL status
4215   */
HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const * hhcd,uint8_t phy_chnum,uint8_t dir)4216 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd,
4217                                           uint8_t phy_chnum, uint8_t dir)
4218 {
4219   /* Out Channel Direction */
4220   if (dir == 0U)
4221   {
4222     if (((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
4223     {
4224       return ((uint8_t)((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
4225     }
4226     else
4227     {
4228       /* Channel not registered Error */
4229       return HCD_LOGICAL_CH_NOT_OPENED;
4230     }
4231   }
4232   /* IN Channel Direction */
4233   else
4234   {
4235     if (((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
4236     {
4237       return ((uint8_t)((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
4238     }
4239     else
4240     {
4241       /* Channel not registered Error */
4242       return HCD_LOGICAL_CH_NOT_OPENED;
4243     }
4244   }
4245 }
4246 
4247 
4248 /**
4249   * @brief  Get a free physical Channel number according to the direction
4250   * @param  hhcd HCD handle
4251   * @param  ch_num Channel number
4252   *         This parameter can be a value from 1 to 15
4253   * @param  epnum Endpoint number
4254   *          This parameter can be a value from 1 to 15
4255   * @param  ep_type Endpoint Type
4256   *          This parameter can be one of these values:
4257   *            EP_TYPE_CTRL Control type,
4258   *            EP_TYPE_ISOC Isochronous type,
4259   *            EP_TYPE_BULK Bulk type,
4260   *            EP_TYPE_INTR Interrupt type
4261   * @retval if physical channel is available return Phy_channel number
4262          else return HCD_FREE_CH_NOT_FOUND
4263   */
HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t epnum,uint8_t ep_type)4264 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
4265                                           uint8_t epnum, uint8_t ep_type)
4266 {
4267   uint8_t idx;
4268 
4269   if ((epnum & 0x7FU) == 0U)
4270   {
4271     idx = 0U;
4272 
4273     if (ch_num == 0U)
4274     {
4275       if (hhcd->phy_chin_state[idx] == 0U)
4276       {
4277         /* chin_state to store the ep_type to be used for the same channel in OUT direction
4278          * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4279         hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4280                                     ((uint16_t)ep_type + 1U) |
4281                                     (((uint16_t)epnum & 0x0FU) << 8U);
4282       }
4283 
4284       if (hhcd->phy_chout_state[idx] == 0U)
4285       {
4286         /* chout_state will store the ep_type to be used for the same channel in IN direction
4287          * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4288         hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4289                                      ((uint16_t)ep_type + 1U) |
4290                                      (((uint16_t)epnum & 0x0FU) << 8U);
4291       }
4292     }
4293     else
4294     {
4295       if ((epnum & 0x80U) != 0U)
4296       {
4297         if (((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
4298         {
4299           /* chin_state to store the ep_type to be used for the same channel in OUT direction
4300            * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4301           hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4302                                       ((uint16_t)ep_type + 1U) |
4303                                       (((uint16_t)epnum & 0x0FU) << 8U);
4304         }
4305       }
4306       else
4307       {
4308         if (((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
4309         {
4310           /* chout_state will store the ep_type to be used for the same channel in IN direction
4311            * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4312           hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4313                                        ((uint16_t)ep_type + 1U) |
4314                                        (((uint16_t)epnum & 0x0FU) << 8U);
4315         }
4316       }
4317     }
4318 
4319     return idx;
4320   }
4321 
4322   if ((epnum & 0x80U) != 0U)
4323   {
4324     /* Find a new available physical in channel */
4325     for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
4326     {
4327       /* Check if the same epnum is allocated then allocate the same physical channel OUT for IN Logical Channel */
4328       if ((hhcd->phy_chin_state[idx] == 0U) &&
4329           ((((hhcd->phy_chout_state[idx] & 0x000FU) == ((uint16_t)ep_type + 1U)) &&
4330             (((hhcd->phy_chout_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU)))) ||
4331            (hhcd->phy_chout_state[idx] == 0U)))
4332       {
4333         /* chin_state to store the ep_type to be used for the same channel in OUT direction
4334          * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4335         hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4336                                     ((uint16_t)ep_type + 1U) |
4337                                     (((uint16_t)epnum & 0x0FU) << 8U);
4338 
4339         return idx;
4340       }
4341     }
4342   }
4343   else
4344   {
4345     /* Find a new available physical out channel */
4346     for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
4347     {
4348       /* Check if the same epnum is allocated then allocate the same physical channel IN for OUT Logical Channel */
4349       if ((hhcd->phy_chout_state[idx] == 0U) &&
4350           ((((hhcd->phy_chin_state[idx] & 0x0FU) == ((uint16_t)ep_type + 1U)) &&
4351             ((hhcd->phy_chin_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU))) ||
4352            (hhcd->phy_chin_state[idx] == 0U)))
4353       {
4354         /* chout_state will store the ep_type to be used for the same channel in IN direction
4355          * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
4356         hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
4357                                      ((uint16_t)ep_type + 1U) |
4358                                      (((uint16_t)epnum & 0x0FU) << 8U);
4359 
4360         return idx;
4361       }
4362     }
4363   }
4364 
4365   /* in case of Error */
4366   return HCD_FREE_CH_NOT_FOUND;
4367 }
4368 
4369 /**
4370   * @brief  Free All Channel allocation
4371   * @param  hhcd HCD handle
4372   * @retval HAL status
4373   */
HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef * hhcd)4374 static void  HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd)
4375 {
4376   uint8_t idx;
4377 
4378   for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
4379   {
4380     /*Reset channel allocation value */
4381     hhcd->phy_chout_state[idx] = 0U;
4382     hhcd->phy_chin_state[idx] = 0U;
4383   }
4384 }
4385 
4386 /*----------------------  PMA Allocation Section --------------------- */
4387 /*
4388                 __col31________________col0__   Column-- >
4389           lin0 | entry31.|.......  | entry0 |   Line
4390                |---------|---------|--------|    |
4391           line1| entry63.|.......  | entry32|    |
4392                |---------|---------|--------|   \|/
4393                | entry127|.......  | entry64|
4394                |---------|---------|--------|
4395                | entry256|......   |entry128|
4396                 ----------------------------
4397            an allocation space of 64byte need 8 Free contiguous Entry in the Matrix
4398            - a Free Entry is a bit with 0 Value/  a busy entry is a bit with 1 value. */
4399 
4400 /**
4401   * @brief  Fetch in the PMA_LockupTable free space of number of mps byte
4402   * @param  hhcd  Host instance
4403   * @param  mps  Channel Max Packet Size
4404   * @retval PMA_Address of the first free block containing mps byte
4405             0xFFFF in case of no space available
4406   */
HAL_HCD_GetFreePMA(HCD_HandleTypeDef * hhcd,uint16_t mps)4407 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps)
4408 {
4409   uint32_t Entry;
4410   uint32_t FreeBlocks = 0U;
4411   uint8_t FirstFreeBlock_col = 0U;
4412   uint8_t FirstFreeBlock_line = 0U;
4413   uint8_t ColIndex;
4414   uint16_t NbrReqBlocks;
4415   uint16_t mps_t = mps;
4416 
4417   /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
4418     allocation in PMA is done in 32Bytes each entry */
4419   if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
4420   {
4421     /* Align the mps to 32byte block to match the allocation in PMA,
4422       check Definition of allocation buffer memory in usb user spec */
4423     mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
4424   }
4425 
4426   /* calculate the number of block(8byte) to allocate */
4427   NbrReqBlocks = mps_t / 8U;
4428 
4429   /* check if we need remaining Block */
4430   if ((mps_t % 8U) != 0U)
4431   {
4432     NbrReqBlocks++;
4433   }
4434 
4435   /* Look For NbrReqBlocks * Empty Block */
4436   for (uint8_t i = 0U; ((i < PMA_BLOCKS) && (FreeBlocks != NbrReqBlocks)); i++)
4437   {
4438     Entry = hhcd->PMALookupTable[i];
4439 
4440     /* when parse is in progress, check the first col to look for a contiguous block */
4441     if ((FreeBlocks != 0U) && ((Entry & (uint32_t)1U) != 0U))
4442     {
4443       FreeBlocks = 0U;
4444     }
4445     uint8_t j = 0U;
4446     while ((j <= 31U) && (FreeBlocks != NbrReqBlocks))
4447     {
4448       /* check if block j is free */
4449       if ((Entry & ((uint32_t)1U << j)) == 0U)
4450       {
4451         if (FreeBlocks == 0U)
4452         {
4453           FirstFreeBlock_col = j;
4454           FirstFreeBlock_line = i;
4455           FreeBlocks++;
4456         }
4457         j++;
4458 
4459         /* Parse Column PMALockTable */
4460         while ((j <= 31U) && ((Entry & ((uint32_t)1U << j)) == 0U) && (FreeBlocks < NbrReqBlocks))
4461         {
4462           FreeBlocks++;
4463           j++;
4464         }
4465 
4466         /* Free contiguous Blocks not found */
4467         if (((FreeBlocks < NbrReqBlocks) && (j < 31U)) ||
4468             ((j == 31U) && ((Entry & ((uint32_t)1U << j)) != 0U)))
4469         {
4470           FreeBlocks = 0U;
4471         }
4472       }
4473       j++;
4474     } /* end for j */
4475   } /* end for i */
4476 
4477   /* Free block found */
4478   if (FreeBlocks >= NbrReqBlocks)
4479   {
4480     ColIndex = FirstFreeBlock_col;
4481 
4482     for (uint8_t i = FirstFreeBlock_line; ((i < PMA_BLOCKS) && (FreeBlocks > 0U)); i++)
4483     {
4484       for (uint8_t j = ColIndex; j <= 31U; j++)
4485       {
4486         hhcd->PMALookupTable[i] |= ((uint32_t)1U << j);
4487         if (--FreeBlocks == 0U)
4488         {
4489           break;
4490         }
4491       }
4492       ColIndex = 0U;
4493     }
4494 
4495     return (uint16_t)((FirstFreeBlock_line * (uint16_t)256U) + (FirstFreeBlock_col * (uint16_t)8U));
4496   }
4497   else
4498   {
4499     return 0xFFFFU;
4500   }
4501 }
4502 
4503 /**
4504   * @brief  Allocate PMA buffer for Channel
4505   *         This API will fetch a free space
4506   * @param  hhcd    Host instance
4507   * @param  ch_num  Channel number
4508   * @param  ch_kind endpoint Kind
4509   *                  USB_SNG_BUF Single Buffer used
4510   *                  USB_DBL_BUF Double Buffer used
4511   * @param  mps Channel Max Packet Size
4512   * @retval HAL status
4513   */
HAL_HCD_PMAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint16_t ch_kind,uint16_t mps)4514 HAL_StatusTypeDef  HAL_HCD_PMAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
4515                                    uint16_t ch_kind, uint16_t mps)
4516 {
4517   uint16_t pma_addr0;
4518 #if (USE_USB_DOUBLE_BUFFER == 1U)
4519   uint16_t pma_addr1; /* used for double buffer mode if enabled */
4520 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4521 
4522   /* Host Channel */
4523   HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
4524 
4525   /* Get a FreePMA Address */
4526   pma_addr0 = HAL_HCD_GetFreePMA(hhcd, mps);
4527 
4528   /* if there is no free space to allocate */
4529   if (pma_addr0 == 0xFFFFU)
4530   {
4531     return HAL_ERROR;
4532   }
4533   else
4534   {
4535     /* Here we check if the endpoint is single or double Buffer */
4536     if (ch_kind == HCD_SNG_BUF)
4537     {
4538       /* Single Buffer */
4539       hc->doublebuffer = 0U;
4540 
4541       if (hc->ep_num == 0U)
4542       {
4543         hhcd->ep0_PmaAllocState = ch_num;
4544         hhcd->ep0_PmaAllocState |= (1U << 8);
4545       }
4546 
4547       /* Configure the PMA */
4548       if (hc->ch_dir == CH_IN_DIR)
4549       {
4550         hc->pmaaddr1 = pma_addr0;
4551         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = hc->pmaaddr1;
4552 
4553         if (hc->ep_num == 0U)
4554         {
4555           hhcd->ep0_PmaAllocState |= (CH_IN_DIR << 4);
4556         }
4557       }
4558       else
4559       {
4560         hc->pmaaddr0 = pma_addr0;
4561         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = hc->pmaaddr0;
4562       }
4563 
4564       /* Set the PmaAddress */
4565       hc->pmaadress = pma_addr0;
4566     }
4567 #if (USE_USB_DOUBLE_BUFFER == 1U)
4568     else /* USB_DBL_BUF */
4569     {
4570       /* Double Buffer Endpoint */
4571       hc->doublebuffer = 1U;
4572 
4573       /* Get a FreePMA Address for buffer 2 */
4574       pma_addr1 = HAL_HCD_GetFreePMA(hhcd, mps);
4575 
4576       if (pma_addr1 == 0xFFFFU)
4577       {
4578         /* Free the first buffer */
4579         (void)HAL_HCD_PMAFree(hhcd, pma_addr0, mps);
4580         return HAL_ERROR;
4581       }
4582       else
4583       {
4584         /* Configure the PMA */
4585         hc->pmaaddr0 = (uint16_t)(pma_addr0);
4586         hc->pmaaddr1 = (uint16_t)(pma_addr1);
4587 
4588         /* Set Buffer0 pma address */
4589         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = pma_addr0;
4590 
4591         /* Set Buffer1 pma address */
4592         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = pma_addr1;
4593 
4594         /* Used for Bulk DB MPS < 64bytes */
4595         if (hc->ch_dir == CH_IN_DIR)
4596         {
4597           hc->pmaadress = hc->pmaaddr1;
4598         }
4599         else
4600         {
4601           hc->pmaadress = hc->pmaaddr0;
4602         }
4603       }
4604     }
4605 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4606   }
4607 
4608   return HAL_OK;
4609 }
4610 
4611 /**
4612   * @brief  PMA De-Allocation for Channel Free the reserved block in the PMA-LookupTable
4613   * @param  hhcd  Host instance
4614   * @param  ch_num Channel number
4615   * @retval HAL status
4616   */
HAL_HCD_PMADeAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num)4617 HAL_StatusTypeDef  HAL_HCD_PMADeAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
4618 {
4619   HAL_StatusTypeDef status;
4620 
4621 #if (USE_USB_DOUBLE_BUFFER == 1U)
4622   uint8_t Err = 0U;
4623 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4624 
4625   /* Host Channel */
4626   HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
4627 
4628   /* Single Buffer */
4629   if (hc->doublebuffer == 0U)
4630   {
4631     status = HAL_HCD_PMAFree(hhcd, hc->pmaadress, hc->max_packet);
4632   }
4633   else   /* Double buffer */
4634   {
4635 #if (USE_USB_DOUBLE_BUFFER == 1U)
4636     status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr0, hc->max_packet);
4637     if (status != HAL_OK)
4638     {
4639       Err++;
4640     }
4641 
4642     status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr1, hc->max_packet);
4643     if (status != HAL_OK)
4644     {
4645       Err++;
4646     }
4647 
4648     if (Err != 0U)
4649     {
4650       return HAL_ERROR;
4651     }
4652 #else
4653     status = HAL_ERROR;
4654 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
4655   }
4656 
4657   return status;
4658 }
4659 
4660 
4661 /**
4662   * @brief  PMA Reset
4663   * @param  hhcd  Host instance
4664   * @retval HAL status
4665   */
HAL_HCD_PMAReset(HCD_HandleTypeDef * hhcd)4666 HAL_StatusTypeDef  HAL_HCD_PMAReset(HCD_HandleTypeDef *hhcd)
4667 {
4668   /* Reset All PMA Entry */
4669   for (uint8_t i = 0U; i < PMA_BLOCKS; i++)
4670   {
4671     hhcd->PMALookupTable[i] = 0U;
4672   }
4673 
4674   /* Allocate a Space for buffer descriptor table depending on the Host channel number */
4675   for (uint8_t i = 0U; i < hhcd->Init.Host_channels; i++)
4676   {
4677     hhcd->PMALookupTable[0] |= ((uint32_t)1U << i);
4678   }
4679 
4680   return HAL_OK;
4681 }
4682 
4683 /**
4684   * @brief  PMA Free
4685   * @param  hhcd   Host instance
4686   * @param  pma_base PMA base offset stored in hhcd->hc.pmaaddr
4687   * @param  mps  Max Packet Size
4688   * @retval HAL status
4689   */
HAL_HCD_PMAFree(HCD_HandleTypeDef * hhcd,uint32_t pma_base,uint16_t mps)4690 static HAL_StatusTypeDef  HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps)
4691 {
4692   uint32_t block_nbr;
4693   uint8_t ColIndex;
4694   uint8_t LineIndex;
4695   uint16_t mps_t = mps;
4696 
4697   /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
4698     allocation in PMA is done in 32Bytes each entry */
4699   if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
4700   {
4701     /* Align the mps to 32byte block to match the allocation in PMA,
4702       check Definition of allocation buffer memory in usb user spec */
4703     mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
4704   }
4705 
4706   /* Calculate the number of needed block to Free */
4707   if ((mps_t / 8U) != 0U)
4708   {
4709     block_nbr = ((uint32_t)mps_t / 8U);
4710 
4711     if ((mps_t % 8U) != 0U)
4712     {
4713       block_nbr++;
4714     }
4715   }
4716   else
4717   {
4718     block_nbr = 1U;
4719   }
4720 
4721   /* Decode Col/Line of PMA_Base position in the PMA_LookupTable */
4722   if (pma_base > 256U)
4723   {
4724     LineIndex = (uint8_t)(pma_base / 256U);
4725     ColIndex = (uint8_t)((pma_base - ((uint32_t)LineIndex * 256U)) / 8U);
4726   }
4727   else
4728   {
4729     LineIndex = 0U;
4730     ColIndex = (uint8_t)(pma_base / 8U);
4731   }
4732 
4733   /* Reset the corresponding bit in the lookupTable */
4734   for (uint8_t i = LineIndex; ((i < PMA_BLOCKS) && (block_nbr > 0U)); i++)
4735   {
4736     for (uint8_t j = ColIndex; j <= 31U; j++)
4737     {
4738       /* Check if the block is not already reserved or it was already closed */
4739       if ((hhcd->PMALookupTable[i] & ((uint32_t)1U << j)) == 0U)
4740       {
4741         return HAL_ERROR;
4742       }
4743       /* Free the reserved block by resetting the corresponding bit */
4744       hhcd->PMALookupTable[i] &= ~(1U << j);
4745 
4746       if (--block_nbr == 0U)
4747       {
4748         break;
4749       }
4750     }
4751     ColIndex = 0U;
4752   }
4753 
4754   return HAL_OK;
4755 }
4756 
4757 /**
4758   * @}
4759   */
4760 
4761 /**
4762   * @}
4763   */
4764 #endif /* defined (USB_DRD_FS) */
4765 #endif /* HAL_HCD_MODULE_ENABLED */
4766 
4767 /**
4768   * @}
4769   */
4770 
4771 /**
4772   * @}
4773   */
4774