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