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