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