Subversion Repositories ScreenTimer

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**
  2.   ******************************************************************************
  3.   * @file    stm32f0xx_hal_pcd.c
  4.   * @author  MCD Application Team
  5.   * @brief   PCD HAL module driver.
  6.   *          This file provides firmware functions to manage the following
  7.   *          functionalities of the USB Peripheral Controller:
  8.   *           + Initialization and de-initialization functions
  9.   *           + IO operation functions
  10.   *           + Peripheral Control functions
  11.   *           + Peripheral State functions
  12.   *
  13.   @verbatim
  14.   ==============================================================================
  15.                     ##### How to use this driver #####
  16.   ==============================================================================
  17.     [..]
  18.       The PCD HAL driver can be used as follows:
  19.  
  20.      (#) Declare a PCD_HandleTypeDef handle structure, for example:
  21.          PCD_HandleTypeDef  hpcd;
  22.  
  23.      (#) Fill parameters of Init structure in HCD handle
  24.  
  25.      (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
  26.  
  27.      (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
  28.          (##) Enable the PCD/USB Low Level interface clock using
  29.               (+++) __HAL_RCC_USB_CLK_ENABLE(); For USB Device only FS peripheral
  30.  
  31.          (##) Initialize the related GPIO clocks
  32.          (##) Configure PCD pin-out
  33.          (##) Configure PCD NVIC interrupt
  34.  
  35.      (#)Associate the Upper USB device stack to the HAL PCD Driver:
  36.          (##) hpcd.pData = pdev;
  37.  
  38.      (#)Enable PCD transmission and reception:
  39.          (##) HAL_PCD_Start();
  40.  
  41.   @endverbatim
  42.   ******************************************************************************
  43.   * @attention
  44.   *
  45.   * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
  46.   * All rights reserved.</center></h2>
  47.   *
  48.   * This software component is licensed by ST under BSD 3-Clause license,
  49.   * the "License"; You may not use this file except in compliance with the
  50.   * License. You may obtain a copy of the License at:
  51.   *                        opensource.org/licenses/BSD-3-Clause
  52.   *
  53.   ******************************************************************************
  54.   */
  55.  
  56. /* Includes ------------------------------------------------------------------*/
  57. #include "stm32f0xx_hal.h"
  58.  
  59. /** @addtogroup STM32F0xx_HAL_Driver
  60.   * @{
  61.   */
  62.  
  63. /** @defgroup PCD PCD
  64.   * @brief PCD HAL module driver
  65.   * @{
  66.   */
  67.  
  68. #ifdef HAL_PCD_MODULE_ENABLED
  69.  
  70. #if defined (USB)
  71.  
  72. /* Private types -------------------------------------------------------------*/
  73. /* Private variables ---------------------------------------------------------*/
  74. /* Private constants ---------------------------------------------------------*/
  75. /* Private macros ------------------------------------------------------------*/
  76. /** @defgroup PCD_Private_Macros PCD Private Macros
  77.   * @{
  78.   */
  79. #define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
  80. #define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
  81. /**
  82.   * @}
  83.   */
  84.  
  85. /* Private functions prototypes ----------------------------------------------*/
  86. /** @defgroup PCD_Private_Functions PCD Private Functions
  87.   * @{
  88.   */
  89.  
  90. static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
  91. static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
  92. static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
  93.  
  94. /**
  95.   * @}
  96.   */
  97.  
  98. /* Exported functions --------------------------------------------------------*/
  99. /** @defgroup PCD_Exported_Functions PCD Exported Functions
  100.   * @{
  101.   */
  102.  
  103. /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
  104.   *  @brief    Initialization and Configuration functions
  105.   *
  106. @verbatim
  107.  ===============================================================================
  108.             ##### Initialization and de-initialization functions #####
  109.  ===============================================================================
  110.     [..]  This section provides functions allowing to:
  111.  
  112. @endverbatim
  113.   * @{
  114.   */
  115.  
  116. /**
  117.   * @brief  Initializes the PCD according to the specified
  118.   *         parameters in the PCD_InitTypeDef and initialize the associated handle.
  119.   * @param  hpcd PCD handle
  120.   * @retval HAL status
  121.   */
  122. HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
  123. {
  124.   uint8_t i;
  125.  
  126.   /* Check the PCD handle allocation */
  127.   if (hpcd == NULL)
  128.   {
  129.     return HAL_ERROR;
  130.   }
  131.  
  132.   /* Check the parameters */
  133.   assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
  134.  
  135.   if (hpcd->State == HAL_PCD_STATE_RESET)
  136.   {
  137.     /* Allocate lock resource and initialize it */
  138.     hpcd->Lock = HAL_UNLOCKED;
  139.  
  140. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  141.     hpcd->SOFCallback = HAL_PCD_SOFCallback;
  142.     hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
  143.     hpcd->ResetCallback = HAL_PCD_ResetCallback;
  144.     hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
  145.     hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
  146.     hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
  147.     hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
  148.     hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
  149.     hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
  150.     hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
  151.     hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
  152.     hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;
  153.     hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;
  154.  
  155.     if (hpcd->MspInitCallback == NULL)
  156.     {
  157.       hpcd->MspInitCallback = HAL_PCD_MspInit;
  158.     }
  159.  
  160.     /* Init the low level hardware */
  161.     hpcd->MspInitCallback(hpcd);
  162. #else
  163.     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
  164.     HAL_PCD_MspInit(hpcd);
  165. #endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
  166.   }
  167.  
  168.   hpcd->State = HAL_PCD_STATE_BUSY;
  169.  
  170.   /* Disable the Interrupts */
  171.   __HAL_PCD_DISABLE(hpcd);
  172.  
  173.   /* Init endpoints structures */
  174.   for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
  175.   {
  176.     /* Init ep structure */
  177.     hpcd->IN_ep[i].is_in = 1U;
  178.     hpcd->IN_ep[i].num = i;
  179.     hpcd->IN_ep[i].tx_fifo_num = i;
  180.     /* Control until ep is activated */
  181.     hpcd->IN_ep[i].type = EP_TYPE_CTRL;
  182.     hpcd->IN_ep[i].maxpacket = 0U;
  183.     hpcd->IN_ep[i].xfer_buff = 0U;
  184.     hpcd->IN_ep[i].xfer_len = 0U;
  185.   }
  186.  
  187.   for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
  188.   {
  189.     hpcd->OUT_ep[i].is_in = 0U;
  190.     hpcd->OUT_ep[i].num = i;
  191.     /* Control until ep is activated */
  192.     hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
  193.     hpcd->OUT_ep[i].maxpacket = 0U;
  194.     hpcd->OUT_ep[i].xfer_buff = 0U;
  195.     hpcd->OUT_ep[i].xfer_len = 0U;
  196.   }
  197.  
  198.   /* Init Device */
  199.   (void)USB_DevInit(hpcd->Instance, hpcd->Init);
  200.  
  201.   hpcd->USB_Address = 0U;
  202.   hpcd->State = HAL_PCD_STATE_READY;
  203.  
  204.   /* Activate LPM */
  205.   if (hpcd->Init.lpm_enable == 1U)
  206.   {
  207.     (void)HAL_PCDEx_ActivateLPM(hpcd);
  208.   }
  209.  
  210.   return HAL_OK;
  211. }
  212.  
  213. /**
  214.   * @brief  DeInitializes the PCD peripheral.
  215.   * @param  hpcd PCD handle
  216.   * @retval HAL status
  217.   */
  218. HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
  219. {
  220.   /* Check the PCD handle allocation */
  221.   if (hpcd == NULL)
  222.   {
  223.     return HAL_ERROR;
  224.   }
  225.  
  226.   hpcd->State = HAL_PCD_STATE_BUSY;
  227.  
  228.   /* Stop Device */
  229.   if (USB_StopDevice(hpcd->Instance) != HAL_OK)
  230.   {
  231.     return HAL_ERROR;
  232.   }
  233.  
  234. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  235.   if (hpcd->MspDeInitCallback == NULL)
  236.   {
  237.     hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit  */
  238.   }
  239.  
  240.   /* DeInit the low level hardware */
  241.   hpcd->MspDeInitCallback(hpcd);
  242. #else
  243.   /* DeInit the low level hardware: CLOCK, NVIC.*/
  244.   HAL_PCD_MspDeInit(hpcd);
  245. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  246.  
  247.   hpcd->State = HAL_PCD_STATE_RESET;
  248.  
  249.   return HAL_OK;
  250. }
  251.  
  252. /**
  253.   * @brief  Initializes the PCD MSP.
  254.   * @param  hpcd PCD handle
  255.   * @retval None
  256.   */
  257. __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
  258. {
  259.   /* Prevent unused argument(s) compilation warning */
  260.   UNUSED(hpcd);
  261.  
  262.   /* NOTE : This function should not be modified, when the callback is needed,
  263.             the HAL_PCD_MspInit could be implemented in the user file
  264.    */
  265. }
  266.  
  267. /**
  268.   * @brief  DeInitializes PCD MSP.
  269.   * @param  hpcd PCD handle
  270.   * @retval None
  271.   */
  272. __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
  273. {
  274.   /* Prevent unused argument(s) compilation warning */
  275.   UNUSED(hpcd);
  276.  
  277.   /* NOTE : This function should not be modified, when the callback is needed,
  278.             the HAL_PCD_MspDeInit could be implemented in the user file
  279.    */
  280. }
  281.  
  282. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  283. /**
  284.   * @brief  Register a User USB PCD Callback
  285.   *         To be used instead of the weak predefined callback
  286.   * @param  hpcd USB PCD handle
  287.   * @param  CallbackID ID of the callback to be registered
  288.   *         This parameter can be one of the following values:
  289.   *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
  290.   *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
  291.   *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
  292.   *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
  293.   *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
  294.   *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
  295.   *          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
  296.   *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
  297.   *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
  298.   * @param  pCallback pointer to the Callback function
  299.   * @retval HAL status
  300.   */
  301. HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
  302.                                            HAL_PCD_CallbackIDTypeDef CallbackID,
  303.                                            pPCD_CallbackTypeDef pCallback)
  304. {
  305.   HAL_StatusTypeDef status = HAL_OK;
  306.  
  307.   if (pCallback == NULL)
  308.   {
  309.     /* Update the error code */
  310.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  311.     return HAL_ERROR;
  312.   }
  313.   /* Process locked */
  314.   __HAL_LOCK(hpcd);
  315.  
  316.   if (hpcd->State == HAL_PCD_STATE_READY)
  317.   {
  318.     switch (CallbackID)
  319.     {
  320.       case HAL_PCD_SOF_CB_ID :
  321.         hpcd->SOFCallback = pCallback;
  322.         break;
  323.  
  324.       case HAL_PCD_SETUPSTAGE_CB_ID :
  325.         hpcd->SetupStageCallback = pCallback;
  326.         break;
  327.  
  328.       case HAL_PCD_RESET_CB_ID :
  329.         hpcd->ResetCallback = pCallback;
  330.         break;
  331.  
  332.       case HAL_PCD_SUSPEND_CB_ID :
  333.         hpcd->SuspendCallback = pCallback;
  334.         break;
  335.  
  336.       case HAL_PCD_RESUME_CB_ID :
  337.         hpcd->ResumeCallback = pCallback;
  338.         break;
  339.  
  340.       case HAL_PCD_CONNECT_CB_ID :
  341.         hpcd->ConnectCallback = pCallback;
  342.         break;
  343.  
  344.       case HAL_PCD_DISCONNECT_CB_ID :
  345.         hpcd->DisconnectCallback = pCallback;
  346.         break;
  347.  
  348.       case HAL_PCD_MSPINIT_CB_ID :
  349.         hpcd->MspInitCallback = pCallback;
  350.         break;
  351.  
  352.       case HAL_PCD_MSPDEINIT_CB_ID :
  353.         hpcd->MspDeInitCallback = pCallback;
  354.         break;
  355.  
  356.       default :
  357.         /* Update the error code */
  358.         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  359.         /* Return error status */
  360.         status =  HAL_ERROR;
  361.         break;
  362.     }
  363.   }
  364.   else if (hpcd->State == HAL_PCD_STATE_RESET)
  365.   {
  366.     switch (CallbackID)
  367.     {
  368.       case HAL_PCD_MSPINIT_CB_ID :
  369.         hpcd->MspInitCallback = pCallback;
  370.         break;
  371.  
  372.       case HAL_PCD_MSPDEINIT_CB_ID :
  373.         hpcd->MspDeInitCallback = pCallback;
  374.         break;
  375.  
  376.       default :
  377.         /* Update the error code */
  378.         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  379.         /* Return error status */
  380.         status =  HAL_ERROR;
  381.         break;
  382.     }
  383.   }
  384.   else
  385.   {
  386.     /* Update the error code */
  387.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  388.     /* Return error status */
  389.     status =  HAL_ERROR;
  390.   }
  391.  
  392.   /* Release Lock */
  393.   __HAL_UNLOCK(hpcd);
  394.   return status;
  395. }
  396.  
  397. /**
  398.   * @brief  Unregister an USB PCD Callback
  399.   *         USB PCD callabck is redirected to the weak predefined callback
  400.   * @param  hpcd USB PCD handle
  401.   * @param  CallbackID ID of the callback to be unregistered
  402.   *         This parameter can be one of the following values:
  403.   *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
  404.   *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
  405.   *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
  406.   *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
  407.   *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
  408.   *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
  409.   *          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
  410.   *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
  411.   *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
  412.   * @retval HAL status
  413.   */
  414. HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
  415. {
  416.   HAL_StatusTypeDef status = HAL_OK;
  417.  
  418.   /* Process locked */
  419.   __HAL_LOCK(hpcd);
  420.  
  421.   /* Setup Legacy weak Callbacks  */
  422.   if (hpcd->State == HAL_PCD_STATE_READY)
  423.   {
  424.     switch (CallbackID)
  425.     {
  426.       case HAL_PCD_SOF_CB_ID :
  427.         hpcd->SOFCallback = HAL_PCD_SOFCallback;
  428.         break;
  429.  
  430.       case HAL_PCD_SETUPSTAGE_CB_ID :
  431.         hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
  432.         break;
  433.  
  434.       case HAL_PCD_RESET_CB_ID :
  435.         hpcd->ResetCallback = HAL_PCD_ResetCallback;
  436.         break;
  437.  
  438.       case HAL_PCD_SUSPEND_CB_ID :
  439.         hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
  440.         break;
  441.  
  442.       case HAL_PCD_RESUME_CB_ID :
  443.         hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
  444.         break;
  445.  
  446.       case HAL_PCD_CONNECT_CB_ID :
  447.         hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
  448.         break;
  449.  
  450.       case HAL_PCD_DISCONNECT_CB_ID :
  451.         hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
  452.         break;
  453.  
  454.       case HAL_PCD_MSPINIT_CB_ID :
  455.         hpcd->MspInitCallback = HAL_PCD_MspInit;
  456.         break;
  457.  
  458.       case HAL_PCD_MSPDEINIT_CB_ID :
  459.         hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
  460.         break;
  461.  
  462.       default :
  463.         /* Update the error code */
  464.         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  465.  
  466.         /* Return error status */
  467.         status =  HAL_ERROR;
  468.         break;
  469.     }
  470.   }
  471.   else if (hpcd->State == HAL_PCD_STATE_RESET)
  472.   {
  473.     switch (CallbackID)
  474.     {
  475.       case HAL_PCD_MSPINIT_CB_ID :
  476.         hpcd->MspInitCallback = HAL_PCD_MspInit;
  477.         break;
  478.  
  479.       case HAL_PCD_MSPDEINIT_CB_ID :
  480.         hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
  481.         break;
  482.  
  483.       default :
  484.         /* Update the error code */
  485.         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  486.  
  487.         /* Return error status */
  488.         status =  HAL_ERROR;
  489.         break;
  490.     }
  491.   }
  492.   else
  493.   {
  494.     /* Update the error code */
  495.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  496.  
  497.     /* Return error status */
  498.     status =  HAL_ERROR;
  499.   }
  500.  
  501.   /* Release Lock */
  502.   __HAL_UNLOCK(hpcd);
  503.   return status;
  504. }
  505.  
  506. /**
  507.   * @brief  Register USB PCD Data OUT Stage Callback
  508.   *         To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
  509.   * @param  hpcd PCD handle
  510.   * @param  pCallback pointer to the USB PCD Data OUT Stage Callback function
  511.   * @retval HAL status
  512.   */
  513. HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
  514.                                                        pPCD_DataOutStageCallbackTypeDef pCallback)
  515. {
  516.   HAL_StatusTypeDef status = HAL_OK;
  517.  
  518.   if (pCallback == NULL)
  519.   {
  520.     /* Update the error code */
  521.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  522.  
  523.     return HAL_ERROR;
  524.   }
  525.  
  526.   /* Process locked */
  527.   __HAL_LOCK(hpcd);
  528.  
  529.   if (hpcd->State == HAL_PCD_STATE_READY)
  530.   {
  531.     hpcd->DataOutStageCallback = pCallback;
  532.   }
  533.   else
  534.   {
  535.     /* Update the error code */
  536.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  537.  
  538.     /* Return error status */
  539.     status =  HAL_ERROR;
  540.   }
  541.  
  542.   /* Release Lock */
  543.   __HAL_UNLOCK(hpcd);
  544.  
  545.   return status;
  546. }
  547.  
  548. /**
  549.   * @brief  Unregister the USB PCD Data OUT Stage Callback
  550.   *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
  551.   * @param  hpcd PCD handle
  552.   * @retval HAL status
  553.   */
  554. HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
  555. {
  556.   HAL_StatusTypeDef status = HAL_OK;
  557.  
  558.   /* Process locked */
  559.   __HAL_LOCK(hpcd);
  560.  
  561.   if (hpcd->State == HAL_PCD_STATE_READY)
  562.   {
  563.     hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback  */
  564.   }
  565.   else
  566.   {
  567.     /* Update the error code */
  568.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  569.  
  570.     /* Return error status */
  571.     status =  HAL_ERROR;
  572.   }
  573.  
  574.   /* Release Lock */
  575.   __HAL_UNLOCK(hpcd);
  576.  
  577.   return status;
  578. }
  579.  
  580. /**
  581.   * @brief  Register USB PCD Data IN Stage Callback
  582.   *         To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
  583.   * @param  hpcd PCD handle
  584.   * @param  pCallback pointer to the USB PCD Data IN Stage Callback function
  585.   * @retval HAL status
  586.   */
  587. HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
  588.                                                       pPCD_DataInStageCallbackTypeDef pCallback)
  589. {
  590.   HAL_StatusTypeDef status = HAL_OK;
  591.  
  592.   if (pCallback == NULL)
  593.   {
  594.     /* Update the error code */
  595.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  596.  
  597.     return HAL_ERROR;
  598.   }
  599.  
  600.   /* Process locked */
  601.   __HAL_LOCK(hpcd);
  602.  
  603.   if (hpcd->State == HAL_PCD_STATE_READY)
  604.   {
  605.     hpcd->DataInStageCallback = pCallback;
  606.   }
  607.   else
  608.   {
  609.     /* Update the error code */
  610.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  611.  
  612.     /* Return error status */
  613.     status =  HAL_ERROR;
  614.   }
  615.  
  616.   /* Release Lock */
  617.   __HAL_UNLOCK(hpcd);
  618.  
  619.   return status;
  620. }
  621.  
  622. /**
  623.   * @brief  Unregister the USB PCD Data IN Stage Callback
  624.   *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
  625.   * @param  hpcd PCD handle
  626.   * @retval HAL status
  627.   */
  628. HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
  629. {
  630.   HAL_StatusTypeDef status = HAL_OK;
  631.  
  632.   /* Process locked */
  633.   __HAL_LOCK(hpcd);
  634.  
  635.   if (hpcd->State == HAL_PCD_STATE_READY)
  636.   {
  637.     hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback  */
  638.   }
  639.   else
  640.   {
  641.     /* Update the error code */
  642.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  643.  
  644.     /* Return error status */
  645.     status =  HAL_ERROR;
  646.   }
  647.  
  648.   /* Release Lock */
  649.   __HAL_UNLOCK(hpcd);
  650.  
  651.   return status;
  652. }
  653.  
  654. /**
  655.   * @brief  Register USB PCD Iso OUT incomplete Callback
  656.   *         To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
  657.   * @param  hpcd PCD handle
  658.   * @param  pCallback pointer to the USB PCD Iso OUT incomplete Callback function
  659.   * @retval HAL status
  660.   */
  661. HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
  662.                                                        pPCD_IsoOutIncpltCallbackTypeDef pCallback)
  663. {
  664.   HAL_StatusTypeDef status = HAL_OK;
  665.  
  666.   if (pCallback == NULL)
  667.   {
  668.     /* Update the error code */
  669.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  670.  
  671.     return HAL_ERROR;
  672.   }
  673.  
  674.   /* Process locked */
  675.   __HAL_LOCK(hpcd);
  676.  
  677.   if (hpcd->State == HAL_PCD_STATE_READY)
  678.   {
  679.     hpcd->ISOOUTIncompleteCallback = pCallback;
  680.   }
  681.   else
  682.   {
  683.     /* Update the error code */
  684.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  685.  
  686.     /* Return error status */
  687.     status =  HAL_ERROR;
  688.   }
  689.  
  690.   /* Release Lock */
  691.   __HAL_UNLOCK(hpcd);
  692.  
  693.   return status;
  694. }
  695.  
  696. /**
  697.   * @brief  Unregister the USB PCD Iso OUT incomplete Callback
  698.   *         USB PCD Iso OUT incomplete Callback is redirected
  699.   *         to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
  700.   * @param  hpcd PCD handle
  701.   * @retval HAL status
  702.   */
  703. HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
  704. {
  705.   HAL_StatusTypeDef status = HAL_OK;
  706.  
  707.   /* Process locked */
  708.   __HAL_LOCK(hpcd);
  709.  
  710.   if (hpcd->State == HAL_PCD_STATE_READY)
  711.   {
  712.     hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback  */
  713.   }
  714.   else
  715.   {
  716.     /* Update the error code */
  717.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  718.  
  719.     /* Return error status */
  720.     status =  HAL_ERROR;
  721.   }
  722.  
  723.   /* Release Lock */
  724.   __HAL_UNLOCK(hpcd);
  725.  
  726.   return status;
  727. }
  728.  
  729. /**
  730.   * @brief  Register USB PCD Iso IN incomplete Callback
  731.   *         To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
  732.   * @param  hpcd PCD handle
  733.   * @param  pCallback pointer to the USB PCD Iso IN incomplete Callback function
  734.   * @retval HAL status
  735.   */
  736. HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
  737.                                                       pPCD_IsoInIncpltCallbackTypeDef pCallback)
  738. {
  739.   HAL_StatusTypeDef status = HAL_OK;
  740.  
  741.   if (pCallback == NULL)
  742.   {
  743.     /* Update the error code */
  744.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  745.  
  746.     return HAL_ERROR;
  747.   }
  748.  
  749.   /* Process locked */
  750.   __HAL_LOCK(hpcd);
  751.  
  752.   if (hpcd->State == HAL_PCD_STATE_READY)
  753.   {
  754.     hpcd->ISOINIncompleteCallback = pCallback;
  755.   }
  756.   else
  757.   {
  758.     /* Update the error code */
  759.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  760.  
  761.     /* Return error status */
  762.     status =  HAL_ERROR;
  763.   }
  764.  
  765.   /* Release Lock */
  766.   __HAL_UNLOCK(hpcd);
  767.  
  768.   return status;
  769. }
  770.  
  771. /**
  772.   * @brief  Unregister the USB PCD Iso IN incomplete Callback
  773.   *         USB PCD Iso IN incomplete Callback is redirected
  774.   *         to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
  775.   * @param  hpcd PCD handle
  776.   * @retval HAL status
  777.   */
  778. HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
  779. {
  780.   HAL_StatusTypeDef status = HAL_OK;
  781.  
  782.   /* Process locked */
  783.   __HAL_LOCK(hpcd);
  784.  
  785.   if (hpcd->State == HAL_PCD_STATE_READY)
  786.   {
  787.     hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback  */
  788.   }
  789.   else
  790.   {
  791.     /* Update the error code */
  792.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  793.  
  794.     /* Return error status */
  795.     status =  HAL_ERROR;
  796.   }
  797.  
  798.   /* Release Lock */
  799.   __HAL_UNLOCK(hpcd);
  800.  
  801.   return status;
  802. }
  803.  
  804. /**
  805.   * @brief  Register USB PCD BCD Callback
  806.   *         To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
  807.   * @param  hpcd PCD handle
  808.   * @param  pCallback pointer to the USB PCD BCD Callback function
  809.   * @retval HAL status
  810.   */
  811. HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
  812. {
  813.   HAL_StatusTypeDef status = HAL_OK;
  814.  
  815.   if (pCallback == NULL)
  816.   {
  817.     /* Update the error code */
  818.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  819.  
  820.     return HAL_ERROR;
  821.   }
  822.  
  823.   /* Process locked */
  824.   __HAL_LOCK(hpcd);
  825.  
  826.   if (hpcd->State == HAL_PCD_STATE_READY)
  827.   {
  828.     hpcd->BCDCallback = pCallback;
  829.   }
  830.   else
  831.   {
  832.     /* Update the error code */
  833.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  834.  
  835.     /* Return error status */
  836.     status =  HAL_ERROR;
  837.   }
  838.  
  839.   /* Release Lock */
  840.   __HAL_UNLOCK(hpcd);
  841.  
  842.   return status;
  843. }
  844.  
  845. /**
  846.   * @brief  Unregister the USB PCD BCD Callback
  847.   *         USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
  848.   * @param  hpcd PCD handle
  849.   * @retval HAL status
  850.   */
  851. HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
  852. {
  853.   HAL_StatusTypeDef status = HAL_OK;
  854.  
  855.   /* Process locked */
  856.   __HAL_LOCK(hpcd);
  857.  
  858.   if (hpcd->State == HAL_PCD_STATE_READY)
  859.   {
  860.     hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback  */
  861.   }
  862.   else
  863.   {
  864.     /* Update the error code */
  865.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  866.  
  867.     /* Return error status */
  868.     status =  HAL_ERROR;
  869.   }
  870.  
  871.   /* Release Lock */
  872.   __HAL_UNLOCK(hpcd);
  873.  
  874.   return status;
  875. }
  876.  
  877. /**
  878.   * @brief  Register USB PCD LPM Callback
  879.   *         To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
  880.   * @param  hpcd PCD handle
  881.   * @param  pCallback pointer to the USB PCD LPM Callback function
  882.   * @retval HAL status
  883.   */
  884. HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
  885. {
  886.   HAL_StatusTypeDef status = HAL_OK;
  887.  
  888.   if (pCallback == NULL)
  889.   {
  890.     /* Update the error code */
  891.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  892.  
  893.     return HAL_ERROR;
  894.   }
  895.  
  896.   /* Process locked */
  897.   __HAL_LOCK(hpcd);
  898.  
  899.   if (hpcd->State == HAL_PCD_STATE_READY)
  900.   {
  901.     hpcd->LPMCallback = pCallback;
  902.   }
  903.   else
  904.   {
  905.     /* Update the error code */
  906.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  907.  
  908.     /* Return error status */
  909.     status =  HAL_ERROR;
  910.   }
  911.  
  912.   /* Release Lock */
  913.   __HAL_UNLOCK(hpcd);
  914.  
  915.   return status;
  916. }
  917.  
  918. /**
  919.   * @brief  Unregister the USB PCD LPM Callback
  920.   *         USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
  921.   * @param  hpcd PCD handle
  922.   * @retval HAL status
  923.   */
  924. HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
  925. {
  926.   HAL_StatusTypeDef status = HAL_OK;
  927.  
  928.   /* Process locked */
  929.   __HAL_LOCK(hpcd);
  930.  
  931.   if (hpcd->State == HAL_PCD_STATE_READY)
  932.   {
  933.     hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback  */
  934.   }
  935.   else
  936.   {
  937.     /* Update the error code */
  938.     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
  939.  
  940.     /* Return error status */
  941.     status =  HAL_ERROR;
  942.   }
  943.  
  944.   /* Release Lock */
  945.   __HAL_UNLOCK(hpcd);
  946.  
  947.   return status;
  948. }
  949. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  950.  
  951. /**
  952.   * @}
  953.   */
  954.  
  955. /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
  956.   *  @brief   Data transfers functions
  957.   *
  958. @verbatim
  959.  ===============================================================================
  960.                       ##### IO operation functions #####
  961.  ===============================================================================
  962.     [..]
  963.     This subsection provides a set of functions allowing to manage the PCD data
  964.     transfers.
  965.  
  966. @endverbatim
  967.   * @{
  968.   */
  969.  
  970. /**
  971.   * @brief  Start the USB device
  972.   * @param  hpcd PCD handle
  973.   * @retval HAL status
  974.   */
  975. HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
  976. {
  977.   __HAL_LOCK(hpcd);
  978.   __HAL_PCD_ENABLE(hpcd);
  979.   (void)USB_DevConnect(hpcd->Instance);
  980.   __HAL_UNLOCK(hpcd);
  981.  
  982.   return HAL_OK;
  983. }
  984.  
  985. /**
  986.   * @brief  Stop the USB device.
  987.   * @param  hpcd PCD handle
  988.   * @retval HAL status
  989.   */
  990. HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
  991. {
  992.   __HAL_LOCK(hpcd);
  993.   __HAL_PCD_DISABLE(hpcd);
  994.   (void)USB_DevDisconnect(hpcd->Instance);
  995.   __HAL_UNLOCK(hpcd);
  996.  
  997.   return HAL_OK;
  998. }
  999.  
  1000.  
  1001. /**
  1002.   * @brief  This function handles PCD interrupt request.
  1003.   * @param  hpcd PCD handle
  1004.   * @retval HAL status
  1005.   */
  1006. void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
  1007. {
  1008.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_CTR))
  1009.   {
  1010.     /* servicing of the endpoint correct transfer interrupt */
  1011.     /* clear of the CTR flag into the sub */
  1012.     (void)PCD_EP_ISR_Handler(hpcd);
  1013.   }
  1014.  
  1015.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_RESET))
  1016.   {
  1017.     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
  1018.  
  1019. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1020.     hpcd->ResetCallback(hpcd);
  1021. #else
  1022.     HAL_PCD_ResetCallback(hpcd);
  1023. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1024.  
  1025.     (void)HAL_PCD_SetAddress(hpcd, 0U);
  1026.   }
  1027.  
  1028.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_PMAOVR))
  1029.   {
  1030.     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
  1031.   }
  1032.  
  1033.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ERR))
  1034.   {
  1035.     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
  1036.   }
  1037.  
  1038.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_WKUP))
  1039.   {
  1040.     hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_LPMODE);
  1041.     hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
  1042.  
  1043.     if (hpcd->LPM_State == LPM_L1)
  1044.     {
  1045.       hpcd->LPM_State = LPM_L0;
  1046. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1047.       hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
  1048. #else
  1049.       HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
  1050. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1051.     }
  1052.  
  1053. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1054.     hpcd->ResumeCallback(hpcd);
  1055. #else
  1056.     HAL_PCD_ResumeCallback(hpcd);
  1057. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1058.  
  1059.     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
  1060.   }
  1061.  
  1062.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SUSP))
  1063.   {
  1064.     /* Force low-power mode in the macrocell */
  1065.     hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
  1066.  
  1067.     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
  1068.     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
  1069.  
  1070.     hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LPMODE;
  1071.  
  1072. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1073.     hpcd->SuspendCallback(hpcd);
  1074. #else
  1075.     HAL_PCD_SuspendCallback(hpcd);
  1076. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1077.   }
  1078.  
  1079.   /* Handle LPM Interrupt */
  1080.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_L1REQ))
  1081.   {
  1082.     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ);
  1083.     if (hpcd->LPM_State == LPM_L0)
  1084.     {
  1085.       /* Force suspend and low-power mode before going to L1 state*/
  1086.       hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LPMODE;
  1087.       hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
  1088.  
  1089.       hpcd->LPM_State = LPM_L1;
  1090.       hpcd->BESL = ((uint32_t)hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >> 2;
  1091. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1092.       hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
  1093. #else
  1094.       HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
  1095. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1096.     }
  1097.     else
  1098.     {
  1099. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1100.       hpcd->SuspendCallback(hpcd);
  1101. #else
  1102.       HAL_PCD_SuspendCallback(hpcd);
  1103. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1104.     }
  1105.   }
  1106.  
  1107.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SOF))
  1108.   {
  1109.     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
  1110.  
  1111. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1112.     hpcd->SOFCallback(hpcd);
  1113. #else
  1114.     HAL_PCD_SOFCallback(hpcd);
  1115. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1116.   }
  1117.  
  1118.   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ESOF))
  1119.   {
  1120.     /* clear ESOF flag in ISTR */
  1121.     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
  1122.   }
  1123. }
  1124.  
  1125.  
  1126. /**
  1127.   * @brief  Data OUT stage callback.
  1128.   * @param  hpcd PCD handle
  1129.   * @param  epnum endpoint number
  1130.   * @retval None
  1131.   */
  1132. __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  1133. {
  1134.   /* Prevent unused argument(s) compilation warning */
  1135.   UNUSED(hpcd);
  1136.   UNUSED(epnum);
  1137.  
  1138.   /* NOTE : This function should not be modified, when the callback is needed,
  1139.             the HAL_PCD_DataOutStageCallback could be implemented in the user file
  1140.    */
  1141. }
  1142.  
  1143. /**
  1144.   * @brief  Data IN stage callback
  1145.   * @param  hpcd PCD handle
  1146.   * @param  epnum endpoint number
  1147.   * @retval None
  1148.   */
  1149. __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  1150. {
  1151.   /* Prevent unused argument(s) compilation warning */
  1152.   UNUSED(hpcd);
  1153.   UNUSED(epnum);
  1154.  
  1155.   /* NOTE : This function should not be modified, when the callback is needed,
  1156.             the HAL_PCD_DataInStageCallback could be implemented in the user file
  1157.    */
  1158. }
  1159. /**
  1160.   * @brief  Setup stage callback
  1161.   * @param  hpcd PCD handle
  1162.   * @retval None
  1163.   */
  1164. __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
  1165. {
  1166.   /* Prevent unused argument(s) compilation warning */
  1167.   UNUSED(hpcd);
  1168.  
  1169.   /* NOTE : This function should not be modified, when the callback is needed,
  1170.             the HAL_PCD_SetupStageCallback could be implemented in the user file
  1171.    */
  1172. }
  1173.  
  1174. /**
  1175.   * @brief  USB Start Of Frame callback.
  1176.   * @param  hpcd PCD handle
  1177.   * @retval None
  1178.   */
  1179. __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
  1180. {
  1181.   /* Prevent unused argument(s) compilation warning */
  1182.   UNUSED(hpcd);
  1183.  
  1184.   /* NOTE : This function should not be modified, when the callback is needed,
  1185.             the HAL_PCD_SOFCallback could be implemented in the user file
  1186.    */
  1187. }
  1188.  
  1189. /**
  1190.   * @brief  USB Reset callback.
  1191.   * @param  hpcd PCD handle
  1192.   * @retval None
  1193.   */
  1194. __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
  1195. {
  1196.   /* Prevent unused argument(s) compilation warning */
  1197.   UNUSED(hpcd);
  1198.  
  1199.   /* NOTE : This function should not be modified, when the callback is needed,
  1200.             the HAL_PCD_ResetCallback could be implemented in the user file
  1201.    */
  1202. }
  1203.  
  1204. /**
  1205.   * @brief  Suspend event callback.
  1206.   * @param  hpcd PCD handle
  1207.   * @retval None
  1208.   */
  1209. __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
  1210. {
  1211.   /* Prevent unused argument(s) compilation warning */
  1212.   UNUSED(hpcd);
  1213.  
  1214.   /* NOTE : This function should not be modified, when the callback is needed,
  1215.             the HAL_PCD_SuspendCallback could be implemented in the user file
  1216.    */
  1217. }
  1218.  
  1219. /**
  1220.   * @brief  Resume event callback.
  1221.   * @param  hpcd PCD handle
  1222.   * @retval None
  1223.   */
  1224. __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
  1225. {
  1226.   /* Prevent unused argument(s) compilation warning */
  1227.   UNUSED(hpcd);
  1228.  
  1229.   /* NOTE : This function should not be modified, when the callback is needed,
  1230.             the HAL_PCD_ResumeCallback could be implemented in the user file
  1231.    */
  1232. }
  1233.  
  1234. /**
  1235.   * @brief  Incomplete ISO OUT callback.
  1236.   * @param  hpcd PCD handle
  1237.   * @param  epnum endpoint number
  1238.   * @retval None
  1239.   */
  1240. __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  1241. {
  1242.   /* Prevent unused argument(s) compilation warning */
  1243.   UNUSED(hpcd);
  1244.   UNUSED(epnum);
  1245.  
  1246.   /* NOTE : This function should not be modified, when the callback is needed,
  1247.             the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
  1248.    */
  1249. }
  1250.  
  1251. /**
  1252.   * @brief  Incomplete ISO IN callback.
  1253.   * @param  hpcd PCD handle
  1254.   * @param  epnum endpoint number
  1255.   * @retval None
  1256.   */
  1257. __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
  1258. {
  1259.   /* Prevent unused argument(s) compilation warning */
  1260.   UNUSED(hpcd);
  1261.   UNUSED(epnum);
  1262.  
  1263.   /* NOTE : This function should not be modified, when the callback is needed,
  1264.             the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
  1265.    */
  1266. }
  1267.  
  1268. /**
  1269.   * @brief  Connection event callback.
  1270.   * @param  hpcd PCD handle
  1271.   * @retval None
  1272.   */
  1273. __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
  1274. {
  1275.   /* Prevent unused argument(s) compilation warning */
  1276.   UNUSED(hpcd);
  1277.  
  1278.   /* NOTE : This function should not be modified, when the callback is needed,
  1279.             the HAL_PCD_ConnectCallback could be implemented in the user file
  1280.    */
  1281. }
  1282.  
  1283. /**
  1284.   * @brief  Disconnection event callback.
  1285.   * @param  hpcd PCD handle
  1286.   * @retval None
  1287.   */
  1288. __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
  1289. {
  1290.   /* Prevent unused argument(s) compilation warning */
  1291.   UNUSED(hpcd);
  1292.  
  1293.   /* NOTE : This function should not be modified, when the callback is needed,
  1294.             the HAL_PCD_DisconnectCallback could be implemented in the user file
  1295.    */
  1296. }
  1297.  
  1298. /**
  1299.   * @}
  1300.   */
  1301.  
  1302. /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
  1303.   *  @brief   management functions
  1304.   *
  1305. @verbatim
  1306.  ===============================================================================
  1307.                       ##### Peripheral Control functions #####
  1308.  ===============================================================================
  1309.     [..]
  1310.     This subsection provides a set of functions allowing to control the PCD data
  1311.     transfers.
  1312.  
  1313. @endverbatim
  1314.   * @{
  1315.   */
  1316.  
  1317. /**
  1318.   * @brief  Connect the USB device
  1319.   * @param  hpcd PCD handle
  1320.   * @retval HAL status
  1321.   */
  1322. HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
  1323. {
  1324.   __HAL_LOCK(hpcd);
  1325.   (void)USB_DevConnect(hpcd->Instance);
  1326.   __HAL_UNLOCK(hpcd);
  1327.  
  1328.   return HAL_OK;
  1329. }
  1330.  
  1331. /**
  1332.   * @brief  Disconnect the USB device.
  1333.   * @param  hpcd PCD handle
  1334.   * @retval HAL status
  1335.   */
  1336. HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
  1337. {
  1338.   __HAL_LOCK(hpcd);
  1339.   (void)USB_DevDisconnect(hpcd->Instance);
  1340.   __HAL_UNLOCK(hpcd);
  1341.  
  1342.   return HAL_OK;
  1343. }
  1344.  
  1345. /**
  1346.   * @brief  Set the USB Device address.
  1347.   * @param  hpcd PCD handle
  1348.   * @param  address new device address
  1349.   * @retval HAL status
  1350.   */
  1351. HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
  1352. {
  1353.   __HAL_LOCK(hpcd);
  1354.   hpcd->USB_Address = address;
  1355.   (void)USB_SetDevAddress(hpcd->Instance, address);
  1356.   __HAL_UNLOCK(hpcd);
  1357.  
  1358.   return HAL_OK;
  1359. }
  1360. /**
  1361.   * @brief  Open and configure an endpoint.
  1362.   * @param  hpcd PCD handle
  1363.   * @param  ep_addr endpoint address
  1364.   * @param  ep_mps endpoint max packet size
  1365.   * @param  ep_type endpoint type
  1366.   * @retval HAL status
  1367.   */
  1368. HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
  1369.                                   uint16_t ep_mps, uint8_t ep_type)
  1370. {
  1371.   HAL_StatusTypeDef  ret = HAL_OK;
  1372.   PCD_EPTypeDef *ep;
  1373.  
  1374.   if ((ep_addr & 0x80U) == 0x80U)
  1375.   {
  1376.     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1377.     ep->is_in = 1U;
  1378.   }
  1379.   else
  1380.   {
  1381.     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1382.     ep->is_in = 0U;
  1383.   }
  1384.  
  1385.   ep->num = ep_addr & EP_ADDR_MSK;
  1386.   ep->maxpacket = ep_mps;
  1387.   ep->type = ep_type;
  1388.  
  1389.   if (ep->is_in != 0U)
  1390.   {
  1391.     /* Assign a Tx FIFO */
  1392.     ep->tx_fifo_num = ep->num;
  1393.   }
  1394.   /* Set initial data PID. */
  1395.   if (ep_type == EP_TYPE_BULK)
  1396.   {
  1397.     ep->data_pid_start = 0U;
  1398.   }
  1399.  
  1400.   __HAL_LOCK(hpcd);
  1401.   (void)USB_ActivateEndpoint(hpcd->Instance, ep);
  1402.   __HAL_UNLOCK(hpcd);
  1403.  
  1404.   return ret;
  1405. }
  1406.  
  1407. /**
  1408.   * @brief  Deactivate an endpoint.
  1409.   * @param  hpcd PCD handle
  1410.   * @param  ep_addr endpoint address
  1411.   * @retval HAL status
  1412.   */
  1413. HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1414. {
  1415.   PCD_EPTypeDef *ep;
  1416.  
  1417.   if ((ep_addr & 0x80U) == 0x80U)
  1418.   {
  1419.     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1420.     ep->is_in = 1U;
  1421.   }
  1422.   else
  1423.   {
  1424.     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1425.     ep->is_in = 0U;
  1426.   }
  1427.   ep->num   = ep_addr & EP_ADDR_MSK;
  1428.  
  1429.   __HAL_LOCK(hpcd);
  1430.   (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
  1431.   __HAL_UNLOCK(hpcd);
  1432.   return HAL_OK;
  1433. }
  1434.  
  1435.  
  1436. /**
  1437.   * @brief  Receive an amount of data.
  1438.   * @param  hpcd PCD handle
  1439.   * @param  ep_addr endpoint address
  1440.   * @param  pBuf pointer to the reception buffer
  1441.   * @param  len amount of data to be received
  1442.   * @retval HAL status
  1443.   */
  1444. HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  1445. {
  1446.   PCD_EPTypeDef *ep;
  1447.  
  1448.   ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1449.  
  1450.   /*setup and start the Xfer */
  1451.   ep->xfer_buff = pBuf;
  1452.   ep->xfer_len = len;
  1453.   ep->xfer_count = 0U;
  1454.   ep->is_in = 0U;
  1455.   ep->num = ep_addr & EP_ADDR_MSK;
  1456.  
  1457.   if ((ep_addr & EP_ADDR_MSK) == 0U)
  1458.   {
  1459.     (void)USB_EP0StartXfer(hpcd->Instance, ep);
  1460.   }
  1461.   else
  1462.   {
  1463.     (void)USB_EPStartXfer(hpcd->Instance, ep);
  1464.   }
  1465.  
  1466.   return HAL_OK;
  1467. }
  1468.  
  1469. /**
  1470.   * @brief  Get Received Data Size
  1471.   * @param  hpcd PCD handle
  1472.   * @param  ep_addr endpoint address
  1473.   * @retval Data Size
  1474.   */
  1475. uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1476. {
  1477.   return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
  1478. }
  1479. /**
  1480.   * @brief  Send an amount of data
  1481.   * @param  hpcd PCD handle
  1482.   * @param  ep_addr endpoint address
  1483.   * @param  pBuf pointer to the transmission buffer
  1484.   * @param  len amount of data to be sent
  1485.   * @retval HAL status
  1486.   */
  1487. HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
  1488. {
  1489.   PCD_EPTypeDef *ep;
  1490.  
  1491.   ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1492.  
  1493.   /*setup and start the Xfer */
  1494.   ep->xfer_buff = pBuf;
  1495.   ep->xfer_len = len;
  1496.   ep->xfer_fill_db = 1U;
  1497.   ep->xfer_len_db = len;
  1498.   ep->xfer_count = 0U;
  1499.   ep->is_in = 1U;
  1500.   ep->num = ep_addr & EP_ADDR_MSK;
  1501.  
  1502.   if ((ep_addr & EP_ADDR_MSK) == 0U)
  1503.   {
  1504.     (void)USB_EP0StartXfer(hpcd->Instance, ep);
  1505.   }
  1506.   else
  1507.   {
  1508.     (void)USB_EPStartXfer(hpcd->Instance, ep);
  1509.   }
  1510.  
  1511.   return HAL_OK;
  1512. }
  1513.  
  1514. /**
  1515.   * @brief  Set a STALL condition over an endpoint
  1516.   * @param  hpcd PCD handle
  1517.   * @param  ep_addr endpoint address
  1518.   * @retval HAL status
  1519.   */
  1520. HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1521. {
  1522.   PCD_EPTypeDef *ep;
  1523.  
  1524.   if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
  1525.   {
  1526.     return HAL_ERROR;
  1527.   }
  1528.  
  1529.   if ((0x80U & ep_addr) == 0x80U)
  1530.   {
  1531.     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1532.     ep->is_in = 1U;
  1533.   }
  1534.   else
  1535.   {
  1536.     ep = &hpcd->OUT_ep[ep_addr];
  1537.     ep->is_in = 0U;
  1538.   }
  1539.  
  1540.   ep->is_stall = 1U;
  1541.   ep->num = ep_addr & EP_ADDR_MSK;
  1542.  
  1543.   __HAL_LOCK(hpcd);
  1544.  
  1545.   (void)USB_EPSetStall(hpcd->Instance, ep);
  1546.  
  1547.   __HAL_UNLOCK(hpcd);
  1548.  
  1549.   return HAL_OK;
  1550. }
  1551.  
  1552. /**
  1553.   * @brief  Clear a STALL condition over in an endpoint
  1554.   * @param  hpcd PCD handle
  1555.   * @param  ep_addr endpoint address
  1556.   * @retval HAL status
  1557.   */
  1558. HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1559. {
  1560.   PCD_EPTypeDef *ep;
  1561.  
  1562.   if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
  1563.   {
  1564.     return HAL_ERROR;
  1565.   }
  1566.  
  1567.   if ((0x80U & ep_addr) == 0x80U)
  1568.   {
  1569.     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
  1570.     ep->is_in = 1U;
  1571.   }
  1572.   else
  1573.   {
  1574.     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
  1575.     ep->is_in = 0U;
  1576.   }
  1577.  
  1578.   ep->is_stall = 0U;
  1579.   ep->num = ep_addr & EP_ADDR_MSK;
  1580.  
  1581.   __HAL_LOCK(hpcd);
  1582.   (void)USB_EPClearStall(hpcd->Instance, ep);
  1583.   __HAL_UNLOCK(hpcd);
  1584.  
  1585.   return HAL_OK;
  1586. }
  1587.  
  1588. /**
  1589.   * @brief  Flush an endpoint
  1590.   * @param  hpcd PCD handle
  1591.   * @param  ep_addr endpoint address
  1592.   * @retval HAL status
  1593.   */
  1594. HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
  1595. {
  1596.   /* Prevent unused argument(s) compilation warning */
  1597.   UNUSED(hpcd);
  1598.   UNUSED(ep_addr);
  1599.  
  1600.   return HAL_OK;
  1601. }
  1602.  
  1603. /**
  1604.   * @brief  Activate remote wakeup signalling
  1605.   * @param  hpcd PCD handle
  1606.   * @retval HAL status
  1607.   */
  1608. HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  1609. {
  1610.   return (USB_ActivateRemoteWakeup(hpcd->Instance));
  1611. }
  1612.  
  1613. /**
  1614.   * @brief  De-activate remote wakeup signalling.
  1615.   * @param  hpcd PCD handle
  1616.   * @retval HAL status
  1617.   */
  1618. HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
  1619. {
  1620.   return (USB_DeActivateRemoteWakeup(hpcd->Instance));
  1621. }
  1622.  
  1623. /**
  1624.   * @}
  1625.   */
  1626.  
  1627. /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
  1628.   *  @brief   Peripheral State functions
  1629.   *
  1630. @verbatim
  1631.  ===============================================================================
  1632.                       ##### Peripheral State functions #####
  1633.  ===============================================================================
  1634.     [..]
  1635.     This subsection permits to get in run-time the status of the peripheral
  1636.     and the data flow.
  1637.  
  1638. @endverbatim
  1639.   * @{
  1640.   */
  1641.  
  1642. /**
  1643.   * @brief  Return the PCD handle state.
  1644.   * @param  hpcd PCD handle
  1645.   * @retval HAL state
  1646.   */
  1647. PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
  1648. {
  1649.   return hpcd->State;
  1650. }
  1651.  
  1652. /**
  1653.   * @}
  1654.   */
  1655.  
  1656. /**
  1657.   * @}
  1658.   */
  1659.  
  1660. /* Private functions ---------------------------------------------------------*/
  1661. /** @addtogroup PCD_Private_Functions
  1662.   * @{
  1663.   */
  1664.  
  1665.  
  1666. /**
  1667.   * @brief  This function handles PCD Endpoint interrupt request.
  1668.   * @param  hpcd PCD handle
  1669.   * @retval HAL status
  1670.   */
  1671. static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
  1672. {
  1673.   PCD_EPTypeDef *ep;
  1674.   uint16_t count, wIstr, wEPVal, TxByteNbre;
  1675.   uint8_t epindex;
  1676.  
  1677.   /* stay in loop while pending interrupts */
  1678.   while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
  1679.   {
  1680.     wIstr = hpcd->Instance->ISTR;
  1681.  
  1682.     /* extract highest priority endpoint number */
  1683.     epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
  1684.  
  1685.     if (epindex == 0U)
  1686.     {
  1687.       /* Decode and service control endpoint interrupt */
  1688.  
  1689.       /* DIR bit = origin of the interrupt */
  1690.       if ((wIstr & USB_ISTR_DIR) == 0U)
  1691.       {
  1692.         /* DIR = 0 */
  1693.  
  1694.         /* DIR = 0 => IN  int */
  1695.         /* DIR = 0 implies that (EP_CTR_TX = 1) always */
  1696.         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1697.         ep = &hpcd->IN_ep[0];
  1698.  
  1699.         ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1700.         ep->xfer_buff += ep->xfer_count;
  1701.  
  1702.         /* TX COMPLETE */
  1703. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1704.         hpcd->DataInStageCallback(hpcd, 0U);
  1705. #else
  1706.         HAL_PCD_DataInStageCallback(hpcd, 0U);
  1707. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1708.  
  1709.         if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
  1710.         {
  1711.           hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
  1712.           hpcd->USB_Address = 0U;
  1713.         }
  1714.       }
  1715.       else
  1716.       {
  1717.         /* DIR = 1 */
  1718.  
  1719.         /* DIR = 1 & CTR_RX => SETUP or OUT int */
  1720.         /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
  1721.         ep = &hpcd->OUT_ep[0];
  1722.         wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
  1723.  
  1724.         if ((wEPVal & USB_EP_SETUP) != 0U)
  1725.         {
  1726.           /* Get SETUP Packet */
  1727.           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1728.  
  1729.           USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
  1730.                       ep->pmaadress, (uint16_t)ep->xfer_count);
  1731.  
  1732.           /* SETUP bit kept frozen while CTR_RX = 1 */
  1733.           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1734.  
  1735.           /* Process SETUP Packet*/
  1736. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1737.           hpcd->SetupStageCallback(hpcd);
  1738. #else
  1739.           HAL_PCD_SetupStageCallback(hpcd);
  1740. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1741.         }
  1742.         else if ((wEPVal & USB_EP_CTR_RX) != 0U)
  1743.         {
  1744.           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
  1745.  
  1746.           /* Get Control Data OUT Packet */
  1747.           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1748.  
  1749.           if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
  1750.           {
  1751.             USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
  1752.                         ep->pmaadress, (uint16_t)ep->xfer_count);
  1753.  
  1754.             ep->xfer_buff += ep->xfer_count;
  1755.  
  1756.             /* Process Control Data OUT Packet */
  1757. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1758.             hpcd->DataOutStageCallback(hpcd, 0U);
  1759. #else
  1760.             HAL_PCD_DataOutStageCallback(hpcd, 0U);
  1761. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1762.           }
  1763.  
  1764.           if ((PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0) & USB_EP_SETUP) == 0U)
  1765.           {
  1766.             PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
  1767.             PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
  1768.           }
  1769.         }
  1770.       }
  1771.     }
  1772.     else
  1773.     {
  1774.       /* Decode and service non control endpoints interrupt */
  1775.       /* process related endpoint register */
  1776.       wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
  1777.  
  1778.       if ((wEPVal & USB_EP_CTR_RX) != 0U)
  1779.       {
  1780.         /* clear int flag */
  1781.         PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
  1782.         ep = &hpcd->OUT_ep[epindex];
  1783.  
  1784.         /* OUT Single Buffering */
  1785.         if (ep->doublebuffer == 0U)
  1786.         {
  1787.           count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
  1788.  
  1789.           if (count != 0U)
  1790.           {
  1791.             USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
  1792.           }
  1793.         }
  1794.         else
  1795.         {
  1796.           /* manage double buffer bulk out */
  1797.           if (ep->type == EP_TYPE_BULK)
  1798.           {
  1799.             count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
  1800.           }
  1801.           else /* manage double buffer iso out */
  1802.           {
  1803.             /* free EP OUT Buffer */
  1804.             PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
  1805.  
  1806.             if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
  1807.             {
  1808.               /* read from endpoint BUF0Addr buffer */
  1809.               count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
  1810.  
  1811.               if (count != 0U)
  1812.               {
  1813.                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
  1814.               }
  1815.             }
  1816.             else
  1817.             {
  1818.               /* read from endpoint BUF1Addr buffer */
  1819.               count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
  1820.  
  1821.               if (count != 0U)
  1822.               {
  1823.                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
  1824.               }
  1825.             }
  1826.           }
  1827.         }
  1828.         /* multi-packet on the NON control OUT endpoint */
  1829.         ep->xfer_count += count;
  1830.         ep->xfer_buff += count;
  1831.  
  1832.         if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
  1833.         {
  1834.           /* RX COMPLETE */
  1835. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1836.           hpcd->DataOutStageCallback(hpcd, ep->num);
  1837. #else
  1838.           HAL_PCD_DataOutStageCallback(hpcd, ep->num);
  1839. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1840.         }
  1841.         else
  1842.         {
  1843.           (void) USB_EPStartXfer(hpcd->Instance, ep);
  1844.         }
  1845.       }
  1846.  
  1847.       if ((wEPVal & USB_EP_CTR_TX) != 0U)
  1848.       {
  1849.         ep = &hpcd->IN_ep[epindex];
  1850.  
  1851.         /* clear int flag */
  1852.         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
  1853.  
  1854.         if (ep->type != EP_TYPE_BULK)
  1855.         {
  1856.           ep->xfer_len = 0U;
  1857.  
  1858.           if ((wEPVal & USB_EP_DTOG_TX) != 0U)
  1859.           {
  1860.             PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
  1861.           }
  1862.           else
  1863.           {
  1864.             PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
  1865.           }
  1866.  
  1867.           /* TX COMPLETE */
  1868. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1869.           hpcd->DataInStageCallback(hpcd, ep->num);
  1870. #else
  1871.           HAL_PCD_DataInStageCallback(hpcd, ep->num);
  1872. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1873.         }
  1874.         else
  1875.         /* Manage Bulk Single Buffer Transaction */
  1876.         if ((ep->type == EP_TYPE_BULK) && ((wEPVal & USB_EP_KIND) == 0U))
  1877.         {
  1878.           /* multi-packet on the NON control IN endpoint */
  1879.           TxByteNbre = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
  1880.  
  1881.           if (ep->xfer_len > TxByteNbre)
  1882.           {
  1883.             ep->xfer_len -= TxByteNbre;
  1884.           }
  1885.           else
  1886.           {
  1887.             ep->xfer_len = 0U;
  1888.           }
  1889.  
  1890.           /* Zero Length Packet? */
  1891.           if (ep->xfer_len == 0U)
  1892.           {
  1893.             /* TX COMPLETE */
  1894. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  1895.             hpcd->DataInStageCallback(hpcd, ep->num);
  1896. #else
  1897.             HAL_PCD_DataInStageCallback(hpcd, ep->num);
  1898. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  1899.           }
  1900.           else
  1901.           {
  1902.             /* Transfer is not yet Done */
  1903.             ep->xfer_buff += TxByteNbre;
  1904.             ep->xfer_count += TxByteNbre;
  1905.             (void)USB_EPStartXfer(hpcd->Instance, ep);
  1906.           }
  1907.         }
  1908.         /* Double Buffer bulk IN (bulk transfer Len > Ep_Mps) */
  1909.         else
  1910.         {
  1911.           (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
  1912.         }
  1913.       }
  1914.     }
  1915.   }
  1916.  
  1917.   return HAL_OK;
  1918. }
  1919.  
  1920.  
  1921. /**
  1922.   * @brief  Manage double buffer bulk out transaction from ISR
  1923.   * @param  hpcd PCD handle
  1924.   * @param  ep current endpoint handle
  1925.   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
  1926.   * @retval HAL status
  1927.   */
  1928. static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
  1929.                                       PCD_EPTypeDef *ep, uint16_t wEPVal)
  1930. {
  1931.   uint16_t count;
  1932.  
  1933.   /* Manage Buffer0 OUT */
  1934.   if ((wEPVal & USB_EP_DTOG_RX) != 0U)
  1935.   {
  1936.     /* Get count of received Data on buffer0 */
  1937.     count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
  1938.  
  1939.     if (ep->xfer_len >= count)
  1940.     {
  1941.       ep->xfer_len -= count;
  1942.     }
  1943.     else
  1944.     {
  1945.       ep->xfer_len = 0U;
  1946.     }
  1947.  
  1948.     if (ep->xfer_len == 0U)
  1949.     {
  1950.       /* set NAK to OUT endpoint since double buffer is enabled */
  1951.       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
  1952.     }
  1953.  
  1954.     /* Check if Buffer1 is in blocked sate which requires to toggle */
  1955.     if ((wEPVal & USB_EP_DTOG_TX) != 0U)
  1956.     {
  1957.       PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
  1958.     }
  1959.  
  1960.     if (count != 0U)
  1961.     {
  1962.       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
  1963.     }
  1964.   }
  1965.   /* Manage Buffer 1 DTOG_RX=0 */
  1966.   else
  1967.   {
  1968.     /* Get count of received data */
  1969.     count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
  1970.  
  1971.     if (ep->xfer_len >= count)
  1972.     {
  1973.       ep->xfer_len -= count;
  1974.     }
  1975.     else
  1976.     {
  1977.       ep->xfer_len = 0U;
  1978.     }
  1979.  
  1980.     if (ep->xfer_len == 0U)
  1981.     {
  1982.       /* set NAK on the current endpoint */
  1983.       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
  1984.     }
  1985.  
  1986.     /*Need to FreeUser Buffer*/
  1987.     if ((wEPVal & USB_EP_DTOG_TX) == 0U)
  1988.     {
  1989.       PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
  1990.     }
  1991.  
  1992.     if (count != 0U)
  1993.     {
  1994.       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
  1995.     }
  1996.   }
  1997.  
  1998.   return count;
  1999. }
  2000.  
  2001.  
  2002. /**
  2003.   * @brief  Manage double buffer bulk IN transaction from ISR
  2004.   * @param  hpcd PCD handle
  2005.   * @param  ep current endpoint handle
  2006.   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
  2007.   * @retval HAL status
  2008.   */
  2009. static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
  2010.                                                 PCD_EPTypeDef *ep, uint16_t wEPVal)
  2011. {
  2012.   uint32_t len;
  2013.   uint16_t TxByteNbre;
  2014.  
  2015.   /* Data Buffer0 ACK received */
  2016.   if ((wEPVal & USB_EP_DTOG_TX) != 0U)
  2017.   {
  2018.     /* multi-packet on the NON control IN endpoint */
  2019.     TxByteNbre = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
  2020.  
  2021.     if (ep->xfer_len > TxByteNbre)
  2022.     {
  2023.       ep->xfer_len -= TxByteNbre;
  2024.     }
  2025.     else
  2026.     {
  2027.       ep->xfer_len = 0U;
  2028.     }
  2029.     /* Transfer is completed */
  2030.     if (ep->xfer_len == 0U)
  2031.     {
  2032.       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
  2033.       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
  2034.  
  2035.       /* TX COMPLETE */
  2036. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  2037.       hpcd->DataInStageCallback(hpcd, ep->num);
  2038. #else
  2039.       HAL_PCD_DataInStageCallback(hpcd, ep->num);
  2040. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  2041.  
  2042.       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
  2043.       {
  2044.         PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
  2045.       }
  2046.     }
  2047.     else /* Transfer is not yet Done */
  2048.     {
  2049.       /* need to Free USB Buff */
  2050.       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
  2051.       {
  2052.         PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
  2053.       }
  2054.  
  2055.       /* Still there is data to Fill in the next Buffer */
  2056.       if (ep->xfer_fill_db == 1U)
  2057.       {
  2058.         ep->xfer_buff += TxByteNbre;
  2059.         ep->xfer_count += TxByteNbre;
  2060.  
  2061.         /* Calculate the len of the new buffer to fill */
  2062.         if (ep->xfer_len_db >= ep->maxpacket)
  2063.         {
  2064.           len = ep->maxpacket;
  2065.           ep->xfer_len_db -= len;
  2066.         }
  2067.         else if (ep->xfer_len_db == 0U)
  2068.         {
  2069.           len = TxByteNbre;
  2070.           ep->xfer_fill_db = 0U;
  2071.         }
  2072.         else
  2073.         {
  2074.           ep->xfer_fill_db = 0U;
  2075.           len = ep->xfer_len_db;
  2076.           ep->xfer_len_db = 0U;
  2077.         }
  2078.  
  2079.         /* Write remaining Data to Buffer */
  2080.         /* Set the Double buffer counter for pma buffer1 */
  2081.         PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
  2082.  
  2083.         /* Copy user buffer to USB PMA */
  2084.         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr0, (uint16_t)len);
  2085.       }
  2086.     }
  2087.   }
  2088.   else /* Data Buffer1 ACK received */
  2089.   {
  2090.     /* multi-packet on the NON control IN endpoint */
  2091.     TxByteNbre = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
  2092.  
  2093.     if (ep->xfer_len >= TxByteNbre)
  2094.     {
  2095.       ep->xfer_len -= TxByteNbre;
  2096.     }
  2097.     else
  2098.     {
  2099.       ep->xfer_len = 0U;
  2100.     }
  2101.  
  2102.     /* Transfer is completed */
  2103.     if (ep->xfer_len == 0U)
  2104.     {
  2105.       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
  2106.       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
  2107.  
  2108.       /* TX COMPLETE */
  2109. #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
  2110.       hpcd->DataInStageCallback(hpcd, ep->num);
  2111. #else
  2112.       HAL_PCD_DataInStageCallback(hpcd, ep->num);
  2113. #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
  2114.  
  2115.       /* need to Free USB Buff */
  2116.       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
  2117.       {
  2118.         PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
  2119.       }
  2120.     }
  2121.     else /* Transfer is not yet Done */
  2122.     {
  2123.       /* need to Free USB Buff */
  2124.       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
  2125.       {
  2126.         PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
  2127.       }
  2128.  
  2129.       /* Still there is data to Fill in the next Buffer */
  2130.       if (ep->xfer_fill_db == 1U)
  2131.       {
  2132.         ep->xfer_buff += TxByteNbre;
  2133.         ep->xfer_count += TxByteNbre;
  2134.  
  2135.         /* Calculate the len of the new buffer to fill */
  2136.         if (ep->xfer_len_db >= ep->maxpacket)
  2137.         {
  2138.           len = ep->maxpacket;
  2139.           ep->xfer_len_db -= len;
  2140.         }
  2141.         else if (ep->xfer_len_db == 0U)
  2142.         {
  2143.           len = TxByteNbre;
  2144.           ep->xfer_fill_db = 0U;
  2145.         }
  2146.         else
  2147.         {
  2148.           len = ep->xfer_len_db;
  2149.           ep->xfer_len_db = 0U;
  2150.           ep->xfer_fill_db = 0;
  2151.         }
  2152.  
  2153.         /* Set the Double buffer counter for pmabuffer1 */
  2154.         PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
  2155.  
  2156.         /* Copy the user buffer to USB PMA */
  2157.         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr1, (uint16_t)len);
  2158.       }
  2159.     }
  2160.   }
  2161.  
  2162.   /*enable endpoint IN*/
  2163.   PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
  2164.  
  2165.   return HAL_OK;
  2166. }
  2167.  
  2168.  
  2169.  
  2170. /**
  2171.   * @}
  2172.   */
  2173. #endif /* defined (USB) */
  2174. #endif /* HAL_PCD_MODULE_ENABLED */
  2175.  
  2176. /**
  2177.   * @}
  2178.   */
  2179.  
  2180. /**
  2181.   * @}
  2182.   */
  2183.  
  2184. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  2185.