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