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