1 /**
2   ******************************************************************************
3   * @file    stm32f0xx_hal_pcd.c
4   * @author  MCD Application Team
5   * @brief   PCD HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the USB Peripheral Controller:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *           + Peripheral Control functions
11   *           + Peripheral State functions
12   *
13   ******************************************************************************
14   * @attention
15   *
16   * Copyright (c) 2016 STMicroelectronics.
17   * All rights reserved.
18   *
19   * This software is licensed under terms that can be found in the LICENSE file
20   * in the root directory of this software component.
21   * If no LICENSE file comes with this software, it is provided AS-IS.
22   *
23   ******************************************************************************
24   @verbatim
25   ==============================================================================
26                     ##### How to use this driver #####
27   ==============================================================================
28     [..]
29       The PCD HAL driver can be used as follows:
30 
31      (#) Declare a PCD_HandleTypeDef handle structure, for example:
32          PCD_HandleTypeDef  hpcd;
33 
34      (#) Fill parameters of Init structure in HCD handle
35 
36      (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
37 
38      (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
39          (##) Enable the PCD/USB Low Level interface clock using
40               (+++) __HAL_RCC_USB_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 "stm32f0xx_hal.h"
58 
59 /** @addtogroup STM32F0xx_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 * hpcd,uint8_t ep_addr)1484 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *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   /* Prevent unused argument(s) compilation warning */
1625   UNUSED(hpcd);
1626   UNUSED(ep_addr);
1627 
1628   return HAL_OK;
1629 }
1630 
1631 /**
1632   * @brief  Activate remote wakeup signalling
1633   * @param  hpcd PCD handle
1634   * @retval HAL status
1635   */
HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1636 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1637 {
1638   return (USB_ActivateRemoteWakeup(hpcd->Instance));
1639 }
1640 
1641 /**
1642   * @brief  De-activate remote wakeup signalling.
1643   * @param  hpcd PCD handle
1644   * @retval HAL status
1645   */
HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1646 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1647 {
1648   return (USB_DeActivateRemoteWakeup(hpcd->Instance));
1649 }
1650 
1651 /**
1652   * @}
1653   */
1654 
1655 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1656   *  @brief   Peripheral State functions
1657   *
1658 @verbatim
1659  ===============================================================================
1660                       ##### Peripheral State functions #####
1661  ===============================================================================
1662     [..]
1663     This subsection permits to get in run-time the status of the peripheral
1664     and the data flow.
1665 
1666 @endverbatim
1667   * @{
1668   */
1669 
1670 /**
1671   * @brief  Return the PCD handle state.
1672   * @param  hpcd PCD handle
1673   * @retval HAL state
1674   */
HAL_PCD_GetState(PCD_HandleTypeDef * hpcd)1675 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1676 {
1677   return hpcd->State;
1678 }
1679 
1680 /**
1681   * @}
1682   */
1683 
1684 /**
1685   * @}
1686   */
1687 
1688 /* Private functions ---------------------------------------------------------*/
1689 /** @addtogroup PCD_Private_Functions
1690   * @{
1691   */
1692 
1693 
1694 /**
1695   * @brief  This function handles PCD Endpoint interrupt request.
1696   * @param  hpcd PCD handle
1697   * @retval HAL status
1698   */
PCD_EP_ISR_Handler(PCD_HandleTypeDef * hpcd)1699 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
1700 {
1701   PCD_EPTypeDef *ep;
1702   uint16_t count;
1703   uint16_t wIstr;
1704   uint16_t wEPVal;
1705   uint16_t TxPctSize;
1706   uint8_t epindex;
1707 
1708 #if (USE_USB_DOUBLE_BUFFER != 1U)
1709   count = 0U;
1710 #endif /* USE_USB_DOUBLE_BUFFER */
1711 
1712   /* stay in loop while pending interrupts */
1713   while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
1714   {
1715     wIstr = hpcd->Instance->ISTR;
1716 
1717     /* extract highest priority endpoint number */
1718     epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
1719 
1720     if (epindex == 0U)
1721     {
1722       /* Decode and service control endpoint interrupt */
1723 
1724       /* DIR bit = origin of the interrupt */
1725       if ((wIstr & USB_ISTR_DIR) == 0U)
1726       {
1727         /* DIR = 0 */
1728 
1729         /* DIR = 0 => IN  int */
1730         /* DIR = 0 implies that (EP_CTR_TX = 1) always */
1731         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1732         ep = &hpcd->IN_ep[0];
1733 
1734         ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1735         ep->xfer_buff += ep->xfer_count;
1736 
1737         /* TX COMPLETE */
1738 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1739         hpcd->DataInStageCallback(hpcd, 0U);
1740 #else
1741         HAL_PCD_DataInStageCallback(hpcd, 0U);
1742 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1743 
1744         if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
1745         {
1746           hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
1747           hpcd->USB_Address = 0U;
1748         }
1749       }
1750       else
1751       {
1752         /* DIR = 1 */
1753 
1754         /* DIR = 1 & CTR_RX => SETUP or OUT int */
1755         /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
1756         ep = &hpcd->OUT_ep[0];
1757         wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1758 
1759         if ((wEPVal & USB_EP_SETUP) != 0U)
1760         {
1761           /* Get SETUP Packet */
1762           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1763 
1764           USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
1765                       ep->pmaadress, (uint16_t)ep->xfer_count);
1766 
1767           /* SETUP bit kept frozen while CTR_RX = 1 */
1768           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1769 
1770           /* Process SETUP Packet*/
1771 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1772           hpcd->SetupStageCallback(hpcd);
1773 #else
1774           HAL_PCD_SetupStageCallback(hpcd);
1775 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1776         }
1777         else if ((wEPVal & USB_EP_CTR_RX) != 0U)
1778         {
1779           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1780 
1781           /* Get Control Data OUT Packet */
1782           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1783 
1784           if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
1785           {
1786             USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
1787                         ep->pmaadress, (uint16_t)ep->xfer_count);
1788 
1789             ep->xfer_buff += ep->xfer_count;
1790 
1791             /* Process Control Data OUT Packet */
1792 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1793             hpcd->DataOutStageCallback(hpcd, 0U);
1794 #else
1795             HAL_PCD_DataOutStageCallback(hpcd, 0U);
1796 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1797           }
1798 
1799           wEPVal = (uint16_t)PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1800 
1801           if (((wEPVal & USB_EP_SETUP) == 0U) && ((wEPVal & USB_EP_RX_STRX) != USB_EP_RX_VALID))
1802           {
1803             PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
1804             PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
1805           }
1806         }
1807       }
1808     }
1809     else
1810     {
1811       /* Decode and service non control endpoints interrupt */
1812       /* process related endpoint register */
1813       wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
1814 
1815       if ((wEPVal & USB_EP_CTR_RX) != 0U)
1816       {
1817         /* clear int flag */
1818         PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
1819         ep = &hpcd->OUT_ep[epindex];
1820 
1821         /* OUT Single Buffering */
1822         if (ep->doublebuffer == 0U)
1823         {
1824           count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1825 
1826           if (count != 0U)
1827           {
1828             USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
1829           }
1830         }
1831 #if (USE_USB_DOUBLE_BUFFER == 1U)
1832         else
1833         {
1834           /* manage double buffer bulk out */
1835           if (ep->type == EP_TYPE_BULK)
1836           {
1837             count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
1838           }
1839           else /* manage double buffer iso out */
1840           {
1841             /* free EP OUT Buffer */
1842             PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
1843 
1844             if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
1845             {
1846               /* read from endpoint BUF0Addr buffer */
1847               count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1848 
1849               if (count != 0U)
1850               {
1851                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
1852               }
1853             }
1854             else
1855             {
1856               /* read from endpoint BUF1Addr buffer */
1857               count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1858 
1859               if (count != 0U)
1860               {
1861                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
1862               }
1863             }
1864           }
1865         }
1866 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1867 
1868         /* multi-packet on the NON control OUT endpoint */
1869         ep->xfer_count += count;
1870         ep->xfer_buff += count;
1871 
1872         if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
1873         {
1874           /* RX COMPLETE */
1875 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1876           hpcd->DataOutStageCallback(hpcd, ep->num);
1877 #else
1878           HAL_PCD_DataOutStageCallback(hpcd, ep->num);
1879 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1880         }
1881         else
1882         {
1883           (void)USB_EPStartXfer(hpcd->Instance, ep);
1884         }
1885       }
1886 
1887       if ((wEPVal & USB_EP_CTR_TX) != 0U)
1888       {
1889         ep = &hpcd->IN_ep[epindex];
1890 
1891         /* clear int flag */
1892         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
1893 
1894         if (ep->type == EP_TYPE_ISOC)
1895         {
1896           ep->xfer_len = 0U;
1897 
1898 #if (USE_USB_DOUBLE_BUFFER == 1U)
1899           if (ep->doublebuffer != 0U)
1900           {
1901             if ((wEPVal & USB_EP_DTOG_TX) != 0U)
1902             {
1903               PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
1904             }
1905             else
1906             {
1907               PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
1908             }
1909           }
1910 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1911 
1912           /* TX COMPLETE */
1913 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1914           hpcd->DataInStageCallback(hpcd, ep->num);
1915 #else
1916           HAL_PCD_DataInStageCallback(hpcd, ep->num);
1917 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1918         }
1919         else
1920         {
1921           /* Manage Single Buffer Transaction */
1922           if ((wEPVal & USB_EP_KIND) == 0U)
1923           {
1924             /* multi-packet on the NON control IN endpoint */
1925             TxPctSize = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1926 
1927             if (ep->xfer_len > TxPctSize)
1928             {
1929               ep->xfer_len -= TxPctSize;
1930             }
1931             else
1932             {
1933               ep->xfer_len = 0U;
1934             }
1935 
1936             /* Zero Length Packet? */
1937             if (ep->xfer_len == 0U)
1938             {
1939               /* TX COMPLETE */
1940 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1941               hpcd->DataInStageCallback(hpcd, ep->num);
1942 #else
1943               HAL_PCD_DataInStageCallback(hpcd, ep->num);
1944 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1945             }
1946             else
1947             {
1948               /* Transfer is not yet Done */
1949               ep->xfer_buff += TxPctSize;
1950               ep->xfer_count += TxPctSize;
1951               (void)USB_EPStartXfer(hpcd->Instance, ep);
1952             }
1953           }
1954 #if (USE_USB_DOUBLE_BUFFER == 1U)
1955           /* Double Buffer bulk IN (bulk transfer Len > Ep_Mps) */
1956           else
1957           {
1958             (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
1959           }
1960 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1961         }
1962       }
1963     }
1964   }
1965 
1966   return HAL_OK;
1967 }
1968 
1969 
1970 #if (USE_USB_DOUBLE_BUFFER == 1U)
1971 /**
1972   * @brief  Manage double buffer bulk out transaction from ISR
1973   * @param  hpcd PCD handle
1974   * @param  ep current endpoint handle
1975   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
1976   * @retval HAL status
1977   */
HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)1978 static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
1979                                       PCD_EPTypeDef *ep, uint16_t wEPVal)
1980 {
1981   uint16_t count;
1982 
1983   /* Manage Buffer0 OUT */
1984   if ((wEPVal & USB_EP_DTOG_RX) != 0U)
1985   {
1986     /* Get count of received Data on buffer0 */
1987     count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1988 
1989     if (ep->xfer_len >= count)
1990     {
1991       ep->xfer_len -= count;
1992     }
1993     else
1994     {
1995       ep->xfer_len = 0U;
1996     }
1997 
1998     if (ep->xfer_len == 0U)
1999     {
2000       /* set NAK to OUT endpoint since double buffer is enabled */
2001       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2002     }
2003 
2004     /* Check if Buffer1 is in blocked state which requires to toggle */
2005     if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2006     {
2007       PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2008     }
2009 
2010     if (count != 0U)
2011     {
2012       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2013     }
2014   }
2015   /* Manage Buffer 1 DTOG_RX=0 */
2016   else
2017   {
2018     /* Get count of received data */
2019     count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2020 
2021     if (ep->xfer_len >= count)
2022     {
2023       ep->xfer_len -= count;
2024     }
2025     else
2026     {
2027       ep->xfer_len = 0U;
2028     }
2029 
2030     if (ep->xfer_len == 0U)
2031     {
2032       /* set NAK on the current endpoint */
2033       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2034     }
2035 
2036     /*Need to FreeUser Buffer*/
2037     if ((wEPVal & USB_EP_DTOG_TX) == 0U)
2038     {
2039       PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2040     }
2041 
2042     if (count != 0U)
2043     {
2044       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2045     }
2046   }
2047 
2048   return count;
2049 }
2050 
2051 
2052 /**
2053   * @brief  Manage double buffer bulk IN transaction from ISR
2054   * @param  hpcd PCD handle
2055   * @param  ep current endpoint handle
2056   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
2057   * @retval HAL status
2058   */
HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)2059 static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
2060                                                 PCD_EPTypeDef *ep, uint16_t wEPVal)
2061 {
2062   uint32_t len;
2063   uint16_t TxPctSize;
2064 
2065   /* Data Buffer0 ACK received */
2066   if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2067   {
2068     /* multi-packet on the NON control IN endpoint */
2069     TxPctSize = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2070 
2071     if (ep->xfer_len > TxPctSize)
2072     {
2073       ep->xfer_len -= TxPctSize;
2074     }
2075     else
2076     {
2077       ep->xfer_len = 0U;
2078     }
2079 
2080     /* Transfer is completed */
2081     if (ep->xfer_len == 0U)
2082     {
2083       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2084       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2085 
2086       /* TX COMPLETE */
2087 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2088       hpcd->DataInStageCallback(hpcd, ep->num);
2089 #else
2090       HAL_PCD_DataInStageCallback(hpcd, ep->num);
2091 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2092 
2093       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2094       {
2095         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2096       }
2097     }
2098     else /* Transfer is not yet Done */
2099     {
2100       /* need to Free USB Buff */
2101       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2102       {
2103         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2104       }
2105 
2106       /* Still there is data to Fill in the next Buffer */
2107       if (ep->xfer_fill_db == 1U)
2108       {
2109         ep->xfer_buff += TxPctSize;
2110         ep->xfer_count += TxPctSize;
2111 
2112         /* Calculate the len of the new buffer to fill */
2113         if (ep->xfer_len_db >= ep->maxpacket)
2114         {
2115           len = ep->maxpacket;
2116           ep->xfer_len_db -= len;
2117         }
2118         else if (ep->xfer_len_db == 0U)
2119         {
2120           len = TxPctSize;
2121           ep->xfer_fill_db = 0U;
2122         }
2123         else
2124         {
2125           ep->xfer_fill_db = 0U;
2126           len = ep->xfer_len_db;
2127           ep->xfer_len_db = 0U;
2128         }
2129 
2130         /* Write remaining Data to Buffer */
2131         /* Set the Double buffer counter for pma buffer1 */
2132         PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2133 
2134         /* Copy user buffer to USB PMA */
2135         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr0, (uint16_t)len);
2136       }
2137     }
2138   }
2139   else /* Data Buffer1 ACK received */
2140   {
2141     /* multi-packet on the NON control IN endpoint */
2142     TxPctSize = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2143 
2144     if (ep->xfer_len >= TxPctSize)
2145     {
2146       ep->xfer_len -= TxPctSize;
2147     }
2148     else
2149     {
2150       ep->xfer_len = 0U;
2151     }
2152 
2153     /* Transfer is completed */
2154     if (ep->xfer_len == 0U)
2155     {
2156       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2157       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2158 
2159       /* TX COMPLETE */
2160 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2161       hpcd->DataInStageCallback(hpcd, ep->num);
2162 #else
2163       HAL_PCD_DataInStageCallback(hpcd, ep->num);
2164 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2165 
2166       /* need to Free USB Buff */
2167       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2168       {
2169         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2170       }
2171     }
2172     else /* Transfer is not yet Done */
2173     {
2174       /* need to Free USB Buff */
2175       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2176       {
2177         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2178       }
2179 
2180       /* Still there is data to Fill in the next Buffer */
2181       if (ep->xfer_fill_db == 1U)
2182       {
2183         ep->xfer_buff += TxPctSize;
2184         ep->xfer_count += TxPctSize;
2185 
2186         /* Calculate the len of the new buffer to fill */
2187         if (ep->xfer_len_db >= ep->maxpacket)
2188         {
2189           len = ep->maxpacket;
2190           ep->xfer_len_db -= len;
2191         }
2192         else if (ep->xfer_len_db == 0U)
2193         {
2194           len = TxPctSize;
2195           ep->xfer_fill_db = 0U;
2196         }
2197         else
2198         {
2199           len = ep->xfer_len_db;
2200           ep->xfer_len_db = 0U;
2201           ep->xfer_fill_db = 0;
2202         }
2203 
2204         /* Set the Double buffer counter for pmabuffer1 */
2205         PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2206 
2207         /* Copy the user buffer to USB PMA */
2208         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr1, (uint16_t)len);
2209       }
2210     }
2211   }
2212 
2213   /*enable endpoint IN*/
2214   PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
2215 
2216   return HAL_OK;
2217 }
2218 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2219 
2220 
2221 
2222 /**
2223   * @}
2224   */
2225 #endif /* defined (USB) */
2226 #endif /* HAL_PCD_MODULE_ENABLED */
2227 
2228 /**
2229   * @}
2230   */
2231 
2232 /**
2233   * @}
2234   */
2235