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