Subversion Repositories DashDisplay

Rev

Rev 61 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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