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