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