STM32H735xx HAL User Manual
stm32h7xx_hal_hcd.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h7xx_hal_hcd.c
00004   * @author  MCD Application Team
00005   * @brief   HCD HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the USB Peripheral Controller:
00008   *           + Initialization and de-initialization functions
00009   *           + IO operation functions
00010   *           + Peripheral Control functions
00011   *           + Peripheral State functions
00012   *
00013   ******************************************************************************
00014   * @attention
00015   *
00016   * Copyright (c) 2017 STMicroelectronics.
00017   * All rights reserved.
00018   *
00019   * This software is licensed under terms that can be found in the LICENSE file
00020   * in the root directory of this software component.
00021   * If no LICENSE file comes with this software, it is provided AS-IS.
00022   *
00023   ******************************************************************************
00024   @verbatim
00025   ==============================================================================
00026                     ##### How to use this driver #####
00027   ==============================================================================
00028   [..]
00029     (#)Declare a HCD_HandleTypeDef handle structure, for example:
00030        HCD_HandleTypeDef  hhcd;
00031 
00032     (#)Fill parameters of Init structure in HCD handle
00033 
00034     (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
00035 
00036     (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
00037         (##) Enable the HCD/USB Low Level interface clock using the following macros
00038              (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
00039              (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
00040              (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
00041 
00042         (##) Initialize the related GPIO clocks
00043         (##) Configure HCD pin-out
00044         (##) Configure HCD NVIC interrupt
00045 
00046     (#)Associate the Upper USB Host stack to the HAL HCD Driver:
00047         (##) hhcd.pData = phost;
00048 
00049     (#)Enable HCD transmission and reception:
00050         (##) HAL_HCD_Start();
00051 
00052   @endverbatim
00053   ******************************************************************************
00054   */
00055 
00056 /* Includes ------------------------------------------------------------------*/
00057 #include "stm32h7xx_hal.h"
00058 
00059 /** @addtogroup STM32H7xx_HAL_Driver
00060   * @{
00061   */
00062 
00063 #ifdef HAL_HCD_MODULE_ENABLED
00064 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
00065 
00066 /** @defgroup HCD HCD
00067   * @brief HCD HAL module driver
00068   * @{
00069   */
00070 
00071 /* Private typedef -----------------------------------------------------------*/
00072 /* Private define ------------------------------------------------------------*/
00073 /* Private macro -------------------------------------------------------------*/
00074 /* Private variables ---------------------------------------------------------*/
00075 /* Private function prototypes -----------------------------------------------*/
00076 /** @defgroup HCD_Private_Functions HCD Private Functions
00077   * @{
00078   */
00079 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
00080 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
00081 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
00082 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
00083 /**
00084   * @}
00085   */
00086 
00087 /* Exported functions --------------------------------------------------------*/
00088 /** @defgroup HCD_Exported_Functions HCD Exported Functions
00089   * @{
00090   */
00091 
00092 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
00093   *  @brief    Initialization and Configuration functions
00094   *
00095 @verbatim
00096  ===============================================================================
00097           ##### Initialization and de-initialization functions #####
00098  ===============================================================================
00099     [..]  This section provides functions allowing to:
00100 
00101 @endverbatim
00102   * @{
00103   */
00104 
00105 /**
00106   * @brief  Initialize the host driver.
00107   * @param  hhcd HCD handle
00108   * @retval HAL status
00109   */
00110 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
00111 {
00112   USB_OTG_GlobalTypeDef *USBx;
00113 
00114   /* Check the HCD handle allocation */
00115   if (hhcd == NULL)
00116   {
00117     return HAL_ERROR;
00118   }
00119 
00120   /* Check the parameters */
00121   assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
00122 
00123   USBx = hhcd->Instance;
00124 
00125   if (hhcd->State == HAL_HCD_STATE_RESET)
00126   {
00127     /* Allocate lock resource and initialize it */
00128     hhcd->Lock = HAL_UNLOCKED;
00129 
00130 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
00131     hhcd->SOFCallback = HAL_HCD_SOF_Callback;
00132     hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
00133     hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
00134     hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
00135     hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
00136     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
00137 
00138     if (hhcd->MspInitCallback == NULL)
00139     {
00140       hhcd->MspInitCallback = HAL_HCD_MspInit;
00141     }
00142 
00143     /* Init the low level hardware */
00144     hhcd->MspInitCallback(hhcd);
00145 #else
00146     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
00147     HAL_HCD_MspInit(hhcd);
00148 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
00149   }
00150 
00151   hhcd->State = HAL_HCD_STATE_BUSY;
00152 
00153   /* Disable DMA mode for FS instance */
00154   if ((USBx->CID & (0x1U << 8)) == 0U)
00155   {
00156     hhcd->Init.dma_enable = 0U;
00157   }
00158 
00159   /* Disable the Interrupts */
00160   __HAL_HCD_DISABLE(hhcd);
00161 
00162   /* Init the Core (common init.) */
00163   (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
00164 
00165   /* Force Host Mode*/
00166   (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
00167 
00168   /* Init Host */
00169   (void)USB_HostInit(hhcd->Instance, hhcd->Init);
00170 
00171   hhcd->State = HAL_HCD_STATE_READY;
00172 
00173   return HAL_OK;
00174 }
00175 
00176 /**
00177   * @brief  Initialize a host channel.
00178   * @param  hhcd HCD handle
00179   * @param  ch_num Channel number.
00180   *         This parameter can be a value from 1 to 15
00181   * @param  epnum Endpoint number.
00182   *          This parameter can be a value from 1 to 15
00183   * @param  dev_address Current device address
00184   *          This parameter can be a value from 0 to 255
00185   * @param  speed Current device speed.
00186   *          This parameter can be one of these values:
00187   *            HCD_DEVICE_SPEED_HIGH: High speed mode,
00188   *            HCD_DEVICE_SPEED_FULL: Full speed mode,
00189   *            HCD_DEVICE_SPEED_LOW: Low speed mode
00190   * @param  ep_type Endpoint Type.
00191   *          This parameter can be one of these values:
00192   *            EP_TYPE_CTRL: Control type,
00193   *            EP_TYPE_ISOC: Isochronous type,
00194   *            EP_TYPE_BULK: Bulk type,
00195   *            EP_TYPE_INTR: Interrupt type
00196   * @param  mps Max Packet Size.
00197   *          This parameter can be a value from 0 to32K
00198   * @retval HAL status
00199   */
00200 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd,
00201                                   uint8_t ch_num,
00202                                   uint8_t epnum,
00203                                   uint8_t dev_address,
00204                                   uint8_t speed,
00205                                   uint8_t ep_type,
00206                                   uint16_t mps)
00207 {
00208   HAL_StatusTypeDef status;
00209 
00210   __HAL_LOCK(hhcd);
00211   hhcd->hc[ch_num].do_ping = 0U;
00212   hhcd->hc[ch_num].dev_addr = dev_address;
00213   hhcd->hc[ch_num].max_packet = mps;
00214   hhcd->hc[ch_num].ch_num = ch_num;
00215   hhcd->hc[ch_num].ep_type = ep_type;
00216   hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
00217 
00218   if ((epnum & 0x80U) == 0x80U)
00219   {
00220     hhcd->hc[ch_num].ep_is_in = 1U;
00221   }
00222   else
00223   {
00224     hhcd->hc[ch_num].ep_is_in = 0U;
00225   }
00226 
00227   hhcd->hc[ch_num].speed = speed;
00228 
00229   status =  USB_HC_Init(hhcd->Instance,
00230                         ch_num,
00231                         epnum,
00232                         dev_address,
00233                         speed,
00234                         ep_type,
00235                         mps);
00236   __HAL_UNLOCK(hhcd);
00237 
00238   return status;
00239 }
00240 
00241 /**
00242   * @brief  Halt a host channel.
00243   * @param  hhcd HCD handle
00244   * @param  ch_num Channel number.
00245   *         This parameter can be a value from 1 to 15
00246   * @retval HAL status
00247   */
00248 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
00249 {
00250   HAL_StatusTypeDef status = HAL_OK;
00251 
00252   __HAL_LOCK(hhcd);
00253   (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
00254   __HAL_UNLOCK(hhcd);
00255 
00256   return status;
00257 }
00258 
00259 /**
00260   * @brief  DeInitialize the host driver.
00261   * @param  hhcd HCD handle
00262   * @retval HAL status
00263   */
00264 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
00265 {
00266   /* Check the HCD handle allocation */
00267   if (hhcd == NULL)
00268   {
00269     return HAL_ERROR;
00270   }
00271 
00272   hhcd->State = HAL_HCD_STATE_BUSY;
00273 
00274 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
00275   if (hhcd->MspDeInitCallback == NULL)
00276   {
00277     hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit  */
00278   }
00279 
00280   /* DeInit the low level hardware */
00281   hhcd->MspDeInitCallback(hhcd);
00282 #else
00283   /* DeInit the low level hardware: CLOCK, NVIC.*/
00284   HAL_HCD_MspDeInit(hhcd);
00285 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
00286 
00287   __HAL_HCD_DISABLE(hhcd);
00288 
00289   hhcd->State = HAL_HCD_STATE_RESET;
00290 
00291   return HAL_OK;
00292 }
00293 
00294 /**
00295   * @brief  Initialize the HCD MSP.
00296   * @param  hhcd HCD handle
00297   * @retval None
00298   */
00299 __weak void  HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
00300 {
00301   /* Prevent unused argument(s) compilation warning */
00302   UNUSED(hhcd);
00303 
00304   /* NOTE : This function should not be modified, when the callback is needed,
00305             the HAL_HCD_MspInit could be implemented in the user file
00306    */
00307 }
00308 
00309 /**
00310   * @brief  DeInitialize the HCD MSP.
00311   * @param  hhcd HCD handle
00312   * @retval None
00313   */
00314 __weak void  HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
00315 {
00316   /* Prevent unused argument(s) compilation warning */
00317   UNUSED(hhcd);
00318 
00319   /* NOTE : This function should not be modified, when the callback is needed,
00320             the HAL_HCD_MspDeInit could be implemented in the user file
00321    */
00322 }
00323 
00324 /**
00325   * @}
00326   */
00327 
00328 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
00329   *  @brief   HCD IO operation functions
00330   *
00331 @verbatim
00332  ===============================================================================
00333                       ##### IO operation functions #####
00334  ===============================================================================
00335  [..] This subsection provides a set of functions allowing to manage the USB Host Data
00336     Transfer
00337 
00338 @endverbatim
00339   * @{
00340   */
00341 
00342 /**
00343   * @brief  Submit a new URB for processing.
00344   * @param  hhcd HCD handle
00345   * @param  ch_num Channel number.
00346   *         This parameter can be a value from 1 to 15
00347   * @param  direction Channel number.
00348   *          This parameter can be one of these values:
00349   *           0 : Output / 1 : Input
00350   * @param  ep_type Endpoint Type.
00351   *          This parameter can be one of these values:
00352   *            EP_TYPE_CTRL: Control type/
00353   *            EP_TYPE_ISOC: Isochronous type/
00354   *            EP_TYPE_BULK: Bulk type/
00355   *            EP_TYPE_INTR: Interrupt type/
00356   * @param  token Endpoint Type.
00357   *          This parameter can be one of these values:
00358   *            0: HC_PID_SETUP / 1: HC_PID_DATA1
00359   * @param  pbuff pointer to URB data
00360   * @param  length Length of URB data
00361   * @param  do_ping activate do ping protocol (for high speed only).
00362   *          This parameter can be one of these values:
00363   *           0 : do ping inactive / 1 : do ping active
00364   * @retval HAL status
00365   */
00366 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
00367                                            uint8_t ch_num,
00368                                            uint8_t direction,
00369                                            uint8_t ep_type,
00370                                            uint8_t token,
00371                                            uint8_t *pbuff,
00372                                            uint16_t length,
00373                                            uint8_t do_ping)
00374 {
00375   hhcd->hc[ch_num].ep_is_in = direction;
00376   hhcd->hc[ch_num].ep_type  = ep_type;
00377 
00378   if (token == 0U)
00379   {
00380     hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
00381     hhcd->hc[ch_num].do_ping = do_ping;
00382   }
00383   else
00384   {
00385     hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
00386   }
00387 
00388   /* Manage Data Toggle */
00389   switch (ep_type)
00390   {
00391     case EP_TYPE_CTRL:
00392       if ((token == 1U) && (direction == 0U)) /*send data */
00393       {
00394         if (length == 0U)
00395         {
00396           /* For Status OUT stage, Length==0, Status Out PID = 1 */
00397           hhcd->hc[ch_num].toggle_out = 1U;
00398         }
00399 
00400         /* Set the Data Toggle bit as per the Flag */
00401         if (hhcd->hc[ch_num].toggle_out == 0U)
00402         {
00403           /* Put the PID 0 */
00404           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
00405         }
00406         else
00407         {
00408           /* Put the PID 1 */
00409           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
00410         }
00411       }
00412       break;
00413 
00414     case EP_TYPE_BULK:
00415       if (direction == 0U)
00416       {
00417         /* Set the Data Toggle bit as per the Flag */
00418         if (hhcd->hc[ch_num].toggle_out == 0U)
00419         {
00420           /* Put the PID 0 */
00421           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
00422         }
00423         else
00424         {
00425           /* Put the PID 1 */
00426           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
00427         }
00428       }
00429       else
00430       {
00431         if (hhcd->hc[ch_num].toggle_in == 0U)
00432         {
00433           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
00434         }
00435         else
00436         {
00437           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
00438         }
00439       }
00440 
00441       break;
00442     case EP_TYPE_INTR:
00443       if (direction == 0U)
00444       {
00445         /* Set the Data Toggle bit as per the Flag */
00446         if (hhcd->hc[ch_num].toggle_out == 0U)
00447         {
00448           /* Put the PID 0 */
00449           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
00450         }
00451         else
00452         {
00453           /* Put the PID 1 */
00454           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
00455         }
00456       }
00457       else
00458       {
00459         if (hhcd->hc[ch_num].toggle_in == 0U)
00460         {
00461           hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
00462         }
00463         else
00464         {
00465           hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
00466         }
00467       }
00468       break;
00469 
00470     case EP_TYPE_ISOC:
00471       hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
00472       break;
00473 
00474     default:
00475       break;
00476   }
00477 
00478   hhcd->hc[ch_num].xfer_buff = pbuff;
00479   hhcd->hc[ch_num].xfer_len  = length;
00480   hhcd->hc[ch_num].urb_state = URB_IDLE;
00481   hhcd->hc[ch_num].xfer_count = 0U;
00482   hhcd->hc[ch_num].ch_num = ch_num;
00483   hhcd->hc[ch_num].state = HC_IDLE;
00484 
00485   return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable);
00486 }
00487 
00488 /**
00489   * @brief  Handle HCD interrupt request.
00490   * @param  hhcd HCD handle
00491   * @retval None
00492   */
00493 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
00494 {
00495   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
00496   uint32_t USBx_BASE = (uint32_t)USBx;
00497   uint32_t i;
00498   uint32_t interrupt;
00499 
00500   /* Ensure that we are in device mode */
00501   if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
00502   {
00503     /* Avoid spurious interrupt */
00504     if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
00505     {
00506       return;
00507     }
00508 
00509     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
00510     {
00511       /* Incorrect mode, acknowledge the interrupt */
00512       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
00513     }
00514 
00515     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
00516     {
00517       /* Incorrect mode, acknowledge the interrupt */
00518       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
00519     }
00520 
00521     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
00522     {
00523       /* Incorrect mode, acknowledge the interrupt */
00524       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
00525     }
00526 
00527     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
00528     {
00529       /* Incorrect mode, acknowledge the interrupt */
00530       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
00531     }
00532 
00533     /* Handle Host Disconnect Interrupts */
00534     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
00535     {
00536       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
00537 
00538       if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
00539       {
00540         /* Flush USB Fifo */
00541         (void)USB_FlushTxFifo(USBx, 0x10U);
00542         (void)USB_FlushRxFifo(USBx);
00543 
00544         /* Restore FS Clock */
00545         (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
00546 
00547         /* Handle Host Port Disconnect Interrupt */
00548 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
00549         hhcd->DisconnectCallback(hhcd);
00550 #else
00551         HAL_HCD_Disconnect_Callback(hhcd);
00552 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
00553       }
00554     }
00555 
00556     /* Handle Host Port Interrupts */
00557     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
00558     {
00559       HCD_Port_IRQHandler(hhcd);
00560     }
00561 
00562     /* Handle Host SOF Interrupt */
00563     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
00564     {
00565 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
00566       hhcd->SOFCallback(hhcd);
00567 #else
00568       HAL_HCD_SOF_Callback(hhcd);
00569 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
00570 
00571       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
00572     }
00573 
00574     /* Handle Rx Queue Level Interrupts */
00575     if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
00576     {
00577       USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
00578 
00579       HCD_RXQLVL_IRQHandler(hhcd);
00580 
00581       USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
00582     }
00583 
00584     /* Handle Host channel Interrupt */
00585     if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
00586     {
00587       interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
00588       for (i = 0U; i < hhcd->Init.Host_channels; i++)
00589       {
00590         if ((interrupt & (1UL << (i & 0xFU))) != 0U)
00591         {
00592           if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
00593           {
00594             HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
00595           }
00596           else
00597           {
00598             HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
00599           }
00600         }
00601       }
00602       __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
00603     }
00604   }
00605 }
00606 
00607 
00608 /**
00609   * @brief  SOF callback.
00610   * @param  hhcd HCD handle
00611   * @retval None
00612   */
00613 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
00614 {
00615   /* Prevent unused argument(s) compilation warning */
00616   UNUSED(hhcd);
00617 
00618   /* NOTE : This function should not be modified, when the callback is needed,
00619             the HAL_HCD_SOF_Callback could be implemented in the user file
00620    */
00621 }
00622 
00623 /**
00624   * @brief Connection Event callback.
00625   * @param  hhcd HCD handle
00626   * @retval None
00627   */
00628 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
00629 {
00630   /* Prevent unused argument(s) compilation warning */
00631   UNUSED(hhcd);
00632 
00633   /* NOTE : This function should not be modified, when the callback is needed,
00634             the HAL_HCD_Connect_Callback could be implemented in the user file
00635    */
00636 }
00637 
00638 /**
00639   * @brief  Disconnection Event callback.
00640   * @param  hhcd HCD handle
00641   * @retval None
00642   */
00643 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
00644 {
00645   /* Prevent unused argument(s) compilation warning */
00646   UNUSED(hhcd);
00647 
00648   /* NOTE : This function should not be modified, when the callback is needed,
00649             the HAL_HCD_Disconnect_Callback could be implemented in the user file
00650    */
00651 }
00652 
00653 /**
00654   * @brief  Port Enabled  Event callback.
00655   * @param  hhcd HCD handle
00656   * @retval None
00657   */
00658 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
00659 {
00660   /* Prevent unused argument(s) compilation warning */
00661   UNUSED(hhcd);
00662 
00663   /* NOTE : This function should not be modified, when the callback is needed,
00664             the HAL_HCD_Disconnect_Callback could be implemented in the user file
00665    */
00666 }
00667 
00668 /**
00669   * @brief  Port Disabled  Event callback.
00670   * @param  hhcd HCD handle
00671   * @retval None
00672   */
00673 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
00674 {
00675   /* Prevent unused argument(s) compilation warning */
00676   UNUSED(hhcd);
00677 
00678   /* NOTE : This function should not be modified, when the callback is needed,
00679             the HAL_HCD_Disconnect_Callback could be implemented in the user file
00680    */
00681 }
00682 
00683 /**
00684   * @brief  Notify URB state change callback.
00685   * @param  hhcd HCD handle
00686   * @param  chnum Channel number.
00687   *         This parameter can be a value from 1 to 15
00688   * @param  urb_state:
00689   *          This parameter can be one of these values:
00690   *            URB_IDLE/
00691   *            URB_DONE/
00692   *            URB_NOTREADY/
00693   *            URB_NYET/
00694   *            URB_ERROR/
00695   *            URB_STALL/
00696   * @retval None
00697   */
00698 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
00699 {
00700   /* Prevent unused argument(s) compilation warning */
00701   UNUSED(hhcd);
00702   UNUSED(chnum);
00703   UNUSED(urb_state);
00704 
00705   /* NOTE : This function should not be modified, when the callback is needed,
00706             the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
00707    */
00708 }
00709 
00710 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
00711 /**
00712   * @brief  Register a User USB HCD Callback
00713   *         To be used instead of the weak predefined callback
00714   * @param  hhcd USB HCD handle
00715   * @param  CallbackID ID of the callback to be registered
00716   *         This parameter can be one of the following values:
00717   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
00718   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
00719   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
00720   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
00721   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
00722   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
00723   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
00724   * @param  pCallback pointer to the Callback function
00725   * @retval HAL status
00726   */
00727 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
00728                                            HAL_HCD_CallbackIDTypeDef CallbackID,
00729                                            pHCD_CallbackTypeDef pCallback)
00730 {
00731   HAL_StatusTypeDef status = HAL_OK;
00732 
00733   if (pCallback == NULL)
00734   {
00735     /* Update the error code */
00736     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00737     return HAL_ERROR;
00738   }
00739   /* Process locked */
00740   __HAL_LOCK(hhcd);
00741 
00742   if (hhcd->State == HAL_HCD_STATE_READY)
00743   {
00744     switch (CallbackID)
00745     {
00746       case HAL_HCD_SOF_CB_ID :
00747         hhcd->SOFCallback = pCallback;
00748         break;
00749 
00750       case HAL_HCD_CONNECT_CB_ID :
00751         hhcd->ConnectCallback = pCallback;
00752         break;
00753 
00754       case HAL_HCD_DISCONNECT_CB_ID :
00755         hhcd->DisconnectCallback = pCallback;
00756         break;
00757 
00758       case HAL_HCD_PORT_ENABLED_CB_ID :
00759         hhcd->PortEnabledCallback = pCallback;
00760         break;
00761 
00762       case HAL_HCD_PORT_DISABLED_CB_ID :
00763         hhcd->PortDisabledCallback = pCallback;
00764         break;
00765 
00766       case HAL_HCD_MSPINIT_CB_ID :
00767         hhcd->MspInitCallback = pCallback;
00768         break;
00769 
00770       case HAL_HCD_MSPDEINIT_CB_ID :
00771         hhcd->MspDeInitCallback = pCallback;
00772         break;
00773 
00774       default :
00775         /* Update the error code */
00776         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00777         /* Return error status */
00778         status =  HAL_ERROR;
00779         break;
00780     }
00781   }
00782   else if (hhcd->State == HAL_HCD_STATE_RESET)
00783   {
00784     switch (CallbackID)
00785     {
00786       case HAL_HCD_MSPINIT_CB_ID :
00787         hhcd->MspInitCallback = pCallback;
00788         break;
00789 
00790       case HAL_HCD_MSPDEINIT_CB_ID :
00791         hhcd->MspDeInitCallback = pCallback;
00792         break;
00793 
00794       default :
00795         /* Update the error code */
00796         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00797         /* Return error status */
00798         status =  HAL_ERROR;
00799         break;
00800     }
00801   }
00802   else
00803   {
00804     /* Update the error code */
00805     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00806     /* Return error status */
00807     status =  HAL_ERROR;
00808   }
00809 
00810   /* Release Lock */
00811   __HAL_UNLOCK(hhcd);
00812   return status;
00813 }
00814 
00815 /**
00816   * @brief  Unregister an USB HCD Callback
00817   *         USB HCD callback is redirected to the weak predefined callback
00818   * @param  hhcd USB HCD handle
00819   * @param  CallbackID ID of the callback to be unregistered
00820   *         This parameter can be one of the following values:
00821   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
00822   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
00823   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
00824   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
00825   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
00826   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
00827   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
00828   * @retval HAL status
00829   */
00830 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
00831 {
00832   HAL_StatusTypeDef status = HAL_OK;
00833 
00834   /* Process locked */
00835   __HAL_LOCK(hhcd);
00836 
00837   /* Setup Legacy weak Callbacks  */
00838   if (hhcd->State == HAL_HCD_STATE_READY)
00839   {
00840     switch (CallbackID)
00841     {
00842       case HAL_HCD_SOF_CB_ID :
00843         hhcd->SOFCallback = HAL_HCD_SOF_Callback;
00844         break;
00845 
00846       case HAL_HCD_CONNECT_CB_ID :
00847         hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
00848         break;
00849 
00850       case HAL_HCD_DISCONNECT_CB_ID :
00851         hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
00852         break;
00853 
00854       case HAL_HCD_PORT_ENABLED_CB_ID :
00855         hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
00856         break;
00857 
00858       case HAL_HCD_PORT_DISABLED_CB_ID :
00859         hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
00860         break;
00861 
00862       case HAL_HCD_MSPINIT_CB_ID :
00863         hhcd->MspInitCallback = HAL_HCD_MspInit;
00864         break;
00865 
00866       case HAL_HCD_MSPDEINIT_CB_ID :
00867         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
00868         break;
00869 
00870       default :
00871         /* Update the error code */
00872         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00873 
00874         /* Return error status */
00875         status =  HAL_ERROR;
00876         break;
00877     }
00878   }
00879   else if (hhcd->State == HAL_HCD_STATE_RESET)
00880   {
00881     switch (CallbackID)
00882     {
00883       case HAL_HCD_MSPINIT_CB_ID :
00884         hhcd->MspInitCallback = HAL_HCD_MspInit;
00885         break;
00886 
00887       case HAL_HCD_MSPDEINIT_CB_ID :
00888         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
00889         break;
00890 
00891       default :
00892         /* Update the error code */
00893         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00894 
00895         /* Return error status */
00896         status =  HAL_ERROR;
00897         break;
00898     }
00899   }
00900   else
00901   {
00902     /* Update the error code */
00903     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00904 
00905     /* Return error status */
00906     status =  HAL_ERROR;
00907   }
00908 
00909   /* Release Lock */
00910   __HAL_UNLOCK(hhcd);
00911   return status;
00912 }
00913 
00914 /**
00915   * @brief  Register USB HCD Host Channel Notify URB Change Callback
00916   *         To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
00917   * @param  hhcd HCD handle
00918   * @param  pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
00919   * @retval HAL status
00920   */
00921 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
00922                                                              pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
00923 {
00924   HAL_StatusTypeDef status = HAL_OK;
00925 
00926   if (pCallback == NULL)
00927   {
00928     /* Update the error code */
00929     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00930 
00931     return HAL_ERROR;
00932   }
00933 
00934   /* Process locked */
00935   __HAL_LOCK(hhcd);
00936 
00937   if (hhcd->State == HAL_HCD_STATE_READY)
00938   {
00939     hhcd->HC_NotifyURBChangeCallback = pCallback;
00940   }
00941   else
00942   {
00943     /* Update the error code */
00944     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00945 
00946     /* Return error status */
00947     status =  HAL_ERROR;
00948   }
00949 
00950   /* Release Lock */
00951   __HAL_UNLOCK(hhcd);
00952 
00953   return status;
00954 }
00955 
00956 /**
00957   * @brief  Unregister the USB HCD Host Channel Notify URB Change Callback
00958   *         USB HCD Host Channel Notify URB Change Callback is redirected
00959   *         to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
00960   * @param  hhcd HCD handle
00961   * @retval HAL status
00962   */
00963 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
00964 {
00965   HAL_StatusTypeDef status = HAL_OK;
00966 
00967   /* Process locked */
00968   __HAL_LOCK(hhcd);
00969 
00970   if (hhcd->State == HAL_HCD_STATE_READY)
00971   {
00972     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback  */
00973   }
00974   else
00975   {
00976     /* Update the error code */
00977     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00978 
00979     /* Return error status */
00980     status =  HAL_ERROR;
00981   }
00982 
00983   /* Release Lock */
00984   __HAL_UNLOCK(hhcd);
00985 
00986   return status;
00987 }
00988 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
00989 
00990 /**
00991   * @}
00992   */
00993 
00994 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
00995   *  @brief   Management functions
00996   *
00997 @verbatim
00998  ===============================================================================
00999                       ##### Peripheral Control functions #####
01000  ===============================================================================
01001     [..]
01002     This subsection provides a set of functions allowing to control the HCD data
01003     transfers.
01004 
01005 @endverbatim
01006   * @{
01007   */
01008 
01009 /**
01010   * @brief  Start the host driver.
01011   * @param  hhcd HCD handle
01012   * @retval HAL status
01013   */
01014 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
01015 {
01016   __HAL_LOCK(hhcd);
01017   /* Enable port power */
01018   (void)USB_DriveVbus(hhcd->Instance, 1U);
01019 
01020   /* Enable global interrupt */
01021   __HAL_HCD_ENABLE(hhcd);
01022   __HAL_UNLOCK(hhcd);
01023 
01024   return HAL_OK;
01025 }
01026 
01027 /**
01028   * @brief  Stop the host driver.
01029   * @param  hhcd HCD handle
01030   * @retval HAL status
01031   */
01032 
01033 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
01034 {
01035   __HAL_LOCK(hhcd);
01036   (void)USB_StopHost(hhcd->Instance);
01037   __HAL_UNLOCK(hhcd);
01038 
01039   return HAL_OK;
01040 }
01041 
01042 /**
01043   * @brief  Reset the host port.
01044   * @param  hhcd HCD handle
01045   * @retval HAL status
01046   */
01047 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
01048 {
01049   return (USB_ResetPort(hhcd->Instance));
01050 }
01051 
01052 /**
01053   * @}
01054   */
01055 
01056 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
01057   *  @brief   Peripheral State functions
01058   *
01059 @verbatim
01060  ===============================================================================
01061                       ##### Peripheral State functions #####
01062  ===============================================================================
01063     [..]
01064     This subsection permits to get in run-time the status of the peripheral
01065     and the data flow.
01066 
01067 @endverbatim
01068   * @{
01069   */
01070 
01071 /**
01072   * @brief  Return the HCD handle state.
01073   * @param  hhcd HCD handle
01074   * @retval HAL state
01075   */
01076 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
01077 {
01078   return hhcd->State;
01079 }
01080 
01081 /**
01082   * @brief  Return  URB state for a channel.
01083   * @param  hhcd HCD handle
01084   * @param  chnum Channel number.
01085   *         This parameter can be a value from 1 to 15
01086   * @retval URB state.
01087   *          This parameter can be one of these values:
01088   *            URB_IDLE/
01089   *            URB_DONE/
01090   *            URB_NOTREADY/
01091   *            URB_NYET/
01092   *            URB_ERROR/
01093   *            URB_STALL
01094   */
01095 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01096 {
01097   return hhcd->hc[chnum].urb_state;
01098 }
01099 
01100 
01101 /**
01102   * @brief  Return the last host transfer size.
01103   * @param  hhcd HCD handle
01104   * @param  chnum Channel number.
01105   *         This parameter can be a value from 1 to 15
01106   * @retval last transfer size in byte
01107   */
01108 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01109 {
01110   return hhcd->hc[chnum].xfer_count;
01111 }
01112 
01113 /**
01114   * @brief  Return the Host Channel state.
01115   * @param  hhcd HCD handle
01116   * @param  chnum Channel number.
01117   *         This parameter can be a value from 1 to 15
01118   * @retval Host channel state
01119   *          This parameter can be one of these values:
01120   *            HC_IDLE/
01121   *            HC_XFRC/
01122   *            HC_HALTED/
01123   *            HC_NYET/
01124   *            HC_NAK/
01125   *            HC_STALL/
01126   *            HC_XACTERR/
01127   *            HC_BBLERR/
01128   *            HC_DATATGLERR
01129   */
01130 HCD_HCStateTypeDef  HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01131 {
01132   return hhcd->hc[chnum].state;
01133 }
01134 
01135 /**
01136   * @brief  Return the current Host frame number.
01137   * @param  hhcd HCD handle
01138   * @retval Current Host frame number
01139   */
01140 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
01141 {
01142   return (USB_GetCurrentFrame(hhcd->Instance));
01143 }
01144 
01145 /**
01146   * @brief  Return the Host enumeration speed.
01147   * @param  hhcd HCD handle
01148   * @retval Enumeration speed
01149   */
01150 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
01151 {
01152   return (USB_GetHostSpeed(hhcd->Instance));
01153 }
01154 
01155 /**
01156   * @}
01157   */
01158 
01159 /**
01160   * @}
01161   */
01162 
01163 /** @addtogroup HCD_Private_Functions
01164   * @{
01165   */
01166 /**
01167   * @brief  Handle Host Channel IN interrupt requests.
01168   * @param  hhcd HCD handle
01169   * @param  chnum Channel number.
01170   *         This parameter can be a value from 1 to 15
01171   * @retval none
01172   */
01173 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01174 {
01175   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
01176   uint32_t USBx_BASE = (uint32_t)USBx;
01177   uint32_t ch_num = (uint32_t)chnum;
01178 
01179   uint32_t tmpreg;
01180 
01181   if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
01182   {
01183     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
01184     hhcd->hc[ch_num].state = HC_XACTERR;
01185     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01186   }
01187   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR)
01188   {
01189     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
01190     hhcd->hc[ch_num].state = HC_BBLERR;
01191     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01192   }
01193   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
01194   {
01195     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
01196   }
01197   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
01198   {
01199     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
01200     hhcd->hc[ch_num].state = HC_STALL;
01201     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01202   }
01203   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
01204   {
01205     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
01206     hhcd->hc[ch_num].state = HC_DATATGLERR;
01207     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01208   }
01209   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
01210   {
01211     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
01212     hhcd->hc[ch_num].state = HC_XACTERR;
01213     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01214   }
01215   else
01216   {
01217     /* ... */
01218   }
01219 
01220   if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
01221   {
01222     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01223     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
01224   }
01225   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
01226   {
01227     if (hhcd->Init.dma_enable != 0U)
01228     {
01229       hhcd->hc[ch_num].xfer_count = hhcd->hc[ch_num].XferSize - \
01230                                     (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
01231     }
01232 
01233     hhcd->hc[ch_num].state = HC_XFRC;
01234     hhcd->hc[ch_num].ErrCnt = 0U;
01235     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
01236 
01237     if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
01238         (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
01239     {
01240       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01241       __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01242     }
01243     else if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
01244     {
01245       USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
01246       hhcd->hc[ch_num].urb_state = URB_DONE;
01247 
01248 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01249       hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01250 #else
01251       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01252 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01253     }
01254     else if (hhcd->hc[ch_num].ep_type == EP_TYPE_ISOC)
01255     {
01256       hhcd->hc[ch_num].urb_state = URB_DONE;
01257       hhcd->hc[ch_num].toggle_in ^= 1U;
01258 
01259 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01260       hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01261 #else
01262       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01263 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01264     }
01265     else
01266     {
01267       /* ... */
01268     }
01269 
01270     if (hhcd->Init.dma_enable == 1U)
01271     {
01272       if (((hhcd->hc[ch_num].XferSize / hhcd->hc[ch_num].max_packet) & 1U) != 0U)
01273       {
01274         hhcd->hc[ch_num].toggle_in ^= 1U;
01275       }
01276     }
01277     else
01278     {
01279       hhcd->hc[ch_num].toggle_in ^= 1U;
01280     }
01281   }
01282   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
01283   {
01284     if (hhcd->hc[ch_num].state == HC_XFRC)
01285     {
01286       hhcd->hc[ch_num].urb_state = URB_DONE;
01287     }
01288     else if (hhcd->hc[ch_num].state == HC_STALL)
01289     {
01290       hhcd->hc[ch_num].urb_state = URB_STALL;
01291     }
01292     else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
01293              (hhcd->hc[ch_num].state == HC_DATATGLERR))
01294     {
01295       hhcd->hc[ch_num].ErrCnt++;
01296       if (hhcd->hc[ch_num].ErrCnt > 2U)
01297       {
01298         hhcd->hc[ch_num].ErrCnt = 0U;
01299         hhcd->hc[ch_num].urb_state = URB_ERROR;
01300       }
01301       else
01302       {
01303         hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01304 
01305         /* re-activate the channel */
01306         tmpreg = USBx_HC(ch_num)->HCCHAR;
01307         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
01308         tmpreg |= USB_OTG_HCCHAR_CHENA;
01309         USBx_HC(ch_num)->HCCHAR = tmpreg;
01310       }
01311     }
01312     else if (hhcd->hc[ch_num].state == HC_NAK)
01313     {
01314       hhcd->hc[ch_num].urb_state  = URB_NOTREADY;
01315 
01316       /* re-activate the channel */
01317       tmpreg = USBx_HC(ch_num)->HCCHAR;
01318       tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
01319       tmpreg |= USB_OTG_HCCHAR_CHENA;
01320       USBx_HC(ch_num)->HCCHAR = tmpreg;
01321     }
01322     else if (hhcd->hc[ch_num].state == HC_BBLERR)
01323     {
01324       hhcd->hc[ch_num].ErrCnt++;
01325       hhcd->hc[ch_num].urb_state = URB_ERROR;
01326     }
01327     else
01328     {
01329       /* ... */
01330     }
01331     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
01332 
01333 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01334     hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01335 #else
01336     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01337 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01338   }
01339   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
01340   {
01341     if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
01342     {
01343       hhcd->hc[ch_num].ErrCnt = 0U;
01344       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01345     }
01346     else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
01347              (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
01348     {
01349       hhcd->hc[ch_num].ErrCnt = 0U;
01350 
01351       if (hhcd->Init.dma_enable == 0U)
01352       {
01353         hhcd->hc[ch_num].state = HC_NAK;
01354         (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01355       }
01356     }
01357     else
01358     {
01359       /* ... */
01360     }
01361     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01362   }
01363   else
01364   {
01365     /* ... */
01366   }
01367 }
01368 
01369 /**
01370   * @brief  Handle Host Channel OUT interrupt requests.
01371   * @param  hhcd HCD handle
01372   * @param  chnum Channel number.
01373   *         This parameter can be a value from 1 to 15
01374   * @retval none
01375   */
01376 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01377 {
01378   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
01379   uint32_t USBx_BASE = (uint32_t)USBx;
01380   uint32_t ch_num = (uint32_t)chnum;
01381   uint32_t tmpreg;
01382   uint32_t num_packets;
01383 
01384   if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
01385   {
01386     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
01387     hhcd->hc[ch_num].state = HC_XACTERR;
01388     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01389   }
01390   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
01391   {
01392     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
01393 
01394     if (hhcd->hc[ch_num].do_ping == 1U)
01395     {
01396       hhcd->hc[ch_num].do_ping = 0U;
01397       hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01398       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01399     }
01400   }
01401   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
01402   {
01403     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
01404     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01405   }
01406   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
01407   {
01408     hhcd->hc[ch_num].ErrCnt = 0U;
01409 
01410     /* transaction completed with NYET state, update do ping state */
01411     if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET)
01412     {
01413       hhcd->hc[ch_num].do_ping = 1U;
01414       __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
01415     }
01416     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
01417     hhcd->hc[ch_num].state = HC_XFRC;
01418     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01419   }
01420   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET)
01421   {
01422     hhcd->hc[ch_num].state = HC_NYET;
01423     hhcd->hc[ch_num].do_ping = 1U;
01424     hhcd->hc[ch_num].ErrCnt = 0U;
01425     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01426     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
01427   }
01428   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
01429   {
01430     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
01431     hhcd->hc[ch_num].state = HC_STALL;
01432     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01433   }
01434   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
01435   {
01436     hhcd->hc[ch_num].ErrCnt = 0U;
01437     hhcd->hc[ch_num].state = HC_NAK;
01438 
01439     if (hhcd->hc[ch_num].do_ping == 0U)
01440     {
01441       if (hhcd->hc[ch_num].speed == HCD_DEVICE_SPEED_HIGH)
01442       {
01443         hhcd->hc[ch_num].do_ping = 1U;
01444       }
01445     }
01446 
01447     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01448     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01449   }
01450   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
01451   {
01452     if (hhcd->Init.dma_enable == 0U)
01453     {
01454       hhcd->hc[ch_num].state = HC_XACTERR;
01455       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01456     }
01457     else
01458     {
01459       hhcd->hc[ch_num].ErrCnt++;
01460       if (hhcd->hc[ch_num].ErrCnt > 2U)
01461       {
01462         hhcd->hc[ch_num].ErrCnt = 0U;
01463         hhcd->hc[ch_num].urb_state = URB_ERROR;
01464 
01465 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01466         hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01467 #else
01468         HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01469 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01470       }
01471       else
01472       {
01473         hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01474       }
01475     }
01476     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
01477   }
01478   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
01479   {
01480     hhcd->hc[ch_num].state = HC_DATATGLERR;
01481     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01482     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
01483   }
01484   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
01485   {
01486     if (hhcd->hc[ch_num].state == HC_XFRC)
01487     {
01488       hhcd->hc[ch_num].urb_state  = URB_DONE;
01489       if ((hhcd->hc[ch_num].ep_type == EP_TYPE_BULK) ||
01490           (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR))
01491       {
01492         if (hhcd->Init.dma_enable == 0U)
01493         {
01494           hhcd->hc[ch_num].toggle_out ^= 1U;
01495         }
01496 
01497         if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[ch_num].xfer_len > 0U))
01498         {
01499           num_packets = (hhcd->hc[ch_num].xfer_len + hhcd->hc[ch_num].max_packet - 1U) / hhcd->hc[ch_num].max_packet;
01500 
01501           if ((num_packets & 1U) != 0U)
01502           {
01503             hhcd->hc[ch_num].toggle_out ^= 1U;
01504           }
01505         }
01506       }
01507     }
01508     else if (hhcd->hc[ch_num].state == HC_NAK)
01509     {
01510       hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01511     }
01512     else if (hhcd->hc[ch_num].state == HC_NYET)
01513     {
01514       hhcd->hc[ch_num].urb_state  = URB_NOTREADY;
01515     }
01516     else if (hhcd->hc[ch_num].state == HC_STALL)
01517     {
01518       hhcd->hc[ch_num].urb_state  = URB_STALL;
01519     }
01520     else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
01521              (hhcd->hc[ch_num].state == HC_DATATGLERR))
01522     {
01523       hhcd->hc[ch_num].ErrCnt++;
01524       if (hhcd->hc[ch_num].ErrCnt > 2U)
01525       {
01526         hhcd->hc[ch_num].ErrCnt = 0U;
01527         hhcd->hc[ch_num].urb_state = URB_ERROR;
01528       }
01529       else
01530       {
01531         hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01532 
01533         /* re-activate the channel  */
01534         tmpreg = USBx_HC(ch_num)->HCCHAR;
01535         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
01536         tmpreg |= USB_OTG_HCCHAR_CHENA;
01537         USBx_HC(ch_num)->HCCHAR = tmpreg;
01538       }
01539     }
01540     else
01541     {
01542       /* ... */
01543     }
01544 
01545     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
01546 
01547 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01548     hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01549 #else
01550     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01551 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01552   }
01553   else
01554   {
01555     /* ... */
01556   }
01557 }
01558 
01559 /**
01560   * @brief  Handle Rx Queue Level interrupt requests.
01561   * @param  hhcd HCD handle
01562   * @retval none
01563   */
01564 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
01565 {
01566   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
01567   uint32_t USBx_BASE = (uint32_t)USBx;
01568   uint32_t pktsts;
01569   uint32_t pktcnt;
01570   uint32_t GrxstspReg;
01571   uint32_t xferSizePktCnt;
01572   uint32_t tmpreg;
01573   uint32_t ch_num;
01574 
01575   GrxstspReg = hhcd->Instance->GRXSTSP;
01576   ch_num = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
01577   pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
01578   pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
01579 
01580   switch (pktsts)
01581   {
01582     case GRXSTS_PKTSTS_IN:
01583       /* Read the data into the host buffer. */
01584       if ((pktcnt > 0U) && (hhcd->hc[ch_num].xfer_buff != (void *)0))
01585       {
01586         if ((hhcd->hc[ch_num].xfer_count + pktcnt) <= hhcd->hc[ch_num].xfer_len)
01587         {
01588           (void)USB_ReadPacket(hhcd->Instance,
01589                                hhcd->hc[ch_num].xfer_buff, (uint16_t)pktcnt);
01590 
01591           /* manage multiple Xfer */
01592           hhcd->hc[ch_num].xfer_buff += pktcnt;
01593           hhcd->hc[ch_num].xfer_count += pktcnt;
01594 
01595           /* get transfer size packet count */
01596           xferSizePktCnt = (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
01597 
01598           if ((hhcd->hc[ch_num].max_packet == pktcnt) && (xferSizePktCnt > 0U))
01599           {
01600             /* re-activate the channel when more packets are expected */
01601             tmpreg = USBx_HC(ch_num)->HCCHAR;
01602             tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
01603             tmpreg |= USB_OTG_HCCHAR_CHENA;
01604             USBx_HC(ch_num)->HCCHAR = tmpreg;
01605             hhcd->hc[ch_num].toggle_in ^= 1U;
01606           }
01607         }
01608         else
01609         {
01610           hhcd->hc[ch_num].urb_state = URB_ERROR;
01611         }
01612       }
01613       break;
01614 
01615     case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
01616       break;
01617 
01618     case GRXSTS_PKTSTS_IN_XFER_COMP:
01619     case GRXSTS_PKTSTS_CH_HALTED:
01620     default:
01621       break;
01622   }
01623 }
01624 
01625 /**
01626   * @brief  Handle Host Port interrupt requests.
01627   * @param  hhcd HCD handle
01628   * @retval None
01629   */
01630 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
01631 {
01632   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
01633   uint32_t USBx_BASE = (uint32_t)USBx;
01634   __IO uint32_t hprt0;
01635   __IO uint32_t hprt0_dup;
01636 
01637   /* Handle Host Port Interrupts */
01638   hprt0 = USBx_HPRT0;
01639   hprt0_dup = USBx_HPRT0;
01640 
01641   hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
01642                  USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
01643 
01644   /* Check whether Port Connect detected */
01645   if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
01646   {
01647     if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
01648     {
01649 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01650       hhcd->ConnectCallback(hhcd);
01651 #else
01652       HAL_HCD_Connect_Callback(hhcd);
01653 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01654     }
01655     hprt0_dup |= USB_OTG_HPRT_PCDET;
01656   }
01657 
01658   /* Check whether Port Enable Changed */
01659   if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
01660   {
01661     hprt0_dup |= USB_OTG_HPRT_PENCHNG;
01662 
01663     if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
01664     {
01665       if (hhcd->Init.phy_itface  == USB_OTG_EMBEDDED_PHY)
01666       {
01667         if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
01668         {
01669           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
01670         }
01671         else
01672         {
01673           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
01674         }
01675       }
01676       else
01677       {
01678         if (hhcd->Init.speed == HCD_SPEED_FULL)
01679         {
01680           USBx_HOST->HFIR = 60000U;
01681         }
01682       }
01683 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01684       hhcd->PortEnabledCallback(hhcd);
01685 #else
01686       HAL_HCD_PortEnabled_Callback(hhcd);
01687 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01688 
01689     }
01690     else
01691     {
01692 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01693       hhcd->PortDisabledCallback(hhcd);
01694 #else
01695       HAL_HCD_PortDisabled_Callback(hhcd);
01696 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01697     }
01698   }
01699 
01700   /* Check for an overcurrent */
01701   if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
01702   {
01703     hprt0_dup |= USB_OTG_HPRT_POCCHNG;
01704   }
01705 
01706   /* Clear Port Interrupts */
01707   USBx_HPRT0 = hprt0_dup;
01708 }
01709 
01710 /**
01711   * @}
01712   */
01713 
01714 /**
01715   * @}
01716   */
01717 
01718 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
01719 #endif /* HAL_HCD_MODULE_ENABLED */
01720 
01721 /**
01722   * @}
01723   */
01724 
01725 /**
01726   * @}
01727   */