STM32F479xx HAL User Manual
stm32f4xx_hal_pcd.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f4xx_hal_pcd.c
00004   * @author  MCD Application Team
00005   * @brief   PCD HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the USB Peripheral Controller:
00008   *           + Initialization and de-initialization functions
00009   *           + IO operation functions
00010   *           + Peripheral Control functions
00011   *           + Peripheral State functions
00012   *
00013   ******************************************************************************
00014   * @attention
00015   *
00016   * Copyright (c) 2016 STMicroelectronics.
00017   * All rights reserved.
00018   *
00019   * This software is licensed under terms that can be found in the LICENSE file
00020   * in the root directory of this software component.
00021   * If no LICENSE file comes with this software, it is provided AS-IS.
00022   *
00023   ******************************************************************************
00024   @verbatim
00025   ==============================================================================
00026                     ##### How to use this driver #####
00027   ==============================================================================
00028     [..]
00029       The PCD HAL driver can be used as follows:
00030 
00031      (#) Declare a PCD_HandleTypeDef handle structure, for example:
00032          PCD_HandleTypeDef  hpcd;
00033 
00034      (#) Fill parameters of Init structure in HCD handle
00035 
00036      (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
00037 
00038      (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
00039          (##) Enable the PCD/USB Low Level interface clock using
00040               (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
00041               (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
00042 
00043          (##) Initialize the related GPIO clocks
00044          (##) Configure PCD pin-out
00045          (##) Configure PCD NVIC interrupt
00046 
00047      (#)Associate the Upper USB device stack to the HAL PCD Driver:
00048          (##) hpcd.pData = pdev;
00049 
00050      (#)Enable PCD transmission and reception:
00051          (##) HAL_PCD_Start();
00052 
00053   @endverbatim
00054   ******************************************************************************
00055   */
00056 
00057 /* Includes ------------------------------------------------------------------*/
00058 #include "stm32f4xx_hal.h"
00059 
00060 /** @addtogroup STM32F4xx_HAL_Driver
00061   * @{
00062   */
00063 
00064 /** @defgroup PCD PCD
00065   * @brief PCD HAL module driver
00066   * @{
00067   */
00068 
00069 #ifdef HAL_PCD_MODULE_ENABLED
00070 
00071 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
00072 
00073 /* Private types -------------------------------------------------------------*/
00074 /* Private variables ---------------------------------------------------------*/
00075 /* Private constants ---------------------------------------------------------*/
00076 /* Private macros ------------------------------------------------------------*/
00077 /** @defgroup PCD_Private_Macros PCD Private Macros
00078   * @{
00079   */
00080 #define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
00081 #define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
00082 /**
00083   * @}
00084   */
00085 
00086 /* Private functions prototypes ----------------------------------------------*/
00087 /** @defgroup PCD_Private_Functions PCD Private Functions
00088   * @{
00089   */
00090 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
00091 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
00092 static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
00093 static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
00094 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
00095 /**
00096   * @}
00097   */
00098 
00099 /* Exported functions --------------------------------------------------------*/
00100 /** @defgroup PCD_Exported_Functions PCD Exported Functions
00101   * @{
00102   */
00103 
00104 /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
00105   *  @brief    Initialization and Configuration functions
00106   *
00107 @verbatim
00108  ===============================================================================
00109             ##### Initialization and de-initialization functions #####
00110  ===============================================================================
00111     [..]  This section provides functions allowing to:
00112 
00113 @endverbatim
00114   * @{
00115   */
00116 
00117 /**
00118   * @brief  Initializes the PCD according to the specified
00119   *         parameters in the PCD_InitTypeDef and initialize the associated handle.
00120   * @param  hpcd PCD handle
00121   * @retval HAL status
00122   */
00123 HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
00124 {
00125   USB_OTG_GlobalTypeDef *USBx;
00126   uint8_t i;
00127 
00128   /* Check the PCD handle allocation */
00129   if (hpcd == NULL)
00130   {
00131     return HAL_ERROR;
00132   }
00133 
00134   /* Check the parameters */
00135   assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
00136 
00137   USBx = hpcd->Instance;
00138 
00139   if (hpcd->State == HAL_PCD_STATE_RESET)
00140   {
00141     /* Allocate lock resource and initialize it */
00142     hpcd->Lock = HAL_UNLOCKED;
00143 
00144 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00145     hpcd->SOFCallback = HAL_PCD_SOFCallback;
00146     hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
00147     hpcd->ResetCallback = HAL_PCD_ResetCallback;
00148     hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
00149     hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
00150     hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
00151     hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
00152     hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
00153     hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
00154     hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
00155     hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
00156     hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;
00157     hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;
00158 
00159     if (hpcd->MspInitCallback == NULL)
00160     {
00161       hpcd->MspInitCallback = HAL_PCD_MspInit;
00162     }
00163 
00164     /* Init the low level hardware */
00165     hpcd->MspInitCallback(hpcd);
00166 #else
00167     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
00168     HAL_PCD_MspInit(hpcd);
00169 #endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
00170   }
00171 
00172   hpcd->State = HAL_PCD_STATE_BUSY;
00173 
00174   /* Disable DMA mode for FS instance */
00175   if ((USBx->CID & (0x1U << 8)) == 0U)
00176   {
00177     hpcd->Init.dma_enable = 0U;
00178   }
00179 
00180   /* Disable the Interrupts */
00181   __HAL_PCD_DISABLE(hpcd);
00182 
00183   /*Init the Core (common init.) */
00184   if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
00185   {
00186     hpcd->State = HAL_PCD_STATE_ERROR;
00187     return HAL_ERROR;
00188   }
00189 
00190   /* Force Device Mode*/
00191   (void)USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE);
00192 
00193   /* Init endpoints structures */
00194   for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
00195   {
00196     /* Init ep structure */
00197     hpcd->IN_ep[i].is_in = 1U;
00198     hpcd->IN_ep[i].num = i;
00199     hpcd->IN_ep[i].tx_fifo_num = i;
00200     /* Control until ep is activated */
00201     hpcd->IN_ep[i].type = EP_TYPE_CTRL;
00202     hpcd->IN_ep[i].maxpacket = 0U;
00203     hpcd->IN_ep[i].xfer_buff = 0U;
00204     hpcd->IN_ep[i].xfer_len = 0U;
00205   }
00206 
00207   for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
00208   {
00209     hpcd->OUT_ep[i].is_in = 0U;
00210     hpcd->OUT_ep[i].num = i;
00211     /* Control until ep is activated */
00212     hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
00213     hpcd->OUT_ep[i].maxpacket = 0U;
00214     hpcd->OUT_ep[i].xfer_buff = 0U;
00215     hpcd->OUT_ep[i].xfer_len = 0U;
00216   }
00217 
00218   /* Init Device */
00219   if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
00220   {
00221     hpcd->State = HAL_PCD_STATE_ERROR;
00222     return HAL_ERROR;
00223   }
00224 
00225   hpcd->USB_Address = 0U;
00226   hpcd->State = HAL_PCD_STATE_READY;
00227 #if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
00228   /* Activate LPM */
00229   if (hpcd->Init.lpm_enable == 1U)
00230   {
00231     (void)HAL_PCDEx_ActivateLPM(hpcd);
00232   }
00233 #endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
00234   (void)USB_DevDisconnect(hpcd->Instance);
00235 
00236   return HAL_OK;
00237 }
00238 
00239 /**
00240   * @brief  DeInitializes the PCD peripheral.
00241   * @param  hpcd PCD handle
00242   * @retval HAL status
00243   */
00244 HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
00245 {
00246   /* Check the PCD handle allocation */
00247   if (hpcd == NULL)
00248   {
00249     return HAL_ERROR;
00250   }
00251 
00252   hpcd->State = HAL_PCD_STATE_BUSY;
00253 
00254   /* Stop Device */
00255   if (USB_StopDevice(hpcd->Instance) != HAL_OK)
00256   {
00257     return HAL_ERROR;
00258   }
00259 
00260 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00261   if (hpcd->MspDeInitCallback == NULL)
00262   {
00263     hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit  */
00264   }
00265 
00266   /* DeInit the low level hardware */
00267   hpcd->MspDeInitCallback(hpcd);
00268 #else
00269   /* DeInit the low level hardware: CLOCK, NVIC.*/
00270   HAL_PCD_MspDeInit(hpcd);
00271 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00272 
00273   hpcd->State = HAL_PCD_STATE_RESET;
00274 
00275   return HAL_OK;
00276 }
00277 
00278 /**
00279   * @brief  Initializes the PCD MSP.
00280   * @param  hpcd PCD handle
00281   * @retval None
00282   */
00283 __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
00284 {
00285   /* Prevent unused argument(s) compilation warning */
00286   UNUSED(hpcd);
00287 
00288   /* NOTE : This function should not be modified, when the callback is needed,
00289             the HAL_PCD_MspInit could be implemented in the user file
00290    */
00291 }
00292 
00293 /**
00294   * @brief  DeInitializes PCD MSP.
00295   * @param  hpcd PCD handle
00296   * @retval None
00297   */
00298 __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
00299 {
00300   /* Prevent unused argument(s) compilation warning */
00301   UNUSED(hpcd);
00302 
00303   /* NOTE : This function should not be modified, when the callback is needed,
00304             the HAL_PCD_MspDeInit could be implemented in the user file
00305    */
00306 }
00307 
00308 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00309 /**
00310   * @brief  Register a User USB PCD Callback
00311   *         To be used instead of the weak predefined callback
00312   * @param  hpcd USB PCD handle
00313   * @param  CallbackID ID of the callback to be registered
00314   *         This parameter can be one of the following values:
00315   *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
00316   *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
00317   *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
00318   *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
00319   *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
00320   *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
00321   *          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
00322   *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
00323   *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
00324   * @param  pCallback pointer to the Callback function
00325   * @retval HAL status
00326   */
00327 HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
00328                                            HAL_PCD_CallbackIDTypeDef CallbackID,
00329                                            pPCD_CallbackTypeDef pCallback)
00330 {
00331   HAL_StatusTypeDef status = HAL_OK;
00332 
00333   if (pCallback == NULL)
00334   {
00335     /* Update the error code */
00336     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00337     return HAL_ERROR;
00338   }
00339   /* Process locked */
00340   __HAL_LOCK(hpcd);
00341 
00342   if (hpcd->State == HAL_PCD_STATE_READY)
00343   {
00344     switch (CallbackID)
00345     {
00346       case HAL_PCD_SOF_CB_ID :
00347         hpcd->SOFCallback = pCallback;
00348         break;
00349 
00350       case HAL_PCD_SETUPSTAGE_CB_ID :
00351         hpcd->SetupStageCallback = pCallback;
00352         break;
00353 
00354       case HAL_PCD_RESET_CB_ID :
00355         hpcd->ResetCallback = pCallback;
00356         break;
00357 
00358       case HAL_PCD_SUSPEND_CB_ID :
00359         hpcd->SuspendCallback = pCallback;
00360         break;
00361 
00362       case HAL_PCD_RESUME_CB_ID :
00363         hpcd->ResumeCallback = pCallback;
00364         break;
00365 
00366       case HAL_PCD_CONNECT_CB_ID :
00367         hpcd->ConnectCallback = pCallback;
00368         break;
00369 
00370       case HAL_PCD_DISCONNECT_CB_ID :
00371         hpcd->DisconnectCallback = pCallback;
00372         break;
00373 
00374       case HAL_PCD_MSPINIT_CB_ID :
00375         hpcd->MspInitCallback = pCallback;
00376         break;
00377 
00378       case HAL_PCD_MSPDEINIT_CB_ID :
00379         hpcd->MspDeInitCallback = pCallback;
00380         break;
00381 
00382       default :
00383         /* Update the error code */
00384         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00385         /* Return error status */
00386         status =  HAL_ERROR;
00387         break;
00388     }
00389   }
00390   else if (hpcd->State == HAL_PCD_STATE_RESET)
00391   {
00392     switch (CallbackID)
00393     {
00394       case HAL_PCD_MSPINIT_CB_ID :
00395         hpcd->MspInitCallback = pCallback;
00396         break;
00397 
00398       case HAL_PCD_MSPDEINIT_CB_ID :
00399         hpcd->MspDeInitCallback = pCallback;
00400         break;
00401 
00402       default :
00403         /* Update the error code */
00404         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00405         /* Return error status */
00406         status =  HAL_ERROR;
00407         break;
00408     }
00409   }
00410   else
00411   {
00412     /* Update the error code */
00413     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00414     /* Return error status */
00415     status =  HAL_ERROR;
00416   }
00417 
00418   /* Release Lock */
00419   __HAL_UNLOCK(hpcd);
00420   return status;
00421 }
00422 
00423 /**
00424   * @brief  Unregister an USB PCD Callback
00425   *         USB PCD callabck is redirected to the weak predefined callback
00426   * @param  hpcd USB PCD handle
00427   * @param  CallbackID ID of the callback to be unregistered
00428   *         This parameter can be one of the following values:
00429   *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
00430   *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
00431   *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
00432   *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
00433   *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
00434   *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
00435   *          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
00436   *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
00437   *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
00438   * @retval HAL status
00439   */
00440 HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
00441 {
00442   HAL_StatusTypeDef status = HAL_OK;
00443 
00444   /* Process locked */
00445   __HAL_LOCK(hpcd);
00446 
00447   /* Setup Legacy weak Callbacks  */
00448   if (hpcd->State == HAL_PCD_STATE_READY)
00449   {
00450     switch (CallbackID)
00451     {
00452       case HAL_PCD_SOF_CB_ID :
00453         hpcd->SOFCallback = HAL_PCD_SOFCallback;
00454         break;
00455 
00456       case HAL_PCD_SETUPSTAGE_CB_ID :
00457         hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
00458         break;
00459 
00460       case HAL_PCD_RESET_CB_ID :
00461         hpcd->ResetCallback = HAL_PCD_ResetCallback;
00462         break;
00463 
00464       case HAL_PCD_SUSPEND_CB_ID :
00465         hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
00466         break;
00467 
00468       case HAL_PCD_RESUME_CB_ID :
00469         hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
00470         break;
00471 
00472       case HAL_PCD_CONNECT_CB_ID :
00473         hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
00474         break;
00475 
00476       case HAL_PCD_DISCONNECT_CB_ID :
00477         hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
00478         break;
00479 
00480       case HAL_PCD_MSPINIT_CB_ID :
00481         hpcd->MspInitCallback = HAL_PCD_MspInit;
00482         break;
00483 
00484       case HAL_PCD_MSPDEINIT_CB_ID :
00485         hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
00486         break;
00487 
00488       default :
00489         /* Update the error code */
00490         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00491 
00492         /* Return error status */
00493         status =  HAL_ERROR;
00494         break;
00495     }
00496   }
00497   else if (hpcd->State == HAL_PCD_STATE_RESET)
00498   {
00499     switch (CallbackID)
00500     {
00501       case HAL_PCD_MSPINIT_CB_ID :
00502         hpcd->MspInitCallback = HAL_PCD_MspInit;
00503         break;
00504 
00505       case HAL_PCD_MSPDEINIT_CB_ID :
00506         hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
00507         break;
00508 
00509       default :
00510         /* Update the error code */
00511         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00512 
00513         /* Return error status */
00514         status =  HAL_ERROR;
00515         break;
00516     }
00517   }
00518   else
00519   {
00520     /* Update the error code */
00521     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00522 
00523     /* Return error status */
00524     status =  HAL_ERROR;
00525   }
00526 
00527   /* Release Lock */
00528   __HAL_UNLOCK(hpcd);
00529   return status;
00530 }
00531 
00532 /**
00533   * @brief  Register USB PCD Data OUT Stage Callback
00534   *         To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
00535   * @param  hpcd PCD handle
00536   * @param  pCallback pointer to the USB PCD Data OUT Stage Callback function
00537   * @retval HAL status
00538   */
00539 HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
00540                                                        pPCD_DataOutStageCallbackTypeDef pCallback)
00541 {
00542   HAL_StatusTypeDef status = HAL_OK;
00543 
00544   if (pCallback == NULL)
00545   {
00546     /* Update the error code */
00547     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00548 
00549     return HAL_ERROR;
00550   }
00551 
00552   /* Process locked */
00553   __HAL_LOCK(hpcd);
00554 
00555   if (hpcd->State == HAL_PCD_STATE_READY)
00556   {
00557     hpcd->DataOutStageCallback = pCallback;
00558   }
00559   else
00560   {
00561     /* Update the error code */
00562     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00563 
00564     /* Return error status */
00565     status =  HAL_ERROR;
00566   }
00567 
00568   /* Release Lock */
00569   __HAL_UNLOCK(hpcd);
00570 
00571   return status;
00572 }
00573 
00574 /**
00575   * @brief  Unregister the USB PCD Data OUT Stage Callback
00576   *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
00577   * @param  hpcd PCD handle
00578   * @retval HAL status
00579   */
00580 HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
00581 {
00582   HAL_StatusTypeDef status = HAL_OK;
00583 
00584   /* Process locked */
00585   __HAL_LOCK(hpcd);
00586 
00587   if (hpcd->State == HAL_PCD_STATE_READY)
00588   {
00589     hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback  */
00590   }
00591   else
00592   {
00593     /* Update the error code */
00594     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00595 
00596     /* Return error status */
00597     status =  HAL_ERROR;
00598   }
00599 
00600   /* Release Lock */
00601   __HAL_UNLOCK(hpcd);
00602 
00603   return status;
00604 }
00605 
00606 /**
00607   * @brief  Register USB PCD Data IN Stage Callback
00608   *         To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
00609   * @param  hpcd PCD handle
00610   * @param  pCallback pointer to the USB PCD Data IN Stage Callback function
00611   * @retval HAL status
00612   */
00613 HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
00614                                                       pPCD_DataInStageCallbackTypeDef pCallback)
00615 {
00616   HAL_StatusTypeDef status = HAL_OK;
00617 
00618   if (pCallback == NULL)
00619   {
00620     /* Update the error code */
00621     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00622 
00623     return HAL_ERROR;
00624   }
00625 
00626   /* Process locked */
00627   __HAL_LOCK(hpcd);
00628 
00629   if (hpcd->State == HAL_PCD_STATE_READY)
00630   {
00631     hpcd->DataInStageCallback = pCallback;
00632   }
00633   else
00634   {
00635     /* Update the error code */
00636     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00637 
00638     /* Return error status */
00639     status =  HAL_ERROR;
00640   }
00641 
00642   /* Release Lock */
00643   __HAL_UNLOCK(hpcd);
00644 
00645   return status;
00646 }
00647 
00648 /**
00649   * @brief  Unregister the USB PCD Data IN Stage Callback
00650   *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
00651   * @param  hpcd PCD handle
00652   * @retval HAL status
00653   */
00654 HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
00655 {
00656   HAL_StatusTypeDef status = HAL_OK;
00657 
00658   /* Process locked */
00659   __HAL_LOCK(hpcd);
00660 
00661   if (hpcd->State == HAL_PCD_STATE_READY)
00662   {
00663     hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback  */
00664   }
00665   else
00666   {
00667     /* Update the error code */
00668     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00669 
00670     /* Return error status */
00671     status =  HAL_ERROR;
00672   }
00673 
00674   /* Release Lock */
00675   __HAL_UNLOCK(hpcd);
00676 
00677   return status;
00678 }
00679 
00680 /**
00681   * @brief  Register USB PCD Iso OUT incomplete Callback
00682   *         To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
00683   * @param  hpcd PCD handle
00684   * @param  pCallback pointer to the USB PCD Iso OUT incomplete Callback function
00685   * @retval HAL status
00686   */
00687 HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
00688                                                        pPCD_IsoOutIncpltCallbackTypeDef pCallback)
00689 {
00690   HAL_StatusTypeDef status = HAL_OK;
00691 
00692   if (pCallback == NULL)
00693   {
00694     /* Update the error code */
00695     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00696 
00697     return HAL_ERROR;
00698   }
00699 
00700   /* Process locked */
00701   __HAL_LOCK(hpcd);
00702 
00703   if (hpcd->State == HAL_PCD_STATE_READY)
00704   {
00705     hpcd->ISOOUTIncompleteCallback = pCallback;
00706   }
00707   else
00708   {
00709     /* Update the error code */
00710     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00711 
00712     /* Return error status */
00713     status =  HAL_ERROR;
00714   }
00715 
00716   /* Release Lock */
00717   __HAL_UNLOCK(hpcd);
00718 
00719   return status;
00720 }
00721 
00722 /**
00723   * @brief  Unregister the USB PCD Iso OUT incomplete Callback
00724   *         USB PCD Iso OUT incomplete Callback is redirected
00725   *         to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
00726   * @param  hpcd PCD handle
00727   * @retval HAL status
00728   */
00729 HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
00730 {
00731   HAL_StatusTypeDef status = HAL_OK;
00732 
00733   /* Process locked */
00734   __HAL_LOCK(hpcd);
00735 
00736   if (hpcd->State == HAL_PCD_STATE_READY)
00737   {
00738     hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback  */
00739   }
00740   else
00741   {
00742     /* Update the error code */
00743     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00744 
00745     /* Return error status */
00746     status =  HAL_ERROR;
00747   }
00748 
00749   /* Release Lock */
00750   __HAL_UNLOCK(hpcd);
00751 
00752   return status;
00753 }
00754 
00755 /**
00756   * @brief  Register USB PCD Iso IN incomplete Callback
00757   *         To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
00758   * @param  hpcd PCD handle
00759   * @param  pCallback pointer to the USB PCD Iso IN incomplete Callback function
00760   * @retval HAL status
00761   */
00762 HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
00763                                                       pPCD_IsoInIncpltCallbackTypeDef pCallback)
00764 {
00765   HAL_StatusTypeDef status = HAL_OK;
00766 
00767   if (pCallback == NULL)
00768   {
00769     /* Update the error code */
00770     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00771 
00772     return HAL_ERROR;
00773   }
00774 
00775   /* Process locked */
00776   __HAL_LOCK(hpcd);
00777 
00778   if (hpcd->State == HAL_PCD_STATE_READY)
00779   {
00780     hpcd->ISOINIncompleteCallback = pCallback;
00781   }
00782   else
00783   {
00784     /* Update the error code */
00785     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00786 
00787     /* Return error status */
00788     status =  HAL_ERROR;
00789   }
00790 
00791   /* Release Lock */
00792   __HAL_UNLOCK(hpcd);
00793 
00794   return status;
00795 }
00796 
00797 /**
00798   * @brief  Unregister the USB PCD Iso IN incomplete Callback
00799   *         USB PCD Iso IN incomplete Callback is redirected
00800   *         to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
00801   * @param  hpcd PCD handle
00802   * @retval HAL status
00803   */
00804 HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
00805 {
00806   HAL_StatusTypeDef status = HAL_OK;
00807 
00808   /* Process locked */
00809   __HAL_LOCK(hpcd);
00810 
00811   if (hpcd->State == HAL_PCD_STATE_READY)
00812   {
00813     hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback  */
00814   }
00815   else
00816   {
00817     /* Update the error code */
00818     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00819 
00820     /* Return error status */
00821     status =  HAL_ERROR;
00822   }
00823 
00824   /* Release Lock */
00825   __HAL_UNLOCK(hpcd);
00826 
00827   return status;
00828 }
00829 
00830 /**
00831   * @brief  Register USB PCD BCD Callback
00832   *         To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
00833   * @param  hpcd PCD handle
00834   * @param  pCallback pointer to the USB PCD BCD Callback function
00835   * @retval HAL status
00836   */
00837 HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
00838 {
00839   HAL_StatusTypeDef status = HAL_OK;
00840 
00841   if (pCallback == NULL)
00842   {
00843     /* Update the error code */
00844     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00845 
00846     return HAL_ERROR;
00847   }
00848 
00849   /* Process locked */
00850   __HAL_LOCK(hpcd);
00851 
00852   if (hpcd->State == HAL_PCD_STATE_READY)
00853   {
00854     hpcd->BCDCallback = pCallback;
00855   }
00856   else
00857   {
00858     /* Update the error code */
00859     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00860 
00861     /* Return error status */
00862     status =  HAL_ERROR;
00863   }
00864 
00865   /* Release Lock */
00866   __HAL_UNLOCK(hpcd);
00867 
00868   return status;
00869 }
00870 
00871 /**
00872   * @brief  Unregister the USB PCD BCD Callback
00873   *         USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
00874   * @param  hpcd PCD handle
00875   * @retval HAL status
00876   */
00877 HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
00878 {
00879   HAL_StatusTypeDef status = HAL_OK;
00880 
00881   /* Process locked */
00882   __HAL_LOCK(hpcd);
00883 
00884   if (hpcd->State == HAL_PCD_STATE_READY)
00885   {
00886     hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback  */
00887   }
00888   else
00889   {
00890     /* Update the error code */
00891     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00892 
00893     /* Return error status */
00894     status =  HAL_ERROR;
00895   }
00896 
00897   /* Release Lock */
00898   __HAL_UNLOCK(hpcd);
00899 
00900   return status;
00901 }
00902 
00903 /**
00904   * @brief  Register USB PCD LPM Callback
00905   *         To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
00906   * @param  hpcd PCD handle
00907   * @param  pCallback pointer to the USB PCD LPM Callback function
00908   * @retval HAL status
00909   */
00910 HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
00911 {
00912   HAL_StatusTypeDef status = HAL_OK;
00913 
00914   if (pCallback == NULL)
00915   {
00916     /* Update the error code */
00917     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00918 
00919     return HAL_ERROR;
00920   }
00921 
00922   /* Process locked */
00923   __HAL_LOCK(hpcd);
00924 
00925   if (hpcd->State == HAL_PCD_STATE_READY)
00926   {
00927     hpcd->LPMCallback = pCallback;
00928   }
00929   else
00930   {
00931     /* Update the error code */
00932     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00933 
00934     /* Return error status */
00935     status =  HAL_ERROR;
00936   }
00937 
00938   /* Release Lock */
00939   __HAL_UNLOCK(hpcd);
00940 
00941   return status;
00942 }
00943 
00944 /**
00945   * @brief  Unregister the USB PCD LPM Callback
00946   *         USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
00947   * @param  hpcd PCD handle
00948   * @retval HAL status
00949   */
00950 HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
00951 {
00952   HAL_StatusTypeDef status = HAL_OK;
00953 
00954   /* Process locked */
00955   __HAL_LOCK(hpcd);
00956 
00957   if (hpcd->State == HAL_PCD_STATE_READY)
00958   {
00959     hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback  */
00960   }
00961   else
00962   {
00963     /* Update the error code */
00964     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
00965 
00966     /* Return error status */
00967     status =  HAL_ERROR;
00968   }
00969 
00970   /* Release Lock */
00971   __HAL_UNLOCK(hpcd);
00972 
00973   return status;
00974 }
00975 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00976 
00977 /**
00978   * @}
00979   */
00980 
00981 /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
00982   *  @brief   Data transfers functions
00983   *
00984 @verbatim
00985  ===============================================================================
00986                       ##### IO operation functions #####
00987  ===============================================================================
00988     [..]
00989     This subsection provides a set of functions allowing to manage the PCD data
00990     transfers.
00991 
00992 @endverbatim
00993   * @{
00994   */
00995 
00996 /**
00997   * @brief  Start the USB device
00998   * @param  hpcd PCD handle
00999   * @retval HAL status
01000   */
01001 HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
01002 {
01003   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
01004 
01005   __HAL_LOCK(hpcd);
01006 
01007   if ((hpcd->Init.battery_charging_enable == 1U) &&
01008       (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
01009   {
01010     /* Enable USB Transceiver */
01011     USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
01012   }
01013 
01014   __HAL_PCD_ENABLE(hpcd);
01015   (void)USB_DevConnect(hpcd->Instance);
01016   __HAL_UNLOCK(hpcd);
01017 
01018   return HAL_OK;
01019 }
01020 
01021 /**
01022   * @brief  Stop the USB device.
01023   * @param  hpcd PCD handle
01024   * @retval HAL status
01025   */
01026 HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
01027 {
01028   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
01029 
01030   __HAL_LOCK(hpcd);
01031   __HAL_PCD_DISABLE(hpcd);
01032   (void)USB_DevDisconnect(hpcd->Instance);
01033 
01034   (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
01035 
01036   if ((hpcd->Init.battery_charging_enable == 1U) &&
01037       (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
01038   {
01039     /* Disable USB Transceiver */
01040     USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
01041   }
01042 
01043   __HAL_UNLOCK(hpcd);
01044 
01045   return HAL_OK;
01046 }
01047 
01048 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
01049 /**
01050   * @brief  Handles PCD interrupt request.
01051   * @param  hpcd PCD handle
01052   * @retval HAL status
01053   */
01054 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
01055 {
01056   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
01057   uint32_t USBx_BASE = (uint32_t)USBx;
01058   USB_OTG_EPTypeDef *ep;
01059   uint32_t i;
01060   uint32_t ep_intr;
01061   uint32_t epint;
01062   uint32_t epnum;
01063   uint32_t fifoemptymsk;
01064   uint32_t temp;
01065 
01066   /* ensure that we are in device mode */
01067   if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
01068   {
01069     /* avoid spurious interrupt */
01070     if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
01071     {
01072       return;
01073     }
01074 
01075     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
01076     {
01077       /* incorrect mode, acknowledge the interrupt */
01078       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
01079     }
01080 
01081     /* Handle RxQLevel Interrupt */
01082     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
01083     {
01084       USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
01085 
01086       temp = USBx->GRXSTSP;
01087 
01088       ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
01089 
01090       if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
01091       {
01092         if ((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
01093         {
01094           (void)USB_ReadPacket(USBx, ep->xfer_buff,
01095                                (uint16_t)((temp & USB_OTG_GRXSTSP_BCNT) >> 4));
01096 
01097           ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
01098           ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
01099         }
01100       }
01101       else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_SETUP_UPDT)
01102       {
01103         (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
01104         ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
01105       }
01106       else
01107       {
01108         /* ... */
01109       }
01110       USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
01111     }
01112 
01113     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
01114     {
01115       epnum = 0U;
01116 
01117       /* Read in the device interrupt bits */
01118       ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
01119 
01120       while (ep_intr != 0U)
01121       {
01122         if ((ep_intr & 0x1U) != 0U)
01123         {
01124           epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
01125 
01126           if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
01127           {
01128             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
01129             (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
01130           }
01131 
01132           if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
01133           {
01134             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
01135             /* Class B setup phase done for previous decoded setup */
01136             (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
01137           }
01138 
01139           if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
01140           {
01141             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
01142           }
01143 
01144           /* Clear Status Phase Received interrupt */
01145           if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
01146           {
01147             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
01148           }
01149 
01150           /* Clear OUT NAK interrupt */
01151           if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
01152           {
01153             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
01154           }
01155         }
01156         epnum++;
01157         ep_intr >>= 1U;
01158       }
01159     }
01160 
01161     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
01162     {
01163       /* Read in the device interrupt bits */
01164       ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
01165 
01166       epnum = 0U;
01167 
01168       while (ep_intr != 0U)
01169       {
01170         if ((ep_intr & 0x1U) != 0U) /* In ITR */
01171         {
01172           epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
01173 
01174           if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
01175           {
01176             fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
01177             USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
01178 
01179             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
01180 
01181             if (hpcd->Init.dma_enable == 1U)
01182             {
01183               hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
01184 
01185               /* this is ZLP, so prepare EP0 for next setup */
01186               if ((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U))
01187               {
01188                 /* prepare to rx more setup packets */
01189                 (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
01190               }
01191             }
01192 
01193 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01194             hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
01195 #else
01196             HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
01197 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01198           }
01199           if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
01200           {
01201             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
01202           }
01203           if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
01204           {
01205             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
01206           }
01207           if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
01208           {
01209             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
01210           }
01211           if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
01212           {
01213             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
01214           }
01215           if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
01216           {
01217             (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
01218           }
01219         }
01220         epnum++;
01221         ep_intr >>= 1U;
01222       }
01223     }
01224 
01225     /* Handle Resume Interrupt */
01226     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
01227     {
01228       /* Clear the Remote Wake-up Signaling */
01229       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
01230 
01231       if (hpcd->LPM_State == LPM_L1)
01232       {
01233         hpcd->LPM_State = LPM_L0;
01234 
01235 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01236         hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
01237 #else
01238         HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
01239 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01240       }
01241       else
01242       {
01243 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01244         hpcd->ResumeCallback(hpcd);
01245 #else
01246         HAL_PCD_ResumeCallback(hpcd);
01247 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01248       }
01249 
01250       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
01251     }
01252 
01253     /* Handle Suspend Interrupt */
01254     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
01255     {
01256       if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
01257       {
01258 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01259         hpcd->SuspendCallback(hpcd);
01260 #else
01261         HAL_PCD_SuspendCallback(hpcd);
01262 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01263       }
01264       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
01265     }
01266 #if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
01267     /* Handle LPM Interrupt */
01268     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
01269     {
01270       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);
01271 
01272       if (hpcd->LPM_State == LPM_L0)
01273       {
01274         hpcd->LPM_State = LPM_L1;
01275         hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >> 2U;
01276 
01277 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01278         hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
01279 #else
01280         HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
01281 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01282       }
01283       else
01284       {
01285 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01286         hpcd->SuspendCallback(hpcd);
01287 #else
01288         HAL_PCD_SuspendCallback(hpcd);
01289 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01290       }
01291     }
01292 #endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
01293     /* Handle Reset Interrupt */
01294     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
01295     {
01296       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
01297       (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
01298 
01299       for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
01300       {
01301         USBx_INEP(i)->DIEPINT = 0xFB7FU;
01302         USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
01303         USBx_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
01304         USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
01305         USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
01306         USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
01307       }
01308       USBx_DEVICE->DAINTMSK |= 0x10001U;
01309 
01310       if (hpcd->Init.use_dedicated_ep1 != 0U)
01311       {
01312         USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
01313                                    USB_OTG_DOEPMSK_XFRCM |
01314                                    USB_OTG_DOEPMSK_EPDM;
01315 
01316         USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
01317                                   USB_OTG_DIEPMSK_XFRCM |
01318                                   USB_OTG_DIEPMSK_EPDM;
01319       }
01320       else
01321       {
01322         USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
01323                                 USB_OTG_DOEPMSK_XFRCM |
01324                                 USB_OTG_DOEPMSK_EPDM |
01325                                 USB_OTG_DOEPMSK_OTEPSPRM |
01326                                 USB_OTG_DOEPMSK_NAKM;
01327 
01328         USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
01329                                 USB_OTG_DIEPMSK_XFRCM |
01330                                 USB_OTG_DIEPMSK_EPDM;
01331       }
01332 
01333       /* Set Default Address to 0 */
01334       USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
01335 
01336       /* setup EP0 to receive SETUP packets */
01337       (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable,
01338                              (uint8_t *)hpcd->Setup);
01339 
01340       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
01341     }
01342 
01343     /* Handle Enumeration done Interrupt */
01344     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
01345     {
01346       (void)USB_ActivateSetup(hpcd->Instance);
01347       hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
01348 
01349       /* Set USB Turnaround time */
01350       (void)USB_SetTurnaroundTime(hpcd->Instance,
01351                                   HAL_RCC_GetHCLKFreq(),
01352                                   (uint8_t)hpcd->Init.speed);
01353 
01354 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01355       hpcd->ResetCallback(hpcd);
01356 #else
01357       HAL_PCD_ResetCallback(hpcd);
01358 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01359 
01360       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
01361     }
01362 
01363     /* Handle SOF Interrupt */
01364     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
01365     {
01366 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01367       hpcd->SOFCallback(hpcd);
01368 #else
01369       HAL_PCD_SOFCallback(hpcd);
01370 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01371 
01372       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
01373     }
01374 
01375     /* Handle Incomplete ISO IN Interrupt */
01376     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
01377     {
01378       /* Keep application checking the corresponding Iso IN endpoint
01379       causing the incomplete Interrupt */
01380       epnum = 0U;
01381 
01382 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01383       hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
01384 #else
01385       HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
01386 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01387 
01388       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
01389     }
01390 
01391     /* Handle Incomplete ISO OUT Interrupt */
01392     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
01393     {
01394       /* Keep application checking the corresponding Iso OUT endpoint
01395       causing the incomplete Interrupt */
01396       epnum = 0U;
01397 
01398 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01399       hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
01400 #else
01401       HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
01402 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01403 
01404       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
01405     }
01406 
01407     /* Handle Connection event Interrupt */
01408     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
01409     {
01410 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01411       hpcd->ConnectCallback(hpcd);
01412 #else
01413       HAL_PCD_ConnectCallback(hpcd);
01414 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01415 
01416       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
01417     }
01418 
01419     /* Handle Disconnection event Interrupt */
01420     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
01421     {
01422       temp = hpcd->Instance->GOTGINT;
01423 
01424       if ((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
01425       {
01426 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
01427         hpcd->DisconnectCallback(hpcd);
01428 #else
01429         HAL_PCD_DisconnectCallback(hpcd);
01430 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
01431       }
01432       hpcd->Instance->GOTGINT |= temp;
01433     }
01434   }
01435 }
01436 
01437 
01438 /**
01439   * @brief  Handles PCD Wakeup interrupt request.
01440   * @param  hpcd PCD handle
01441   * @retval HAL status
01442   */
01443 void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
01444 {
01445   USB_OTG_GlobalTypeDef *USBx;
01446 
01447   USBx = hpcd->Instance;
01448 
01449   if ((USBx->CID & (0x1U << 8)) == 0U)
01450   {
01451     /* Clear EXTI pending Bit */
01452     __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG();
01453   }
01454   else
01455   {
01456     /* Clear EXTI pending Bit */
01457     __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG();
01458   }
01459 }
01460 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
01461 
01462 
01463 /**
01464   * @brief  Data OUT stage callback.
01465   * @param  hpcd PCD handle
01466   * @param  epnum endpoint number
01467   * @retval None
01468   */
01469 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
01470 {
01471   /* Prevent unused argument(s) compilation warning */
01472   UNUSED(hpcd);
01473   UNUSED(epnum);
01474 
01475   /* NOTE : This function should not be modified, when the callback is needed,
01476             the HAL_PCD_DataOutStageCallback could be implemented in the user file
01477    */
01478 }
01479 
01480 /**
01481   * @brief  Data IN stage callback
01482   * @param  hpcd PCD handle
01483   * @param  epnum endpoint number
01484   * @retval None
01485   */
01486 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
01487 {
01488   /* Prevent unused argument(s) compilation warning */
01489   UNUSED(hpcd);
01490   UNUSED(epnum);
01491 
01492   /* NOTE : This function should not be modified, when the callback is needed,
01493             the HAL_PCD_DataInStageCallback could be implemented in the user file
01494    */
01495 }
01496 /**
01497   * @brief  Setup stage callback
01498   * @param  hpcd PCD handle
01499   * @retval None
01500   */
01501 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
01502 {
01503   /* Prevent unused argument(s) compilation warning */
01504   UNUSED(hpcd);
01505 
01506   /* NOTE : This function should not be modified, when the callback is needed,
01507             the HAL_PCD_SetupStageCallback could be implemented in the user file
01508    */
01509 }
01510 
01511 /**
01512   * @brief  USB Start Of Frame callback.
01513   * @param  hpcd PCD handle
01514   * @retval None
01515   */
01516 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
01517 {
01518   /* Prevent unused argument(s) compilation warning */
01519   UNUSED(hpcd);
01520 
01521   /* NOTE : This function should not be modified, when the callback is needed,
01522             the HAL_PCD_SOFCallback could be implemented in the user file
01523    */
01524 }
01525 
01526 /**
01527   * @brief  USB Reset callback.
01528   * @param  hpcd PCD handle
01529   * @retval None
01530   */
01531 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
01532 {
01533   /* Prevent unused argument(s) compilation warning */
01534   UNUSED(hpcd);
01535 
01536   /* NOTE : This function should not be modified, when the callback is needed,
01537             the HAL_PCD_ResetCallback could be implemented in the user file
01538    */
01539 }
01540 
01541 /**
01542   * @brief  Suspend event callback.
01543   * @param  hpcd PCD handle
01544   * @retval None
01545   */
01546 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
01547 {
01548   /* Prevent unused argument(s) compilation warning */
01549   UNUSED(hpcd);
01550 
01551   /* NOTE : This function should not be modified, when the callback is needed,
01552             the HAL_PCD_SuspendCallback could be implemented in the user file
01553    */
01554 }
01555 
01556 /**
01557   * @brief  Resume event callback.
01558   * @param  hpcd PCD handle
01559   * @retval None
01560   */
01561 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
01562 {
01563   /* Prevent unused argument(s) compilation warning */
01564   UNUSED(hpcd);
01565 
01566   /* NOTE : This function should not be modified, when the callback is needed,
01567             the HAL_PCD_ResumeCallback could be implemented in the user file
01568    */
01569 }
01570 
01571 /**
01572   * @brief  Incomplete ISO OUT callback.
01573   * @param  hpcd PCD handle
01574   * @param  epnum endpoint number
01575   * @retval None
01576   */
01577 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
01578 {
01579   /* Prevent unused argument(s) compilation warning */
01580   UNUSED(hpcd);
01581   UNUSED(epnum);
01582 
01583   /* NOTE : This function should not be modified, when the callback is needed,
01584             the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
01585    */
01586 }
01587 
01588 /**
01589   * @brief  Incomplete ISO IN callback.
01590   * @param  hpcd PCD handle
01591   * @param  epnum endpoint number
01592   * @retval None
01593   */
01594 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
01595 {
01596   /* Prevent unused argument(s) compilation warning */
01597   UNUSED(hpcd);
01598   UNUSED(epnum);
01599 
01600   /* NOTE : This function should not be modified, when the callback is needed,
01601             the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
01602    */
01603 }
01604 
01605 /**
01606   * @brief  Connection event callback.
01607   * @param  hpcd PCD handle
01608   * @retval None
01609   */
01610 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
01611 {
01612   /* Prevent unused argument(s) compilation warning */
01613   UNUSED(hpcd);
01614 
01615   /* NOTE : This function should not be modified, when the callback is needed,
01616             the HAL_PCD_ConnectCallback could be implemented in the user file
01617    */
01618 }
01619 
01620 /**
01621   * @brief  Disconnection event callback.
01622   * @param  hpcd PCD handle
01623   * @retval None
01624   */
01625 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
01626 {
01627   /* Prevent unused argument(s) compilation warning */
01628   UNUSED(hpcd);
01629 
01630   /* NOTE : This function should not be modified, when the callback is needed,
01631             the HAL_PCD_DisconnectCallback could be implemented in the user file
01632    */
01633 }
01634 
01635 /**
01636   * @}
01637   */
01638 
01639 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
01640   *  @brief   management functions
01641   *
01642 @verbatim
01643  ===============================================================================
01644                       ##### Peripheral Control functions #####
01645  ===============================================================================
01646     [..]
01647     This subsection provides a set of functions allowing to control the PCD data
01648     transfers.
01649 
01650 @endverbatim
01651   * @{
01652   */
01653 
01654 /**
01655   * @brief  Connect the USB device
01656   * @param  hpcd PCD handle
01657   * @retval HAL status
01658   */
01659 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
01660 {
01661   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
01662 
01663   __HAL_LOCK(hpcd);
01664 
01665   if ((hpcd->Init.battery_charging_enable == 1U) &&
01666       (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
01667   {
01668     /* Enable USB Transceiver */
01669     USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
01670   }
01671   (void)USB_DevConnect(hpcd->Instance);
01672   __HAL_UNLOCK(hpcd);
01673 
01674   return HAL_OK;
01675 }
01676 
01677 /**
01678   * @brief  Disconnect the USB device.
01679   * @param  hpcd PCD handle
01680   * @retval HAL status
01681   */
01682 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
01683 {
01684   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
01685 
01686   __HAL_LOCK(hpcd);
01687   (void)USB_DevDisconnect(hpcd->Instance);
01688 
01689   if ((hpcd->Init.battery_charging_enable == 1U) &&
01690       (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
01691   {
01692     /* Disable USB Transceiver */
01693     USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
01694   }
01695 
01696   __HAL_UNLOCK(hpcd);
01697 
01698   return HAL_OK;
01699 }
01700 
01701 /**
01702   * @brief  Set the USB Device address.
01703   * @param  hpcd PCD handle
01704   * @param  address new device address
01705   * @retval HAL status
01706   */
01707 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
01708 {
01709   __HAL_LOCK(hpcd);
01710   hpcd->USB_Address = address;
01711   (void)USB_SetDevAddress(hpcd->Instance, address);
01712   __HAL_UNLOCK(hpcd);
01713 
01714   return HAL_OK;
01715 }
01716 /**
01717   * @brief  Open and configure an endpoint.
01718   * @param  hpcd PCD handle
01719   * @param  ep_addr endpoint address
01720   * @param  ep_mps endpoint max packet size
01721   * @param  ep_type endpoint type
01722   * @retval HAL status
01723   */
01724 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
01725                                   uint16_t ep_mps, uint8_t ep_type)
01726 {
01727   HAL_StatusTypeDef  ret = HAL_OK;
01728   PCD_EPTypeDef *ep;
01729 
01730   if ((ep_addr & 0x80U) == 0x80U)
01731   {
01732     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
01733     ep->is_in = 1U;
01734   }
01735   else
01736   {
01737     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
01738     ep->is_in = 0U;
01739   }
01740 
01741   ep->num = ep_addr & EP_ADDR_MSK;
01742   ep->maxpacket = ep_mps;
01743   ep->type = ep_type;
01744 
01745   if (ep->is_in != 0U)
01746   {
01747     /* Assign a Tx FIFO */
01748     ep->tx_fifo_num = ep->num;
01749   }
01750   /* Set initial data PID. */
01751   if (ep_type == EP_TYPE_BULK)
01752   {
01753     ep->data_pid_start = 0U;
01754   }
01755 
01756   __HAL_LOCK(hpcd);
01757   (void)USB_ActivateEndpoint(hpcd->Instance, ep);
01758   __HAL_UNLOCK(hpcd);
01759 
01760   return ret;
01761 }
01762 
01763 /**
01764   * @brief  Deactivate an endpoint.
01765   * @param  hpcd PCD handle
01766   * @param  ep_addr endpoint address
01767   * @retval HAL status
01768   */
01769 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01770 {
01771   PCD_EPTypeDef *ep;
01772 
01773   if ((ep_addr & 0x80U) == 0x80U)
01774   {
01775     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
01776     ep->is_in = 1U;
01777   }
01778   else
01779   {
01780     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
01781     ep->is_in = 0U;
01782   }
01783   ep->num   = ep_addr & EP_ADDR_MSK;
01784 
01785   __HAL_LOCK(hpcd);
01786   (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
01787   __HAL_UNLOCK(hpcd);
01788   return HAL_OK;
01789 }
01790 
01791 
01792 /**
01793   * @brief  Receive an amount of data.
01794   * @param  hpcd PCD handle
01795   * @param  ep_addr endpoint address
01796   * @param  pBuf pointer to the reception buffer
01797   * @param  len amount of data to be received
01798   * @retval HAL status
01799   */
01800 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
01801 {
01802   PCD_EPTypeDef *ep;
01803 
01804   ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
01805 
01806   /*setup and start the Xfer */
01807   ep->xfer_buff = pBuf;
01808   ep->xfer_len = len;
01809   ep->xfer_count = 0U;
01810   ep->is_in = 0U;
01811   ep->num = ep_addr & EP_ADDR_MSK;
01812 
01813   if (hpcd->Init.dma_enable == 1U)
01814   {
01815     ep->dma_addr = (uint32_t)pBuf;
01816   }
01817 
01818   if ((ep_addr & EP_ADDR_MSK) == 0U)
01819   {
01820     (void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
01821   }
01822   else
01823   {
01824     (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
01825   }
01826 
01827   return HAL_OK;
01828 }
01829 
01830 /**
01831   * @brief  Get Received Data Size
01832   * @param  hpcd PCD handle
01833   * @param  ep_addr endpoint address
01834   * @retval Data Size
01835   */
01836 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01837 {
01838   return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
01839 }
01840 /**
01841   * @brief  Send an amount of data
01842   * @param  hpcd PCD handle
01843   * @param  ep_addr endpoint address
01844   * @param  pBuf pointer to the transmission buffer
01845   * @param  len amount of data to be sent
01846   * @retval HAL status
01847   */
01848 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
01849 {
01850   PCD_EPTypeDef *ep;
01851 
01852   ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
01853 
01854   /*setup and start the Xfer */
01855   ep->xfer_buff = pBuf;
01856   ep->xfer_len = len;
01857   ep->xfer_count = 0U;
01858   ep->is_in = 1U;
01859   ep->num = ep_addr & EP_ADDR_MSK;
01860 
01861   if (hpcd->Init.dma_enable == 1U)
01862   {
01863     ep->dma_addr = (uint32_t)pBuf;
01864   }
01865 
01866   if ((ep_addr & EP_ADDR_MSK) == 0U)
01867   {
01868     (void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
01869   }
01870   else
01871   {
01872     (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
01873   }
01874 
01875   return HAL_OK;
01876 }
01877 
01878 /**
01879   * @brief  Set a STALL condition over an endpoint
01880   * @param  hpcd PCD handle
01881   * @param  ep_addr endpoint address
01882   * @retval HAL status
01883   */
01884 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01885 {
01886   PCD_EPTypeDef *ep;
01887 
01888   if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
01889   {
01890     return HAL_ERROR;
01891   }
01892 
01893   if ((0x80U & ep_addr) == 0x80U)
01894   {
01895     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
01896     ep->is_in = 1U;
01897   }
01898   else
01899   {
01900     ep = &hpcd->OUT_ep[ep_addr];
01901     ep->is_in = 0U;
01902   }
01903 
01904   ep->is_stall = 1U;
01905   ep->num = ep_addr & EP_ADDR_MSK;
01906 
01907   __HAL_LOCK(hpcd);
01908 
01909   (void)USB_EPSetStall(hpcd->Instance, ep);
01910 
01911   if ((ep_addr & EP_ADDR_MSK) == 0U)
01912   {
01913     (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
01914   }
01915 
01916   __HAL_UNLOCK(hpcd);
01917 
01918   return HAL_OK;
01919 }
01920 
01921 /**
01922   * @brief  Clear a STALL condition over in an endpoint
01923   * @param  hpcd PCD handle
01924   * @param  ep_addr endpoint address
01925   * @retval HAL status
01926   */
01927 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01928 {
01929   PCD_EPTypeDef *ep;
01930 
01931   if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
01932   {
01933     return HAL_ERROR;
01934   }
01935 
01936   if ((0x80U & ep_addr) == 0x80U)
01937   {
01938     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
01939     ep->is_in = 1U;
01940   }
01941   else
01942   {
01943     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
01944     ep->is_in = 0U;
01945   }
01946 
01947   ep->is_stall = 0U;
01948   ep->num = ep_addr & EP_ADDR_MSK;
01949 
01950   __HAL_LOCK(hpcd);
01951   (void)USB_EPClearStall(hpcd->Instance, ep);
01952   __HAL_UNLOCK(hpcd);
01953 
01954   return HAL_OK;
01955 }
01956 
01957 /**
01958   * @brief  Flush an endpoint
01959   * @param  hpcd PCD handle
01960   * @param  ep_addr endpoint address
01961   * @retval HAL status
01962   */
01963 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01964 {
01965   __HAL_LOCK(hpcd);
01966 
01967   if ((ep_addr & 0x80U) == 0x80U)
01968   {
01969     (void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
01970   }
01971   else
01972   {
01973     (void)USB_FlushRxFifo(hpcd->Instance);
01974   }
01975 
01976   __HAL_UNLOCK(hpcd);
01977 
01978   return HAL_OK;
01979 }
01980 
01981 /**
01982   * @brief  Activate remote wakeup signalling
01983   * @param  hpcd PCD handle
01984   * @retval HAL status
01985   */
01986 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
01987 {
01988   return (USB_ActivateRemoteWakeup(hpcd->Instance));
01989 }
01990 
01991 /**
01992   * @brief  De-activate remote wakeup signalling.
01993   * @param  hpcd PCD handle
01994   * @retval HAL status
01995   */
01996 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
01997 {
01998   return (USB_DeActivateRemoteWakeup(hpcd->Instance));
01999 }
02000 
02001 /**
02002   * @}
02003   */
02004 
02005 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
02006   *  @brief   Peripheral State functions
02007   *
02008 @verbatim
02009  ===============================================================================
02010                       ##### Peripheral State functions #####
02011  ===============================================================================
02012     [..]
02013     This subsection permits to get in run-time the status of the peripheral
02014     and the data flow.
02015 
02016 @endverbatim
02017   * @{
02018   */
02019 
02020 /**
02021   * @brief  Return the PCD handle state.
02022   * @param  hpcd PCD handle
02023   * @retval HAL state
02024   */
02025 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
02026 {
02027   return hpcd->State;
02028 }
02029 
02030 /**
02031   * @}
02032   */
02033 
02034 /**
02035   * @}
02036   */
02037 
02038 /* Private functions ---------------------------------------------------------*/
02039 /** @addtogroup PCD_Private_Functions
02040   * @{
02041   */
02042 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
02043 /**
02044   * @brief  Check FIFO for the next packet to be loaded.
02045   * @param  hpcd PCD handle
02046   * @param  epnum endpoint number
02047   * @retval HAL status
02048   */
02049 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
02050 {
02051   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
02052   uint32_t USBx_BASE = (uint32_t)USBx;
02053   USB_OTG_EPTypeDef *ep;
02054   uint32_t len;
02055   uint32_t len32b;
02056   uint32_t fifoemptymsk;
02057 
02058   ep = &hpcd->IN_ep[epnum];
02059 
02060   if (ep->xfer_count > ep->xfer_len)
02061   {
02062     return HAL_ERROR;
02063   }
02064 
02065   len = ep->xfer_len - ep->xfer_count;
02066 
02067   if (len > ep->maxpacket)
02068   {
02069     len = ep->maxpacket;
02070   }
02071 
02072   len32b = (len + 3U) / 4U;
02073 
02074   while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
02075          (ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
02076   {
02077     /* Write the FIFO */
02078     len = ep->xfer_len - ep->xfer_count;
02079 
02080     if (len > ep->maxpacket)
02081     {
02082       len = ep->maxpacket;
02083     }
02084     len32b = (len + 3U) / 4U;
02085 
02086     (void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len,
02087                           (uint8_t)hpcd->Init.dma_enable);
02088 
02089     ep->xfer_buff  += len;
02090     ep->xfer_count += len;
02091   }
02092 
02093   if (ep->xfer_len <= ep->xfer_count)
02094   {
02095     fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
02096     USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
02097   }
02098 
02099   return HAL_OK;
02100 }
02101 
02102 
02103 /**
02104   * @brief  process EP OUT transfer complete interrupt.
02105   * @param  hpcd PCD handle
02106   * @param  epnum endpoint number
02107   * @retval HAL status
02108   */
02109 static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
02110 {
02111   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
02112   uint32_t USBx_BASE = (uint32_t)USBx;
02113   uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);
02114   uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
02115 
02116   if (hpcd->Init.dma_enable == 1U)
02117   {
02118     if ((DoepintReg & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) /* Class C */
02119     {
02120       /* StupPktRcvd = 1 this is a setup packet */
02121       if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
02122           ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
02123       {
02124         CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
02125       }
02126     }
02127     else if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) /* Class E */
02128     {
02129       CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
02130     }
02131     else if ((DoepintReg & (USB_OTG_DOEPINT_STUP | USB_OTG_DOEPINT_OTEPSPR)) == 0U)
02132     {
02133       /* StupPktRcvd = 1 this is a setup packet */
02134       if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
02135           ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
02136       {
02137         CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
02138       }
02139       else
02140       {
02141         /* out data packet received over EP0 */
02142         hpcd->OUT_ep[epnum].xfer_count =
02143           hpcd->OUT_ep[epnum].maxpacket -
02144           (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
02145 
02146         hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket;
02147 
02148         if ((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U))
02149         {
02150           /* this is ZLP, so prepare EP0 for next setup */
02151           (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
02152         }
02153 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
02154         hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
02155 #else
02156         HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
02157 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
02158       }
02159     }
02160     else
02161     {
02162       /* ... */
02163     }
02164   }
02165   else
02166   {
02167     if (gSNPSiD == USB_OTG_CORE_ID_310A)
02168     {
02169       /* StupPktRcvd = 1 this is a setup packet */
02170       if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
02171       {
02172         CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
02173       }
02174       else
02175       {
02176         if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
02177         {
02178           CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
02179         }
02180 
02181 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
02182         hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
02183 #else
02184         HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
02185 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
02186       }
02187     }
02188     else
02189     {
02190       if ((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U))
02191       {
02192         /* this is ZLP, so prepare EP0 for next setup */
02193         (void)USB_EP0_OutStart(hpcd->Instance, 0U, (uint8_t *)hpcd->Setup);
02194       }
02195 
02196 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
02197       hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
02198 #else
02199       HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
02200 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
02201     }
02202   }
02203 
02204   return HAL_OK;
02205 }
02206 
02207 
02208 /**
02209   * @brief  process EP OUT setup packet received interrupt.
02210   * @param  hpcd PCD handle
02211   * @param  epnum endpoint number
02212   * @retval HAL status
02213   */
02214 static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
02215 {
02216   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
02217   uint32_t USBx_BASE = (uint32_t)USBx;
02218   uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);
02219   uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
02220 
02221   if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
02222       ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
02223   {
02224     CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
02225   }
02226 
02227   /* Inform the upper layer that a setup packet is available */
02228 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
02229   hpcd->SetupStageCallback(hpcd);
02230 #else
02231   HAL_PCD_SetupStageCallback(hpcd);
02232 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
02233 
02234   if ((gSNPSiD > USB_OTG_CORE_ID_300A) && (hpcd->Init.dma_enable == 1U))
02235   {
02236     (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
02237   }
02238 
02239   return HAL_OK;
02240 }
02241 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
02242 
02243 
02244 /**
02245   * @}
02246   */
02247 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
02248 #endif /* HAL_PCD_MODULE_ENABLED */
02249 
02250 /**
02251   * @}
02252   */
02253 
02254 /**
02255   * @}
02256   */