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