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