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