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