STM32F479xx HAL User Manual
stm32f4xx_hal_hcd.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f4xx_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) 2016 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 "stm32f4xx_hal.h"
00058 
00059 /** @addtogroup STM32F4xx_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  Handles HCD Wakeup interrupt request.
00610   * @param  hhcd HCD handle
00611   * @retval HAL status
00612   */
00613 void HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef *hhcd)
00614 {
00615   UNUSED(hhcd);
00616 }
00617 
00618 
00619 /**
00620   * @brief  SOF callback.
00621   * @param  hhcd HCD handle
00622   * @retval None
00623   */
00624 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
00625 {
00626   /* Prevent unused argument(s) compilation warning */
00627   UNUSED(hhcd);
00628 
00629   /* NOTE : This function should not be modified, when the callback is needed,
00630             the HAL_HCD_SOF_Callback could be implemented in the user file
00631    */
00632 }
00633 
00634 /**
00635   * @brief Connection Event callback.
00636   * @param  hhcd HCD handle
00637   * @retval None
00638   */
00639 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
00640 {
00641   /* Prevent unused argument(s) compilation warning */
00642   UNUSED(hhcd);
00643 
00644   /* NOTE : This function should not be modified, when the callback is needed,
00645             the HAL_HCD_Connect_Callback could be implemented in the user file
00646    */
00647 }
00648 
00649 /**
00650   * @brief  Disconnection Event callback.
00651   * @param  hhcd HCD handle
00652   * @retval None
00653   */
00654 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
00655 {
00656   /* Prevent unused argument(s) compilation warning */
00657   UNUSED(hhcd);
00658 
00659   /* NOTE : This function should not be modified, when the callback is needed,
00660             the HAL_HCD_Disconnect_Callback could be implemented in the user file
00661    */
00662 }
00663 
00664 /**
00665   * @brief  Port Enabled  Event callback.
00666   * @param  hhcd HCD handle
00667   * @retval None
00668   */
00669 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
00670 {
00671   /* Prevent unused argument(s) compilation warning */
00672   UNUSED(hhcd);
00673 
00674   /* NOTE : This function should not be modified, when the callback is needed,
00675             the HAL_HCD_Disconnect_Callback could be implemented in the user file
00676    */
00677 }
00678 
00679 /**
00680   * @brief  Port Disabled  Event callback.
00681   * @param  hhcd HCD handle
00682   * @retval None
00683   */
00684 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
00685 {
00686   /* Prevent unused argument(s) compilation warning */
00687   UNUSED(hhcd);
00688 
00689   /* NOTE : This function should not be modified, when the callback is needed,
00690             the HAL_HCD_Disconnect_Callback could be implemented in the user file
00691    */
00692 }
00693 
00694 /**
00695   * @brief  Notify URB state change callback.
00696   * @param  hhcd HCD handle
00697   * @param  chnum Channel number.
00698   *         This parameter can be a value from 1 to 15
00699   * @param  urb_state:
00700   *          This parameter can be one of these values:
00701   *            URB_IDLE/
00702   *            URB_DONE/
00703   *            URB_NOTREADY/
00704   *            URB_NYET/
00705   *            URB_ERROR/
00706   *            URB_STALL/
00707   * @retval None
00708   */
00709 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
00710 {
00711   /* Prevent unused argument(s) compilation warning */
00712   UNUSED(hhcd);
00713   UNUSED(chnum);
00714   UNUSED(urb_state);
00715 
00716   /* NOTE : This function should not be modified, when the callback is needed,
00717             the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
00718    */
00719 }
00720 
00721 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
00722 /**
00723   * @brief  Register a User USB HCD Callback
00724   *         To be used instead of the weak predefined callback
00725   * @param  hhcd USB HCD handle
00726   * @param  CallbackID ID of the callback to be registered
00727   *         This parameter can be one of the following values:
00728   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
00729   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
00730   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
00731   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
00732   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
00733   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
00734   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
00735   * @param  pCallback pointer to the Callback function
00736   * @retval HAL status
00737   */
00738 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
00739                                            HAL_HCD_CallbackIDTypeDef CallbackID,
00740                                            pHCD_CallbackTypeDef pCallback)
00741 {
00742   HAL_StatusTypeDef status = HAL_OK;
00743 
00744   if (pCallback == NULL)
00745   {
00746     /* Update the error code */
00747     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00748     return HAL_ERROR;
00749   }
00750   /* Process locked */
00751   __HAL_LOCK(hhcd);
00752 
00753   if (hhcd->State == HAL_HCD_STATE_READY)
00754   {
00755     switch (CallbackID)
00756     {
00757       case HAL_HCD_SOF_CB_ID :
00758         hhcd->SOFCallback = pCallback;
00759         break;
00760 
00761       case HAL_HCD_CONNECT_CB_ID :
00762         hhcd->ConnectCallback = pCallback;
00763         break;
00764 
00765       case HAL_HCD_DISCONNECT_CB_ID :
00766         hhcd->DisconnectCallback = pCallback;
00767         break;
00768 
00769       case HAL_HCD_PORT_ENABLED_CB_ID :
00770         hhcd->PortEnabledCallback = pCallback;
00771         break;
00772 
00773       case HAL_HCD_PORT_DISABLED_CB_ID :
00774         hhcd->PortDisabledCallback = pCallback;
00775         break;
00776 
00777       case HAL_HCD_MSPINIT_CB_ID :
00778         hhcd->MspInitCallback = pCallback;
00779         break;
00780 
00781       case HAL_HCD_MSPDEINIT_CB_ID :
00782         hhcd->MspDeInitCallback = pCallback;
00783         break;
00784 
00785       default :
00786         /* Update the error code */
00787         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00788         /* Return error status */
00789         status =  HAL_ERROR;
00790         break;
00791     }
00792   }
00793   else if (hhcd->State == HAL_HCD_STATE_RESET)
00794   {
00795     switch (CallbackID)
00796     {
00797       case HAL_HCD_MSPINIT_CB_ID :
00798         hhcd->MspInitCallback = pCallback;
00799         break;
00800 
00801       case HAL_HCD_MSPDEINIT_CB_ID :
00802         hhcd->MspDeInitCallback = pCallback;
00803         break;
00804 
00805       default :
00806         /* Update the error code */
00807         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00808         /* Return error status */
00809         status =  HAL_ERROR;
00810         break;
00811     }
00812   }
00813   else
00814   {
00815     /* Update the error code */
00816     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00817     /* Return error status */
00818     status =  HAL_ERROR;
00819   }
00820 
00821   /* Release Lock */
00822   __HAL_UNLOCK(hhcd);
00823   return status;
00824 }
00825 
00826 /**
00827   * @brief  Unregister an USB HCD Callback
00828   *         USB HCD callback is redirected to the weak predefined callback
00829   * @param  hhcd USB HCD handle
00830   * @param  CallbackID ID of the callback to be unregistered
00831   *         This parameter can be one of the following values:
00832   *          @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
00833   *          @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
00834   *          @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
00835   *          @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
00836   *          @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
00837   *          @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
00838   *          @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
00839   * @retval HAL status
00840   */
00841 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
00842 {
00843   HAL_StatusTypeDef status = HAL_OK;
00844 
00845   /* Process locked */
00846   __HAL_LOCK(hhcd);
00847 
00848   /* Setup Legacy weak Callbacks  */
00849   if (hhcd->State == HAL_HCD_STATE_READY)
00850   {
00851     switch (CallbackID)
00852     {
00853       case HAL_HCD_SOF_CB_ID :
00854         hhcd->SOFCallback = HAL_HCD_SOF_Callback;
00855         break;
00856 
00857       case HAL_HCD_CONNECT_CB_ID :
00858         hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
00859         break;
00860 
00861       case HAL_HCD_DISCONNECT_CB_ID :
00862         hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
00863         break;
00864 
00865       case HAL_HCD_PORT_ENABLED_CB_ID :
00866         hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
00867         break;
00868 
00869       case HAL_HCD_PORT_DISABLED_CB_ID :
00870         hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
00871         break;
00872 
00873       case HAL_HCD_MSPINIT_CB_ID :
00874         hhcd->MspInitCallback = HAL_HCD_MspInit;
00875         break;
00876 
00877       case HAL_HCD_MSPDEINIT_CB_ID :
00878         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
00879         break;
00880 
00881       default :
00882         /* Update the error code */
00883         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00884 
00885         /* Return error status */
00886         status =  HAL_ERROR;
00887         break;
00888     }
00889   }
00890   else if (hhcd->State == HAL_HCD_STATE_RESET)
00891   {
00892     switch (CallbackID)
00893     {
00894       case HAL_HCD_MSPINIT_CB_ID :
00895         hhcd->MspInitCallback = HAL_HCD_MspInit;
00896         break;
00897 
00898       case HAL_HCD_MSPDEINIT_CB_ID :
00899         hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
00900         break;
00901 
00902       default :
00903         /* Update the error code */
00904         hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00905 
00906         /* Return error status */
00907         status =  HAL_ERROR;
00908         break;
00909     }
00910   }
00911   else
00912   {
00913     /* Update the error code */
00914     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00915 
00916     /* Return error status */
00917     status =  HAL_ERROR;
00918   }
00919 
00920   /* Release Lock */
00921   __HAL_UNLOCK(hhcd);
00922   return status;
00923 }
00924 
00925 /**
00926   * @brief  Register USB HCD Host Channel Notify URB Change Callback
00927   *         To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
00928   * @param  hhcd HCD handle
00929   * @param  pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
00930   * @retval HAL status
00931   */
00932 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
00933                                                              pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
00934 {
00935   HAL_StatusTypeDef status = HAL_OK;
00936 
00937   if (pCallback == NULL)
00938   {
00939     /* Update the error code */
00940     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00941 
00942     return HAL_ERROR;
00943   }
00944 
00945   /* Process locked */
00946   __HAL_LOCK(hhcd);
00947 
00948   if (hhcd->State == HAL_HCD_STATE_READY)
00949   {
00950     hhcd->HC_NotifyURBChangeCallback = pCallback;
00951   }
00952   else
00953   {
00954     /* Update the error code */
00955     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00956 
00957     /* Return error status */
00958     status =  HAL_ERROR;
00959   }
00960 
00961   /* Release Lock */
00962   __HAL_UNLOCK(hhcd);
00963 
00964   return status;
00965 }
00966 
00967 /**
00968   * @brief  Unregister the USB HCD Host Channel Notify URB Change Callback
00969   *         USB HCD Host Channel Notify URB Change Callback is redirected
00970   *         to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
00971   * @param  hhcd HCD handle
00972   * @retval HAL status
00973   */
00974 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
00975 {
00976   HAL_StatusTypeDef status = HAL_OK;
00977 
00978   /* Process locked */
00979   __HAL_LOCK(hhcd);
00980 
00981   if (hhcd->State == HAL_HCD_STATE_READY)
00982   {
00983     hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback  */
00984   }
00985   else
00986   {
00987     /* Update the error code */
00988     hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
00989 
00990     /* Return error status */
00991     status =  HAL_ERROR;
00992   }
00993 
00994   /* Release Lock */
00995   __HAL_UNLOCK(hhcd);
00996 
00997   return status;
00998 }
00999 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01000 
01001 /**
01002   * @}
01003   */
01004 
01005 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
01006   *  @brief   Management functions
01007   *
01008 @verbatim
01009  ===============================================================================
01010                       ##### Peripheral Control functions #####
01011  ===============================================================================
01012     [..]
01013     This subsection provides a set of functions allowing to control the HCD data
01014     transfers.
01015 
01016 @endverbatim
01017   * @{
01018   */
01019 
01020 /**
01021   * @brief  Start the host driver.
01022   * @param  hhcd HCD handle
01023   * @retval HAL status
01024   */
01025 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
01026 {
01027   __HAL_LOCK(hhcd);
01028   /* Enable port power */
01029   (void)USB_DriveVbus(hhcd->Instance, 1U);
01030 
01031   /* Enable global interrupt */
01032   __HAL_HCD_ENABLE(hhcd);
01033   __HAL_UNLOCK(hhcd);
01034 
01035   return HAL_OK;
01036 }
01037 
01038 /**
01039   * @brief  Stop the host driver.
01040   * @param  hhcd HCD handle
01041   * @retval HAL status
01042   */
01043 
01044 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
01045 {
01046   __HAL_LOCK(hhcd);
01047   (void)USB_StopHost(hhcd->Instance);
01048   __HAL_UNLOCK(hhcd);
01049 
01050   return HAL_OK;
01051 }
01052 
01053 /**
01054   * @brief  Reset the host port.
01055   * @param  hhcd HCD handle
01056   * @retval HAL status
01057   */
01058 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
01059 {
01060   return (USB_ResetPort(hhcd->Instance));
01061 }
01062 
01063 /**
01064   * @}
01065   */
01066 
01067 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
01068   *  @brief   Peripheral State functions
01069   *
01070 @verbatim
01071  ===============================================================================
01072                       ##### Peripheral State functions #####
01073  ===============================================================================
01074     [..]
01075     This subsection permits to get in run-time the status of the peripheral
01076     and the data flow.
01077 
01078 @endverbatim
01079   * @{
01080   */
01081 
01082 /**
01083   * @brief  Return the HCD handle state.
01084   * @param  hhcd HCD handle
01085   * @retval HAL state
01086   */
01087 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
01088 {
01089   return hhcd->State;
01090 }
01091 
01092 /**
01093   * @brief  Return  URB state for a channel.
01094   * @param  hhcd HCD handle
01095   * @param  chnum Channel number.
01096   *         This parameter can be a value from 1 to 15
01097   * @retval URB state.
01098   *          This parameter can be one of these values:
01099   *            URB_IDLE/
01100   *            URB_DONE/
01101   *            URB_NOTREADY/
01102   *            URB_NYET/
01103   *            URB_ERROR/
01104   *            URB_STALL
01105   */
01106 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01107 {
01108   return hhcd->hc[chnum].urb_state;
01109 }
01110 
01111 
01112 /**
01113   * @brief  Return the last host transfer size.
01114   * @param  hhcd HCD handle
01115   * @param  chnum Channel number.
01116   *         This parameter can be a value from 1 to 15
01117   * @retval last transfer size in byte
01118   */
01119 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01120 {
01121   return hhcd->hc[chnum].xfer_count;
01122 }
01123 
01124 /**
01125   * @brief  Return the Host Channel state.
01126   * @param  hhcd HCD handle
01127   * @param  chnum Channel number.
01128   *         This parameter can be a value from 1 to 15
01129   * @retval Host channel state
01130   *          This parameter can be one of these values:
01131   *            HC_IDLE/
01132   *            HC_XFRC/
01133   *            HC_HALTED/
01134   *            HC_NYET/
01135   *            HC_NAK/
01136   *            HC_STALL/
01137   *            HC_XACTERR/
01138   *            HC_BBLERR/
01139   *            HC_DATATGLERR
01140   */
01141 HCD_HCStateTypeDef  HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01142 {
01143   return hhcd->hc[chnum].state;
01144 }
01145 
01146 /**
01147   * @brief  Return the current Host frame number.
01148   * @param  hhcd HCD handle
01149   * @retval Current Host frame number
01150   */
01151 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
01152 {
01153   return (USB_GetCurrentFrame(hhcd->Instance));
01154 }
01155 
01156 /**
01157   * @brief  Return the Host enumeration speed.
01158   * @param  hhcd HCD handle
01159   * @retval Enumeration speed
01160   */
01161 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
01162 {
01163   return (USB_GetHostSpeed(hhcd->Instance));
01164 }
01165 
01166 /**
01167   * @}
01168   */
01169 
01170 /**
01171   * @}
01172   */
01173 
01174 /** @addtogroup HCD_Private_Functions
01175   * @{
01176   */
01177 /**
01178   * @brief  Handle Host Channel IN interrupt requests.
01179   * @param  hhcd HCD handle
01180   * @param  chnum Channel number.
01181   *         This parameter can be a value from 1 to 15
01182   * @retval none
01183   */
01184 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01185 {
01186   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
01187   uint32_t USBx_BASE = (uint32_t)USBx;
01188   uint32_t ch_num = (uint32_t)chnum;
01189 
01190   uint32_t tmpreg;
01191 
01192   if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
01193   {
01194     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
01195     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01196   }
01197   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR)
01198   {
01199     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR);
01200     hhcd->hc[ch_num].state = HC_BBLERR;
01201     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01202     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01203   }
01204   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
01205   {
01206     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
01207   }
01208   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
01209   {
01210     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01211     hhcd->hc[ch_num].state = HC_STALL;
01212     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01213     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
01214     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01215   }
01216   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
01217   {
01218     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01219     hhcd->hc[ch_num].state = HC_DATATGLERR;
01220     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01221     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
01222     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01223   }
01224   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
01225   {
01226     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01227     hhcd->hc[ch_num].state = HC_XACTERR;
01228     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01229     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
01230   }
01231   else
01232   {
01233     /* ... */
01234   }
01235 
01236   if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
01237   {
01238     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01239     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01240     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
01241   }
01242   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
01243   {
01244     if (hhcd->Init.dma_enable != 0U)
01245     {
01246       hhcd->hc[ch_num].xfer_count = hhcd->hc[ch_num].XferSize - \
01247                                     (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
01248     }
01249 
01250     hhcd->hc[ch_num].state = HC_XFRC;
01251     hhcd->hc[ch_num].ErrCnt = 0U;
01252     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
01253 
01254     if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
01255         (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
01256     {
01257       __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01258       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01259       __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01260     }
01261     else if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
01262     {
01263       USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
01264       hhcd->hc[ch_num].urb_state = URB_DONE;
01265 
01266 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01267       hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01268 #else
01269       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01270 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01271     }
01272     else if (hhcd->hc[ch_num].ep_type == EP_TYPE_ISOC)
01273     {
01274       hhcd->hc[ch_num].urb_state = URB_DONE;
01275       hhcd->hc[ch_num].toggle_in ^= 1U;
01276 
01277 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01278       hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01279 #else
01280       HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01281 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01282     }
01283     else
01284     {
01285       /* ... */
01286     }
01287 
01288     if (hhcd->Init.dma_enable == 1U)
01289     {
01290       if (((hhcd->hc[ch_num].XferSize / hhcd->hc[ch_num].max_packet) & 1U) != 0U)
01291       {
01292         hhcd->hc[ch_num].toggle_in ^= 1U;
01293       }
01294     }
01295     else
01296     {
01297       hhcd->hc[ch_num].toggle_in ^= 1U;
01298     }
01299   }
01300   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
01301   {
01302     __HAL_HCD_MASK_HALT_HC_INT(ch_num);
01303 
01304     if (hhcd->hc[ch_num].state == HC_XFRC)
01305     {
01306       hhcd->hc[ch_num].urb_state = URB_DONE;
01307     }
01308     else if (hhcd->hc[ch_num].state == HC_STALL)
01309     {
01310       hhcd->hc[ch_num].urb_state = URB_STALL;
01311     }
01312     else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
01313              (hhcd->hc[ch_num].state == HC_DATATGLERR))
01314     {
01315       hhcd->hc[ch_num].ErrCnt++;
01316       if (hhcd->hc[ch_num].ErrCnt > 2U)
01317       {
01318         hhcd->hc[ch_num].ErrCnt = 0U;
01319         hhcd->hc[ch_num].urb_state = URB_ERROR;
01320       }
01321       else
01322       {
01323         hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01324 
01325         /* re-activate the channel */
01326         tmpreg = USBx_HC(ch_num)->HCCHAR;
01327         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
01328         tmpreg |= USB_OTG_HCCHAR_CHENA;
01329         USBx_HC(ch_num)->HCCHAR = tmpreg;
01330       }
01331     }
01332     else if (hhcd->hc[ch_num].state == HC_NAK)
01333     {
01334       hhcd->hc[ch_num].urb_state  = URB_NOTREADY;
01335 
01336       /* re-activate the channel */
01337       tmpreg = USBx_HC(ch_num)->HCCHAR;
01338       tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
01339       tmpreg |= USB_OTG_HCCHAR_CHENA;
01340       USBx_HC(ch_num)->HCCHAR = tmpreg;
01341     }
01342     else if (hhcd->hc[ch_num].state == HC_BBLERR)
01343     {
01344       hhcd->hc[ch_num].ErrCnt++;
01345       hhcd->hc[ch_num].urb_state = URB_ERROR;
01346     }
01347     else
01348     {
01349       /* ... */
01350     }
01351     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
01352     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01353   }
01354   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
01355   {
01356     if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
01357     {
01358       hhcd->hc[ch_num].ErrCnt = 0U;
01359       __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01360       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01361     }
01362     else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
01363              (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
01364     {
01365       hhcd->hc[ch_num].ErrCnt = 0U;
01366 
01367       if (hhcd->Init.dma_enable == 0U)
01368       {
01369         hhcd->hc[ch_num].state = HC_NAK;
01370         __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01371         (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01372       }
01373     }
01374     else
01375     {
01376       /* ... */
01377     }
01378     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01379   }
01380   else
01381   {
01382     /* ... */
01383   }
01384 }
01385 
01386 /**
01387   * @brief  Handle Host Channel OUT interrupt requests.
01388   * @param  hhcd HCD handle
01389   * @param  chnum Channel number.
01390   *         This parameter can be a value from 1 to 15
01391   * @retval none
01392   */
01393 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
01394 {
01395   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
01396   uint32_t USBx_BASE = (uint32_t)USBx;
01397   uint32_t ch_num = (uint32_t)chnum;
01398   uint32_t tmpreg;
01399   uint32_t num_packets;
01400 
01401   if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
01402   {
01403     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
01404     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01405   }
01406   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
01407   {
01408     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
01409 
01410     if (hhcd->hc[ch_num].do_ping == 1U)
01411     {
01412       hhcd->hc[ch_num].do_ping = 0U;
01413       hhcd->hc[ch_num].urb_state  = URB_NOTREADY;
01414       __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01415       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01416     }
01417   }
01418   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
01419   {
01420     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01421     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01422     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
01423   }
01424   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
01425   {
01426     hhcd->hc[ch_num].ErrCnt = 0U;
01427 
01428     /* transaction completed with NYET state, update do ping state */
01429     if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET)
01430     {
01431       hhcd->hc[ch_num].do_ping = 1U;
01432       __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
01433     }
01434     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01435     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01436     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
01437     hhcd->hc[ch_num].state = HC_XFRC;
01438   }
01439   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET)
01440   {
01441     hhcd->hc[ch_num].state = HC_NYET;
01442     hhcd->hc[ch_num].do_ping = 1U;
01443     hhcd->hc[ch_num].ErrCnt = 0U;
01444     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01445     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01446     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
01447   }
01448   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
01449   {
01450     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
01451     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01452     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01453     hhcd->hc[ch_num].state = HC_STALL;
01454   }
01455   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
01456   {
01457     hhcd->hc[ch_num].ErrCnt = 0U;
01458     hhcd->hc[ch_num].state = HC_NAK;
01459 
01460     if (hhcd->hc[ch_num].do_ping == 0U)
01461     {
01462       if (hhcd->hc[ch_num].speed == HCD_DEVICE_SPEED_HIGH)
01463       {
01464         hhcd->hc[ch_num].do_ping = 1U;
01465       }
01466     }
01467 
01468     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01469     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01470     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01471   }
01472   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
01473   {
01474     if (hhcd->Init.dma_enable == 0U)
01475     {
01476       hhcd->hc[ch_num].state = HC_XACTERR;
01477       __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01478       (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01479     }
01480     else
01481     {
01482       hhcd->hc[ch_num].ErrCnt++;
01483       if (hhcd->hc[ch_num].ErrCnt > 2U)
01484       {
01485         hhcd->hc[ch_num].ErrCnt = 0U;
01486         hhcd->hc[ch_num].urb_state = URB_ERROR;
01487         HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num,
01488                                             hhcd->hc[ch_num].urb_state);
01489       }
01490       else
01491       {
01492         hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01493       }
01494     }
01495     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
01496   }
01497   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
01498   {
01499     __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
01500     (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
01501     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
01502     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
01503     hhcd->hc[ch_num].state = HC_DATATGLERR;
01504   }
01505   else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
01506   {
01507     __HAL_HCD_MASK_HALT_HC_INT(ch_num);
01508 
01509     if (hhcd->hc[ch_num].state == HC_XFRC)
01510     {
01511       hhcd->hc[ch_num].urb_state  = URB_DONE;
01512       if ((hhcd->hc[ch_num].ep_type == EP_TYPE_BULK) ||
01513           (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR))
01514       {
01515         if (hhcd->Init.dma_enable == 0U)
01516         {
01517           hhcd->hc[ch_num].toggle_out ^= 1U;
01518         }
01519 
01520         if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[ch_num].xfer_len > 0U))
01521         {
01522           num_packets = (hhcd->hc[ch_num].xfer_len + hhcd->hc[ch_num].max_packet - 1U) / hhcd->hc[ch_num].max_packet;
01523 
01524           if ((num_packets & 1U) != 0U)
01525           {
01526             hhcd->hc[ch_num].toggle_out ^= 1U;
01527           }
01528         }
01529       }
01530     }
01531     else if (hhcd->hc[ch_num].state == HC_NAK)
01532     {
01533       hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01534     }
01535     else if (hhcd->hc[ch_num].state == HC_NYET)
01536     {
01537       hhcd->hc[ch_num].urb_state  = URB_NOTREADY;
01538     }
01539     else if (hhcd->hc[ch_num].state == HC_STALL)
01540     {
01541       hhcd->hc[ch_num].urb_state  = URB_STALL;
01542     }
01543     else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
01544              (hhcd->hc[ch_num].state == HC_DATATGLERR))
01545     {
01546       hhcd->hc[ch_num].ErrCnt++;
01547       if (hhcd->hc[ch_num].ErrCnt > 2U)
01548       {
01549         hhcd->hc[ch_num].ErrCnt = 0U;
01550         hhcd->hc[ch_num].urb_state = URB_ERROR;
01551       }
01552       else
01553       {
01554         hhcd->hc[ch_num].urb_state = URB_NOTREADY;
01555 
01556         /* re-activate the channel  */
01557         tmpreg = USBx_HC(ch_num)->HCCHAR;
01558         tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
01559         tmpreg |= USB_OTG_HCCHAR_CHENA;
01560         USBx_HC(ch_num)->HCCHAR = tmpreg;
01561       }
01562     }
01563     else
01564     {
01565       /* ... */
01566     }
01567 
01568     __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
01569     HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
01570   }
01571   else
01572   {
01573     /* ... */
01574   }
01575 }
01576 
01577 /**
01578   * @brief  Handle Rx Queue Level interrupt requests.
01579   * @param  hhcd HCD handle
01580   * @retval none
01581   */
01582 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
01583 {
01584   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
01585   uint32_t USBx_BASE = (uint32_t)USBx;
01586   uint32_t pktsts;
01587   uint32_t pktcnt;
01588   uint32_t GrxstspReg;
01589   uint32_t xferSizePktCnt;
01590   uint32_t tmpreg;
01591   uint32_t ch_num;
01592 
01593   GrxstspReg = hhcd->Instance->GRXSTSP;
01594   ch_num = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
01595   pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
01596   pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
01597 
01598   switch (pktsts)
01599   {
01600     case GRXSTS_PKTSTS_IN:
01601       /* Read the data into the host buffer. */
01602       if ((pktcnt > 0U) && (hhcd->hc[ch_num].xfer_buff != (void *)0))
01603       {
01604         if ((hhcd->hc[ch_num].xfer_count + pktcnt) <= hhcd->hc[ch_num].xfer_len)
01605         {
01606           (void)USB_ReadPacket(hhcd->Instance,
01607                                hhcd->hc[ch_num].xfer_buff, (uint16_t)pktcnt);
01608 
01609           /* manage multiple Xfer */
01610           hhcd->hc[ch_num].xfer_buff += pktcnt;
01611           hhcd->hc[ch_num].xfer_count += pktcnt;
01612 
01613           /* get transfer size packet count */
01614           xferSizePktCnt = (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
01615 
01616           if ((hhcd->hc[ch_num].max_packet == pktcnt) && (xferSizePktCnt > 0U))
01617           {
01618             /* re-activate the channel when more packets are expected */
01619             tmpreg = USBx_HC(ch_num)->HCCHAR;
01620             tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
01621             tmpreg |= USB_OTG_HCCHAR_CHENA;
01622             USBx_HC(ch_num)->HCCHAR = tmpreg;
01623             hhcd->hc[ch_num].toggle_in ^= 1U;
01624           }
01625         }
01626         else
01627         {
01628           hhcd->hc[ch_num].urb_state = URB_ERROR;
01629         }
01630       }
01631       break;
01632 
01633     case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
01634       break;
01635 
01636     case GRXSTS_PKTSTS_IN_XFER_COMP:
01637     case GRXSTS_PKTSTS_CH_HALTED:
01638     default:
01639       break;
01640   }
01641 }
01642 
01643 /**
01644   * @brief  Handle Host Port interrupt requests.
01645   * @param  hhcd HCD handle
01646   * @retval None
01647   */
01648 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
01649 {
01650   USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
01651   uint32_t USBx_BASE = (uint32_t)USBx;
01652   __IO uint32_t hprt0;
01653   __IO uint32_t hprt0_dup;
01654 
01655   /* Handle Host Port Interrupts */
01656   hprt0 = USBx_HPRT0;
01657   hprt0_dup = USBx_HPRT0;
01658 
01659   hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
01660                  USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
01661 
01662   /* Check whether Port Connect detected */
01663   if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
01664   {
01665     if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
01666     {
01667 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01668       hhcd->ConnectCallback(hhcd);
01669 #else
01670       HAL_HCD_Connect_Callback(hhcd);
01671 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01672     }
01673     hprt0_dup |= USB_OTG_HPRT_PCDET;
01674   }
01675 
01676   /* Check whether Port Enable Changed */
01677   if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
01678   {
01679     hprt0_dup |= USB_OTG_HPRT_PENCHNG;
01680 
01681     if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
01682     {
01683       if (hhcd->Init.phy_itface  == USB_OTG_EMBEDDED_PHY)
01684       {
01685         if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
01686         {
01687           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
01688         }
01689         else
01690         {
01691           (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
01692         }
01693       }
01694       else
01695       {
01696         if (hhcd->Init.speed == HCD_SPEED_FULL)
01697         {
01698           USBx_HOST->HFIR = 60000U;
01699         }
01700       }
01701 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01702       hhcd->PortEnabledCallback(hhcd);
01703 #else
01704       HAL_HCD_PortEnabled_Callback(hhcd);
01705 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01706 
01707     }
01708     else
01709     {
01710 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
01711       hhcd->PortDisabledCallback(hhcd);
01712 #else
01713       HAL_HCD_PortDisabled_Callback(hhcd);
01714 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
01715     }
01716   }
01717 
01718   /* Check for an overcurrent */
01719   if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
01720   {
01721     hprt0_dup |= USB_OTG_HPRT_POCCHNG;
01722   }
01723 
01724   /* Clear Port Interrupts */
01725   USBx_HPRT0 = hprt0_dup;
01726 }
01727 
01728 /**
01729   * @}
01730   */
01731 
01732 /**
01733   * @}
01734   */
01735 
01736 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
01737 #endif /* HAL_HCD_MODULE_ENABLED */
01738 
01739 /**
01740   * @}
01741   */
01742 
01743 /**
01744   * @}
01745   */