1 /**
2   ******************************************************************************
3   * @file    stm32c0xx_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) 2022 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_CLK_ENABLE();
39         (##) Initialize the related GPIO clocks
40         (##) Configure HCD pin-out
41         (##) Configure HCD NVIC interrupt
42 
43     (#)Associate the Upper USB Host stack to the HAL HCD Driver:
44         (##) hhcd.pData = phost;
45 
46     (#)Enable HCD transmission and reception:
47         (##) HAL_HCD_Start();
48 
49   @endverbatim
50   ******************************************************************************
51   */
52 
53 /* Includes ------------------------------------------------------------------*/
54 #include "stm32c0xx_hal.h"
55 
56 /** @addtogroup STM32C0xx_HAL_Driver
57   * @{
58   */
59 
60 #ifdef HAL_HCD_MODULE_ENABLED
61 #if defined (USB_DRD_FS)
62 
63 /** @defgroup HCD HCD
64   * @brief HCD HAL module driver
65   * @{
66   */
67 
68 /* Private typedef -----------------------------------------------------------*/
69 /* Private define ------------------------------------------------------------*/
70 /* Private macro -------------------------------------------------------------*/
71 /* Private variables ---------------------------------------------------------*/
72 /* Private function ----------------------------------------------------------*/
73 /** @defgroup HCD_Private_Functions HCD Private Functions
74   * @{
75   */
76 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
77 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
78 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
79 static void HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd);
80 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd, uint8_t phy_chnum, uint8_t dir);
81 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num);
82 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum, uint8_t ep_type);
83 
84 #if (USE_USB_DOUBLE_BUFFER == 1U)
85 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
86 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
87 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
88 
89 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps);
90 static HAL_StatusTypeDef  HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps);
91 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue);
92 /**
93   * @}
94   */
95 
96 /* Exported functions --------------------------------------------------------*/
97 /** @defgroup HCD_Exported_Functions HCD Exported Functions
98   * @{
99   */
100 
101 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
102   *  @brief    Initialization and Configuration functions
103   *
104 @verbatim
105 ===============================================================================
106 ##### Initialization and de-initialization functions #####
107 ===============================================================================
108 [..]  This section provides functions allowing to:
109 
110 @endverbatim
111   * @{
112   */
113 
114 /**
115   * @brief  Initialize the host driver.
116   * @param  hhcd HCD handle
117   * @retval HAL status
118   */
HAL_HCD_Init(HCD_HandleTypeDef * hhcd)119 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
120 {
121   /* Check the HCD handle allocation */
122   if (hhcd == NULL)
123   {
124     return HAL_ERROR;
125   }
126 
127   /* Check the parameters */
128   assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
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   hhcd->State = HAL_HCD_STATE_BUSY;
156 
157   /* Disable the Interrupts */
158   (void)__HAL_HCD_DISABLE(hhcd);
159 
160   /* Dma not supported, force to zero */
161   hhcd->Init.dma_enable = 0U;
162 
163   /* Init the Core (common init.) */
164   (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
165 
166   /* Force Host Mode */
167   (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
168 
169   /* Init Host */
170   (void)USB_HostInit(hhcd->Instance, hhcd->Init);
171 
172   hhcd->State = HAL_HCD_STATE_READY;
173 
174   /* Host Port State */
175   hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
176 
177   /* Init PMA Address */
178   (void)HAL_HCD_PMAReset(hhcd);
179 
180   hhcd->State = HAL_HCD_STATE_READY;
181 
182   return HAL_OK;
183 }
184 
185 /**
186   * @brief  Initialize a host channel.
187   * @param  hhcd HCD handle
188   * @param  ch_num Channel number.
189   *         This parameter can be a value from 1 to 15
190   * @param  epnum Endpoint number.
191   *          This parameter can be a value from 1 to 15
192   * @param  dev_address Current device address
193   *          This parameter can be a value from 0 to 255
194   * @param  speed Current device speed.
195   *          This parameter can be one of these values:
196   *            HCD_DEVICE_SPEED_HIGH High speed mode,
197   *            HCD_DEVICE_SPEED_FULL Full speed mode,
198   *            HCD_DEVICE_SPEED_LOW Low speed mode
199   * @param  ep_type Endpoint Type.
200   *          This parameter can be one of these values:
201   *            USBH_EP_CONTROL Control type,
202   *            USBH_EP_ISO Isochronous type,
203   *            USBH_EP_BULK Bulk type,
204   *            USBH_EP_INTERRUPT Interrupt type
205   * @param  mps Max Packet Size.
206   *          This parameter can be a value from 0 to32K
207   * @retval HAL status
208   */
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)209 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
210                                   uint8_t epnum, uint8_t dev_address,
211                                   uint8_t speed, uint8_t ep_type, uint16_t mps)
212 {
213   HAL_StatusTypeDef status;
214   uint8_t used_channel;
215   uint8_t ep0_virtual_channel;
216 
217   __HAL_LOCK(hhcd);
218 
219   if (ch_num > 16U)
220   {
221     __HAL_UNLOCK(hhcd);
222     return HAL_ERROR;
223   }
224 
225   if (((epnum & 0xFU) == 0U) && ((hhcd->ep0_PmaAllocState & 0xF000U) != 0U))
226   {
227     hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[0U].pmaadress;
228     hhcd->hc[ch_num & 0xFU].pmaaddr0 = hhcd->hc[0U].pmaaddr0;
229     hhcd->hc[ch_num & 0xFU].pmaaddr1 = hhcd->hc[0U].pmaaddr1;
230 
231     hhcd->phy_chin_state[0U] = (((uint16_t)ch_num + 1U) << 4U) |
232                                ((uint16_t)ep_type + 1U) |
233                                (((uint16_t)epnum & 0x0FU) << 8U);
234 
235     hhcd->phy_chout_state[0U] = (((uint16_t)ch_num + 1U) << 4U) |
236                                 ((uint16_t)ep_type + 1U) |
237                                 (((uint16_t)epnum & 0x0FU) << 8U);
238   }
239 
240   /* Check if the logical channel are already allocated */
241   used_channel = HAL_HCD_Check_usedChannel(hhcd, ch_num);
242 
243   /* Check if the channel is not already opened */
244   if (used_channel == 0U)
245   {
246     /* Allocate New Physical channel */
247     hhcd->hc[ch_num & 0xFU].phy_ch_num = HAL_HCD_Get_FreePhyChannel(hhcd, ch_num, epnum, ep_type);
248 
249     /* No free Channel available, return error */
250     if (hhcd->hc[ch_num & 0xFU].phy_ch_num == HCD_FREE_CH_NOT_FOUND)
251     {
252       __HAL_UNLOCK(hhcd);
253       return HAL_ERROR;
254     }
255   }
256   /* Channel already opened */
257   else
258   {
259     /* Get Physical Channel number */
260     hhcd->hc[ch_num & 0xFU].phy_ch_num = (used_channel & 0xF0U) >> 4U;
261   }
262 
263   if ((epnum & 0x80U) != 0U)
264   {
265     hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
266   }
267   else
268   {
269     hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
270   }
271 
272   hhcd->hc[ch_num & 0xFU].dev_addr   = dev_address;
273   hhcd->hc[ch_num & 0xFU].max_packet = mps;
274   hhcd->hc[ch_num & 0xFU].ep_type    = ep_type;
275   hhcd->hc[ch_num & 0xFU].ep_num     = epnum & 0x7FU;
276   hhcd->hc[ch_num & 0xFU].speed      = speed;
277 
278   /* Check if the channel is not already opened */
279   if (used_channel == 0U)
280   {
281     if (((ep_type == EP_TYPE_ISOC) && (hhcd->Init.iso_singlebuffer_enable == 0U)) ||
282         ((ep_type == EP_TYPE_BULK) && (hhcd->Init.bulk_doublebuffer_enable == 1U)))
283     {
284       /* PMA Dynamic Allocation */
285       status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_DBL_BUF, mps);
286 
287       if (status == HAL_ERROR)
288       {
289         __HAL_UNLOCK(hhcd);
290         return HAL_ERROR;
291       }
292 
293       /* Clear Channel DTOG_TX */
294       HCD_CLEAR_TX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
295 
296       /* Clear Channel DTOG RX */
297       HCD_CLEAR_RX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
298 
299     }
300     else
301     {
302       if (hhcd->hc[ch_num & 0xFU].ep_num != 0U)
303       {
304         status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, mps);
305 
306         if (status == HAL_ERROR)
307         {
308           __HAL_UNLOCK(hhcd);
309           return HAL_ERROR;
310         }
311       }
312       else
313       {
314         if (ch_num == 0U)
315         {
316           ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
317 
318           if ((ep0_virtual_channel != 0U) && (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR))
319           {
320             if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_OUT_DIR)
321             {
322               status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
323 
324               if (status == HAL_ERROR)
325               {
326                 __HAL_UNLOCK(hhcd);
327                 return HAL_ERROR;
328               }
329             }
330             else
331             {
332               __HAL_UNLOCK(hhcd);
333               return HAL_ERROR;
334             }
335           }
336           else
337           {
338             /* This is a dual EP0 PMA allocation */
339             hhcd->ep0_PmaAllocState |= (0x1U << 12);
340 
341             /* PMA Dynamic Allocation for EP0 OUT direction */
342             hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
343             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
344 
345             if (status == HAL_ERROR)
346             {
347               __HAL_UNLOCK(hhcd);
348               return HAL_ERROR;
349             }
350 
351             /* PMA Dynamic Allocation for EP0 IN direction */
352             hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
353             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
354 
355             if (status == HAL_ERROR)
356             {
357               __HAL_UNLOCK(hhcd);
358               return HAL_ERROR;
359             }
360           }
361         }
362         else
363         {
364           if (((hhcd->ep0_PmaAllocState & 0xF00U) >> 8) == 1U)
365           {
366             ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
367 
368             if (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR)
369             {
370               hhcd->hc[ch_num & 0xFU].pmaaddr1 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr1;
371             }
372             else
373             {
374               hhcd->hc[ch_num & 0xFU].pmaaddr0 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr0;
375             }
376           }
377           else
378           {
379             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
380 
381             if (status == HAL_ERROR)
382             {
383               __HAL_UNLOCK(hhcd);
384               return HAL_ERROR;
385             }
386           }
387         }
388       }
389     }
390   }
391 
392   if ((epnum & 0x80U) != 0U)
393   {
394     hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
395 
396     if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
397     {
398       hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr1;
399     }
400   }
401   else
402   {
403     hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
404 
405     if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
406     {
407       hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr0;
408     }
409   }
410 
411   /* Init the USB Channel CHEPRx */
412   status =  USB_HC_Init(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
413                         epnum, dev_address, speed, ep_type, mps);
414 
415   /* check single buffer for isochronous channel */
416   if (ep_type == EP_TYPE_ISOC)
417   {
418     if (hhcd->Init.iso_singlebuffer_enable == 1U)
419     {
420       (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
421                                 USB_DRD_ISOC_DBUFF_DISABLE);
422     }
423   }
424 
425   /* Bulk double buffer check */
426   if (ep_type == EP_TYPE_BULK)
427   {
428     if (hhcd->Init.bulk_doublebuffer_enable == 1U)
429     {
430       (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
431                                 USB_DRD_BULK_DBUFF_ENBALE);
432     }
433   }
434 
435   __HAL_UNLOCK(hhcd);
436 
437   return status;
438 }
439 
440 /**
441   * @brief  HAL_HCD_HC_Close Pipe
442   * @param  hhcd HCD handle
443   * @param  ch_num Channel number.
444   *         This parameter can be a value from 1 to 15
445   * @retval HAL status
446   */
HAL_HCD_HC_Close(HCD_HandleTypeDef * hhcd,uint8_t ch_num)447 HAL_StatusTypeDef HAL_HCD_HC_Close(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
448 {
449   /* Stop the channel */
450   (void) HAL_HCD_HC_Halt(hhcd, ch_num);
451 
452   HAL_Delay(3U);
453 
454   if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
455   {
456     /* Free Allocated Channel */
457     hhcd->phy_chin_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
458   }
459   else
460   {
461     /* Free Allocated Channel */
462     hhcd->phy_chout_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
463   }
464 
465   /* Reset PMA Channel_Allocation */
466   (void)HAL_HCD_PMADeAlloc(hhcd, ch_num);
467 
468   return HAL_OK;
469 }
470 
471 /**
472   * @brief  Halt a host channel.
473   * @param  hhcd HCD handle
474   * @param  ch_num Channel number.
475   *         This parameter can be a value from 1 to 15
476   * @retval HAL status
477   */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)478 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
479 {
480   HAL_StatusTypeDef status = HAL_OK;
481 
482   __HAL_LOCK(hhcd);
483   if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
484   {
485     (void)USB_HC_IN_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
486   }
487   else
488   {
489     (void)USB_HC_OUT_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
490   }
491   __HAL_UNLOCK(hhcd);
492 
493   return status;
494 }
495 
496 /**
497   * @brief  DeInitialize the host driver.
498   * @param  hhcd HCD handle
499   * @retval HAL status
500   */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)501 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
502 {
503   uint8_t idx;
504 
505   /* Check the HCD handle allocation */
506   if (hhcd == NULL)
507   {
508     return HAL_ERROR;
509   }
510 
511   /* Host Port State */
512   hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
513 
514   /* Reset PMA Address */
515   (void)HAL_HCD_PMAReset(hhcd);
516 
517   for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
518   {
519     hhcd->phy_chin_state[idx] = 0U;
520     hhcd->phy_chout_state[idx] = 0U;
521   }
522 
523   /* reset Ep0 Pma allocation state */
524   hhcd->ep0_PmaAllocState = 0U;
525 
526   hhcd->State = HAL_HCD_STATE_BUSY;
527 
528 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
529   if (hhcd->MspDeInitCallback == NULL)
530   {
531     hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
532   }
533 
534   /* DeInit the low level hardware */
535   hhcd->MspDeInitCallback(hhcd);
536 #else
537   /* DeInit the low level hardware: CLOCK, NVIC. */
538   HAL_HCD_MspDeInit(hhcd);
539 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
540 
541   hhcd->State = HAL_HCD_STATE_RESET;
542 
543   return HAL_OK;
544 }
545 
546 /**
547   * @brief  Initialize the HCD MSP.
548   * @param  hhcd HCD handle
549   * @retval None
550   */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)551 __weak void  HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
552 {
553   /* Prevent unused argument(s) compilation warning */
554   UNUSED(hhcd);
555 
556   /* NOTE : This function Should not be modified, when the callback is needed,
557   the HAL_HCD_MspInit could be implemented in the user file
558   */
559 }
560 
561 /**
562   * @brief  DeInitialize the HCD MSP.
563   * @param  hhcd HCD handle
564   * @retval None
565   */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)566 __weak void  HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
567 {
568   /* Prevent unused argument(s) compilation warning */
569   UNUSED(hhcd);
570 
571   /* NOTE : This function Should not be modified, when the callback is needed,
572   the HAL_HCD_MspDeInit could be implemented in the user file
573   */
574 }
575 
HAL_HCD_SuspendCallback(HCD_HandleTypeDef * hhcd)576 __weak void HAL_HCD_SuspendCallback(HCD_HandleTypeDef *hhcd)
577 {
578   /* Prevent unused argument(s) compilation warning */
579   UNUSED(hhcd);
580 
581   /* NOTE : This function Should not be modified, when the callback is needed,
582   the HAL_HCD_SuspendCallback could be implemented in the user file
583   */
584 
585 }
586 
HAL_HCD_ResumeCallback(HCD_HandleTypeDef * hhcd)587 __weak void HAL_HCD_ResumeCallback(HCD_HandleTypeDef *hhcd)
588 {
589   /* Prevent unused argument(s) compilation warning */
590   UNUSED(hhcd);
591 
592   /* NOTE : This function Should not be modified, when the callback is needed,
593   the HAL_HCD_ResumeCallback could be implemented in the user file
594   */
595 }
596 
597 /**
598   * @}
599   */
600 
601 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
602   *  @brief   HCD IO operation functions
603   *
604 @verbatim
605 ===============================================================================
606 ##### IO operation functions #####
607 ===============================================================================
608 [..] This subsection provides a set of functions allowing to manage the USB Host Data
609 Transfer
610 
611 @endverbatim
612   * @{
613   */
614 
615 /**
616   * @brief  Submit a new URB for processing.
617   * @param  hhcd HCD handle
618   * @param  ch_num Channel number.
619   *         This parameter can be a value from 1 to 15
620   * @param  direction Channel number.
621   *          This parameter can be one of these values:
622   *           0 : Output / 1 : Input
623   * @param  ep_type Endpoint Type.
624   *          This parameter can be one of these values:
625   *            USBH_EP_CONTROL   : Control type/
626   *            USBH_EP_ISO       : Isochronous type/
627   *            USBH_EP_BULK      : Bulk type/
628   *            USBH_EP_INTERRUPT : Interrupt type/
629   * @param  token Endpoint Type.
630   *          This parameter can be one of these values:
631   *            0: HC_PID_SETUP / 1: HC_PID_DATA1
632   * @param  pbuff pointer to URB data
633   * @param  length Length of URB data
634   * @param  do_ping activate do ping protocol (for high speed only).
635   *          This parameter can be one of these values:
636   *           0 : do ping inactive / 1 : do ping active
637   * @retval HAL status
638   */
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)639 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
640                                            uint8_t direction, uint8_t ep_type,
641                                            uint8_t token, uint8_t *pbuff,
642                                            uint16_t length, uint8_t do_ping)
643 {
644   UNUSED(do_ping);
645 
646   if (token == 0U)
647   {
648     hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_SETUP;
649   }
650   else
651   {
652     hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
653   }
654 
655   /* Manage Data Toggle */
656   switch (ep_type)
657   {
658     case EP_TYPE_CTRL:
659       if ((token == 1U) && (direction == 0U)) /* send data */
660       {
661         if (length == 0U)
662         {
663           /* For Status OUT stage, Length==0, Status Out PID = 1 */
664           hhcd->hc[ch_num & 0xFU].toggle_out = 1U;
665         }
666 
667         /* Set the Data Toggle bit as per the Flag */
668         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
669         {
670           /* Put the PID 0 */
671           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
672         }
673         else
674         {
675           /* Put the PID 1 */
676           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
677         }
678       }
679       break;
680 
681     case EP_TYPE_BULK:
682       if (direction == 0U)
683       {
684         /* Set the Data Toggle bit as per the Flag */
685         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
686         {
687           /* Put the PID 0 */
688           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
689         }
690         else
691         {
692           /* Put the PID 1 */
693           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
694         }
695       }
696       else
697       {
698         if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
699         {
700           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
701         }
702         else
703         {
704           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
705         }
706       }
707       break;
708 
709     case EP_TYPE_INTR:
710       if (direction == 0U)
711       {
712         /* Set the Data Toggle bit as per the Flag */
713         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
714         {
715           /* Put the PID 0 */
716           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
717         }
718         else
719         {
720           /* Put the PID 1 */
721           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
722         }
723       }
724       else
725       {
726         if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
727         {
728           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
729         }
730         else
731         {
732           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
733         }
734       }
735       break;
736 
737     case EP_TYPE_ISOC:
738       hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
739       break;
740 
741     default:
742       break;
743   }
744 
745   hhcd->hc[ch_num & 0xFU].xfer_buff = pbuff;
746   hhcd->hc[ch_num & 0xFU].xfer_len = length;
747   hhcd->hc[ch_num & 0xFU].xfer_len_db = length;
748   hhcd->hc[ch_num & 0xFU].urb_state = URB_IDLE;
749   hhcd->hc[ch_num & 0xFU].xfer_count = 0U;
750   hhcd->hc[ch_num & 0xFU].state = HC_IDLE;
751 
752   return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num & 0xFU]);
753 }
754 /**
755   * @brief  Handle HCD interrupt request.
756   * @param  hhcd HCD handle
757   * @retval None
758   */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)759 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
760 {
761   uint8_t phy_chnum;
762   uint8_t ch_dir;
763   uint32_t wIstr = USB_ReadInterrupts(hhcd->Instance);
764 
765   /* Port Change Detected (Connection/Disconnection) */
766   if ((wIstr & USB_ISTR_DCON) == USB_ISTR_DCON)
767   {
768     /* Clear Flag */
769     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_DCON);
770 
771     /* Call Port IRQHandler */
772     HCD_Port_IRQHandler(hhcd);
773 
774     return;
775   }
776 
777   /* Correct Transaction Detected -------*/
778   if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
779   {
780     /* Get Physical channel */
781     phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
782 
783     /* Get channel direction */
784     ch_dir = (uint8_t)__HAL_HCD_GET_CHDIR(hhcd);
785 
786     if (ch_dir == CH_OUT_DIR)
787     {
788       /* Call Channel_OUT_IRQ() */
789       HCD_HC_OUT_IRQHandler(hhcd, phy_chnum);
790     }
791     else
792     {
793       /* Call Channel_IN_IRQ() */
794       HCD_HC_IN_IRQHandler(hhcd, phy_chnum);
795     }
796 
797     return;
798   }
799 
800   /* Wakeup Flag Detected */
801   if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
802   {
803     if (hhcd->HostState == HCD_HCD_STATE_SUSPEND)
804     {
805       /* Set The L2Resume bit */
806       hhcd->Instance->CNTR |= USB_CNTR_L2RES;
807 
808       /* Clear the wake-up flag */
809       __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
810 
811       /* Update the USB Software state machine */
812       HAL_HCD_ResumeCallback(hhcd);
813       hhcd->HostState = HCD_HCD_STATE_RESUME;
814     }
815     else
816     {
817       /* Clear the wake-up flag */
818       __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
819     }
820 
821     return;
822   }
823 
824   /* Global Error Flag Detected */
825   if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
826   {
827     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_ERR);
828 
829     return;
830   }
831 
832   /* PMA Overrun detected */
833   if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
834   {
835     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_PMAOVR);
836 
837     return;
838   }
839 
840   /* Suspend Detected */
841   if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
842   {
843     /* Set HAL State to Suspend */
844     hhcd->HostState = HCD_HCD_STATE_SUSPEND;
845 
846     /* Force low-power mode in the macrocell */
847     hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
848 
849     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
850     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SUSP);
851 
852     /* Call suspend Callback */
853     HAL_HCD_SuspendCallback(hhcd);
854 
855     return;
856   }
857 
858   /* Start Of Frame Detected */
859   if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
860   {
861 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
862     hhcd->SOFCallback(hhcd);
863 #else
864     HAL_HCD_SOF_Callback(hhcd);
865 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
866 
867     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SOF);
868 
869     /* when first SOF is detected after USB_RESET is asserted */
870     if (hhcd->HostState == HCD_HCD_STATE_RESETED)
871     {
872       /* HAL State */
873       hhcd->HostState = HCD_HCD_STATE_RUN;
874 
875 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
876       hhcd->PortEnabledCallback(hhcd);
877 #else
878       HAL_HCD_PortEnabled_Callback(hhcd);
879 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
880     }
881 
882     return;
883   }
884 }
885 
886 /**
887   * @brief  SOF callback.
888   * @param  hhcd HCD handle
889   * @retval None
890   */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)891 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
892 {
893   /* Prevent unused argument(s) compilation warning */
894   UNUSED(hhcd);
895 
896   /* NOTE : This function Should not be modified, when the callback is needed,
897   the HAL_HCD_SOF_Callback could be implemented in the user file
898   */
899 }
900 
901 /**
902   * @brief Connection Event callback.
903   * @param  hhcd HCD handle
904   * @retval None
905   */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)906 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
907 {
908   /* Prevent unused argument(s) compilation warning */
909   UNUSED(hhcd);
910 
911   /* NOTE : This function Should not be modified, when the callback is needed,
912   the HAL_HCD_Connect_Callback could be implemented in the user file
913   */
914 }
915 
916 /**
917   * @brief  Disconnection Event callback.
918   * @param  hhcd HCD handle
919   * @retval None
920   */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)921 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
922 {
923   /* Prevent unused argument(s) compilation warning */
924   UNUSED(hhcd);
925 
926   /* NOTE : This function Should not be modified, when the callback is needed,
927   the HAL_HCD_Disconnect_Callback could be implemented in the user file
928   */
929 }
930 /**
931   * @brief  Port Enabled  Event callback.
932   * @param  hhcd HCD handle
933   * @retval None
934   */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)935 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
936 {
937   /* Prevent unused argument(s) compilation warning */
938   UNUSED(hhcd);
939 
940   /* NOTE : This function should not be modified, when the callback is needed,
941             the HAL_HCD_Disconnect_Callback could be implemented in the user file
942    */
943 }
944 /**
945   * @brief  Port Disabled  Event callback.
946   * @param  hhcd HCD handle
947   * @retval None
948   */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)949 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
950 {
951   /* Prevent unused argument(s) compilation warning */
952   UNUSED(hhcd);
953 
954   /* NOTE : This function should not be modified, when the callback is needed,
955             the HAL_HCD_Disconnect_Callback could be implemented in the user file
956    */
957 }
958 
959 /**
960   * @brief  Notify URB state change callback.
961   * @param  hhcd HCD handle
962   * @param  chnum Channel number.
963   *         This parameter can be a value from 1 to 15
964   * @param  urb_state
965   *          This parameter can be one of these values:
966   *            URB_IDLE/
967   *            URB_DONE/
968   *            URB_NOTREADY/
969   *            URB_NYET/
970   *            URB_ERROR/
971   *            URB_STALL/
972   * @retval None
973   */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)974 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd,
975                                                 uint8_t chnum, HCD_URBStateTypeDef urb_state)
976 {
977   /* Prevent unused argument(s) compilation warning */
978   UNUSED(hhcd);
979   UNUSED(chnum);
980   UNUSED(urb_state);
981 
982   /* NOTE : This function Should not be modified, when the callback is needed,
983   the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
984   */
985 }
986 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
987 /**
988   * @brief  Register a User USB HCD Callback
989   *         To be used instead of the weak predefined callback
990   * @param  hhcd USB HCD handle
991   * @param  CallbackID ID of the callback to be registered
992   *         This parameter can be one of the following values:
993   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
994   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
995   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID HCD Disconnect callback ID
996   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
997   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
998   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
999   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
1000   * @param  pCallback pointer to the Callback function
1001   * @retval HAL status
1002   */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)1003 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
1004                                            HAL_HCD_CallbackIDTypeDef CallbackID,
1005                                            pHCD_CallbackTypeDef pCallback)
1006 {
1007   HAL_StatusTypeDef status = HAL_OK;
1008 
1009   if (pCallback == NULL)
1010   {
1011     /* Update the error code */
1012     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1013     return HAL_ERROR;
1014   }
1015   /* Process locked */
1016   __HAL_LOCK(hhcd);
1017 
1018   if (hhcd->State == HAL_HCD_STATE_READY)
1019   {
1020     switch (CallbackID)
1021     {
1022       case HAL_HCD_SOF_CB_ID :
1023         hhcd->SOFCallback = pCallback;
1024         break;
1025 
1026       case HAL_HCD_CONNECT_CB_ID :
1027         hhcd->ConnectCallback = pCallback;
1028         break;
1029 
1030       case HAL_HCD_DISCONNECT_CB_ID :
1031         hhcd->DisconnectCallback = pCallback;
1032         break;
1033 
1034       case HAL_HCD_PORT_ENABLED_CB_ID :
1035         hhcd->PortEnabledCallback = pCallback;
1036         break;
1037 
1038       case HAL_HCD_PORT_DISABLED_CB_ID :
1039         hhcd->PortDisabledCallback = pCallback;
1040         break;
1041 
1042       case HAL_HCD_MSPINIT_CB_ID :
1043         hhcd->MspInitCallback = pCallback;
1044         break;
1045 
1046       case HAL_HCD_MSPDEINIT_CB_ID :
1047         hhcd->MspDeInitCallback = pCallback;
1048         break;
1049 
1050       default :
1051         /* Update the error code */
1052         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1053         /* Return error status */
1054         status =  HAL_ERROR;
1055         break;
1056     }
1057   }
1058   else if (hhcd->State == HAL_HCD_STATE_RESET)
1059   {
1060     switch (CallbackID)
1061     {
1062       case HAL_HCD_MSPINIT_CB_ID :
1063         hhcd->MspInitCallback = pCallback;
1064         break;
1065 
1066       case HAL_HCD_MSPDEINIT_CB_ID :
1067         hhcd->MspDeInitCallback = pCallback;
1068         break;
1069 
1070       default :
1071         /* Update the error code */
1072         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1073         /* Return error status */
1074         status =  HAL_ERROR;
1075         break;
1076     }
1077   }
1078   else
1079   {
1080     /* Update the error code */
1081     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1082     /* Return error status */
1083     status =  HAL_ERROR;
1084   }
1085 
1086   /* Release Lock */
1087   __HAL_UNLOCK(hhcd);
1088   return status;
1089 }
1090 
1091 /**
1092   * @brief  Unregister an USB HCD Callback
1093   *         USB HCD callback is redirected to the weak predefined callback
1094   * @param  hhcd USB HCD handle
1095   * @param  CallbackID ID of the callback to be unregistered
1096   *         This parameter can be one of the following values:
1097   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
1098   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
1099   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID DRD HCD Disconnect callback ID
1100   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
1101   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
1102   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
1103   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
1104   * @retval HAL status
1105   */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)1106 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd,
1107                                              HAL_HCD_CallbackIDTypeDef CallbackID)
1108 {
1109   HAL_StatusTypeDef status = HAL_OK;
1110 
1111   /* Process locked */
1112   __HAL_LOCK(hhcd);
1113 
1114   /* Setup Legacy weak Callbacks */
1115   if (hhcd->State == HAL_HCD_STATE_READY)
1116   {
1117     switch (CallbackID)
1118     {
1119       case HAL_HCD_SOF_CB_ID :
1120         hhcd->SOFCallback = HAL_HCD_SOF_Callback;
1121         break;
1122 
1123       case HAL_HCD_CONNECT_CB_ID :
1124         hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
1125         break;
1126 
1127       case HAL_HCD_DISCONNECT_CB_ID :
1128         hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
1129         break;
1130 
1131       case HAL_HCD_PORT_ENABLED_CB_ID :
1132         hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
1133         break;
1134 
1135       case HAL_HCD_PORT_DISABLED_CB_ID :
1136         hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
1137         break;
1138 
1139       case HAL_HCD_MSPINIT_CB_ID :
1140         hhcd->MspInitCallback = HAL_HCD_MspInit;
1141         break;
1142 
1143       case HAL_HCD_MSPDEINIT_CB_ID :
1144         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
1145         break;
1146 
1147       default :
1148         /* Update the error code */
1149         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1150 
1151         /* Return error status */
1152         status =  HAL_ERROR;
1153         break;
1154     }
1155   }
1156   else if (hhcd->State == HAL_HCD_STATE_RESET)
1157   {
1158     switch (CallbackID)
1159     {
1160       case HAL_HCD_MSPINIT_CB_ID :
1161         hhcd->MspInitCallback = HAL_HCD_MspInit;
1162         break;
1163 
1164       case HAL_HCD_MSPDEINIT_CB_ID :
1165         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
1166         break;
1167 
1168       default :
1169         /* Update the error code */
1170         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1171 
1172         /* Return error status */
1173         status =  HAL_ERROR;
1174         break;
1175     }
1176   }
1177   else
1178   {
1179     /* Update the error code */
1180     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1181 
1182     /* Return error status */
1183     status =  HAL_ERROR;
1184   }
1185 
1186   /* Release Lock */
1187   __HAL_UNLOCK(hhcd);
1188   return status;
1189 }
1190 
1191 /**
1192   * @brief  Register USB HCD Host Channel Notify URB Change Callback
1193   *         To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
1194   * @param  hhcd HCD handle
1195   * @param  pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
1196   * @retval HAL status
1197   */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)1198 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
1199                                                              pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
1200 {
1201   HAL_StatusTypeDef status = HAL_OK;
1202 
1203   if (pCallback == NULL)
1204   {
1205     /* Update the error code */
1206     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1207 
1208     return HAL_ERROR;
1209   }
1210 
1211   /* Process locked */
1212   __HAL_LOCK(hhcd);
1213 
1214   if (hhcd->State == HAL_HCD_STATE_READY)
1215   {
1216     hhcd->HC_NotifyURBChangeCallback = pCallback;
1217   }
1218   else
1219   {
1220     /* Update the error code */
1221     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1222 
1223     /* Return error status */
1224     status = HAL_ERROR;
1225   }
1226 
1227   /* Release Lock */
1228   __HAL_UNLOCK(hhcd);
1229 
1230   return status;
1231 }
1232 
1233 /**
1234   * @brief  Unregister the USB HCD Host Channel Notify URB Change Callback
1235   *         USB HCD Host Channel Notify URB Change Callback is redirected
1236   *         to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
1237   * @param  hhcd HCD handle
1238   * @retval HAL status
1239   */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)1240 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
1241 {
1242   HAL_StatusTypeDef status = HAL_OK;
1243 
1244   /* Process locked */
1245   __HAL_LOCK(hhcd);
1246 
1247   if (hhcd->State == HAL_HCD_STATE_READY)
1248   {
1249     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
1250   }
1251   else
1252   {
1253     /* Update the error code */
1254     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1255 
1256     /* Return error status */
1257     status =  HAL_ERROR;
1258   }
1259 
1260   /* Release Lock */
1261   __HAL_UNLOCK(hhcd);
1262 
1263   return status;
1264 }
1265 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1266 
1267 
1268 /**
1269   * @}
1270   */
1271 
1272 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1273   *  @brief   Management functions
1274   *
1275 @verbatim
1276 ===============================================================================
1277 ##### Peripheral Control functions #####
1278 ===============================================================================
1279 [..]
1280 This subsection provides a set of functions allowing to control the HCD data
1281 transfers.
1282 
1283 @endverbatim
1284   * @{
1285   */
1286 
1287 /**
1288   * @brief  Start the host driver.
1289   * @param  hhcd HCD handle
1290   * @retval HAL status
1291   */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1292 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1293 {
1294   __IO uint32_t count = HCD_PDWN_EXIT_CNT;
1295 
1296   __HAL_LOCK(hhcd);
1297 
1298   /* Remove PowerDown */
1299   hhcd->Instance->CNTR &= ~USB_CNTR_PDWN;
1300 
1301   /* Few cycles to ensure exit from powerdown */
1302   while (count > 0U)
1303   {
1304     count--;
1305   }
1306 
1307   /* Clear Reset */
1308   hhcd->Instance->CNTR &= ~USB_CNTR_USBRST;
1309 
1310   __HAL_UNLOCK(hhcd);
1311 
1312   return HAL_OK;
1313 }
1314 
1315 /**
1316   * @brief  Stop the host driver.
1317   * @param  hhcd HCD handle
1318   * @retval HAL status
1319   */
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1320 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1321 {
1322   __HAL_LOCK(hhcd);
1323   /*Stop the Host IP: setting powerdown  */
1324   (void)USB_StopHost(hhcd->Instance);
1325 
1326   /* clear all allocated virtual channel */
1327   HAL_HCD_ClearPhyChannel(hhcd);
1328 
1329   /* Reset the PMA current pointer */
1330   (void)HAL_HCD_PMAReset(hhcd);
1331 
1332   /* reset Ep0 Pma allocation state */
1333   hhcd->ep0_PmaAllocState = 0U;
1334 
1335   __HAL_UNLOCK(hhcd);
1336   return HAL_OK;
1337 }
1338 
1339 /**
1340   * @brief  Put the Device in suspend mode
1341   * @param  hhcd HCD handle
1342   * @retval HAL status
1343   */
HAL_HCD_Suspend(HCD_HandleTypeDef * hhcd)1344 HAL_StatusTypeDef HAL_HCD_Suspend(HCD_HandleTypeDef *hhcd)
1345 {
1346   __IO uint32_t count = 0U;
1347 
1348   /* Set Suspend Mode */
1349   hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
1350 
1351   /* wait for Suspend Ready */
1352   while ((hhcd->Instance->CNTR & USB_CNTR_SUSPRDY) == 0U)
1353   {
1354     if (++count > HAL_USB_TIMEOUT)
1355     {
1356       return HAL_TIMEOUT;
1357     }
1358   }
1359 
1360   return HAL_OK;
1361 }
1362 
1363 /**
1364   * @brief  Resume host port
1365   * @param  hhcd HCD handle
1366   * @retval HAL status
1367   */
HAL_HCD_Resume(HCD_HandleTypeDef * hhcd)1368 HAL_StatusTypeDef HAL_HCD_Resume(HCD_HandleTypeDef *hhcd)
1369 {
1370   /* Set Resume bit */
1371   hhcd->Instance->CNTR |= USB_CNTR_L2RES;
1372 
1373   return HAL_OK;
1374 }
1375 
1376 /**
1377   * @brief  Reset the host port.
1378   * @param  hhcd HCD handle
1379   * @retval HAL status
1380   */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1381 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1382 {
1383   __HAL_LOCK(hhcd);
1384 
1385   /* Reset the USB Port by inserting an SE0 on the bus */
1386   (void)USB_ResetPort(hhcd->Instance);
1387 
1388   if (hhcd->HostState == HCD_HCD_STATE_CONNECTED)
1389   {
1390     hhcd->HostState = HCD_HCD_STATE_RESETED;
1391   }
1392   __HAL_UNLOCK(hhcd);
1393 
1394   return HAL_OK;
1395 }
1396 
1397 /**
1398   * @brief  Resme the host port.
1399   * @param  hhcd HCD handle
1400   * @retval HAL status
1401   */
HAL_HCD_ResumePort(HCD_HandleTypeDef * hhcd)1402 HAL_StatusTypeDef HAL_HCD_ResumePort(HCD_HandleTypeDef *hhcd)
1403 {
1404   /* Set Resume bit */
1405   hhcd->Instance->CNTR |= USB_CNTR_L2RES;
1406   HAL_Delay(30U);
1407 
1408   /* Clear Resume bit */
1409   hhcd->Instance->CNTR &= ~USB_CNTR_L2RES;
1410 
1411   return HAL_OK;
1412 }
1413 
1414 
1415 /**
1416   * @}
1417   */
1418 
1419 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1420   *  @brief   Peripheral State functions
1421   *
1422 @verbatim
1423 ===============================================================================
1424 ##### Peripheral State functions #####
1425 ===============================================================================
1426 [..]
1427 This subsection permits to get in run-time the status of the peripheral
1428 and the data flow.
1429 
1430 @endverbatim
1431   * @{
1432   */
1433 
1434 /**
1435   * @brief  Return the HCD handle state.
1436   * @param  hhcd HCD handle
1437   * @retval HAL state
1438   */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)1439 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
1440 {
1441   return hhcd->State;
1442 }
1443 
1444 /**
1445   * @brief  Return  URB state for a channel.
1446   * @param  hhcd HCD handle
1447   * @param  chnum Channel number.
1448   *         This parameter can be a value from 1 to 15
1449   * @retval URB state.
1450   *          This parameter can be one of these values:
1451   *            URB_IDLE/
1452   *            URB_DONE/
1453   *            URB_NOTREADY/
1454   *            URB_NYET/
1455   *            URB_ERROR/
1456   *            URB_STALL
1457   */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1458 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1459 {
1460   return hhcd->hc[chnum].urb_state;
1461 }
1462 
1463 
1464 /**
1465   * @brief  Return the last host transfer size.
1466   * @param  hhcd HCD handle
1467   * @param  chnum Channel number.
1468   *         This parameter can be a value from 1 to 15
1469   * @retval last transfer size in byte
1470   */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1471 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1472 {
1473   return hhcd->hc[chnum].xfer_count;
1474 }
1475 
1476 /**
1477   * @brief  Return the Host Channel state.
1478   * @param  hhcd HCD handle
1479   * @param  chnum Channel number.
1480   *         This parameter can be a value from 1 to 15
1481   * @retval Host channel state
1482   *          This parameter can be one of these values:
1483   *            HC_IDLE/
1484   *            HC_XFRC/
1485   *            HC_HALTED/
1486   *            HC_NYET/
1487   *            HC_NAK/
1488   *            HC_STALL/
1489   *            HC_XACTERR/
1490   *            HC_BBLERR/
1491   *            HC_DATATGLERR
1492   */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1493 HCD_HCStateTypeDef  HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1494 {
1495   return hhcd->hc[chnum].state;
1496 }
1497 
1498 /**
1499   * @brief  Return the current Host frame number.
1500   * @param  hhcd HCD handle
1501   * @retval Current Host frame number
1502   */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1503 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1504 {
1505   return (USB_GetCurrentFrame(hhcd->Instance));
1506 }
1507 
1508 /**
1509   * @brief  Return the Host enumeration speed.
1510   * @param  hhcd HCD handle
1511   * @retval speed : Device speed after Host enumeration
1512   *          This parameter can be one of these values:
1513   *            @arg HCD_DEVICE_SPEED_FULL: Full speed mode
1514   *            @arg HCD_DEVICE_SPEED_LOW: Low speed mode
1515   */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1516 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1517 {
1518   return (USB_GetHostSpeed(hhcd->Instance));
1519 }
1520 
1521 /**
1522   * @brief  Set host channel Hub Information.
1523   * @param  hhcd HCD handle
1524   * @param  ch_num Channel number.
1525   *         This parameter can be a value from 1 to 8
1526   * @param  addr Hub address
1527   * @param  PortNbr Hub port number
1528   * @retval HAL status
1529   */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)1530 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1531                                         uint8_t addr, uint8_t PortNbr)
1532 {
1533   hhcd->hc[ch_num].hub_addr = addr;
1534   hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1535 
1536   return HAL_OK;
1537 }
1538 
1539 
1540 /**
1541   * @brief  Clear host channel hub information.
1542   * @param  hhcd HCD handle
1543   * @param  ch_num Channel number.
1544   *         This parameter can be a value from 1 to 8
1545   * @retval HAL status
1546   */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1547 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1548 {
1549   hhcd->hc[ch_num].hub_addr = 0U;
1550   hhcd->hc[ch_num].hub_port_nbr = 0U;
1551 
1552   return HAL_OK;
1553 }
1554 
1555 #if (USE_USB_DOUBLE_BUFFER == 1U)
1556 /**
1557   * @brief  Handle Host Channel OUT Double Buffer Bulk requests.
1558   * @param  hhcd HCD handle
1559   * @param  ch_num Channel number This parameter can be a value from 1 to 15
1560   * @param  phy_chnum Physical Channel number [0..7]
1561   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
1562   * @retval none
1563   */
HCD_HC_OUT_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1564 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1565                               uint8_t phy_chnum, uint32_t regvalue)
1566 {
1567   uint16_t data_xfr;
1568   uint16_t len;
1569 
1570   /* Send Buffer0 */
1571   if ((regvalue & USB_CH_DTOG_TX) != 0U)
1572   {
1573     data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
1574 
1575     if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr)
1576     {
1577       hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
1578     }
1579     else
1580     {
1581       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1582     }
1583 
1584     /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
1585     if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
1586     {
1587       /* manage multiple Xfer */
1588       hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1589 
1590       /* check if we need to free user buffer */
1591       if ((regvalue & USB_CH_DTOG_RX) != 0U)
1592       {
1593         /* Toggle SwBuff */
1594         HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
1595         HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
1596         HCD_TX_DTOG(hhcd->Instance, phy_chnum);
1597       }
1598 
1599       /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
1600       if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
1601       {
1602         hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
1603 
1604         /* calculate len of new buffer to fill */
1605         if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
1606         {
1607           len = (uint16_t)hhcd->hc[ch_num & 0xFU].max_packet;
1608           hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
1609         }
1610         else
1611         {
1612           len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
1613           hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
1614         }
1615 
1616         /* Write remaining data to Buffer0 */
1617         HCD_SET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
1618         USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1619                      hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)len);
1620       }
1621       /* start a new transfer */
1622       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
1623     }
1624     else
1625     {
1626       /* Transfer complete state */
1627       hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1628       hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1629       hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1630       hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1631       /* Close the Channel */
1632       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
1633     }
1634   }
1635   else
1636   {
1637     /* Send Buffer1 */
1638     data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->RXBD & 0x03FF0000U) >> 16U);
1639 
1640     if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr) /* updated */
1641     {
1642       hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
1643     }
1644 
1645     /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
1646     if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
1647     {
1648       /* manage multiple Xfer */
1649       hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1650 
1651       /* check if we need to free user buffer */
1652       if ((regvalue & USB_CH_DTOG_RX) == 0U)
1653       {
1654         /* Toggle SwBuff */
1655         HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
1656         HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
1657         HCD_RX_DTOG(hhcd->Instance, phy_chnum);
1658       }
1659 
1660       /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
1661       if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
1662       {
1663         hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
1664 
1665         /* calculate len of new buffer to fill */
1666         if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
1667         {
1668           len = hhcd->hc[ch_num & 0xFU].max_packet;
1669           hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
1670         }
1671         else
1672         {
1673           len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
1674           hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
1675         }
1676 
1677         /* Write remaining data to Buffer0 */
1678         HCD_SET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
1679 
1680         USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1681                      hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)len);
1682       }
1683 
1684       /* start a new transfer */
1685       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
1686     }
1687     else
1688     {
1689       /* Transfer complete state */
1690       hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1691       hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1692       hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1693       hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1694 
1695       /* Close the channel */
1696       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
1697     }
1698   }
1699 }
1700 
1701 
1702 /**
1703   * @brief  Handle Host Channel IN Double Buffer Bulk requests.
1704   * @param  hhcd HCD handle
1705   * @param  ch_num Channel number: This parameter can be a value from 1 to 15
1706   * @param  phy_chnum Physical Channel number [0..7]
1707   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
1708   * @retval none
1709   */
HCD_HC_IN_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1710 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd,
1711                              uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue)
1712 {
1713   uint16_t received_bytes;
1714 
1715   /* Read from Buffer 0 */
1716   if ((regvalue & USB_CH_DTOG_RX) != 0U)
1717   {
1718     received_bytes = (uint16_t)HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
1719 
1720     if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1721     {
1722       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1723     }
1724     else
1725     {
1726       hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1727     }
1728 
1729     /* Check if we Need to free the other buffer for the IP */
1730     if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) != 0U))
1731     {
1732       /* Toggle SwBuff to Allow the IP to submit a new IN */
1733       HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
1734     }
1735 
1736     /* Read the byte from PMA to user Buffer(System Memory) */
1737     USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1738                 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)received_bytes);
1739   }
1740   else
1741   {
1742     /* Read from Buffer 1 */
1743     received_bytes = (uint16_t) HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
1744 
1745     if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1746     {
1747       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1748     }
1749     else
1750     {
1751       hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1752     }
1753 
1754     /* Check if we Need to free the other buffer for the IP */
1755     if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) == 0U))
1756     {
1757       /* Toggle SwBuff */
1758       HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
1759     }
1760 
1761     /* Read the byte from PMA to user Buffer(System Memory) */
1762     USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1763                 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)received_bytes);
1764   }
1765 
1766   /* update the global number of all received bytes */
1767   hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
1768 
1769   /* Transfer complete state */
1770   hhcd->hc[ch_num & 0xFU].state = HC_ACK;
1771   hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1772 
1773   if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
1774       ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
1775   {
1776     hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1777     hhcd->hc[ch_num & 0xFU].state  = HC_XFRC;
1778 
1779     /* disable channel */
1780     HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1781   }
1782   else
1783   {
1784     hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
1785 
1786     /* Reactivate the Channel Submit an other URB since the Transfer is not yet completed */
1787     HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
1788   }
1789 }
1790 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1791 
1792 /**
1793   * @brief  Handle Host Channel IN Isochronous Transaction
1794   * @param  hhcd HCD handle
1795   * @param  ch_num Channel number: This parameter can be a value from 1 to 15
1796   * @param  phy_chnum Physical Channel number [0..7]
1797   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
1798   * @retval none
1799   */
HCD_HC_IN_ISO(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1800 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1801                                  uint8_t phy_chnum, uint32_t regvalue)
1802 {
1803   /* Check if Double buffer isochronous */
1804   if ((regvalue & USB_CH_KIND) != 0U)
1805   {
1806     /* Get Data IN Packet */
1807     hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
1808     if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1809     {
1810       USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1811                   hhcd->hc[ch_num & 0xFU].pmaadress,
1812                   (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1813 
1814       hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1815     }
1816   }
1817 #if (USE_USB_DOUBLE_BUFFER == 1U)
1818   else  /* double buffer isochronous */
1819   {
1820     /* Read from Buffer0 */
1821     if ((regvalue & USB_CH_DTOG_RX) != 0U)
1822     {
1823       /* Get number of Received byte in buffer0 */
1824       hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
1825 
1826       if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1827       {
1828         /* Read from Buffer0 */
1829         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1830                     hhcd->hc[ch_num & 0xFU].pmaaddr0,
1831                     (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1832 
1833         hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1834       }
1835     }
1836     else
1837     {
1838       /* Get number of Received byte in buffer1 */
1839       hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
1840 
1841       if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1842       {
1843         /* Read from Buffer1 */
1844         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1845                     hhcd->hc[ch_num & 0xFU].pmaaddr1,
1846                     (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1847 
1848         hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1849       }
1850     }
1851   }
1852 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1853 
1854   /* Transfer complete state */
1855   hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1856 
1857   /* Clear VTRX */
1858   HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
1859 }
1860 
1861 /**
1862   * @brief  Handle Host Channel IN interrupt requests.
1863   * @param  hhcd HCD handle
1864   * @param  chnum Channel number
1865   *         This parameter can be a value from 1 to 8
1866   * @retval none
1867   */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)1868 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1869 {
1870   uint16_t received_bytes;
1871   uint8_t phy_chnum = chnum;
1872   uint8_t ch_num = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 1U);
1873 
1874   /* Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control and status */
1875   uint32_t ch_reg =  HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
1876 
1877   /* Manage Correct Transaction */
1878   if ((ch_reg & USB_CH_ERRRX) == 0U)
1879   {
1880     /* Isochronous Channel */
1881     if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
1882     {
1883       HCD_HC_IN_ISO(hhcd, ch_num, phy_chnum, ch_reg);
1884     }
1885     else
1886     {
1887       /* manage ACK response single buffer */
1888       if (((ch_reg) & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF)
1889       {
1890         /* Get Control Data OUT Packet */
1891         received_bytes = (uint16_t)HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
1892 
1893         /* Read the byte from PMA to user Buffer(System Memory) */
1894         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1895                     hhcd->hc[ch_num & 0xFU].pmaadress, (uint16_t)received_bytes);
1896 
1897         /* update the global number of all received bytes */
1898         hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
1899 
1900         /* Transfer complete state */
1901         hhcd->hc[ch_num & 0xFU].state = HC_ACK;
1902         hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1903 
1904         if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1905         {
1906           hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1907         }
1908         else
1909         {
1910           hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1911         }
1912 
1913         if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
1914             ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
1915         {
1916           hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1917           hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1918         }
1919         else
1920         {
1921           hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
1922 
1923           /* Reactivate the Channel to Submit another URB since the Transfer is not yet completed */
1924           HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
1925         }
1926 
1927         if ((hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_BULK) ||
1928             (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR))
1929         {
1930           hhcd->hc[ch_num & 0xFU].toggle_in ^= 1U;
1931         }
1932       }
1933       /* Manage NACK Response */
1934       else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK)
1935                && (hhcd->hc[ch_num & 0xFU].urb_state != URB_DONE))
1936       {
1937         hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
1938         hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1939         hhcd->hc[ch_num & 0xFU].state = HC_NAK;
1940 
1941         if (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR)
1942         {
1943           /* Close the channel */
1944           HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1945         }
1946       }
1947       /* Manage STALL Response */
1948       else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL)
1949       {
1950         (void)HAL_HCD_HC_Halt(hhcd, ch_num);
1951         hhcd->hc[ch_num & 0xFU].state = HC_STALL;
1952         hhcd->hc[ch_num & 0xFU].urb_state = URB_STALL;
1953 
1954         /* Close the channel */
1955         HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1956       }
1957 #if (USE_USB_DOUBLE_BUFFER == 1U)
1958       /* Double Buffer Management in case of Bulk Transaction */
1959       else  if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_DBUF)
1960                 && ((ch_reg & USB_CH_KIND) != 0U))
1961       {
1962         /* Bulk IN Double Buffer ISR */
1963         HCD_HC_IN_BulkDb(hhcd, ch_num, phy_chnum, ch_reg);
1964       }
1965 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1966       else
1967       {
1968         /*....*/
1969         /* not defined state: STRX=11 in single buffer no iso is not defined */
1970       }
1971 
1972 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1973       hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
1974 #else
1975       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
1976 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1977 
1978       /*Clear VTRX */
1979       HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
1980     }
1981   }
1982   else   /* Error detected during last transaction */
1983   {
1984     /* Set URB Error State */
1985     hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
1986     hhcd->hc[ch_num & 0xFU].ErrCnt++;
1987     hhcd->hc[ch_num & 0xFU].state = HC_XACTERR;
1988 
1989     /* Clear VTTRX & ERR_RX */
1990     HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
1991 
1992     /* Check Error number */
1993     if (hhcd->hc[ch_num & 0xFU].ErrCnt > 3U)
1994     {
1995       hhcd->hc[ch_num & 0xFU].urb_state = URB_ERROR;
1996       HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1997 
1998       /* Clear pending err_tx */
1999       HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
2000     }
2001 
2002 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2003     hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2004 #else
2005     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2006 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2007   }
2008 }
2009 
2010 
2011 /**
2012   * @brief  Handle Host Channel OUT interrupt requests.
2013   * @param  hhcd  HCD handle
2014   * @param  chnum Channel number
2015   *         This parameter can be a value from 1 to 8
2016   * @retval none
2017   */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)2018 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
2019 {
2020   __IO uint32_t WregCh;
2021   uint16_t data_xfr;
2022   uint8_t phy_chnum = chnum;
2023 
2024   /* Get Virtual Channel number */
2025   uint8_t ch_num = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 0U);
2026 
2027   /* Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control &status */
2028   uint32_t ch_reg =  *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
2029 
2030   /*------ Manage Correct Transaction ------*/
2031   if ((ch_reg & USB_CH_ERRTX) == 0U)
2032   {
2033     /* Handle Isochronous channel */
2034     if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
2035     {
2036       /* Correct transaction */
2037       if ((hhcd->Instance->ISTR & USB_ISTR_ERR) == 0U)
2038       {
2039         /* Double buffer isochronous out */
2040         if ((ch_reg & USB_CH_KIND) != 0U)
2041         {
2042           HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
2043         }
2044 #if (USE_USB_DOUBLE_BUFFER == 1U)
2045         else /* Double buffer isochronous out */
2046         {
2047           /* Odd Transaction */
2048           if ((ch_reg & USB_CH_DTOG_TX) != 0U)
2049           {
2050             HCD_SET_CH_TX_CNT(hhcd->Instance, phy_chnum, 0U);
2051           }
2052           /* Even Transaction */
2053           else
2054           {
2055             HCD_SET_CH_RX_CNT(hhcd->Instance, phy_chnum, 0U);
2056           }
2057 
2058           USB_DRD_SET_CHEP_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
2059         }
2060 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2061 
2062         /* Transfer complete state */
2063         hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
2064         hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
2065       }
2066 
2067       /*Clear Correct Transfer */
2068       HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
2069 
2070       /*TX COMPLETE*/
2071 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2072       hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2073 #else
2074       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2075 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2076 
2077     }
2078     else /* Manage all Non Isochronous Transaction */
2079     {
2080       /* Check ACK response */
2081       if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF)
2082       {
2083         data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
2084 
2085         if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr)
2086         {
2087           hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
2088         }
2089         else
2090         {
2091           hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
2092         }
2093 
2094         if ((hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_BULK) ||
2095             (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR))
2096         {
2097           hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
2098         }
2099 
2100         /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
2101         if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
2102         {
2103           /* Manage multiple Xfer */
2104           hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
2105           hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
2106 
2107           /* Start a new transfer */
2108           (void) USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num & 0xFU]);
2109         }
2110         else
2111         {
2112           /* Transfer complete */
2113           hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
2114           hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
2115           hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
2116         }
2117       }
2118       /* Check NACK Response */
2119       else if (((ch_reg & USB_CHEP_NAK) == USB_CHEP_NAK) ||
2120                ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK))
2121       {
2122         /* Update Channel status */
2123         hhcd->hc[ch_num & 0xFU].state = HC_NAK;
2124         hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
2125         hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
2126 
2127         /* Get Channel register value */
2128         WregCh = *(__IO uint32_t *)(&(hhcd->Instance->CHEP0R) + phy_chnum);
2129 
2130         /* Clear NAK status */
2131         WregCh &= ~USB_CHEP_NAK & USB_CHEP_REG_MASK;
2132 
2133         /* Update channel register Value */
2134         HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, WregCh);
2135 
2136         if (hhcd->hc[ch_num & 0xFU].doublebuffer == 0U)
2137         {
2138 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2139           hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2140 #else
2141           HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2142 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2143         }
2144       }
2145       /* Check STALL Response */
2146       else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL)
2147       {
2148         (void) HAL_HCD_HC_Halt(hhcd, (uint8_t)ch_num);
2149         hhcd->hc[ch_num & 0xFU].state = HC_STALL;
2150         hhcd->hc[ch_num & 0xFU].urb_state = URB_STALL;
2151       }
2152 #if (USE_USB_DOUBLE_BUFFER == 1U)
2153       /* Check double buffer ACK in case of bulk transaction */
2154       else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_DBUF)
2155       {
2156         /* Double buffer management Bulk Out */
2157         (void) HCD_HC_OUT_BulkDb(hhcd, ch_num, (uint8_t)phy_chnum, ch_reg);
2158       }
2159 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2160       else
2161       {
2162         /*...*/
2163       }
2164 
2165       if ((ch_reg & USB_CH_TX_STTX) != USB_CH_TX_NAK)
2166       {
2167 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2168         hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2169 #else
2170         HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2171 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2172       }
2173 
2174       HCD_CLEAR_TX_CH_CTR(hhcd->Instance, phy_chnum);
2175     }  /* End no isochronous */
2176   }
2177   /*------ Manage Transaction Error------*/
2178   else
2179   {
2180     hhcd->hc[ch_num & 0xFU].ErrCnt++;
2181     if (hhcd->hc[ch_num & 0xFU].ErrCnt > 3U)
2182     {
2183       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
2184       hhcd->hc[ch_num & 0xFU].urb_state = URB_ERROR;
2185     }
2186     else
2187     {
2188       hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
2189     }
2190 
2191     hhcd->hc[ch_num & 0xFU].state = HC_XACTERR;
2192 
2193     /* Clear ERR_TX */
2194     HCD_CLEAR_TX_CH_ERR(hhcd->Instance, phy_chnum);
2195 
2196 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2197     hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2198 #else
2199     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2200 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2201   }
2202 }
2203 
2204 
2205 /**
2206   * @brief  Handle Host Port interrupt requests.
2207   * @param  hhcd  HCD handle
2208   * @retval None
2209   */
HCD_Port_IRQHandler(HCD_HandleTypeDef * hhcd)2210 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
2211 {
2212   uint32_t FnrReg = hhcd->Instance->FNR;
2213   uint32_t IstrReg = hhcd->Instance->ISTR;
2214 
2215   /* SE0 detected USB Disconnected state */
2216   if ((FnrReg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U)
2217   {
2218     /* Host Port State */
2219     hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2220 
2221     /* Clear all allocated virtual channel */
2222     HAL_HCD_ClearPhyChannel(hhcd);
2223 
2224     /* Reset the PMA current pointer */
2225     (void)HAL_HCD_PMAReset(hhcd);
2226 
2227     /* Reset Ep0 Pma allocation state */
2228     hhcd->ep0_PmaAllocState = 0U;
2229 
2230     /* Disconnection Callback */
2231 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2232     hhcd->DisconnectCallback(hhcd);
2233 #else
2234     HAL_HCD_Disconnect_Callback(hhcd);
2235 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2236 
2237     return;
2238   }
2239 
2240   if ((hhcd->HostState == HCD_HCD_STATE_DISCONNECTED) != 0U)
2241   {
2242     /* J-state or K-state detected & LastState=Disconnected */
2243     if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
2244     {
2245       hhcd->HostState = HCD_HCD_STATE_CONNECTED;
2246 
2247 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2248       hhcd->ConnectCallback(hhcd);
2249 #else
2250       HAL_HCD_Connect_Callback(hhcd);
2251 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2252     }
2253   }
2254   else
2255   {
2256     /* J-state or K-state detected & lastState=Connected: a Missed disconnection is detected */
2257     if (((FnrReg & USB_FNR_RXDP) != 0U) || ((IstrReg & USB_ISTR_LS_DCONN) != 0U))
2258     {
2259       /* Host Port State */
2260       hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
2261 
2262       /* clear all allocated virtual channel */
2263       HAL_HCD_ClearPhyChannel(hhcd);
2264 
2265       /* Reset the PMA current pointer */
2266       (void)HAL_HCD_PMAReset(hhcd);
2267 
2268       /* reset Ep0 PMA allocation state */
2269       hhcd->ep0_PmaAllocState = 0U;
2270 
2271       /* Disconnection Callback */
2272 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2273       hhcd->DisconnectCallback(hhcd);
2274 #else
2275       HAL_HCD_Disconnect_Callback(hhcd);
2276 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2277     }
2278   }
2279 }
2280 
2281 
2282 /**
2283   * @brief  Check if the ch_num are already reserved to a physical channel
2284   * @param  hhcd  HCD handle
2285   * @param  ch_num  Channel number
2286   *         This parameter can be a value from 1 to 15
2287   * @retval HAL status
2288   */
HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const * hhcd,uint8_t ch_num)2289 static uint8_t HAL_HCD_Check_usedChannel(HCD_HandleTypeDef const *hhcd, uint8_t ch_num)
2290 {
2291   uint8_t idx;
2292 
2293   /* Check if the logical channel are already opened  */
2294   for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
2295   {
2296     if ((((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
2297         (hhcd->phy_chin_state[idx] != 0U))
2298     {
2299       return (1U | (idx << 4U));
2300     }
2301 
2302     if ((((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) == ((uint16_t)ch_num + 1U)) &&
2303         (hhcd->phy_chout_state[idx] != 0U))
2304     {
2305       return (1U | (idx << 4U));
2306     }
2307   }
2308 
2309   return 0U;
2310 }
2311 
2312 
2313 /**
2314   * @brief  Get a Logical Channel number from  physical Channel
2315   * @param  hhcd  HCD handle
2316   * @param  phy_chnum
2317   *         This parameter can be a value from 1 to 15
2318   * @param  dir  Channel direction
2319   *         -0 OUT_Channel
2320   *         -1 IN_Channel
2321   * @retval HAL status
2322   */
HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const * hhcd,uint8_t phy_chnum,uint8_t dir)2323 static uint8_t HAL_HCD_GetLogical_Channel(HCD_HandleTypeDef const *hhcd,
2324                                           uint8_t phy_chnum, uint8_t dir)
2325 {
2326   /* Out Channel Direction */
2327   if (dir == 0U)
2328   {
2329     if (((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
2330     {
2331       return ((uint8_t)((hhcd->phy_chout_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
2332     }
2333     else
2334     {
2335       /* Channel not registered Error */
2336       return HCD_LOGICAL_CH_NOT_OPENED;
2337     }
2338   }
2339   /* IN Channel Direction */
2340   else
2341   {
2342     if (((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) != 0U)
2343     {
2344       return ((uint8_t)((hhcd->phy_chin_state[phy_chnum & 0x7U] & 0x00F0U) >> 4U) - 1U);
2345     }
2346     else
2347     {
2348       /* Channel not registered Error */
2349       return HCD_LOGICAL_CH_NOT_OPENED;
2350     }
2351   }
2352 }
2353 
2354 
2355 /**
2356   * @brief  Get a free physical Channel number according to the direction
2357   * @param  hhcd HCD handle
2358   * @param  ch_num Channel number
2359   *         This parameter can be a value from 1 to 15
2360   * @param  epnum Endpoint number
2361   *          This parameter can be a value from 1 to 15
2362   * @param  ep_type Endpoint Type
2363   *          This parameter can be one of these values:
2364   *            EP_TYPE_CTRL Control type,
2365   *            EP_TYPE_ISOC Isochronous type,
2366   *            EP_TYPE_BULK Bulk type,
2367   *            EP_TYPE_INTR Interrupt type
2368   * @retval if physical channel is available return Phy_channel number
2369          else return HCD_FREE_CH_NOT_FOUND
2370   */
HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t epnum,uint8_t ep_type)2371 static uint8_t HAL_HCD_Get_FreePhyChannel(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2372                                           uint8_t epnum, uint8_t ep_type)
2373 {
2374   uint8_t idx;
2375 
2376   if ((epnum & 0x7FU) == 0U)
2377   {
2378     idx = 0U;
2379 
2380     if (ch_num == 0U)
2381     {
2382       if (hhcd->phy_chin_state[idx] == 0U)
2383       {
2384         /* chin_state to store the ep_type to be used for the same channel in OUT direction
2385          * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2386         hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2387                                     ((uint16_t)ep_type + 1U) |
2388                                     (((uint16_t)epnum & 0x0FU) << 8U);
2389       }
2390 
2391       if (hhcd->phy_chout_state[idx] == 0U)
2392       {
2393         /* chout_state will store the ep_type to be used for the same channel in IN direction
2394          * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2395         hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2396                                      ((uint16_t)ep_type + 1U) |
2397                                      (((uint16_t)epnum & 0x0FU) << 8U);
2398       }
2399     }
2400     else
2401     {
2402       if ((epnum & 0x80U) != 0U)
2403       {
2404         if (((hhcd->phy_chin_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
2405         {
2406           /* chin_state to store the ep_type to be used for the same channel in OUT direction
2407            * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2408           hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2409                                       ((uint16_t)ep_type + 1U) |
2410                                       (((uint16_t)epnum & 0x0FU) << 8U);
2411         }
2412       }
2413       else
2414       {
2415         if (((hhcd->phy_chout_state[idx] & 0xF0U) >> 4U) != ((uint16_t)ch_num + 1U))
2416         {
2417           /* chout_state will store the ep_type to be used for the same channel in IN direction
2418            * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2419           hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2420                                        ((uint16_t)ep_type + 1U) |
2421                                        (((uint16_t)epnum & 0x0FU) << 8U);
2422         }
2423       }
2424     }
2425 
2426     return idx;
2427   }
2428 
2429   if ((epnum & 0x80U) != 0U)
2430   {
2431     /* Find a new available physical in channel */
2432     for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
2433     {
2434       /* Check if the same epnum is allocated then allocate the same physical channel OUT for IN Logical Channel */
2435       if ((hhcd->phy_chin_state[idx] == 0U) &&
2436           ((((hhcd->phy_chout_state[idx] & 0x000FU) == ((uint16_t)ep_type + 1U)) &&
2437             (((hhcd->phy_chout_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU)))) ||
2438            (hhcd->phy_chout_state[idx] == 0U)))
2439       {
2440         /* chin_state to store the ep_type to be used for the same channel in OUT direction
2441          * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2442         hhcd->phy_chin_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2443                                     ((uint16_t)ep_type + 1U) |
2444                                     (((uint16_t)epnum & 0x0FU) << 8U);
2445 
2446         return idx;
2447       }
2448     }
2449   }
2450   else
2451   {
2452     /* Find a new available physical out channel */
2453     for (idx = 1U; idx < hhcd->Init.Host_channels; idx++)
2454     {
2455       /* Check if the same epnum is allocated then allocate the same physical channel IN for OUT Logical Channel */
2456       if ((hhcd->phy_chout_state[idx] == 0U) &&
2457           ((((hhcd->phy_chin_state[idx] & 0x0FU) == ((uint16_t)ep_type + 1U)) &&
2458             ((hhcd->phy_chin_state[idx] & 0x0F00U) == ((uint16_t)epnum & 0x0FU))) ||
2459            (hhcd->phy_chin_state[idx] == 0U)))
2460       {
2461         /* chout_state will store the ep_type to be used for the same channel in IN direction
2462          * adding + 1 to ep_type avoid starting with a 0 value. ep_type take by default (0/1/2/3) */
2463         hhcd->phy_chout_state[idx] = (((uint16_t)ch_num + 1U) << 4U) |
2464                                      ((uint16_t)ep_type + 1U) |
2465                                      (((uint16_t)epnum & 0x0FU) << 8U);
2466 
2467         return idx;
2468       }
2469     }
2470   }
2471 
2472   /* in case of Error */
2473   return HCD_FREE_CH_NOT_FOUND;
2474 }
2475 
2476 /**
2477   * @brief  Free All Channel allocation
2478   * @param  hhcd HCD handle
2479   * @retval HAL status
2480   */
HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef * hhcd)2481 static void  HAL_HCD_ClearPhyChannel(HCD_HandleTypeDef *hhcd)
2482 {
2483   uint8_t idx;
2484 
2485   for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
2486   {
2487     /*Reset channel allocation value */
2488     hhcd->phy_chout_state[idx] = 0U;
2489     hhcd->phy_chin_state[idx] = 0U;
2490   }
2491 }
2492 
2493 /*----------------------  PMA Allocation Section --------------------- */
2494 /*
2495                 __col31________________col0__   Column-- >
2496           lin0 | entry31.|.......  | entry0 |   Line
2497                |---------|---------|--------|    |
2498           line1| entry63.|.......  | entry32|    |
2499                |---------|---------|--------|   \|/
2500                | entry127|.......  | entry64|
2501                |---------|---------|--------|
2502                | entry256|......   |entry128|
2503                 ----------------------------
2504            an allocation space of 64byte need 8 Free contiguous Entry in the Matrix
2505            - a Free Entry is a bit with 0 Value/  a busy entry is a bit with 1 value. */
2506 
2507 /**
2508   * @brief  Fetch in the PMA_LockupTable free space of number of mps byte
2509   * @param  hhcd  Host instance
2510   * @param  mps  Channel Max Packet Size
2511   * @retval PMA_Address of the first free block containing mps byte
2512             0xFFFF in case of no space available
2513   */
HAL_HCD_GetFreePMA(HCD_HandleTypeDef * hhcd,uint16_t mps)2514 static uint16_t HAL_HCD_GetFreePMA(HCD_HandleTypeDef *hhcd, uint16_t mps)
2515 {
2516   uint32_t Entry;
2517   uint32_t FreeBlocks = 0U;
2518   uint8_t FirstFreeBlock_col = 0U;
2519   uint8_t FirstFreeBlock_line = 0U;
2520   uint8_t ColIndex;
2521   uint16_t NbrReqBlocks;
2522   uint16_t mps_t = mps;
2523 
2524   /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
2525     allocation in PMA is done in 32Bytes each entry */
2526   if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
2527   {
2528     /* Align the mps to 32byte block to match the allocation in PMA,
2529       check Definition of allocation buffer memory in usb user spec */
2530     mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
2531   }
2532 
2533   /* calculate the number of block(8byte) to allocate */
2534   NbrReqBlocks = mps_t / 8U;
2535 
2536   /* check if we need remaining Block */
2537   if ((mps_t % 8U) != 0U)
2538   {
2539     NbrReqBlocks++;
2540   }
2541 
2542   /* Look For NbrReqBlocks * Empty Block */
2543   for (uint8_t i = 0U; ((i < PMA_BLOCKS) && (FreeBlocks != NbrReqBlocks)); i++)
2544   {
2545     Entry = hhcd->PMALookupTable[i];
2546 
2547     /* when parse is in progress, check the first col to look for a contiguous block */
2548     if ((FreeBlocks != 0U) && ((Entry & (uint32_t)1U) != 0U))
2549     {
2550       FreeBlocks = 0U;
2551     }
2552     uint8_t j = 0U;
2553     while ((j <= 31U) && (FreeBlocks != NbrReqBlocks))
2554     {
2555       /* check if block j is free */
2556       if ((Entry & ((uint32_t)1U << j)) == 0U)
2557       {
2558         if (FreeBlocks == 0U)
2559         {
2560           FirstFreeBlock_col = j;
2561           FirstFreeBlock_line = i;
2562           FreeBlocks++;
2563         }
2564         j++;
2565 
2566         /* Parse Column PMALockTable */
2567         while ((j <= 31U) && ((Entry & ((uint32_t)1U << j)) == 0U) && (FreeBlocks < NbrReqBlocks))
2568         {
2569           FreeBlocks++;
2570           j++;
2571         }
2572 
2573         /* Free contiguous Blocks not found */
2574         if (((FreeBlocks < NbrReqBlocks) && (j < 31U)) ||
2575             ((j == 31U) && ((Entry & ((uint32_t)1U << j)) != 0U)))
2576         {
2577           FreeBlocks = 0U;
2578         }
2579       }
2580       j++;
2581     } /* end for j */
2582   } /* end for i */
2583 
2584   /* Free block found */
2585   if (FreeBlocks >= NbrReqBlocks)
2586   {
2587     ColIndex = FirstFreeBlock_col;
2588 
2589     for (uint8_t i = FirstFreeBlock_line; ((i < PMA_BLOCKS) && (FreeBlocks > 0U)); i++)
2590     {
2591       for (uint8_t j = ColIndex; j <= 31U; j++)
2592       {
2593         hhcd->PMALookupTable[i] |= ((uint32_t)1U << j);
2594         if (--FreeBlocks == 0U)
2595         {
2596           break;
2597         }
2598       }
2599       ColIndex = 0U;
2600     }
2601 
2602     return (uint16_t)((FirstFreeBlock_line * (uint16_t)256U) + (FirstFreeBlock_col * (uint16_t)8U));
2603   }
2604   else
2605   {
2606     return 0xFFFFU;
2607   }
2608 }
2609 
2610 /**
2611   * @brief  Allocate PMA buffer for Channel
2612   *         This API will fetch a free space
2613   * @param  hhcd    Host instance
2614   * @param  ch_num  Channel number
2615   * @param  ch_kind endpoint Kind
2616   *                  USB_SNG_BUF Single Buffer used
2617   *                  USB_DBL_BUF Double Buffer used
2618   * @param  mps Channel Max Packet Size
2619   * @retval HAL status
2620   */
HAL_HCD_PMAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint16_t ch_kind,uint16_t mps)2621 HAL_StatusTypeDef  HAL_HCD_PMAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
2622                                    uint16_t ch_kind, uint16_t mps)
2623 {
2624   uint16_t pma_addr0;
2625 #if (USE_USB_DOUBLE_BUFFER == 1U)
2626   uint16_t pma_addr1; /* used for double buffer mode if enabled */
2627 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2628 
2629   /* Host Channel */
2630   HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
2631 
2632   /* Get a FreePMA Address */
2633   pma_addr0 = HAL_HCD_GetFreePMA(hhcd, mps);
2634 
2635   /* If there is no free space to allocate */
2636   if (pma_addr0 == 0xFFFFU)
2637   {
2638     return HAL_ERROR;
2639   }
2640   else
2641   {
2642     /* Here we check if the endpoint is single or double Buffer */
2643     if (ch_kind == HCD_SNG_BUF)
2644     {
2645       /* Single Buffer */
2646       hc->doublebuffer = 0U;
2647 
2648       if (hc->ep_num == 0U)
2649       {
2650         hhcd->ep0_PmaAllocState &= 0xFFF0U;
2651         hhcd->ep0_PmaAllocState |= ch_num;
2652         hhcd->ep0_PmaAllocState |= (1U << 8);
2653       }
2654 
2655       /* Configure the PMA */
2656       if (hc->ch_dir == CH_IN_DIR)
2657       {
2658         hc->pmaaddr1 = pma_addr0;
2659         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = hc->pmaaddr1;
2660 
2661         if (hc->ep_num == 0U)
2662         {
2663           hhcd->ep0_PmaAllocState |= (CH_IN_DIR << 4);
2664         }
2665       }
2666       else
2667       {
2668         hc->pmaaddr0 = pma_addr0;
2669         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = hc->pmaaddr0;
2670       }
2671 
2672       /* Set the PmaAddress */
2673       hc->pmaadress = pma_addr0;
2674     }
2675 #if (USE_USB_DOUBLE_BUFFER == 1U)
2676     else /* USB_DBL_BUF */
2677     {
2678       /* Double Buffer Endpoint */
2679       hc->doublebuffer = 1U;
2680 
2681       /* Get a FreePMA Address for buffer 2 */
2682       pma_addr1 = HAL_HCD_GetFreePMA(hhcd, mps);
2683 
2684       if (pma_addr1 == 0xFFFFU)
2685       {
2686         /* Free the first buffer */
2687         (void)HAL_HCD_PMAFree(hhcd, pma_addr0, mps);
2688         return HAL_ERROR;
2689       }
2690       else
2691       {
2692         /* Configure the PMA */
2693         hc->pmaaddr0 = (uint16_t)(pma_addr0);
2694         hc->pmaaddr1 = (uint16_t)(pma_addr1);
2695 
2696         /* Set Buffer0 pma address */
2697         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = pma_addr0;
2698 
2699         /* Set Buffer1 pma address */
2700         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = pma_addr1;
2701 
2702         /* Used for Bulk DB MPS < 64bytes */
2703         if (hc->ch_dir == CH_IN_DIR)
2704         {
2705           hc->pmaadress = hc->pmaaddr1;
2706         }
2707         else
2708         {
2709           hc->pmaadress = hc->pmaaddr0;
2710         }
2711       }
2712     }
2713 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2714   }
2715 
2716   return HAL_OK;
2717 }
2718 
2719 /**
2720   * @brief  PMA De-Allocation for Channel Free the reserved block in the PMA-LookupTable
2721   * @param  hhcd  Host instance
2722   * @param  ch_num Channel number
2723   * @retval HAL status
2724   */
HAL_HCD_PMADeAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num)2725 HAL_StatusTypeDef  HAL_HCD_PMADeAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
2726 {
2727   HAL_StatusTypeDef status;
2728 
2729 #if (USE_USB_DOUBLE_BUFFER == 1U)
2730   uint8_t Err = 0U;
2731 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2732 
2733   /* Host Channel */
2734   HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
2735 
2736   /* Single Buffer */
2737   if (hc->doublebuffer == 0U)
2738   {
2739     status = HAL_HCD_PMAFree(hhcd, hc->pmaadress, hc->max_packet);
2740   }
2741   else   /* Double buffer */
2742   {
2743 #if (USE_USB_DOUBLE_BUFFER == 1U)
2744     status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr0, hc->max_packet);
2745     if (status != HAL_OK)
2746     {
2747       Err++;
2748     }
2749 
2750     status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr1, hc->max_packet);
2751     if (status != HAL_OK)
2752     {
2753       Err++;
2754     }
2755 
2756     if (Err != 0U)
2757     {
2758       return HAL_ERROR;
2759     }
2760 #else
2761     status = HAL_ERROR;
2762 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2763   }
2764 
2765   return status;
2766 }
2767 
2768 
2769 /**
2770   * @brief  PMA Reset
2771   * @param  hhcd  Host instance
2772   * @retval HAL status
2773   */
HAL_HCD_PMAReset(HCD_HandleTypeDef * hhcd)2774 HAL_StatusTypeDef  HAL_HCD_PMAReset(HCD_HandleTypeDef *hhcd)
2775 {
2776   /* Reset All PMA Entry */
2777   for (uint8_t i = 0U; i < PMA_BLOCKS; i++)
2778   {
2779     hhcd->PMALookupTable[i] = 0U;
2780   }
2781 
2782   /* Allocate a Space for buffer descriptor table depending on the Host channel number */
2783   for (uint8_t i = 0U; i < hhcd->Init.Host_channels; i++)
2784   {
2785     hhcd->PMALookupTable[0] |= ((uint32_t)1U << i);
2786   }
2787 
2788   return HAL_OK;
2789 }
2790 
2791 /**
2792   * @brief  PMA Free
2793   * @param  hhcd   Host instance
2794   * @param  pma_base PMA base offset stored in hhcd->hc.pmaaddr
2795   * @param  mps  Max Packet Size
2796   * @retval HAL status
2797   */
HAL_HCD_PMAFree(HCD_HandleTypeDef * hhcd,uint32_t pma_base,uint16_t mps)2798 static HAL_StatusTypeDef  HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps)
2799 {
2800   uint32_t block_nbr;
2801   uint8_t ColIndex;
2802   uint8_t LineIndex;
2803   uint16_t mps_t = mps;
2804 
2805   /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
2806     allocation in PMA is done in 32Bytes each entry */
2807   if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
2808   {
2809     /* Align the mps to 32byte block to match the allocation in PMA,
2810       check Definition of allocation buffer memory in usb user spec */
2811     mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
2812   }
2813 
2814   /* Calculate the number of needed block to Free */
2815   if ((mps_t / 8U) != 0U)
2816   {
2817     block_nbr = ((uint32_t)mps_t / 8U);
2818 
2819     if ((mps_t % 8U) != 0U)
2820     {
2821       block_nbr++;
2822     }
2823   }
2824   else
2825   {
2826     block_nbr = 1U;
2827   }
2828 
2829   /* Decode Col/Line of PMA_Base position in the PMA_LookupTable */
2830   if (pma_base > 256U)
2831   {
2832     LineIndex = (uint8_t)(pma_base / 256U);
2833     ColIndex = (uint8_t)((pma_base - ((uint32_t)LineIndex * 256U)) / 8U);
2834   }
2835   else
2836   {
2837     LineIndex = 0U;
2838     ColIndex = (uint8_t)(pma_base / 8U);
2839   }
2840 
2841   /* Reset the corresponding bit in the lookupTable */
2842   for (uint8_t i = LineIndex; ((i < PMA_BLOCKS) && (block_nbr > 0U)); i++)
2843   {
2844     for (uint8_t j = ColIndex; j <= 31U; j++)
2845     {
2846       /* Check if the block is not already reserved or it was already closed */
2847       if ((hhcd->PMALookupTable[i] & ((uint32_t)1U << j)) == 0U)
2848       {
2849         return HAL_ERROR;
2850       }
2851       /* Free the reserved block by resetting the corresponding bit */
2852       hhcd->PMALookupTable[i] &= ~(1U << j);
2853 
2854       if (--block_nbr == 0U)
2855       {
2856         break;
2857       }
2858     }
2859     ColIndex = 0U;
2860   }
2861 
2862   return HAL_OK;
2863 }
2864 
2865 /**
2866   * @}
2867   */
2868 
2869 /**
2870   * @}
2871   */
2872 #endif /* defined (USB_DRD_FS) */
2873 #endif /* HAL_HCD_MODULE_ENABLED */
2874 
2875 /**
2876   * @}
2877   */
2878 
2879 /**
2880   * @}
2881   */
2882