1 /**
2   ******************************************************************************
3   * @file    stm32wbxx_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) 2019 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 "stm32wbxx_hal.h"
58 
59 /** @addtogroup STM32WBxx_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)
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   if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
1012   {
1013     /* servicing of the endpoint correct transfer interrupt */
1014     /* clear of the CTR flag into the sub */
1015     (void)PCD_EP_ISR_Handler(hpcd);
1016 
1017     return;
1018   }
1019 
1020   if ((wIstr & USB_ISTR_RESET) == USB_ISTR_RESET)
1021   {
1022     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
1023 
1024 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1025     hpcd->ResetCallback(hpcd);
1026 #else
1027     HAL_PCD_ResetCallback(hpcd);
1028 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1029 
1030     (void)HAL_PCD_SetAddress(hpcd, 0U);
1031 
1032     return;
1033   }
1034 
1035   if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
1036   {
1037     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
1038 
1039     return;
1040   }
1041 
1042   if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
1043   {
1044     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
1045 
1046     return;
1047   }
1048 
1049   if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
1050   {
1051     hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_LPMODE);
1052     hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
1053 
1054     if (hpcd->LPM_State == LPM_L1)
1055     {
1056       hpcd->LPM_State = LPM_L0;
1057 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1058       hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
1059 #else
1060       HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
1061 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1062     }
1063 
1064 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1065     hpcd->ResumeCallback(hpcd);
1066 #else
1067     HAL_PCD_ResumeCallback(hpcd);
1068 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1069 
1070     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
1071 
1072     return;
1073   }
1074 
1075   if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
1076   {
1077     /* Force low-power mode in the macrocell */
1078     hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
1079 
1080     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
1081     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
1082 
1083     hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LPMODE;
1084 
1085 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1086     hpcd->SuspendCallback(hpcd);
1087 #else
1088     HAL_PCD_SuspendCallback(hpcd);
1089 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1090 
1091     return;
1092   }
1093 
1094   /* Handle LPM Interrupt */
1095   if ((wIstr & USB_ISTR_L1REQ) == USB_ISTR_L1REQ)
1096   {
1097     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ);
1098     if (hpcd->LPM_State == LPM_L0)
1099     {
1100       /* Force suspend and low-power mode before going to L1 state*/
1101       hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LPMODE;
1102       hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
1103 
1104       hpcd->LPM_State = LPM_L1;
1105       hpcd->BESL = ((uint32_t)hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >> 2;
1106 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1107       hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
1108 #else
1109       HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
1110 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1111     }
1112     else
1113     {
1114 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1115       hpcd->SuspendCallback(hpcd);
1116 #else
1117       HAL_PCD_SuspendCallback(hpcd);
1118 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1119     }
1120 
1121     return;
1122   }
1123 
1124   if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
1125   {
1126     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
1127 
1128 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1129     hpcd->SOFCallback(hpcd);
1130 #else
1131     HAL_PCD_SOFCallback(hpcd);
1132 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1133 
1134     return;
1135   }
1136 
1137   if ((wIstr & USB_ISTR_ESOF) == USB_ISTR_ESOF)
1138   {
1139     /* clear ESOF flag in ISTR */
1140     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
1141 
1142     return;
1143   }
1144 }
1145 
1146 
1147 /**
1148   * @brief  Data OUT stage callback.
1149   * @param  hpcd PCD handle
1150   * @param  epnum endpoint number
1151   * @retval None
1152   */
HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1153 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1154 {
1155   /* Prevent unused argument(s) compilation warning */
1156   UNUSED(hpcd);
1157   UNUSED(epnum);
1158 
1159   /* NOTE : This function should not be modified, when the callback is needed,
1160             the HAL_PCD_DataOutStageCallback could be implemented in the user file
1161    */
1162 }
1163 
1164 /**
1165   * @brief  Data IN stage callback
1166   * @param  hpcd PCD handle
1167   * @param  epnum endpoint number
1168   * @retval None
1169   */
HAL_PCD_DataInStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1170 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1171 {
1172   /* Prevent unused argument(s) compilation warning */
1173   UNUSED(hpcd);
1174   UNUSED(epnum);
1175 
1176   /* NOTE : This function should not be modified, when the callback is needed,
1177             the HAL_PCD_DataInStageCallback could be implemented in the user file
1178    */
1179 }
1180 /**
1181   * @brief  Setup stage callback
1182   * @param  hpcd PCD handle
1183   * @retval None
1184   */
HAL_PCD_SetupStageCallback(PCD_HandleTypeDef * hpcd)1185 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
1186 {
1187   /* Prevent unused argument(s) compilation warning */
1188   UNUSED(hpcd);
1189 
1190   /* NOTE : This function should not be modified, when the callback is needed,
1191             the HAL_PCD_SetupStageCallback could be implemented in the user file
1192    */
1193 }
1194 
1195 /**
1196   * @brief  USB Start Of Frame callback.
1197   * @param  hpcd PCD handle
1198   * @retval None
1199   */
HAL_PCD_SOFCallback(PCD_HandleTypeDef * hpcd)1200 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
1201 {
1202   /* Prevent unused argument(s) compilation warning */
1203   UNUSED(hpcd);
1204 
1205   /* NOTE : This function should not be modified, when the callback is needed,
1206             the HAL_PCD_SOFCallback could be implemented in the user file
1207    */
1208 }
1209 
1210 /**
1211   * @brief  USB Reset callback.
1212   * @param  hpcd PCD handle
1213   * @retval None
1214   */
HAL_PCD_ResetCallback(PCD_HandleTypeDef * hpcd)1215 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
1216 {
1217   /* Prevent unused argument(s) compilation warning */
1218   UNUSED(hpcd);
1219 
1220   /* NOTE : This function should not be modified, when the callback is needed,
1221             the HAL_PCD_ResetCallback could be implemented in the user file
1222    */
1223 }
1224 
1225 /**
1226   * @brief  Suspend event callback.
1227   * @param  hpcd PCD handle
1228   * @retval None
1229   */
HAL_PCD_SuspendCallback(PCD_HandleTypeDef * hpcd)1230 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
1231 {
1232   /* Prevent unused argument(s) compilation warning */
1233   UNUSED(hpcd);
1234 
1235   /* NOTE : This function should not be modified, when the callback is needed,
1236             the HAL_PCD_SuspendCallback could be implemented in the user file
1237    */
1238 }
1239 
1240 /**
1241   * @brief  Resume event callback.
1242   * @param  hpcd PCD handle
1243   * @retval None
1244   */
HAL_PCD_ResumeCallback(PCD_HandleTypeDef * hpcd)1245 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
1246 {
1247   /* Prevent unused argument(s) compilation warning */
1248   UNUSED(hpcd);
1249 
1250   /* NOTE : This function should not be modified, when the callback is needed,
1251             the HAL_PCD_ResumeCallback could be implemented in the user file
1252    */
1253 }
1254 
1255 /**
1256   * @brief  Incomplete ISO OUT callback.
1257   * @param  hpcd PCD handle
1258   * @param  epnum endpoint number
1259   * @retval None
1260   */
HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1261 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1262 {
1263   /* Prevent unused argument(s) compilation warning */
1264   UNUSED(hpcd);
1265   UNUSED(epnum);
1266 
1267   /* NOTE : This function should not be modified, when the callback is needed,
1268             the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
1269    */
1270 }
1271 
1272 /**
1273   * @brief  Incomplete ISO IN callback.
1274   * @param  hpcd PCD handle
1275   * @param  epnum endpoint number
1276   * @retval None
1277   */
HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1278 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1279 {
1280   /* Prevent unused argument(s) compilation warning */
1281   UNUSED(hpcd);
1282   UNUSED(epnum);
1283 
1284   /* NOTE : This function should not be modified, when the callback is needed,
1285             the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1286    */
1287 }
1288 
1289 /**
1290   * @brief  Connection event callback.
1291   * @param  hpcd PCD handle
1292   * @retval None
1293   */
HAL_PCD_ConnectCallback(PCD_HandleTypeDef * hpcd)1294 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
1295 {
1296   /* Prevent unused argument(s) compilation warning */
1297   UNUSED(hpcd);
1298 
1299   /* NOTE : This function should not be modified, when the callback is needed,
1300             the HAL_PCD_ConnectCallback could be implemented in the user file
1301    */
1302 }
1303 
1304 /**
1305   * @brief  Disconnection event callback.
1306   * @param  hpcd PCD handle
1307   * @retval None
1308   */
HAL_PCD_DisconnectCallback(PCD_HandleTypeDef * hpcd)1309 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
1310 {
1311   /* Prevent unused argument(s) compilation warning */
1312   UNUSED(hpcd);
1313 
1314   /* NOTE : This function should not be modified, when the callback is needed,
1315             the HAL_PCD_DisconnectCallback could be implemented in the user file
1316    */
1317 }
1318 
1319 /**
1320   * @}
1321   */
1322 
1323 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
1324   *  @brief   management functions
1325   *
1326 @verbatim
1327  ===============================================================================
1328                       ##### Peripheral Control functions #####
1329  ===============================================================================
1330     [..]
1331     This subsection provides a set of functions allowing to control the PCD data
1332     transfers.
1333 
1334 @endverbatim
1335   * @{
1336   */
1337 
1338 /**
1339   * @brief  Connect the USB device
1340   * @param  hpcd PCD handle
1341   * @retval HAL status
1342   */
HAL_PCD_DevConnect(PCD_HandleTypeDef * hpcd)1343 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
1344 {
1345   __HAL_LOCK(hpcd);
1346   (void)USB_DevConnect(hpcd->Instance);
1347   __HAL_UNLOCK(hpcd);
1348 
1349   return HAL_OK;
1350 }
1351 
1352 /**
1353   * @brief  Disconnect the USB device.
1354   * @param  hpcd PCD handle
1355   * @retval HAL status
1356   */
HAL_PCD_DevDisconnect(PCD_HandleTypeDef * hpcd)1357 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
1358 {
1359   __HAL_LOCK(hpcd);
1360   (void)USB_DevDisconnect(hpcd->Instance);
1361   __HAL_UNLOCK(hpcd);
1362 
1363   return HAL_OK;
1364 }
1365 
1366 /**
1367   * @brief  Set the USB Device address.
1368   * @param  hpcd PCD handle
1369   * @param  address new device address
1370   * @retval HAL status
1371   */
HAL_PCD_SetAddress(PCD_HandleTypeDef * hpcd,uint8_t address)1372 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
1373 {
1374   __HAL_LOCK(hpcd);
1375   hpcd->USB_Address = address;
1376   (void)USB_SetDevAddress(hpcd->Instance, address);
1377   __HAL_UNLOCK(hpcd);
1378 
1379   return HAL_OK;
1380 }
1381 /**
1382   * @brief  Open and configure an endpoint.
1383   * @param  hpcd PCD handle
1384   * @param  ep_addr endpoint address
1385   * @param  ep_mps endpoint max packet size
1386   * @param  ep_type endpoint type
1387   * @retval HAL status
1388   */
HAL_PCD_EP_Open(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint16_t ep_mps,uint8_t ep_type)1389 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
1390                                   uint16_t ep_mps, uint8_t ep_type)
1391 {
1392   HAL_StatusTypeDef  ret = HAL_OK;
1393   PCD_EPTypeDef *ep;
1394 
1395   if ((ep_addr & 0x80U) == 0x80U)
1396   {
1397     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1398     ep->is_in = 1U;
1399   }
1400   else
1401   {
1402     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1403     ep->is_in = 0U;
1404   }
1405 
1406   ep->num = ep_addr & EP_ADDR_MSK;
1407   ep->maxpacket = ep_mps;
1408   ep->type = ep_type;
1409 
1410   /* Set initial data PID. */
1411   if (ep_type == EP_TYPE_BULK)
1412   {
1413     ep->data_pid_start = 0U;
1414   }
1415 
1416   __HAL_LOCK(hpcd);
1417   (void)USB_ActivateEndpoint(hpcd->Instance, ep);
1418   __HAL_UNLOCK(hpcd);
1419 
1420   return ret;
1421 }
1422 
1423 /**
1424   * @brief  Deactivate an endpoint.
1425   * @param  hpcd PCD handle
1426   * @param  ep_addr endpoint address
1427   * @retval HAL status
1428   */
HAL_PCD_EP_Close(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1429 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1430 {
1431   PCD_EPTypeDef *ep;
1432 
1433   if ((ep_addr & 0x80U) == 0x80U)
1434   {
1435     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1436     ep->is_in = 1U;
1437   }
1438   else
1439   {
1440     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1441     ep->is_in = 0U;
1442   }
1443   ep->num = ep_addr & EP_ADDR_MSK;
1444 
1445   __HAL_LOCK(hpcd);
1446   (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
1447   __HAL_UNLOCK(hpcd);
1448   return HAL_OK;
1449 }
1450 
1451 
1452 /**
1453   * @brief  Receive an amount of data.
1454   * @param  hpcd PCD handle
1455   * @param  ep_addr endpoint address
1456   * @param  pBuf pointer to the reception buffer
1457   * @param  len amount of data to be received
1458   * @retval HAL status
1459   */
HAL_PCD_EP_Receive(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)1460 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1461 {
1462   PCD_EPTypeDef *ep;
1463 
1464   ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1465 
1466   /*setup and start the Xfer */
1467   ep->xfer_buff = pBuf;
1468   ep->xfer_len = len;
1469   ep->xfer_count = 0U;
1470   ep->is_in = 0U;
1471   ep->num = ep_addr & EP_ADDR_MSK;
1472 
1473   (void)USB_EPStartXfer(hpcd->Instance, ep);
1474 
1475   return HAL_OK;
1476 }
1477 
1478 /**
1479   * @brief  Get Received Data Size
1480   * @param  hpcd PCD handle
1481   * @param  ep_addr endpoint address
1482   * @retval Data Size
1483   */
HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const * hpcd,uint8_t ep_addr)1484 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const *hpcd, uint8_t ep_addr)
1485 {
1486   return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
1487 }
1488 /**
1489   * @brief  Send an amount of data
1490   * @param  hpcd PCD handle
1491   * @param  ep_addr endpoint address
1492   * @param  pBuf pointer to the transmission buffer
1493   * @param  len amount of data to be sent
1494   * @retval HAL status
1495   */
HAL_PCD_EP_Transmit(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)1496 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1497 {
1498   PCD_EPTypeDef *ep;
1499 
1500   ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1501 
1502   /*setup and start the Xfer */
1503   ep->xfer_buff = pBuf;
1504   ep->xfer_len = len;
1505   ep->xfer_fill_db = 1U;
1506   ep->xfer_len_db = len;
1507   ep->xfer_count = 0U;
1508   ep->is_in = 1U;
1509   ep->num = ep_addr & EP_ADDR_MSK;
1510 
1511   (void)USB_EPStartXfer(hpcd->Instance, ep);
1512 
1513   return HAL_OK;
1514 }
1515 
1516 /**
1517   * @brief  Set a STALL condition over an endpoint
1518   * @param  hpcd PCD handle
1519   * @param  ep_addr endpoint address
1520   * @retval HAL status
1521   */
HAL_PCD_EP_SetStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1522 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1523 {
1524   PCD_EPTypeDef *ep;
1525 
1526   if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
1527   {
1528     return HAL_ERROR;
1529   }
1530 
1531   if ((0x80U & ep_addr) == 0x80U)
1532   {
1533     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1534     ep->is_in = 1U;
1535   }
1536   else
1537   {
1538     ep = &hpcd->OUT_ep[ep_addr];
1539     ep->is_in = 0U;
1540   }
1541 
1542   ep->is_stall = 1U;
1543   ep->num = ep_addr & EP_ADDR_MSK;
1544 
1545   __HAL_LOCK(hpcd);
1546 
1547   (void)USB_EPSetStall(hpcd->Instance, ep);
1548 
1549   __HAL_UNLOCK(hpcd);
1550 
1551   return HAL_OK;
1552 }
1553 
1554 /**
1555   * @brief  Clear a STALL condition over in an endpoint
1556   * @param  hpcd PCD handle
1557   * @param  ep_addr endpoint address
1558   * @retval HAL status
1559   */
HAL_PCD_EP_ClrStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1560 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1561 {
1562   PCD_EPTypeDef *ep;
1563 
1564   if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
1565   {
1566     return HAL_ERROR;
1567   }
1568 
1569   if ((0x80U & ep_addr) == 0x80U)
1570   {
1571     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1572     ep->is_in = 1U;
1573   }
1574   else
1575   {
1576     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1577     ep->is_in = 0U;
1578   }
1579 
1580   ep->is_stall = 0U;
1581   ep->num = ep_addr & EP_ADDR_MSK;
1582 
1583   __HAL_LOCK(hpcd);
1584   (void)USB_EPClearStall(hpcd->Instance, ep);
1585   __HAL_UNLOCK(hpcd);
1586 
1587   return HAL_OK;
1588 }
1589 
1590 /**
1591    * @brief  Abort an USB EP transaction.
1592    * @param  hpcd PCD handle
1593    * @param  ep_addr endpoint address
1594    * @retval HAL status
1595    */
HAL_PCD_EP_Abort(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1596 HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1597 {
1598   HAL_StatusTypeDef ret;
1599   PCD_EPTypeDef *ep;
1600 
1601   if ((0x80U & ep_addr) == 0x80U)
1602   {
1603     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1604   }
1605   else
1606   {
1607     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1608   }
1609 
1610   /* Stop Xfer */
1611   ret = USB_EPStopXfer(hpcd->Instance, ep);
1612 
1613   return ret;
1614 }
1615 
1616 /**
1617   * @brief  Flush an endpoint
1618   * @param  hpcd PCD handle
1619   * @param  ep_addr endpoint address
1620   * @retval HAL status
1621   */
HAL_PCD_EP_Flush(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1622 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1623 {
1624   __HAL_LOCK(hpcd);
1625 
1626   if ((ep_addr & 0x80U) == 0x80U)
1627   {
1628     (void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
1629   }
1630   else
1631   {
1632     (void)USB_FlushRxFifo(hpcd->Instance);
1633   }
1634 
1635   __HAL_UNLOCK(hpcd);
1636 
1637   return HAL_OK;
1638 }
1639 
1640 /**
1641   * @brief  Activate remote wakeup signalling
1642   * @param  hpcd PCD handle
1643   * @retval HAL status
1644   */
HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1645 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1646 {
1647   return (USB_ActivateRemoteWakeup(hpcd->Instance));
1648 }
1649 
1650 /**
1651   * @brief  De-activate remote wakeup signalling.
1652   * @param  hpcd PCD handle
1653   * @retval HAL status
1654   */
HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1655 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1656 {
1657   return (USB_DeActivateRemoteWakeup(hpcd->Instance));
1658 }
1659 
1660 /**
1661   * @}
1662   */
1663 
1664 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1665   *  @brief   Peripheral State functions
1666   *
1667 @verbatim
1668  ===============================================================================
1669                       ##### Peripheral State functions #####
1670  ===============================================================================
1671     [..]
1672     This subsection permits to get in run-time the status of the peripheral
1673     and the data flow.
1674 
1675 @endverbatim
1676   * @{
1677   */
1678 
1679 /**
1680   * @brief  Return the PCD handle state.
1681   * @param  hpcd PCD handle
1682   * @retval HAL state
1683   */
HAL_PCD_GetState(PCD_HandleTypeDef const * hpcd)1684 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef const *hpcd)
1685 {
1686   return hpcd->State;
1687 }
1688 
1689 /**
1690   * @}
1691   */
1692 
1693 /**
1694   * @}
1695   */
1696 
1697 /* Private functions ---------------------------------------------------------*/
1698 /** @addtogroup PCD_Private_Functions
1699   * @{
1700   */
1701 
1702 
1703 /**
1704   * @brief  This function handles PCD Endpoint interrupt request.
1705   * @param  hpcd PCD handle
1706   * @retval HAL status
1707   */
PCD_EP_ISR_Handler(PCD_HandleTypeDef * hpcd)1708 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
1709 {
1710   PCD_EPTypeDef *ep;
1711   uint16_t count;
1712   uint16_t wIstr;
1713   uint16_t wEPVal;
1714   uint16_t TxPctSize;
1715   uint8_t epindex;
1716 
1717 #if (USE_USB_DOUBLE_BUFFER != 1U)
1718   count = 0U;
1719 #endif /* USE_USB_DOUBLE_BUFFER */
1720 
1721   /* stay in loop while pending interrupts */
1722   while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
1723   {
1724     wIstr = hpcd->Instance->ISTR;
1725 
1726     /* extract highest priority endpoint number */
1727     epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
1728 
1729     if (epindex == 0U)
1730     {
1731       /* Decode and service control endpoint interrupt */
1732 
1733       /* DIR bit = origin of the interrupt */
1734       if ((wIstr & USB_ISTR_DIR) == 0U)
1735       {
1736         /* DIR = 0 */
1737 
1738         /* DIR = 0 => IN  int */
1739         /* DIR = 0 implies that (EP_CTR_TX = 1) always */
1740         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1741         ep = &hpcd->IN_ep[0];
1742 
1743         ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1744         ep->xfer_buff += ep->xfer_count;
1745 
1746         /* TX COMPLETE */
1747 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1748         hpcd->DataInStageCallback(hpcd, 0U);
1749 #else
1750         HAL_PCD_DataInStageCallback(hpcd, 0U);
1751 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1752 
1753         if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
1754         {
1755           hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
1756           hpcd->USB_Address = 0U;
1757         }
1758       }
1759       else
1760       {
1761         /* DIR = 1 */
1762 
1763         /* DIR = 1 & CTR_RX => SETUP or OUT int */
1764         /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
1765         ep = &hpcd->OUT_ep[0];
1766         wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1767 
1768         if ((wEPVal & USB_EP_SETUP) != 0U)
1769         {
1770           /* Get SETUP Packet */
1771           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1772 
1773           USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
1774                       ep->pmaadress, (uint16_t)ep->xfer_count);
1775 
1776           /* SETUP bit kept frozen while CTR_RX = 1 */
1777           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1778 
1779           /* Process SETUP Packet*/
1780 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1781           hpcd->SetupStageCallback(hpcd);
1782 #else
1783           HAL_PCD_SetupStageCallback(hpcd);
1784 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1785         }
1786         else if ((wEPVal & USB_EP_CTR_RX) != 0U)
1787         {
1788           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1789 
1790           /* Get Control Data OUT Packet */
1791           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1792 
1793           if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
1794           {
1795             USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
1796                         ep->pmaadress, (uint16_t)ep->xfer_count);
1797 
1798             ep->xfer_buff += ep->xfer_count;
1799 
1800             /* Process Control Data OUT Packet */
1801 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1802             hpcd->DataOutStageCallback(hpcd, 0U);
1803 #else
1804             HAL_PCD_DataOutStageCallback(hpcd, 0U);
1805 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1806           }
1807 
1808           wEPVal = (uint16_t)PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1809 
1810           if (((wEPVal & USB_EP_SETUP) == 0U) && ((wEPVal & USB_EP_RX_STRX) != USB_EP_RX_VALID))
1811           {
1812             PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
1813             PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
1814           }
1815         }
1816       }
1817     }
1818     else
1819     {
1820       /* Decode and service non control endpoints interrupt */
1821       /* process related endpoint register */
1822       wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
1823 
1824       if ((wEPVal & USB_EP_CTR_RX) != 0U)
1825       {
1826         /* clear int flag */
1827         PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
1828         ep = &hpcd->OUT_ep[epindex];
1829 
1830         /* OUT Single Buffering */
1831         if (ep->doublebuffer == 0U)
1832         {
1833           count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1834 
1835           if (count != 0U)
1836           {
1837             USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
1838           }
1839         }
1840 #if (USE_USB_DOUBLE_BUFFER == 1U)
1841         else
1842         {
1843           /* manage double buffer bulk out */
1844           if (ep->type == EP_TYPE_BULK)
1845           {
1846             count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
1847           }
1848           else /* manage double buffer iso out */
1849           {
1850             /* free EP OUT Buffer */
1851             PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
1852 
1853             if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
1854             {
1855               /* read from endpoint BUF0Addr buffer */
1856               count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1857 
1858               if (count != 0U)
1859               {
1860                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
1861               }
1862             }
1863             else
1864             {
1865               /* read from endpoint BUF1Addr buffer */
1866               count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1867 
1868               if (count != 0U)
1869               {
1870                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
1871               }
1872             }
1873           }
1874         }
1875 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1876 
1877         /* multi-packet on the NON control OUT endpoint */
1878         ep->xfer_count += count;
1879         ep->xfer_buff += count;
1880 
1881         if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
1882         {
1883           /* RX COMPLETE */
1884 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1885           hpcd->DataOutStageCallback(hpcd, ep->num);
1886 #else
1887           HAL_PCD_DataOutStageCallback(hpcd, ep->num);
1888 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1889         }
1890         else
1891         {
1892           (void)USB_EPStartXfer(hpcd->Instance, ep);
1893         }
1894       }
1895 
1896       if ((wEPVal & USB_EP_CTR_TX) != 0U)
1897       {
1898         ep = &hpcd->IN_ep[epindex];
1899 
1900         /* clear int flag */
1901         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
1902 
1903         if (ep->type == EP_TYPE_ISOC)
1904         {
1905           ep->xfer_len = 0U;
1906 
1907 #if (USE_USB_DOUBLE_BUFFER == 1U)
1908           if (ep->doublebuffer != 0U)
1909           {
1910             if ((wEPVal & USB_EP_DTOG_TX) != 0U)
1911             {
1912               PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
1913             }
1914             else
1915             {
1916               PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
1917             }
1918           }
1919 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1920 
1921           /* TX COMPLETE */
1922 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1923           hpcd->DataInStageCallback(hpcd, ep->num);
1924 #else
1925           HAL_PCD_DataInStageCallback(hpcd, ep->num);
1926 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1927         }
1928         else
1929         {
1930           /* Manage Single Buffer Transaction */
1931           if ((wEPVal & USB_EP_KIND) == 0U)
1932           {
1933             /* multi-packet on the NON control IN endpoint */
1934             TxPctSize = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1935 
1936             if (ep->xfer_len > TxPctSize)
1937             {
1938               ep->xfer_len -= TxPctSize;
1939             }
1940             else
1941             {
1942               ep->xfer_len = 0U;
1943             }
1944 
1945             /* Zero Length Packet? */
1946             if (ep->xfer_len == 0U)
1947             {
1948               /* TX COMPLETE */
1949 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1950               hpcd->DataInStageCallback(hpcd, ep->num);
1951 #else
1952               HAL_PCD_DataInStageCallback(hpcd, ep->num);
1953 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1954             }
1955             else
1956             {
1957               /* Transfer is not yet Done */
1958               ep->xfer_buff += TxPctSize;
1959               ep->xfer_count += TxPctSize;
1960               (void)USB_EPStartXfer(hpcd->Instance, ep);
1961             }
1962           }
1963 #if (USE_USB_DOUBLE_BUFFER == 1U)
1964           /* Double Buffer bulk IN (bulk transfer Len > Ep_Mps) */
1965           else
1966           {
1967             (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
1968           }
1969 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1970         }
1971       }
1972     }
1973   }
1974 
1975   return HAL_OK;
1976 }
1977 
1978 
1979 #if (USE_USB_DOUBLE_BUFFER == 1U)
1980 /**
1981   * @brief  Manage double buffer bulk out transaction from ISR
1982   * @param  hpcd PCD handle
1983   * @param  ep current endpoint handle
1984   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
1985   * @retval HAL status
1986   */
HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)1987 static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
1988                                       PCD_EPTypeDef *ep, uint16_t wEPVal)
1989 {
1990   uint16_t count;
1991 
1992   /* Manage Buffer0 OUT */
1993   if ((wEPVal & USB_EP_DTOG_RX) != 0U)
1994   {
1995     /* Get count of received Data on buffer0 */
1996     count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1997 
1998     if (ep->xfer_len >= count)
1999     {
2000       ep->xfer_len -= count;
2001     }
2002     else
2003     {
2004       ep->xfer_len = 0U;
2005     }
2006 
2007     if (ep->xfer_len == 0U)
2008     {
2009       /* set NAK to OUT endpoint since double buffer is enabled */
2010       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2011     }
2012 
2013     /* Check if Buffer1 is in blocked state which requires to toggle */
2014     if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2015     {
2016       PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2017     }
2018 
2019     if (count != 0U)
2020     {
2021       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2022     }
2023   }
2024   /* Manage Buffer 1 DTOG_RX=0 */
2025   else
2026   {
2027     /* Get count of received data */
2028     count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2029 
2030     if (ep->xfer_len >= count)
2031     {
2032       ep->xfer_len -= count;
2033     }
2034     else
2035     {
2036       ep->xfer_len = 0U;
2037     }
2038 
2039     if (ep->xfer_len == 0U)
2040     {
2041       /* set NAK on the current endpoint */
2042       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2043     }
2044 
2045     /*Need to FreeUser Buffer*/
2046     if ((wEPVal & USB_EP_DTOG_TX) == 0U)
2047     {
2048       PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2049     }
2050 
2051     if (count != 0U)
2052     {
2053       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2054     }
2055   }
2056 
2057   return count;
2058 }
2059 
2060 
2061 /**
2062   * @brief  Manage double buffer bulk IN transaction from ISR
2063   * @param  hpcd PCD handle
2064   * @param  ep current endpoint handle
2065   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
2066   * @retval HAL status
2067   */
HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)2068 static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
2069                                                 PCD_EPTypeDef *ep, uint16_t wEPVal)
2070 {
2071   uint32_t len;
2072   uint16_t TxPctSize;
2073 
2074   /* Data Buffer0 ACK received */
2075   if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2076   {
2077     /* multi-packet on the NON control IN endpoint */
2078     TxPctSize = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2079 
2080     if (ep->xfer_len > TxPctSize)
2081     {
2082       ep->xfer_len -= TxPctSize;
2083     }
2084     else
2085     {
2086       ep->xfer_len = 0U;
2087     }
2088 
2089     /* Transfer is completed */
2090     if (ep->xfer_len == 0U)
2091     {
2092       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2093       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2094 
2095       /* TX COMPLETE */
2096 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2097       hpcd->DataInStageCallback(hpcd, ep->num);
2098 #else
2099       HAL_PCD_DataInStageCallback(hpcd, ep->num);
2100 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2101 
2102       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2103       {
2104         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2105       }
2106     }
2107     else /* Transfer is not yet Done */
2108     {
2109       /* need to Free USB Buff */
2110       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2111       {
2112         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2113       }
2114 
2115       /* Still there is data to Fill in the next Buffer */
2116       if (ep->xfer_fill_db == 1U)
2117       {
2118         ep->xfer_buff += TxPctSize;
2119         ep->xfer_count += TxPctSize;
2120 
2121         /* Calculate the len of the new buffer to fill */
2122         if (ep->xfer_len_db >= ep->maxpacket)
2123         {
2124           len = ep->maxpacket;
2125           ep->xfer_len_db -= len;
2126         }
2127         else if (ep->xfer_len_db == 0U)
2128         {
2129           len = TxPctSize;
2130           ep->xfer_fill_db = 0U;
2131         }
2132         else
2133         {
2134           ep->xfer_fill_db = 0U;
2135           len = ep->xfer_len_db;
2136           ep->xfer_len_db = 0U;
2137         }
2138 
2139         /* Write remaining Data to Buffer */
2140         /* Set the Double buffer counter for pma buffer1 */
2141         PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2142 
2143         /* Copy user buffer to USB PMA */
2144         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr0, (uint16_t)len);
2145       }
2146     }
2147   }
2148   else /* Data Buffer1 ACK received */
2149   {
2150     /* multi-packet on the NON control IN endpoint */
2151     TxPctSize = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2152 
2153     if (ep->xfer_len >= TxPctSize)
2154     {
2155       ep->xfer_len -= TxPctSize;
2156     }
2157     else
2158     {
2159       ep->xfer_len = 0U;
2160     }
2161 
2162     /* Transfer is completed */
2163     if (ep->xfer_len == 0U)
2164     {
2165       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2166       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2167 
2168       /* TX COMPLETE */
2169 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2170       hpcd->DataInStageCallback(hpcd, ep->num);
2171 #else
2172       HAL_PCD_DataInStageCallback(hpcd, ep->num);
2173 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2174 
2175       /* need to Free USB Buff */
2176       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2177       {
2178         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2179       }
2180     }
2181     else /* Transfer is not yet Done */
2182     {
2183       /* need to Free USB Buff */
2184       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2185       {
2186         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2187       }
2188 
2189       /* Still there is data to Fill in the next Buffer */
2190       if (ep->xfer_fill_db == 1U)
2191       {
2192         ep->xfer_buff += TxPctSize;
2193         ep->xfer_count += TxPctSize;
2194 
2195         /* Calculate the len of the new buffer to fill */
2196         if (ep->xfer_len_db >= ep->maxpacket)
2197         {
2198           len = ep->maxpacket;
2199           ep->xfer_len_db -= len;
2200         }
2201         else if (ep->xfer_len_db == 0U)
2202         {
2203           len = TxPctSize;
2204           ep->xfer_fill_db = 0U;
2205         }
2206         else
2207         {
2208           len = ep->xfer_len_db;
2209           ep->xfer_len_db = 0U;
2210           ep->xfer_fill_db = 0;
2211         }
2212 
2213         /* Set the Double buffer counter for pmabuffer1 */
2214         PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2215 
2216         /* Copy the user buffer to USB PMA */
2217         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr1, (uint16_t)len);
2218       }
2219     }
2220   }
2221 
2222   /*enable endpoint IN*/
2223   PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
2224 
2225   return HAL_OK;
2226 }
2227 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2228 
2229 
2230 
2231 /**
2232   * @}
2233   */
2234 #endif /* defined (USB) */
2235 #endif /* HAL_PCD_MODULE_ENABLED */
2236 
2237 /**
2238   * @}
2239   */
2240 
2241 /**
2242   * @}
2243   */
2244