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