1 /**
2   ******************************************************************************
3   * @file    stm32g0xx_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) 2018 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 "stm32g0xx_hal.h"
55 
56 /** @addtogroup STM32G0xx_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   /* Deactivate the power down */
173   hhcd->Instance->CNTR &= ~USB_CNTR_PDWN;
174 
175   hhcd->State = HAL_HCD_STATE_READY;
176 
177   /* Host Port State */
178   hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
179 
180   /* Init PMA Address */
181   (void)HAL_HCD_PMAReset(hhcd);
182 
183   hhcd->State = HAL_HCD_STATE_READY;
184 
185   return HAL_OK;
186 }
187 
188 /**
189   * @brief  Initialize a host channel.
190   * @param  hhcd HCD handle
191   * @param  ch_num Channel number.
192   *         This parameter can be a value from 1 to 15
193   * @param  epnum Endpoint number.
194   *          This parameter can be a value from 1 to 15
195   * @param  dev_address Current device address
196   *          This parameter can be a value from 0 to 255
197   * @param  speed Current device speed.
198   *          This parameter can be one of these values:
199   *            HCD_DEVICE_SPEED_HIGH High speed mode,
200   *            HCD_DEVICE_SPEED_FULL Full speed mode,
201   *            HCD_DEVICE_SPEED_LOW Low speed mode
202   * @param  ep_type Endpoint Type.
203   *          This parameter can be one of these values:
204   *            USBH_EP_CONTROL Control type,
205   *            USBH_EP_ISO Isochronous type,
206   *            USBH_EP_BULK Bulk type,
207   *            USBH_EP_INTERRUPT Interrupt type
208   * @param  mps Max Packet Size.
209   *          This parameter can be a value from 0 to32K
210   * @retval HAL status
211   */
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)212 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
213                                   uint8_t epnum, uint8_t dev_address,
214                                   uint8_t speed, uint8_t ep_type, uint16_t mps)
215 {
216   HAL_StatusTypeDef status;
217   uint8_t used_channel;
218   uint8_t ep0_virtual_channel;
219 
220   __HAL_LOCK(hhcd);
221 
222   /* Check if the logical channel are already allocated */
223   used_channel = HAL_HCD_Check_usedChannel(hhcd, ch_num);
224 
225   /* Check if the channel is not already opened */
226   if (used_channel == 0U)
227   {
228     /* Allocate New Physical channel */
229     hhcd->hc[ch_num & 0xFU].phy_ch_num = HAL_HCD_Get_FreePhyChannel(hhcd, ch_num, epnum, ep_type);
230 
231     /* No free Channel available, return error */
232     if (hhcd->hc[ch_num & 0xFU].phy_ch_num == HCD_FREE_CH_NOT_FOUND)
233     {
234       return HAL_ERROR;
235     }
236   }
237   /* Channel already opened */
238   else
239   {
240     /* Get Physical Channel number */
241     hhcd->hc[ch_num & 0xFU].phy_ch_num = (used_channel & 0xF0U) >> 4U;
242   }
243 
244   if ((epnum & 0x80U) != 0U)
245   {
246     hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
247   }
248   else
249   {
250     hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
251   }
252 
253   hhcd->hc[ch_num & 0xFU].dev_addr   = dev_address;
254   hhcd->hc[ch_num & 0xFU].max_packet = mps;
255   hhcd->hc[ch_num & 0xFU].ep_type    = ep_type;
256   hhcd->hc[ch_num & 0xFU].ep_num     = epnum & 0x7FU;
257   hhcd->hc[ch_num & 0xFU].speed      = speed;
258 
259   /* Check if the channel is not already opened */
260   if (used_channel == 0U)
261   {
262     if (((ep_type == EP_TYPE_ISOC) && (hhcd->Init.iso_singlebuffer_enable == 0U)) ||
263         ((ep_type == EP_TYPE_BULK) && (hhcd->Init.bulk_doublebuffer_enable == 1U)))
264     {
265       /* PMA Dynamic Allocation */
266       status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_DBL_BUF, mps);
267 
268       if (status == HAL_ERROR)
269       {
270         return HAL_ERROR;
271       }
272 
273       /* Clear Channel DTOG_TX */
274       HCD_CLEAR_TX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
275 
276       /* Clear Channel DTOG RX */
277       HCD_CLEAR_RX_DTOG(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num);
278 
279     }
280     else
281     {
282       if (hhcd->hc[ch_num & 0xFU].ep_num != 0U)
283       {
284         status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, mps);
285 
286         if (status == HAL_ERROR)
287         {
288           return HAL_ERROR;
289         }
290       }
291       else
292       {
293         if (ch_num == 0U)
294         {
295           ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
296 
297           if ((ep0_virtual_channel != 0U) && (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR))
298           {
299             if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_OUT_DIR)
300             {
301               status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
302 
303               if (status == HAL_ERROR)
304               {
305                 return HAL_ERROR;
306               }
307             }
308             else
309             {
310               return HAL_ERROR;
311             }
312           }
313           else
314           {
315             /* PMA Dynamic Allocation for EP0 OUT direction */
316             hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
317             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
318 
319             if (status == HAL_ERROR)
320             {
321               return HAL_ERROR;
322             }
323 
324             /* PMA Dynamic Allocation for EP0 IN direction */
325             hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
326             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
327 
328             if (status == HAL_ERROR)
329             {
330               return HAL_ERROR;
331             }
332           }
333         }
334         else
335         {
336           if (((hhcd->ep0_PmaAllocState & 0xF00U) >> 8) == 1U)
337           {
338             ep0_virtual_channel = (uint8_t)(hhcd->ep0_PmaAllocState & 0xFU);
339 
340             if (((hhcd->ep0_PmaAllocState & 0xF0U) >> 4) == CH_IN_DIR)
341             {
342               hhcd->hc[ch_num & 0xFU].pmaaddr1 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr1;
343             }
344             else
345             {
346               hhcd->hc[ch_num & 0xFU].pmaaddr0 = hhcd->hc[ep0_virtual_channel & 0xFU].pmaaddr0;
347             }
348           }
349           else
350           {
351             status = HAL_HCD_PMAlloc(hhcd, ch_num, HCD_SNG_BUF, 64U);
352 
353             if (status == HAL_ERROR)
354             {
355               return HAL_ERROR;
356             }
357           }
358         }
359       }
360     }
361   }
362 
363   if ((epnum & 0x80U) != 0U)
364   {
365     hhcd->hc[ch_num & 0xFU].ch_dir = CH_IN_DIR;
366 
367     if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
368     {
369       hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr1;
370     }
371   }
372   else
373   {
374     hhcd->hc[ch_num & 0xFU].ch_dir = CH_OUT_DIR;
375 
376     if (hhcd->hc[ch_num & 0xFU].ep_num == 0U)
377     {
378       hhcd->hc[ch_num & 0xFU].pmaadress = hhcd->hc[ch_num & 0xFU].pmaaddr0;
379     }
380   }
381 
382   /* Init the USB Channel CHEPRx */
383   status =  USB_HC_Init(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
384                         epnum, dev_address, speed, ep_type, mps);
385 
386   /* check single buffer for isochronous channel */
387   if (ep_type == EP_TYPE_ISOC)
388   {
389     if (hhcd->Init.iso_singlebuffer_enable == 1U)
390     {
391       (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
392                                 USB_DRD_ISOC_DBUFF_DISABLE);
393     }
394   }
395 
396   /* Bulk double buffer check */
397   if (ep_type == EP_TYPE_BULK)
398   {
399     if (hhcd->Init.bulk_doublebuffer_enable == 1U)
400     {
401       (void)USB_HC_DoubleBuffer(hhcd->Instance, hhcd->hc[ch_num & 0xFU].phy_ch_num,
402                                 USB_DRD_BULK_DBUFF_ENBALE);
403     }
404   }
405 
406   __HAL_UNLOCK(hhcd);
407 
408   return status;
409 }
410 
411 /**
412   * @brief  HAL_HCD_HC_Close Pipe
413   * @param  hhcd HCD handle
414   * @param  ch_num Channel number.
415   *         This parameter can be a value from 1 to 15
416   * @retval HAL status
417   */
HAL_HCD_HC_Close(HCD_HandleTypeDef * hhcd,uint8_t ch_num)418 HAL_StatusTypeDef HAL_HCD_HC_Close(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
419 {
420   /* Stop the channel */
421   (void) HAL_HCD_HC_Halt(hhcd, ch_num);
422 
423   HAL_Delay(3U);
424 
425   if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
426   {
427     /* Free Allocated Channel */
428     hhcd->phy_chin_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
429   }
430   else
431   {
432     /* Free Allocated Channel */
433     hhcd->phy_chout_state[hhcd->hc[ch_num & 0xFU].phy_ch_num] = 0U;
434   }
435 
436   /* Reset PMA Channel_Allocation */
437   (void)HAL_HCD_PMADeAlloc(hhcd, ch_num);
438 
439   return HAL_OK;
440 }
441 
442 /**
443   * @brief  Halt a host channel.
444   * @param  hhcd HCD handle
445   * @param  ch_num Channel number.
446   *         This parameter can be a value from 1 to 15
447   * @retval HAL status
448   */
HAL_HCD_HC_Halt(HCD_HandleTypeDef * hhcd,uint8_t ch_num)449 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
450 {
451   HAL_StatusTypeDef status = HAL_OK;
452 
453   __HAL_LOCK(hhcd);
454   if (hhcd->hc[ch_num & 0xFU].ch_dir == CH_IN_DIR)
455   {
456     (void)USB_HC_IN_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
457   }
458   else
459   {
460     (void)USB_HC_OUT_Halt(hhcd->Instance, (uint8_t) hhcd->hc[ch_num & 0xFU].phy_ch_num);
461   }
462   __HAL_UNLOCK(hhcd);
463 
464   return status;
465 }
466 
467 /**
468   * @brief  DeInitialize the host driver.
469   * @param  hhcd HCD handle
470   * @retval HAL status
471   */
HAL_HCD_DeInit(HCD_HandleTypeDef * hhcd)472 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
473 {
474   uint8_t idx;
475 
476   /* Check the HCD handle allocation */
477   if (hhcd == NULL)
478   {
479     return HAL_ERROR;
480   }
481 
482   /* Host Port State */
483   hhcd->HostState = HCD_HCD_STATE_DISCONNECTED;
484 
485   /* Reset PMA Address */
486   (void)HAL_HCD_PMAReset(hhcd);
487 
488   for (idx = 0U; idx < hhcd->Init.Host_channels; idx++)
489   {
490     hhcd->phy_chin_state[idx] = 0U;
491     hhcd->phy_chout_state[idx] = 0U;
492   }
493 
494   /* reset Ep0 Pma allocation state */
495   hhcd->ep0_PmaAllocState = 0U;
496 
497   hhcd->State = HAL_HCD_STATE_BUSY;
498 
499 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
500   if (hhcd->MspDeInitCallback == NULL)
501   {
502     hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
503   }
504 
505   /* DeInit the low level hardware */
506   hhcd->MspDeInitCallback(hhcd);
507 #else
508   /* DeInit the low level hardware: CLOCK, NVIC. */
509   HAL_HCD_MspDeInit(hhcd);
510 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
511 
512   hhcd->State = HAL_HCD_STATE_RESET;
513 
514   return HAL_OK;
515 }
516 
517 /**
518   * @brief  Initialize the HCD MSP.
519   * @param  hhcd HCD handle
520   * @retval None
521   */
HAL_HCD_MspInit(HCD_HandleTypeDef * hhcd)522 __weak void  HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
523 {
524   /* Prevent unused argument(s) compilation warning */
525   UNUSED(hhcd);
526 
527   /* NOTE : This function Should not be modified, when the callback is needed,
528   the HAL_HCD_MspInit could be implemented in the user file
529   */
530 }
531 
532 /**
533   * @brief  DeInitialize the HCD MSP.
534   * @param  hhcd HCD handle
535   * @retval None
536   */
HAL_HCD_MspDeInit(HCD_HandleTypeDef * hhcd)537 __weak void  HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
538 {
539   /* Prevent unused argument(s) compilation warning */
540   UNUSED(hhcd);
541 
542   /* NOTE : This function Should not be modified, when the callback is needed,
543   the HAL_HCD_MspDeInit could be implemented in the user file
544   */
545 }
546 
HAL_HCD_SuspendCallback(HCD_HandleTypeDef * hhcd)547 __weak void HAL_HCD_SuspendCallback(HCD_HandleTypeDef *hhcd)
548 {
549   /* Prevent unused argument(s) compilation warning */
550   UNUSED(hhcd);
551 
552   /* NOTE : This function Should not be modified, when the callback is needed,
553   the HAL_HCD_SuspendCallback could be implemented in the user file
554   */
555 
556 }
557 
HAL_HCD_ResumeCallback(HCD_HandleTypeDef * hhcd)558 __weak void HAL_HCD_ResumeCallback(HCD_HandleTypeDef *hhcd)
559 {
560   /* Prevent unused argument(s) compilation warning */
561   UNUSED(hhcd);
562 
563   /* NOTE : This function Should not be modified, when the callback is needed,
564   the HAL_HCD_ResumeCallback could be implemented in the user file
565   */
566 }
567 
568 /**
569   * @}
570   */
571 
572 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
573   *  @brief   HCD IO operation functions
574   *
575 @verbatim
576 ===============================================================================
577 ##### IO operation functions #####
578 ===============================================================================
579 [..] This subsection provides a set of functions allowing to manage the USB Host Data
580 Transfer
581 
582 @endverbatim
583   * @{
584   */
585 
586 /**
587   * @brief  Submit a new URB for processing.
588   * @param  hhcd HCD handle
589   * @param  ch_num Channel number.
590   *         This parameter can be a value from 1 to 15
591   * @param  direction Channel number.
592   *          This parameter can be one of these values:
593   *           0 : Output / 1 : Input
594   * @param  ep_type Endpoint Type.
595   *          This parameter can be one of these values:
596   *            USBH_EP_CONTROL   : Control type/
597   *            USBH_EP_ISO       : Isochronous type/
598   *            USBH_EP_BULK      : Bulk type/
599   *            USBH_EP_INTERRUPT : Interrupt type/
600   * @param  token Endpoint Type.
601   *          This parameter can be one of these values:
602   *            0: HC_PID_SETUP / 1: HC_PID_DATA1
603   * @param  pbuff pointer to URB data
604   * @param  length Length of URB data
605   * @param  do_ping activate do ping protocol (for high speed only).
606   *          This parameter can be one of these values:
607   *           0 : do ping inactive / 1 : do ping active
608   * @retval HAL status
609   */
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)610 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
611                                            uint8_t direction, uint8_t ep_type,
612                                            uint8_t token, uint8_t *pbuff,
613                                            uint16_t length, uint8_t do_ping)
614 {
615   UNUSED(do_ping);
616 
617   if (token == 0U)
618   {
619     hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_SETUP;
620   }
621   else
622   {
623     hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
624   }
625 
626   /* Manage Data Toggle */
627   switch (ep_type)
628   {
629     case EP_TYPE_CTRL:
630       if ((token == 1U) && (direction == 0U)) /* send data */
631       {
632         if (length == 0U)
633         {
634           /* For Status OUT stage, Length==0, Status Out PID = 1 */
635           hhcd->hc[ch_num & 0xFU].toggle_out = 1U;
636         }
637 
638         /* Set the Data Toggle bit as per the Flag */
639         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
640         {
641           /* Put the PID 0 */
642           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
643         }
644         else
645         {
646           /* Put the PID 1 */
647           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
648         }
649       }
650       break;
651 
652     case EP_TYPE_BULK:
653       if (direction == 0U)
654       {
655         /* Set the Data Toggle bit as per the Flag */
656         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
657         {
658           /* Put the PID 0 */
659           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
660         }
661         else
662         {
663           /* Put the PID 1 */
664           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
665         }
666       }
667       else
668       {
669         if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
670         {
671           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
672         }
673         else
674         {
675           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
676         }
677       }
678       break;
679 
680     case EP_TYPE_INTR:
681       if (direction == 0U)
682       {
683         /* Set the Data Toggle bit as per the Flag */
684         if (hhcd->hc[ch_num & 0xFU].toggle_out == 0U)
685         {
686           /* Put the PID 0 */
687           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
688         }
689         else
690         {
691           /* Put the PID 1 */
692           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
693         }
694       }
695       else
696       {
697         if (hhcd->hc[ch_num & 0xFU].toggle_in == 0U)
698         {
699           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
700         }
701         else
702         {
703           hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA1;
704         }
705       }
706       break;
707 
708     case EP_TYPE_ISOC:
709       hhcd->hc[ch_num & 0xFU].data_pid = HC_PID_DATA0;
710       break;
711 
712     default:
713       break;
714   }
715 
716   hhcd->hc[ch_num & 0xFU].xfer_buff = pbuff;
717   hhcd->hc[ch_num & 0xFU].xfer_len = length;
718   hhcd->hc[ch_num & 0xFU].xfer_len_db = length;
719   hhcd->hc[ch_num & 0xFU].urb_state = URB_IDLE;
720   hhcd->hc[ch_num & 0xFU].xfer_count = 0U;
721   hhcd->hc[ch_num & 0xFU].state = HC_IDLE;
722 
723   return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num & 0xFU]);
724 }
725 /**
726   * @brief  Handle HCD interrupt request.
727   * @param  hhcd HCD handle
728   * @retval None
729   */
HAL_HCD_IRQHandler(HCD_HandleTypeDef * hhcd)730 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
731 {
732   uint8_t phy_chnum;
733   uint8_t chnum;
734   uint32_t epch_reg;
735   uint32_t wIstr = USB_ReadInterrupts(hhcd->Instance);
736 
737   /* check if this is an USB pending IT */
738   if ((SYSCFG->IT_LINE_SR[8] & (0x1U << 2)) == 0U)
739   {
740     return;
741   }
742 
743   /* Port Change Detected (Connection/Disconnection) */
744   if ((wIstr & USB_ISTR_DCON) == USB_ISTR_DCON)
745   {
746     /* Clear Flag */
747     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_DCON);
748 
749     /* Call Port IRQHandler */
750     HCD_Port_IRQHandler(hhcd);
751 
752     return;
753   }
754 
755   /* Correct Transaction Detected -------*/
756   if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
757   {
758     /* Handle Host channel Interrupt */
759     for (phy_chnum = 0U; phy_chnum < hhcd->Init.Host_channels; phy_chnum++)
760     {
761       if ((HCD_GET_CHANNEL(hhcd->Instance, phy_chnum) & USB_CH_VTRX) != 0U)
762       {
763         /* Get Logical channel to check if the channel is already opened */
764         chnum = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 1U);
765 
766         if (chnum != HCD_LOGICAL_CH_NOT_OPENED)
767         {
768           /* Call Channel_IN_IRQ() */
769           HCD_HC_IN_IRQHandler(hhcd, chnum);
770         }
771         else
772         {
773           /*Channel was not closed correctly still have interrupt */
774           epch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
775           epch_reg = (epch_reg & (USB_CHEP_REG_MASK & (~USB_CH_ERRRX) & (~USB_CH_VTRX))) |
776                      (USB_CH_VTTX | USB_CH_ERRTX);
777 
778           HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, epch_reg);
779         }
780       }
781 
782       if ((HCD_GET_CHANNEL(hhcd->Instance, phy_chnum) & USB_CH_VTTX) != 0U)
783       {
784         /* Get Logical channel to check if the channel is already opened */
785         chnum = HAL_HCD_GetLogical_Channel(hhcd, phy_chnum, 0U);
786 
787         if (chnum != HCD_LOGICAL_CH_NOT_OPENED)
788         {
789           /*Call Channel_OUT_IRQ()*/
790           HCD_HC_OUT_IRQHandler(hhcd, chnum);
791         }
792         else
793         {
794           /* Clear Error & unwanted VTTX or Channel was not closed correctly */
795           epch_reg = HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
796           epch_reg = (epch_reg & (USB_CHEP_REG_MASK & (~USB_CH_ERRTX) & (~USB_CH_VTTX))) |
797                      (USB_CH_VTRX | USB_CH_ERRRX);
798 
799           HCD_SET_CHANNEL(hhcd->Instance, phy_chnum, epch_reg);
800         }
801       }
802     }
803 
804     return;
805   }
806 
807   /* Wakeup Flag Detected */
808   if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
809   {
810     if (hhcd->HostState == HCD_HCD_STATE_SUSPEND)
811     {
812       /* Set The L2Resume bit */
813       hhcd->Instance->CNTR |= USB_CNTR_L2RES;
814 
815       /* Clear the wake-up flag */
816       __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
817 
818       /* Update the USB Software state machine */
819       HAL_HCD_ResumeCallback(hhcd);
820       hhcd->HostState = HCD_HCD_STATE_RESUME;
821     }
822     else
823     {
824       /* Clear the wake-up flag */
825       __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_WKUP);
826     }
827 
828     return;
829   }
830 
831   /* Global Error Flag Detected */
832   if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
833   {
834     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_ERR);
835 
836     return;
837   }
838 
839   /* PMA Overrun detected */
840   if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
841   {
842     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_PMAOVR);
843 
844     return;
845   }
846 
847   /* Suspend Detected */
848   if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
849   {
850     /* Set HAL State to Suspend */
851     hhcd->HostState = HCD_HCD_STATE_SUSPEND;
852 
853     /* Force low-power mode in the macrocell */
854     hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
855 
856     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
857     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SUSP);
858 
859     /* Call suspend Callback */
860     HAL_HCD_SuspendCallback(hhcd);
861 
862     return;
863   }
864 
865   /* Start Of Frame Detected */
866   if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
867   {
868 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
869     hhcd->SOFCallback(hhcd);
870 #else
871     HAL_HCD_SOF_Callback(hhcd);
872 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
873 
874     __HAL_HCD_CLEAR_FLAG(hhcd, USB_ISTR_SOF);
875 
876     /* when first SOF is detected after USB_RESET is asserted */
877     if (hhcd->HostState == HCD_HCD_STATE_RESETED)
878     {
879       /* HAL State */
880       hhcd->HostState = HCD_HCD_STATE_RUN;
881 
882 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
883       hhcd->PortEnabledCallback(hhcd);
884 #else
885       HAL_HCD_PortEnabled_Callback(hhcd);
886 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
887     }
888 
889     return;
890   }
891 }
892 
893 /**
894   * @brief  SOF callback.
895   * @param  hhcd HCD handle
896   * @retval None
897   */
HAL_HCD_SOF_Callback(HCD_HandleTypeDef * hhcd)898 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
899 {
900   /* Prevent unused argument(s) compilation warning */
901   UNUSED(hhcd);
902 
903   /* NOTE : This function Should not be modified, when the callback is needed,
904   the HAL_HCD_SOF_Callback could be implemented in the user file
905   */
906 }
907 
908 /**
909   * @brief Connection Event callback.
910   * @param  hhcd HCD handle
911   * @retval None
912   */
HAL_HCD_Connect_Callback(HCD_HandleTypeDef * hhcd)913 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
914 {
915   /* Prevent unused argument(s) compilation warning */
916   UNUSED(hhcd);
917 
918   /* NOTE : This function Should not be modified, when the callback is needed,
919   the HAL_HCD_Connect_Callback could be implemented in the user file
920   */
921 }
922 
923 /**
924   * @brief  Disconnection Event callback.
925   * @param  hhcd HCD handle
926   * @retval None
927   */
HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef * hhcd)928 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
929 {
930   /* Prevent unused argument(s) compilation warning */
931   UNUSED(hhcd);
932 
933   /* NOTE : This function Should not be modified, when the callback is needed,
934   the HAL_HCD_Disconnect_Callback could be implemented in the user file
935   */
936 }
937 /**
938   * @brief  Port Enabled  Event callback.
939   * @param  hhcd HCD handle
940   * @retval None
941   */
HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef * hhcd)942 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
943 {
944   /* Prevent unused argument(s) compilation warning */
945   UNUSED(hhcd);
946 
947   /* NOTE : This function should not be modified, when the callback is needed,
948             the HAL_HCD_Disconnect_Callback could be implemented in the user file
949    */
950 }
951 /**
952   * @brief  Port Disabled  Event callback.
953   * @param  hhcd HCD handle
954   * @retval None
955   */
HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef * hhcd)956 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
957 {
958   /* Prevent unused argument(s) compilation warning */
959   UNUSED(hhcd);
960 
961   /* NOTE : This function should not be modified, when the callback is needed,
962             the HAL_HCD_Disconnect_Callback could be implemented in the user file
963    */
964 }
965 
966 /**
967   * @brief  Notify URB state change callback.
968   * @param  hhcd HCD handle
969   * @param  chnum Channel number.
970   *         This parameter can be a value from 1 to 15
971   * @param  urb_state
972   *          This parameter can be one of these values:
973   *            URB_IDLE/
974   *            URB_DONE/
975   *            URB_NOTREADY/
976   *            URB_NYET/
977   *            URB_ERROR/
978   *            URB_STALL/
979   * @retval None
980   */
HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef * hhcd,uint8_t chnum,HCD_URBStateTypeDef urb_state)981 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd,
982                                                 uint8_t chnum, HCD_URBStateTypeDef urb_state)
983 {
984   /* Prevent unused argument(s) compilation warning */
985   UNUSED(hhcd);
986   UNUSED(chnum);
987   UNUSED(urb_state);
988 
989   /* NOTE : This function Should not be modified, when the callback is needed,
990   the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
991   */
992 }
993 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
994 /**
995   * @brief  Register a User USB HCD Callback
996   *         To be used instead of the weak predefined callback
997   * @param  hhcd USB HCD handle
998   * @param  CallbackID ID of the callback to be registered
999   *         This parameter can be one of the following values:
1000   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
1001   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
1002   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID HCD Disconnect callback ID
1003   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
1004   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
1005   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
1006   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
1007   * @param  pCallback pointer to the Callback function
1008   * @retval HAL status
1009   */
HAL_HCD_RegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID,pHCD_CallbackTypeDef pCallback)1010 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
1011                                            HAL_HCD_CallbackIDTypeDef CallbackID,
1012                                            pHCD_CallbackTypeDef pCallback)
1013 {
1014   HAL_StatusTypeDef status = HAL_OK;
1015 
1016   if (pCallback == NULL)
1017   {
1018     /* Update the error code */
1019     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1020     return HAL_ERROR;
1021   }
1022   /* Process locked */
1023   __HAL_LOCK(hhcd);
1024 
1025   if (hhcd->State == HAL_HCD_STATE_READY)
1026   {
1027     switch (CallbackID)
1028     {
1029       case HAL_HCD_SOF_CB_ID :
1030         hhcd->SOFCallback = pCallback;
1031         break;
1032 
1033       case HAL_HCD_CONNECT_CB_ID :
1034         hhcd->ConnectCallback = pCallback;
1035         break;
1036 
1037       case HAL_HCD_DISCONNECT_CB_ID :
1038         hhcd->DisconnectCallback = pCallback;
1039         break;
1040 
1041       case HAL_HCD_PORT_ENABLED_CB_ID :
1042         hhcd->PortEnabledCallback = pCallback;
1043         break;
1044 
1045       case HAL_HCD_PORT_DISABLED_CB_ID :
1046         hhcd->PortDisabledCallback = pCallback;
1047         break;
1048 
1049       case HAL_HCD_MSPINIT_CB_ID :
1050         hhcd->MspInitCallback = pCallback;
1051         break;
1052 
1053       case HAL_HCD_MSPDEINIT_CB_ID :
1054         hhcd->MspDeInitCallback = pCallback;
1055         break;
1056 
1057       default :
1058         /* Update the error code */
1059         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1060         /* Return error status */
1061         status =  HAL_ERROR;
1062         break;
1063     }
1064   }
1065   else if (hhcd->State == HAL_HCD_STATE_RESET)
1066   {
1067     switch (CallbackID)
1068     {
1069       case HAL_HCD_MSPINIT_CB_ID :
1070         hhcd->MspInitCallback = pCallback;
1071         break;
1072 
1073       case HAL_HCD_MSPDEINIT_CB_ID :
1074         hhcd->MspDeInitCallback = pCallback;
1075         break;
1076 
1077       default :
1078         /* Update the error code */
1079         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1080         /* Return error status */
1081         status =  HAL_ERROR;
1082         break;
1083     }
1084   }
1085   else
1086   {
1087     /* Update the error code */
1088     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1089     /* Return error status */
1090     status =  HAL_ERROR;
1091   }
1092 
1093   /* Release Lock */
1094   __HAL_UNLOCK(hhcd);
1095   return status;
1096 }
1097 
1098 /**
1099   * @brief  Unregister an USB HCD Callback
1100   *         USB HCD callback is redirected to the weak predefined callback
1101   * @param  hhcd USB HCD handle
1102   * @param  CallbackID ID of the callback to be unregistered
1103   *         This parameter can be one of the following values:
1104   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
1105   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
1106   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID DRD HCD Disconnect callback ID
1107   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
1108   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
1109   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
1110   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
1111   * @retval HAL status
1112   */
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef * hhcd,HAL_HCD_CallbackIDTypeDef CallbackID)1113 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd,
1114                                              HAL_HCD_CallbackIDTypeDef CallbackID)
1115 {
1116   HAL_StatusTypeDef status = HAL_OK;
1117 
1118   /* Process locked */
1119   __HAL_LOCK(hhcd);
1120 
1121   /* Setup Legacy weak Callbacks */
1122   if (hhcd->State == HAL_HCD_STATE_READY)
1123   {
1124     switch (CallbackID)
1125     {
1126       case HAL_HCD_SOF_CB_ID :
1127         hhcd->SOFCallback = HAL_HCD_SOF_Callback;
1128         break;
1129 
1130       case HAL_HCD_CONNECT_CB_ID :
1131         hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
1132         break;
1133 
1134       case HAL_HCD_DISCONNECT_CB_ID :
1135         hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
1136         break;
1137 
1138       case HAL_HCD_PORT_ENABLED_CB_ID :
1139         hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
1140         break;
1141 
1142       case HAL_HCD_PORT_DISABLED_CB_ID :
1143         hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
1144         break;
1145 
1146       case HAL_HCD_MSPINIT_CB_ID :
1147         hhcd->MspInitCallback = HAL_HCD_MspInit;
1148         break;
1149 
1150       case HAL_HCD_MSPDEINIT_CB_ID :
1151         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
1152         break;
1153 
1154       default :
1155         /* Update the error code */
1156         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1157 
1158         /* Return error status */
1159         status =  HAL_ERROR;
1160         break;
1161     }
1162   }
1163   else if (hhcd->State == HAL_HCD_STATE_RESET)
1164   {
1165     switch (CallbackID)
1166     {
1167       case HAL_HCD_MSPINIT_CB_ID :
1168         hhcd->MspInitCallback = HAL_HCD_MspInit;
1169         break;
1170 
1171       case HAL_HCD_MSPDEINIT_CB_ID :
1172         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
1173         break;
1174 
1175       default :
1176         /* Update the error code */
1177         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1178 
1179         /* Return error status */
1180         status =  HAL_ERROR;
1181         break;
1182     }
1183   }
1184   else
1185   {
1186     /* Update the error code */
1187     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1188 
1189     /* Return error status */
1190     status =  HAL_ERROR;
1191   }
1192 
1193   /* Release Lock */
1194   __HAL_UNLOCK(hhcd);
1195   return status;
1196 }
1197 
1198 /**
1199   * @brief  Register USB HCD Host Channel Notify URB Change Callback
1200   *         To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
1201   * @param  hhcd HCD handle
1202   * @param  pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
1203   * @retval HAL status
1204   */
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd,pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)1205 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
1206                                                              pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
1207 {
1208   HAL_StatusTypeDef status = HAL_OK;
1209 
1210   if (pCallback == NULL)
1211   {
1212     /* Update the error code */
1213     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1214 
1215     return HAL_ERROR;
1216   }
1217 
1218   /* Process locked */
1219   __HAL_LOCK(hhcd);
1220 
1221   if (hhcd->State == HAL_HCD_STATE_READY)
1222   {
1223     hhcd->HC_NotifyURBChangeCallback = pCallback;
1224   }
1225   else
1226   {
1227     /* Update the error code */
1228     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1229 
1230     /* Return error status */
1231     status = HAL_ERROR;
1232   }
1233 
1234   /* Release Lock */
1235   __HAL_UNLOCK(hhcd);
1236 
1237   return status;
1238 }
1239 
1240 /**
1241   * @brief  Unregister the USB HCD Host Channel Notify URB Change Callback
1242   *         USB HCD Host Channel Notify URB Change Callback is redirected
1243   *         to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
1244   * @param  hhcd HCD handle
1245   * @retval HAL status
1246   */
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef * hhcd)1247 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
1248 {
1249   HAL_StatusTypeDef status = HAL_OK;
1250 
1251   /* Process locked */
1252   __HAL_LOCK(hhcd);
1253 
1254   if (hhcd->State == HAL_HCD_STATE_READY)
1255   {
1256     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
1257   }
1258   else
1259   {
1260     /* Update the error code */
1261     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
1262 
1263     /* Return error status */
1264     status =  HAL_ERROR;
1265   }
1266 
1267   /* Release Lock */
1268   __HAL_UNLOCK(hhcd);
1269 
1270   return status;
1271 }
1272 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1273 
1274 
1275 /**
1276   * @}
1277   */
1278 
1279 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1280   *  @brief   Management functions
1281   *
1282 @verbatim
1283 ===============================================================================
1284 ##### Peripheral Control functions #####
1285 ===============================================================================
1286 [..]
1287 This subsection provides a set of functions allowing to control the HCD data
1288 transfers.
1289 
1290 @endverbatim
1291   * @{
1292   */
1293 
1294 /**
1295   * @brief  Start the host driver.
1296   * @param  hhcd HCD handle
1297   * @retval HAL status
1298   */
HAL_HCD_Start(HCD_HandleTypeDef * hhcd)1299 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1300 {
1301   __HAL_LOCK(hhcd);
1302 
1303   /*Set the PullDown on the PHY */
1304   hhcd->Instance->BCDR |= USB_BCDR_DPPD;
1305 
1306   /* Clear Reset  */
1307   hhcd->Instance->CNTR &= ~USB_CNTR_USBRST;
1308 
1309   /*Remove PowerDown */
1310   hhcd->Instance->CNTR &= ~USB_CNTR_PDWN;
1311 
1312   __HAL_UNLOCK(hhcd);
1313 
1314   return HAL_OK;
1315 }
1316 
1317 /**
1318   * @brief  Stop the host driver.
1319   * @param  hhcd HCD handle
1320   * @retval HAL status
1321   */
HAL_HCD_Stop(HCD_HandleTypeDef * hhcd)1322 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1323 {
1324   __HAL_LOCK(hhcd);
1325   /*Stop the Host IP: setting powerdown  */
1326   (void)USB_StopHost(hhcd->Instance);
1327 
1328   /* clear all allocated virtual channel */
1329   HAL_HCD_ClearPhyChannel(hhcd);
1330 
1331   /* Reset the PMA current pointer */
1332   (void)HAL_HCD_PMAReset(hhcd);
1333 
1334   /* reset Ep0 Pma allocation state */
1335   hhcd->ep0_PmaAllocState = 0U;
1336 
1337   __HAL_UNLOCK(hhcd);
1338   return HAL_OK;
1339 }
1340 
1341 /**
1342   * @brief  Put the Device in suspend mode
1343   * @param  hhcd HCD handle
1344   * @retval HAL status
1345   */
HAL_HCD_Suspend(HCD_HandleTypeDef * hhcd)1346 HAL_StatusTypeDef HAL_HCD_Suspend(HCD_HandleTypeDef *hhcd)
1347 {
1348   __IO uint32_t count = 0U;
1349 
1350   /* Set Suspend Mode */
1351   hhcd->Instance->CNTR |= USB_CNTR_SUSPEN;
1352 
1353   /* wait for Suspend Ready */
1354   while ((hhcd->Instance->CNTR & USB_CNTR_SUSPRDY) == 0U)
1355   {
1356     if (++count > HAL_USB_TIMEOUT)
1357     {
1358       return HAL_TIMEOUT;
1359     }
1360   }
1361 
1362   return HAL_OK;
1363 }
1364 
1365 /**
1366   * @brief  Resume host port
1367   * @param  hhcd HCD handle
1368   * @retval HAL status
1369   */
HAL_HCD_Resume(HCD_HandleTypeDef * hhcd)1370 HAL_StatusTypeDef HAL_HCD_Resume(HCD_HandleTypeDef *hhcd)
1371 {
1372   /* Set Resume bit */
1373   hhcd->Instance->CNTR |= USB_CNTR_L2RES;
1374 
1375   return HAL_OK;
1376 }
1377 
1378 /**
1379   * @brief  Reset the host port.
1380   * @param  hhcd HCD handle
1381   * @retval HAL status
1382   */
HAL_HCD_ResetPort(HCD_HandleTypeDef * hhcd)1383 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1384 {
1385   __HAL_LOCK(hhcd);
1386 
1387   /* Reset the USB Port by inserting an SE0 on the bus */
1388   (void)USB_ResetPort(hhcd->Instance);
1389 
1390   if (hhcd->HostState == HCD_HCD_STATE_CONNECTED)
1391   {
1392     hhcd->HostState = HCD_HCD_STATE_RESETED;
1393   }
1394   __HAL_UNLOCK(hhcd);
1395 
1396   return HAL_OK;
1397 }
1398 
1399 /**
1400   * @brief  Resme the host port.
1401   * @param  hhcd HCD handle
1402   * @retval HAL status
1403   */
HAL_HCD_ResumePort(HCD_HandleTypeDef * hhcd)1404 HAL_StatusTypeDef HAL_HCD_ResumePort(HCD_HandleTypeDef *hhcd)
1405 {
1406   /* Set Resume bit */
1407   hhcd->Instance->CNTR |= USB_CNTR_L2RES;
1408   HAL_Delay(30U);
1409 
1410   /* Clear Resume bit */
1411   hhcd->Instance->CNTR &= ~USB_CNTR_L2RES;
1412 
1413   return HAL_OK;
1414 }
1415 
1416 
1417 /**
1418   * @}
1419   */
1420 
1421 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1422   *  @brief   Peripheral State functions
1423   *
1424 @verbatim
1425 ===============================================================================
1426 ##### Peripheral State functions #####
1427 ===============================================================================
1428 [..]
1429 This subsection permits to get in run-time the status of the peripheral
1430 and the data flow.
1431 
1432 @endverbatim
1433   * @{
1434   */
1435 
1436 /**
1437   * @brief  Return the HCD handle state.
1438   * @param  hhcd HCD handle
1439   * @retval HAL state
1440   */
HAL_HCD_GetState(HCD_HandleTypeDef const * hhcd)1441 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
1442 {
1443   return hhcd->State;
1444 }
1445 
1446 /**
1447   * @brief  Return  URB state for a channel.
1448   * @param  hhcd HCD handle
1449   * @param  chnum Channel number.
1450   *         This parameter can be a value from 1 to 15
1451   * @retval URB state.
1452   *          This parameter can be one of these values:
1453   *            URB_IDLE/
1454   *            URB_DONE/
1455   *            URB_NOTREADY/
1456   *            URB_NYET/
1457   *            URB_ERROR/
1458   *            URB_STALL
1459   */
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1460 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1461 {
1462   return hhcd->hc[chnum].urb_state;
1463 }
1464 
1465 
1466 /**
1467   * @brief  Return the last host transfer size.
1468   * @param  hhcd HCD handle
1469   * @param  chnum Channel number.
1470   *         This parameter can be a value from 1 to 15
1471   * @retval last transfer size in byte
1472   */
HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1473 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1474 {
1475   return hhcd->hc[chnum].xfer_count;
1476 }
1477 
1478 /**
1479   * @brief  Return the Host Channel state.
1480   * @param  hhcd HCD handle
1481   * @param  chnum Channel number.
1482   *         This parameter can be a value from 1 to 15
1483   * @retval Host channel state
1484   *          This parameter can be one of these values:
1485   *            HC_IDLE/
1486   *            HC_XFRC/
1487   *            HC_HALTED/
1488   *            HC_NYET/
1489   *            HC_NAK/
1490   *            HC_STALL/
1491   *            HC_XACTERR/
1492   *            HC_BBLERR/
1493   *            HC_DATATGLERR
1494   */
HAL_HCD_HC_GetState(HCD_HandleTypeDef const * hhcd,uint8_t chnum)1495 HCD_HCStateTypeDef  HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
1496 {
1497   return hhcd->hc[chnum].state;
1498 }
1499 
1500 /**
1501   * @brief  Return the current Host frame number.
1502   * @param  hhcd HCD handle
1503   * @retval Current Host frame number
1504   */
HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef * hhcd)1505 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1506 {
1507   return (USB_GetCurrentFrame(hhcd->Instance));
1508 }
1509 
1510 /**
1511   * @brief  Return the Host enumeration speed.
1512   * @param  hhcd HCD handle
1513   * @retval speed : Device speed after Host enumeration
1514   *          This parameter can be one of these values:
1515   *            @arg HCD_DEVICE_SPEED_FULL: Full speed mode
1516   *            @arg HCD_DEVICE_SPEED_LOW: Low speed mode
1517   */
HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef * hhcd)1518 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1519 {
1520   return (USB_GetHostSpeed(hhcd->Instance));
1521 }
1522 
1523 /**
1524   * @brief  Set host channel Hub Information.
1525   * @param  hhcd HCD handle
1526   * @param  ch_num Channel number.
1527   *         This parameter can be a value from 1 to 8
1528   * @param  addr Hub address
1529   * @param  PortNbr Hub port number
1530   * @retval HAL status
1531   */
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t addr,uint8_t PortNbr)1532 HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1533                                         uint8_t addr, uint8_t PortNbr)
1534 {
1535   hhcd->hc[ch_num].hub_addr = addr;
1536   hhcd->hc[ch_num].hub_port_nbr = PortNbr;
1537 
1538   return HAL_OK;
1539 }
1540 
1541 
1542 /**
1543   * @brief  Clear host channel hub information.
1544   * @param  hhcd HCD handle
1545   * @param  ch_num Channel number.
1546   *         This parameter can be a value from 1 to 8
1547   * @retval HAL status
1548   */
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1549 HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1550 {
1551   hhcd->hc[ch_num].hub_addr = 0U;
1552   hhcd->hc[ch_num].hub_port_nbr = 0U;
1553 
1554   return HAL_OK;
1555 }
1556 
1557 #if (USE_USB_DOUBLE_BUFFER == 1U)
1558 /**
1559   * @brief  Handle Host Channel OUT Double Buffer Bulk requests.
1560   * @param  hhcd HCD handle
1561   * @param  ch_num Channel number This parameter can be a value from 1 to 15
1562   * @param  phy_chnum Physical Channel number [0..7]
1563   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
1564   * @retval none
1565   */
HCD_HC_OUT_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1566 static void HCD_HC_OUT_BulkDb(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1567                               uint8_t phy_chnum, uint32_t regvalue)
1568 {
1569   uint16_t data_xfr;
1570   uint16_t len;
1571 
1572   /* Send Buffer0 */
1573   if ((regvalue & USB_CH_DTOG_TX) != 0U)
1574   {
1575     data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->TXBD & 0x03FF0000U) >> 16U);
1576 
1577     if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr)
1578     {
1579       hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
1580     }
1581     else
1582     {
1583       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1584     }
1585 
1586     /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
1587     if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
1588     {
1589       /* manage multiple Xfer */
1590       hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1591 
1592       /* check if we need to free user buffer */
1593       if ((regvalue & USB_CH_DTOG_RX) != 0U)
1594       {
1595         /* Toggle SwBuff */
1596         HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
1597         HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
1598         HCD_TX_DTOG(hhcd->Instance, phy_chnum);
1599       }
1600 
1601       /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
1602       if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
1603       {
1604         hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
1605 
1606         /* calculate len of new buffer to fill */
1607         if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
1608         {
1609           len = (uint16_t)hhcd->hc[ch_num & 0xFU].max_packet;
1610           hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
1611         }
1612         else
1613         {
1614           len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
1615           hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
1616         }
1617 
1618         /* Write remaining data to Buffer0 */
1619         HCD_SET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
1620         USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1621                      hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)len);
1622       }
1623       /* start a new transfer */
1624       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
1625     }
1626     else
1627     {
1628       /* Transfer complete state */
1629       hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1630       hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1631       hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1632       hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1633       /* Close the Channel */
1634       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
1635     }
1636   }
1637   else
1638   {
1639     /* Send Buffer1 */
1640     data_xfr = (uint16_t)(((USB_DRD_PMA_BUFF + phy_chnum)->RXBD & 0x03FF0000U) >> 16U);
1641 
1642     if (hhcd->hc[ch_num & 0xFU].xfer_len >= data_xfr) /* updated */
1643     {
1644       hhcd->hc[ch_num & 0xFU].xfer_len -= data_xfr;
1645     }
1646 
1647     /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
1648     if (hhcd->hc[ch_num & 0xFU].xfer_len != 0U)
1649     {
1650       /* manage multiple Xfer */
1651       hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1652 
1653       /* check if we need to free user buffer */
1654       if ((regvalue & USB_CH_DTOG_RX) == 0U)
1655       {
1656         /* Toggle SwBuff */
1657         HCD_CLEAR_TX_DTOG(hhcd->Instance, phy_chnum);
1658         HCD_CLEAR_RX_DTOG(hhcd->Instance, phy_chnum);
1659         HCD_RX_DTOG(hhcd->Instance, phy_chnum);
1660       }
1661 
1662       /* hhcd->hc[ch_num&0xFU].xfer_len_db==0 ==> when all data are written in the PMA to yet transferred */
1663       if (hhcd->hc[ch_num & 0xFU].xfer_len_db > 0U) /* Still data to fill in the buffer */
1664       {
1665         hhcd->hc[ch_num & 0xFU].xfer_buff += data_xfr;
1666 
1667         /* calculate len of new buffer to fill */
1668         if (hhcd->hc[ch_num & 0xFU].xfer_len_db > hhcd->hc[ch_num & 0xFU].max_packet)
1669         {
1670           len = hhcd->hc[ch_num & 0xFU].max_packet;
1671           hhcd->hc[ch_num & 0xFU].xfer_len_db -= len;
1672         }
1673         else
1674         {
1675           len = (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_len_db;
1676           hhcd->hc[ch_num & 0xFU].xfer_len_db = 0U; /* end of fill buffer */
1677         }
1678 
1679         /* Write remaining data to Buffer0 */
1680         HCD_SET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum, 1U, (uint16_t)len);
1681 
1682         USB_WritePMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1683                      hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)len);
1684       }
1685 
1686       /* start a new transfer */
1687       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_VALID);
1688     }
1689     else
1690     {
1691       /* Transfer complete state */
1692       hhcd->hc[ch_num & 0xFU].xfer_count += data_xfr;
1693       hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1694       hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1695       hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1696 
1697       /* Close the channel */
1698       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
1699     }
1700   }
1701 }
1702 
1703 
1704 /**
1705   * @brief  Handle Host Channel IN Double Buffer Bulk requests.
1706   * @param  hhcd HCD handle
1707   * @param  ch_num Channel number: This parameter can be a value from 1 to 15
1708   * @param  phy_chnum Physical Channel number [0..7]
1709   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
1710   * @retval none
1711   */
HCD_HC_IN_BulkDb(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1712 static void HCD_HC_IN_BulkDb(HCD_HandleTypeDef *hhcd,
1713                              uint8_t ch_num, uint8_t phy_chnum, uint32_t regvalue)
1714 {
1715   uint16_t received_bytes;
1716 
1717   /* Read from Buffer 0 */
1718   if ((regvalue & USB_CH_DTOG_RX) != 0U)
1719   {
1720     received_bytes = (uint16_t)HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
1721 
1722     if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1723     {
1724       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1725     }
1726     else
1727     {
1728       hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1729     }
1730 
1731     /* Check if we Need to free the other buffer for the IP */
1732     if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) != 0U))
1733     {
1734       /* Toggle SwBuff to Allow the IP to submit a new IN */
1735       HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
1736     }
1737 
1738     /* Read the byte from PMA to user Buffer(System Memory) */
1739     USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1740                 hhcd->hc[ch_num & 0xFU].pmaaddr0, (uint16_t)received_bytes);
1741   }
1742   else
1743   {
1744     /* Read from Buffer 1 */
1745     received_bytes = (uint16_t) HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
1746 
1747     if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1748     {
1749       hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1750     }
1751     else
1752     {
1753       hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1754     }
1755 
1756     /* Check if we Need to free the other buffer for the IP */
1757     if ((hhcd->hc[ch_num & 0xFU].xfer_len != 0U) && ((regvalue & USB_CH_DTOG_TX) == 0U))
1758     {
1759       /* Toggle SwBuff */
1760       HCD_FREE_USER_BUFFER(hhcd->Instance, phy_chnum, 0U);
1761     }
1762 
1763     /* Read the byte from PMA to user Buffer(System Memory) */
1764     USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1765                 hhcd->hc[ch_num & 0xFU].pmaaddr1, (uint16_t)received_bytes);
1766   }
1767 
1768   /* update the global number of all received bytes */
1769   hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
1770 
1771   /* Transfer complete state */
1772   hhcd->hc[ch_num & 0xFU].state = HC_ACK;
1773   hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1774 
1775   if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
1776       ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
1777   {
1778     hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1779     hhcd->hc[ch_num & 0xFU].state  = HC_XFRC;
1780 
1781     /* disable channel */
1782     HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1783   }
1784   else
1785   {
1786     hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
1787 
1788     /* Reactivate the Channel Submit an other URB since the Transfer is not yet completed */
1789     HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
1790   }
1791 }
1792 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1793 
1794 /**
1795   * @brief  Handle Host Channel IN Isochronous Transaction
1796   * @param  hhcd HCD handle
1797   * @param  ch_num Channel number: This parameter can be a value from 1 to 15
1798   * @param  phy_chnum Physical Channel number [0..7]
1799   * @param  regvalue contain Snapshot of the EPCHn register when ISR is detected
1800   * @retval none
1801   */
HCD_HC_IN_ISO(HCD_HandleTypeDef * hhcd,uint8_t ch_num,uint8_t phy_chnum,uint32_t regvalue)1802 static void inline HCD_HC_IN_ISO(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
1803                                  uint8_t phy_chnum, uint32_t regvalue)
1804 {
1805   /* Check if Double buffer isochronous */
1806   if ((regvalue & USB_CH_KIND) != 0U)
1807   {
1808     /* Get Data IN Packet */
1809     hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
1810     if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1811     {
1812       USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1813                   hhcd->hc[ch_num & 0xFU].pmaadress,
1814                   (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1815 
1816       hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1817     }
1818   }
1819 #if (USE_USB_DOUBLE_BUFFER == 1U)
1820   else  /* double buffer isochronous */
1821   {
1822     /* Read from Buffer0 */
1823     if ((regvalue & USB_CH_DTOG_RX) != 0U)
1824     {
1825       /* Get number of Received byte in buffer0 */
1826       hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF0_CNT(hhcd->Instance, phy_chnum);
1827 
1828       if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1829       {
1830         /* Read from Buffer0 */
1831         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1832                     hhcd->hc[ch_num & 0xFU].pmaaddr0,
1833                     (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1834 
1835         hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1836       }
1837     }
1838     else
1839     {
1840       /* Get number of Received byte in buffer1 */
1841       hhcd->hc[ch_num & 0xFU].xfer_count = HCD_GET_CH_DBUF1_CNT(hhcd->Instance, phy_chnum);
1842 
1843       if (hhcd->hc[ch_num & 0xFU].xfer_count != 0U)
1844       {
1845         /* Read from Buffer1 */
1846         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1847                     hhcd->hc[ch_num & 0xFU].pmaaddr1,
1848                     (uint16_t)hhcd->hc[ch_num & 0xFU].xfer_count);
1849 
1850         hhcd->hc[ch_num & 0xFU].urb_state = URB_DONE;
1851       }
1852     }
1853   }
1854 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1855 
1856   /* Transfer complete state */
1857   hhcd->hc[ch_num & 0xFU].state = HC_XFRC;
1858 
1859   /* Clear VTRX */
1860   HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
1861 }
1862 
1863 /**
1864   * @brief  Handle Host Channel IN interrupt requests.
1865   * @param  hhcd HCD handle
1866   * @param  ch_num Channel number
1867   *         This parameter can be a value from 1 to 15
1868   * @retval none
1869   */
HCD_HC_IN_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t ch_num)1870 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
1871 {
1872   uint16_t received_bytes;
1873   uint8_t phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
1874 
1875   /*Take a Flag snapshot from the CHEP register, due to STRX bits are used for both control and status */
1876   uint32_t ch_reg =  HCD_GET_CHANNEL(hhcd->Instance, phy_chnum);
1877 
1878   /* Manage Correct Transaction */
1879   if ((ch_reg & USB_CH_ERRRX) == 0U)
1880   {
1881     /* Isochronous Channel */
1882     if ((ch_reg & USB_CH_UTYPE) == USB_EP_ISOCHRONOUS)
1883     {
1884       HCD_HC_IN_ISO(hhcd, ch_num, phy_chnum, ch_reg);
1885     }
1886     else
1887     {
1888       /* manage ACK response single buffer */
1889       if (((ch_reg) & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF)
1890       {
1891         /* Get Control Data OUT Packet */
1892         received_bytes = (uint16_t)HCD_GET_CH_RX_CNT(hhcd->Instance, phy_chnum);
1893 
1894         /* Read the byte from PMA to user Buffer(System Memory) */
1895         USB_ReadPMA(hhcd->Instance, hhcd->hc[ch_num & 0xFU].xfer_buff,
1896                     hhcd->hc[ch_num & 0xFU].pmaadress, (uint16_t)received_bytes);
1897 
1898         /* update the global number of all received bytes */
1899         hhcd->hc[ch_num & 0xFU].xfer_count += received_bytes;
1900 
1901         /* Transfer complete state */
1902         hhcd->hc[ch_num & 0xFU].state = HC_ACK;
1903         hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1904 
1905         if (hhcd->hc[ch_num & 0xFU].xfer_len <= received_bytes)
1906         {
1907           hhcd->hc[ch_num & 0xFU].xfer_len = 0U;
1908         }
1909         else
1910         {
1911           hhcd->hc[ch_num & 0xFU].xfer_len -= received_bytes;
1912         }
1913 
1914         if ((hhcd->hc[ch_num & 0xFU].xfer_len == 0U) ||
1915             ((received_bytes < hhcd->hc[ch_num & 0xFU].max_packet)))
1916         {
1917           hhcd->hc[ch_num & 0xFU].urb_state  = URB_DONE;
1918           hhcd->hc[ch_num & 0xFU].state  = HC_XFRC;
1919         }
1920         else
1921         {
1922           hhcd->hc[ch_num & 0xFU].xfer_buff += received_bytes;
1923 
1924           /* Reactivate the Channel to Submit another URB since the Transfer is not yet completed */
1925           HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_STRX);
1926         }
1927 
1928         if ((hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_BULK) ||
1929             (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR))
1930         {
1931           hhcd->hc[ch_num & 0xFU].toggle_out ^= 1U;
1932         }
1933       }
1934       /* manage NACK Response */
1935       else if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK)
1936                && (hhcd->hc[ch_num & 0xFU].urb_state != URB_DONE))
1937       {
1938         hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
1939         hhcd->hc[ch_num & 0xFU].ErrCnt = 0U;
1940         hhcd->hc[ch_num & 0xFU].state = HC_NAK;
1941 
1942         if (hhcd->hc[ch_num & 0xFU].ep_type == EP_TYPE_INTR)
1943         {
1944           /* Close the channel */
1945           HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1946         }
1947       }
1948       /* manage STALL Response */
1949       else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL)
1950       {
1951         (void)HAL_HCD_HC_Halt(hhcd, ch_num);
1952         hhcd->hc[ch_num & 0xFU].state = HC_STALL;
1953         hhcd->hc[ch_num & 0xFU].urb_state = URB_STALL;
1954 
1955         /* Close the channel */
1956         HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1957       }
1958 #if (USE_USB_DOUBLE_BUFFER == 1U)
1959       /* Double Buffer Management in case of Bulk Transaction */
1960       else  if (((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_DBUF)
1961                 && ((ch_reg & USB_CH_KIND) != 0U))
1962       {
1963         /* Bulk IN Double Buffer ISR */
1964         HCD_HC_IN_BulkDb(hhcd, ch_num, phy_chnum, ch_reg);
1965       }
1966 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1967       else
1968       {
1969         /*....*/
1970         /* not defined state: STRX=11 in single buffer no iso is not defined */
1971       }
1972 
1973 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1974       hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
1975 #else
1976       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
1977 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1978 
1979       /*Clear VTRX */
1980       HCD_CLEAR_RX_CH_CTR(hhcd->Instance, phy_chnum);
1981     }
1982   }
1983   else   /* Error detected during last transaction */
1984   {
1985     /* Set URB Error State */
1986     hhcd->hc[ch_num & 0xFU].urb_state = URB_NOTREADY;
1987     hhcd->hc[ch_num & 0xFU].ErrCnt++;
1988     hhcd->hc[ch_num & 0xFU].state = HC_XACTERR;
1989 
1990     /* Clear VTTRX & ERR_RX */
1991     HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
1992 
1993     /* Check Error number */
1994     if (hhcd->hc[ch_num & 0xFU].ErrCnt > 3U)
1995     {
1996       hhcd->hc[ch_num & 0xFU].urb_state = URB_ERROR;
1997       HCD_SET_CH_RX_STATUS(hhcd->Instance, phy_chnum, USB_CH_RX_DIS);
1998 
1999       /* Clear pending err_tx */
2000       HCD_CLEAR_RX_CH_ERR(hhcd->Instance, phy_chnum);
2001     }
2002 
2003 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2004     hhcd->HC_NotifyURBChangeCallback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2005 #else
2006     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, ch_num, hhcd->hc[ch_num & 0xFU].urb_state);
2007 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
2008   }
2009 }
2010 
2011 
2012 /**
2013   * @brief  Handle Host Channel OUT interrupt requests.
2014   * @param  hhcd  HCD handle
2015   * @param  chnum Channel number
2016   *         This parameter can be a value from 1 to 15
2017   * @retval none
2018   */
HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef * hhcd,uint8_t chnum)2019 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
2020 {
2021   uint16_t data_xfr;
2022   __IO uint32_t WregCh;
2023 
2024   /* Get Physical Channel number */
2025   uint32_t phy_chnum = (uint8_t)__HAL_HCD_GET_CHNUM(hhcd);
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[chnum & 0xFU].state = HC_XFRC;
2064         hhcd->hc[chnum & 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)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2073 #else
2074       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 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[chnum & 0xFU].xfer_len >= data_xfr)
2086         {
2087           hhcd->hc[chnum & 0xFU].xfer_len -= data_xfr;
2088         }
2089         else
2090         {
2091           hhcd->hc[chnum & 0xFU].xfer_len = 0U;
2092         }
2093 
2094         /* Transfer no yet finished only one packet of mps is transferred and ACKed from device */
2095         if (hhcd->hc[chnum & 0xFU].xfer_len != 0U)
2096         {
2097           /* manage multiple Xfer */
2098           hhcd->hc[chnum & 0xFU].xfer_buff += data_xfr;
2099           hhcd->hc[chnum & 0xFU].xfer_count += data_xfr;
2100 
2101           /* start a new transfer */
2102           (void) USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[chnum & 0xFU]);
2103         }
2104         else
2105         {
2106           /* Transfer complete */
2107           hhcd->hc[chnum & 0xFU].xfer_count += data_xfr;
2108           hhcd->hc[chnum & 0xFU].state = HC_XFRC;
2109           hhcd->hc[chnum & 0xFU].urb_state = URB_DONE;
2110 
2111           if ((hhcd->hc[chnum & 0xFU].ep_type == EP_TYPE_BULK) ||
2112               (hhcd->hc[chnum & 0xFU].ep_type == EP_TYPE_INTR))
2113           {
2114             hhcd->hc[chnum & 0xFU].toggle_out ^= 1U;
2115           }
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[chnum & 0xFU].state = HC_NAK;
2124         hhcd->hc[chnum & 0xFU].urb_state = URB_NOTREADY;
2125         hhcd->hc[chnum & 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[chnum & 0xFU].doublebuffer == 0U)
2137         {
2138 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
2139           hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2140 #else
2141           HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 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)chnum);
2149         hhcd->hc[chnum & 0xFU].state = HC_STALL;
2150         hhcd->hc[chnum & 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, chnum, (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)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2169 #else
2170         HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 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[chnum & 0xFU].ErrCnt++;
2181     if (hhcd->hc[chnum & 0xFU].ErrCnt > 3U)
2182     {
2183       HCD_SET_CH_TX_STATUS(hhcd->Instance, phy_chnum, USB_CH_TX_DIS);
2184       hhcd->hc[chnum & 0xFU].urb_state = URB_ERROR;
2185     }
2186     else
2187     {
2188       hhcd->hc[chnum & 0xFU].urb_state = URB_NOTREADY;
2189     }
2190 
2191     hhcd->hc[chnum & 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)chnum, hhcd->hc[chnum & 0xFU].urb_state);
2198 #else
2199     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)chnum, hhcd->hc[chnum & 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 = ch_num;
2651         hhcd->ep0_PmaAllocState |= (1U << 8);
2652       }
2653 
2654       /* Configure the PMA */
2655       if (hc->ch_dir == CH_IN_DIR)
2656       {
2657         hc->pmaaddr1 = pma_addr0;
2658         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = hc->pmaaddr1;
2659 
2660         if (hc->ep_num == 0U)
2661         {
2662           hhcd->ep0_PmaAllocState |= (CH_IN_DIR << 4);
2663         }
2664       }
2665       else
2666       {
2667         hc->pmaaddr0 = pma_addr0;
2668         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = hc->pmaaddr0;
2669       }
2670 
2671       /* Set the PmaAddress */
2672       hc->pmaadress = pma_addr0;
2673     }
2674 #if (USE_USB_DOUBLE_BUFFER == 1U)
2675     else /* USB_DBL_BUF */
2676     {
2677       /* Double Buffer Endpoint */
2678       hc->doublebuffer = 1U;
2679 
2680       /* Get a FreePMA Address for buffer 2 */
2681       pma_addr1 = HAL_HCD_GetFreePMA(hhcd, mps);
2682 
2683       if (pma_addr1 == 0xFFFFU)
2684       {
2685         /* Free the first buffer */
2686         (void)HAL_HCD_PMAFree(hhcd, pma_addr0, mps);
2687         return HAL_ERROR;
2688       }
2689       else
2690       {
2691         /* Configure the PMA */
2692         hc->pmaaddr0 = (uint16_t)(pma_addr0);
2693         hc->pmaaddr1 = (uint16_t)(pma_addr1);
2694 
2695         /* Set Buffer0 pma address */
2696         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->TXBD = pma_addr0;
2697 
2698         /* Set Buffer1 pma address */
2699         (USB_DRD_PMA_BUFF + hc->phy_ch_num)->RXBD = pma_addr1;
2700 
2701         /* Used for Bulk DB MPS < 64bytes */
2702         if (hc->ch_dir == CH_IN_DIR)
2703         {
2704           hc->pmaadress = hc->pmaaddr1;
2705         }
2706         else
2707         {
2708           hc->pmaadress = hc->pmaaddr0;
2709         }
2710       }
2711     }
2712 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2713   }
2714 
2715   return HAL_OK;
2716 }
2717 
2718 /**
2719   * @brief  PMA De-Allocation for Channel Free the reserved block in the PMA-LookupTable
2720   * @param  hhcd  Host instance
2721   * @param  ch_num Channel number
2722   * @retval HAL status
2723   */
HAL_HCD_PMADeAlloc(HCD_HandleTypeDef * hhcd,uint8_t ch_num)2724 HAL_StatusTypeDef  HAL_HCD_PMADeAlloc(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
2725 {
2726   HAL_StatusTypeDef status;
2727 
2728 #if (USE_USB_DOUBLE_BUFFER == 1U)
2729   uint8_t Err = 0U;
2730 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2731 
2732   /* Host Channel */
2733   HCD_HCTypeDef *hc = &(hhcd->hc[ch_num]);
2734 
2735   /* Single Buffer */
2736   if (hc->doublebuffer == 0U)
2737   {
2738     status = HAL_HCD_PMAFree(hhcd, hc->pmaadress, hc->max_packet);
2739   }
2740   else   /* Double buffer */
2741   {
2742 #if (USE_USB_DOUBLE_BUFFER == 1U)
2743     status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr0, hc->max_packet);
2744     if (status != HAL_OK)
2745     {
2746       Err++;
2747     }
2748 
2749     status = HAL_HCD_PMAFree(hhcd, hc->pmaaddr1, hc->max_packet);
2750     if (status != HAL_OK)
2751     {
2752       Err++;
2753     }
2754 
2755     if (Err != 0U)
2756     {
2757       return HAL_ERROR;
2758     }
2759 #else
2760     status = HAL_ERROR;
2761 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2762   }
2763 
2764   return status;
2765 }
2766 
2767 
2768 /**
2769   * @brief  PMA Reset
2770   * @param  hhcd  Host instance
2771   * @retval HAL status
2772   */
HAL_HCD_PMAReset(HCD_HandleTypeDef * hhcd)2773 HAL_StatusTypeDef  HAL_HCD_PMAReset(HCD_HandleTypeDef *hhcd)
2774 {
2775   /* Reset All PMA Entry */
2776   for (uint8_t i = 0U; i < PMA_BLOCKS; i++)
2777   {
2778     hhcd->PMALookupTable[i] = 0U;
2779   }
2780 
2781   /* Allocate a Space for buffer descriptor table depending on the Host channel number */
2782   for (uint8_t i = 0U; i < hhcd->Init.Host_channels; i++)
2783   {
2784     hhcd->PMALookupTable[0] |= ((uint32_t)1U << i);
2785   }
2786 
2787   return HAL_OK;
2788 }
2789 
2790 /**
2791   * @brief  PMA Free
2792   * @param  hhcd   Host instance
2793   * @param  pma_base PMA base offset stored in hhcd->hc.pmaaddr
2794   * @param  mps  Max Packet Size
2795   * @retval HAL status
2796   */
HAL_HCD_PMAFree(HCD_HandleTypeDef * hhcd,uint32_t pma_base,uint16_t mps)2797 static HAL_StatusTypeDef  HAL_HCD_PMAFree(HCD_HandleTypeDef *hhcd, uint32_t pma_base, uint16_t mps)
2798 {
2799   uint32_t block_nbr;
2800   uint8_t ColIndex;
2801   uint8_t LineIndex;
2802   uint16_t mps_t = mps;
2803 
2804   /* since PMA buffer descriptor RXBD allocate address according to BLSIZE, BLSIZE=1==> mps>64
2805     allocation in PMA is done in 32Bytes each entry */
2806   if ((mps_t > 64U) && ((mps_t % 32U) != 0U))
2807   {
2808     /* Align the mps to 32byte block to match the allocation in PMA,
2809       check Definition of allocation buffer memory in usb user spec */
2810     mps_t = (uint16_t)(((mps_t / 32U) + 1U) * 32U);
2811   }
2812 
2813   /* Calculate the number of needed block to Free */
2814   if ((mps_t / 8U) != 0U)
2815   {
2816     block_nbr = ((uint32_t)mps_t / 8U);
2817 
2818     if ((mps_t % 8U) != 0U)
2819     {
2820       block_nbr++;
2821     }
2822   }
2823   else
2824   {
2825     block_nbr = 1U;
2826   }
2827 
2828   /* Decode Col/Line of PMA_Base position in the PMA_LookupTable */
2829   if (pma_base > 256U)
2830   {
2831     LineIndex = (uint8_t)(pma_base / 256U);
2832     ColIndex = (uint8_t)((pma_base - ((uint32_t)LineIndex * 256U)) / 8U);
2833   }
2834   else
2835   {
2836     LineIndex = 0U;
2837     ColIndex = (uint8_t)(pma_base / 8U);
2838   }
2839 
2840   /* Reset the corresponding bit in the lookupTable */
2841   for (uint8_t i = LineIndex; ((i < PMA_BLOCKS) && (block_nbr > 0U)); i++)
2842   {
2843     for (uint8_t j = ColIndex; j <= 31U; j++)
2844     {
2845       /* Check if the block is not already reserved or it was already closed */
2846       if ((hhcd->PMALookupTable[i] & ((uint32_t)1U << j)) == 0U)
2847       {
2848         return HAL_ERROR;
2849       }
2850       /* Free the reserved block by resetting the corresponding bit */
2851       hhcd->PMALookupTable[i] &= ~(1U << j);
2852 
2853       if (--block_nbr == 0U)
2854       {
2855         break;
2856       }
2857     }
2858     ColIndex = 0U;
2859   }
2860 
2861   return HAL_OK;
2862 }
2863 
2864 /**
2865   * @}
2866   */
2867 
2868 /**
2869   * @}
2870   */
2871 #endif /* defined (USB_DRD_FS) */
2872 #endif /* HAL_HCD_MODULE_ENABLED */
2873 
2874 /**
2875   * @}
2876   */
2877 
2878 /**
2879   * @}
2880   */
2881