1 /**
2   ******************************************************************************
3   * @file    stm32f1xx_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 "stm32f1xx_hal.h"
58 
59 /** @addtogroup STM32F1xx_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) || defined (USB_OTG_FS)
71 
72 /* Private types -------------------------------------------------------------*/
73 /* Private variables ---------------------------------------------------------*/
74 /* Private constants ---------------------------------------------------------*/
75 /* Private macros ------------------------------------------------------------*/
76 /** @defgroup PCD_Private_Macros PCD Private Macros
77   * @{
78   */
79 #define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
80 #define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
81 /**
82   * @}
83   */
84 
85 /* Private functions prototypes ----------------------------------------------*/
86 /** @defgroup PCD_Private_Functions PCD Private Functions
87   * @{
88   */
89 #if defined (USB_OTG_FS)
90 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
91 static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
92 static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
93 #endif /* defined (USB_OTG_FS) */
94 
95 #if defined (USB)
96 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
97 static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
98 static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
99 #endif /* defined (USB) */
100 /**
101   * @}
102   */
103 
104 /* Exported functions --------------------------------------------------------*/
105 /** @defgroup PCD_Exported_Functions PCD Exported Functions
106   * @{
107   */
108 
109 /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
110   *  @brief    Initialization and Configuration functions
111   *
112 @verbatim
113  ===============================================================================
114             ##### Initialization and de-initialization functions #####
115  ===============================================================================
116     [..]  This section provides functions allowing to:
117 
118 @endverbatim
119   * @{
120   */
121 
122 /**
123   * @brief  Initializes the PCD according to the specified
124   *         parameters in the PCD_InitTypeDef and initialize the associated handle.
125   * @param  hpcd PCD handle
126   * @retval HAL status
127   */
HAL_PCD_Init(PCD_HandleTypeDef * hpcd)128 HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
129 {
130 #if defined (USB_OTG_FS)
131   USB_OTG_GlobalTypeDef *USBx;
132 #endif /* defined (USB_OTG_FS) */
133   uint8_t i;
134 
135   /* Check the PCD handle allocation */
136   if (hpcd == NULL)
137   {
138     return HAL_ERROR;
139   }
140 
141   /* Check the parameters */
142   assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
143 
144 #if defined (USB_OTG_FS)
145   USBx = hpcd->Instance;
146 #endif /* defined (USB_OTG_FS) */
147 
148   if (hpcd->State == HAL_PCD_STATE_RESET)
149   {
150     /* Allocate lock resource and initialize it */
151     hpcd->Lock = HAL_UNLOCKED;
152 
153 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
154     hpcd->SOFCallback = HAL_PCD_SOFCallback;
155     hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
156     hpcd->ResetCallback = HAL_PCD_ResetCallback;
157     hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
158     hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
159     hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
160     hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
161     hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
162     hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
163     hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
164     hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
165 
166     if (hpcd->MspInitCallback == NULL)
167     {
168       hpcd->MspInitCallback = HAL_PCD_MspInit;
169     }
170 
171     /* Init the low level hardware */
172     hpcd->MspInitCallback(hpcd);
173 #else
174     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
175     HAL_PCD_MspInit(hpcd);
176 #endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
177   }
178 
179   hpcd->State = HAL_PCD_STATE_BUSY;
180 
181 #if defined (USB_OTG_FS)
182   /* Disable DMA mode for FS instance */
183   if ((USBx->CID & (0x1U << 8)) == 0U)
184   {
185     hpcd->Init.dma_enable = 0U;
186   }
187 #endif /* defined (USB_OTG_FS) */
188 
189   /* Disable the Interrupts */
190   __HAL_PCD_DISABLE(hpcd);
191 
192   /*Init the Core (common init.) */
193   if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
194   {
195     hpcd->State = HAL_PCD_STATE_ERROR;
196     return HAL_ERROR;
197   }
198 
199   /* Force Device Mode*/
200   (void)USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE);
201 
202   /* Init endpoints structures */
203   for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
204   {
205     /* Init ep structure */
206     hpcd->IN_ep[i].is_in = 1U;
207     hpcd->IN_ep[i].num = i;
208     hpcd->IN_ep[i].tx_fifo_num = i;
209     /* Control until ep is activated */
210     hpcd->IN_ep[i].type = EP_TYPE_CTRL;
211     hpcd->IN_ep[i].maxpacket = 0U;
212     hpcd->IN_ep[i].xfer_buff = 0U;
213     hpcd->IN_ep[i].xfer_len = 0U;
214   }
215 
216   for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
217   {
218     hpcd->OUT_ep[i].is_in = 0U;
219     hpcd->OUT_ep[i].num = i;
220     /* Control until ep is activated */
221     hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
222     hpcd->OUT_ep[i].maxpacket = 0U;
223     hpcd->OUT_ep[i].xfer_buff = 0U;
224     hpcd->OUT_ep[i].xfer_len = 0U;
225   }
226 
227   /* Init Device */
228   if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
229   {
230     hpcd->State = HAL_PCD_STATE_ERROR;
231     return HAL_ERROR;
232   }
233 
234   hpcd->USB_Address = 0U;
235   hpcd->State = HAL_PCD_STATE_READY;
236   (void)USB_DevDisconnect(hpcd->Instance);
237 
238   return HAL_OK;
239 }
240 
241 /**
242   * @brief  DeInitializes the PCD peripheral.
243   * @param  hpcd PCD handle
244   * @retval HAL status
245   */
HAL_PCD_DeInit(PCD_HandleTypeDef * hpcd)246 HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
247 {
248   /* Check the PCD handle allocation */
249   if (hpcd == NULL)
250   {
251     return HAL_ERROR;
252   }
253 
254   hpcd->State = HAL_PCD_STATE_BUSY;
255 
256   /* Stop Device */
257   if (USB_StopDevice(hpcd->Instance) != HAL_OK)
258   {
259     return HAL_ERROR;
260   }
261 
262 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
263   if (hpcd->MspDeInitCallback == NULL)
264   {
265     hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit  */
266   }
267 
268   /* DeInit the low level hardware */
269   hpcd->MspDeInitCallback(hpcd);
270 #else
271   /* DeInit the low level hardware: CLOCK, NVIC.*/
272   HAL_PCD_MspDeInit(hpcd);
273 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
274 
275   hpcd->State = HAL_PCD_STATE_RESET;
276 
277   return HAL_OK;
278 }
279 
280 /**
281   * @brief  Initializes the PCD MSP.
282   * @param  hpcd PCD handle
283   * @retval None
284   */
HAL_PCD_MspInit(PCD_HandleTypeDef * hpcd)285 __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
286 {
287   /* Prevent unused argument(s) compilation warning */
288   UNUSED(hpcd);
289 
290   /* NOTE : This function should not be modified, when the callback is needed,
291             the HAL_PCD_MspInit could be implemented in the user file
292    */
293 }
294 
295 /**
296   * @brief  DeInitializes PCD MSP.
297   * @param  hpcd PCD handle
298   * @retval None
299   */
HAL_PCD_MspDeInit(PCD_HandleTypeDef * hpcd)300 __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
301 {
302   /* Prevent unused argument(s) compilation warning */
303   UNUSED(hpcd);
304 
305   /* NOTE : This function should not be modified, when the callback is needed,
306             the HAL_PCD_MspDeInit could be implemented in the user file
307    */
308 }
309 
310 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
311 /**
312   * @brief  Register a User USB PCD Callback
313   *         To be used instead of the weak predefined callback
314   * @param  hpcd USB PCD handle
315   * @param  CallbackID ID of the callback to be registered
316   *         This parameter can be one of the following values:
317   *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
318   *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
319   *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
320   *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
321   *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
322   *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
323   *          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
324   *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
325   *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
326   * @param  pCallback pointer to the Callback function
327   * @retval HAL status
328   */
HAL_PCD_RegisterCallback(PCD_HandleTypeDef * hpcd,HAL_PCD_CallbackIDTypeDef CallbackID,pPCD_CallbackTypeDef pCallback)329 HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
330                                            HAL_PCD_CallbackIDTypeDef CallbackID,
331                                            pPCD_CallbackTypeDef pCallback)
332 {
333   HAL_StatusTypeDef status = HAL_OK;
334 
335   if (pCallback == NULL)
336   {
337     /* Update the error code */
338     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
339     return HAL_ERROR;
340   }
341   /* Process locked */
342   __HAL_LOCK(hpcd);
343 
344   if (hpcd->State == HAL_PCD_STATE_READY)
345   {
346     switch (CallbackID)
347     {
348       case HAL_PCD_SOF_CB_ID :
349         hpcd->SOFCallback = pCallback;
350         break;
351 
352       case HAL_PCD_SETUPSTAGE_CB_ID :
353         hpcd->SetupStageCallback = pCallback;
354         break;
355 
356       case HAL_PCD_RESET_CB_ID :
357         hpcd->ResetCallback = pCallback;
358         break;
359 
360       case HAL_PCD_SUSPEND_CB_ID :
361         hpcd->SuspendCallback = pCallback;
362         break;
363 
364       case HAL_PCD_RESUME_CB_ID :
365         hpcd->ResumeCallback = pCallback;
366         break;
367 
368       case HAL_PCD_CONNECT_CB_ID :
369         hpcd->ConnectCallback = pCallback;
370         break;
371 
372       case HAL_PCD_DISCONNECT_CB_ID :
373         hpcd->DisconnectCallback = pCallback;
374         break;
375 
376       case HAL_PCD_MSPINIT_CB_ID :
377         hpcd->MspInitCallback = pCallback;
378         break;
379 
380       case HAL_PCD_MSPDEINIT_CB_ID :
381         hpcd->MspDeInitCallback = pCallback;
382         break;
383 
384       default :
385         /* Update the error code */
386         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
387         /* Return error status */
388         status =  HAL_ERROR;
389         break;
390     }
391   }
392   else if (hpcd->State == HAL_PCD_STATE_RESET)
393   {
394     switch (CallbackID)
395     {
396       case HAL_PCD_MSPINIT_CB_ID :
397         hpcd->MspInitCallback = pCallback;
398         break;
399 
400       case HAL_PCD_MSPDEINIT_CB_ID :
401         hpcd->MspDeInitCallback = pCallback;
402         break;
403 
404       default :
405         /* Update the error code */
406         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
407         /* Return error status */
408         status =  HAL_ERROR;
409         break;
410     }
411   }
412   else
413   {
414     /* Update the error code */
415     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
416     /* Return error status */
417     status =  HAL_ERROR;
418   }
419 
420   /* Release Lock */
421   __HAL_UNLOCK(hpcd);
422   return status;
423 }
424 
425 /**
426   * @brief  Unregister an USB PCD Callback
427   *         USB PCD callabck is redirected to the weak predefined callback
428   * @param  hpcd USB PCD handle
429   * @param  CallbackID ID of the callback to be unregistered
430   *         This parameter can be one of the following values:
431   *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
432   *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
433   *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
434   *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
435   *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
436   *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
437   *          @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
438   *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
439   *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
440   * @retval HAL status
441   */
HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef * hpcd,HAL_PCD_CallbackIDTypeDef CallbackID)442 HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
443 {
444   HAL_StatusTypeDef status = HAL_OK;
445 
446   /* Process locked */
447   __HAL_LOCK(hpcd);
448 
449   /* Setup Legacy weak Callbacks  */
450   if (hpcd->State == HAL_PCD_STATE_READY)
451   {
452     switch (CallbackID)
453     {
454       case HAL_PCD_SOF_CB_ID :
455         hpcd->SOFCallback = HAL_PCD_SOFCallback;
456         break;
457 
458       case HAL_PCD_SETUPSTAGE_CB_ID :
459         hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
460         break;
461 
462       case HAL_PCD_RESET_CB_ID :
463         hpcd->ResetCallback = HAL_PCD_ResetCallback;
464         break;
465 
466       case HAL_PCD_SUSPEND_CB_ID :
467         hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
468         break;
469 
470       case HAL_PCD_RESUME_CB_ID :
471         hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
472         break;
473 
474       case HAL_PCD_CONNECT_CB_ID :
475         hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
476         break;
477 
478       case HAL_PCD_DISCONNECT_CB_ID :
479         hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
480         break;
481 
482       case HAL_PCD_MSPINIT_CB_ID :
483         hpcd->MspInitCallback = HAL_PCD_MspInit;
484         break;
485 
486       case HAL_PCD_MSPDEINIT_CB_ID :
487         hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
488         break;
489 
490       default :
491         /* Update the error code */
492         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
493 
494         /* Return error status */
495         status =  HAL_ERROR;
496         break;
497     }
498   }
499   else if (hpcd->State == HAL_PCD_STATE_RESET)
500   {
501     switch (CallbackID)
502     {
503       case HAL_PCD_MSPINIT_CB_ID :
504         hpcd->MspInitCallback = HAL_PCD_MspInit;
505         break;
506 
507       case HAL_PCD_MSPDEINIT_CB_ID :
508         hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
509         break;
510 
511       default :
512         /* Update the error code */
513         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
514 
515         /* Return error status */
516         status =  HAL_ERROR;
517         break;
518     }
519   }
520   else
521   {
522     /* Update the error code */
523     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
524 
525     /* Return error status */
526     status =  HAL_ERROR;
527   }
528 
529   /* Release Lock */
530   __HAL_UNLOCK(hpcd);
531   return status;
532 }
533 
534 /**
535   * @brief  Register USB PCD Data OUT Stage Callback
536   *         To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
537   * @param  hpcd PCD handle
538   * @param  pCallback pointer to the USB PCD Data OUT Stage Callback function
539   * @retval HAL status
540   */
HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef * hpcd,pPCD_DataOutStageCallbackTypeDef pCallback)541 HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
542                                                        pPCD_DataOutStageCallbackTypeDef pCallback)
543 {
544   HAL_StatusTypeDef status = HAL_OK;
545 
546   if (pCallback == NULL)
547   {
548     /* Update the error code */
549     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
550 
551     return HAL_ERROR;
552   }
553 
554   /* Process locked */
555   __HAL_LOCK(hpcd);
556 
557   if (hpcd->State == HAL_PCD_STATE_READY)
558   {
559     hpcd->DataOutStageCallback = pCallback;
560   }
561   else
562   {
563     /* Update the error code */
564     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
565 
566     /* Return error status */
567     status =  HAL_ERROR;
568   }
569 
570   /* Release Lock */
571   __HAL_UNLOCK(hpcd);
572 
573   return status;
574 }
575 
576 /**
577   * @brief  Unregister the USB PCD Data OUT Stage Callback
578   *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
579   * @param  hpcd PCD handle
580   * @retval HAL status
581   */
HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef * hpcd)582 HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
583 {
584   HAL_StatusTypeDef status = HAL_OK;
585 
586   /* Process locked */
587   __HAL_LOCK(hpcd);
588 
589   if (hpcd->State == HAL_PCD_STATE_READY)
590   {
591     hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback  */
592   }
593   else
594   {
595     /* Update the error code */
596     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
597 
598     /* Return error status */
599     status =  HAL_ERROR;
600   }
601 
602   /* Release Lock */
603   __HAL_UNLOCK(hpcd);
604 
605   return status;
606 }
607 
608 /**
609   * @brief  Register USB PCD Data IN Stage Callback
610   *         To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
611   * @param  hpcd PCD handle
612   * @param  pCallback pointer to the USB PCD Data IN Stage Callback function
613   * @retval HAL status
614   */
HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef * hpcd,pPCD_DataInStageCallbackTypeDef pCallback)615 HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
616                                                       pPCD_DataInStageCallbackTypeDef pCallback)
617 {
618   HAL_StatusTypeDef status = HAL_OK;
619 
620   if (pCallback == NULL)
621   {
622     /* Update the error code */
623     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
624 
625     return HAL_ERROR;
626   }
627 
628   /* Process locked */
629   __HAL_LOCK(hpcd);
630 
631   if (hpcd->State == HAL_PCD_STATE_READY)
632   {
633     hpcd->DataInStageCallback = pCallback;
634   }
635   else
636   {
637     /* Update the error code */
638     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
639 
640     /* Return error status */
641     status =  HAL_ERROR;
642   }
643 
644   /* Release Lock */
645   __HAL_UNLOCK(hpcd);
646 
647   return status;
648 }
649 
650 /**
651   * @brief  Unregister the USB PCD Data IN Stage Callback
652   *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
653   * @param  hpcd PCD handle
654   * @retval HAL status
655   */
HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef * hpcd)656 HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
657 {
658   HAL_StatusTypeDef status = HAL_OK;
659 
660   /* Process locked */
661   __HAL_LOCK(hpcd);
662 
663   if (hpcd->State == HAL_PCD_STATE_READY)
664   {
665     hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback  */
666   }
667   else
668   {
669     /* Update the error code */
670     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
671 
672     /* Return error status */
673     status =  HAL_ERROR;
674   }
675 
676   /* Release Lock */
677   __HAL_UNLOCK(hpcd);
678 
679   return status;
680 }
681 
682 /**
683   * @brief  Register USB PCD Iso OUT incomplete Callback
684   *         To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
685   * @param  hpcd PCD handle
686   * @param  pCallback pointer to the USB PCD Iso OUT incomplete Callback function
687   * @retval HAL status
688   */
HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef * hpcd,pPCD_IsoOutIncpltCallbackTypeDef pCallback)689 HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
690                                                        pPCD_IsoOutIncpltCallbackTypeDef pCallback)
691 {
692   HAL_StatusTypeDef status = HAL_OK;
693 
694   if (pCallback == NULL)
695   {
696     /* Update the error code */
697     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
698 
699     return HAL_ERROR;
700   }
701 
702   /* Process locked */
703   __HAL_LOCK(hpcd);
704 
705   if (hpcd->State == HAL_PCD_STATE_READY)
706   {
707     hpcd->ISOOUTIncompleteCallback = pCallback;
708   }
709   else
710   {
711     /* Update the error code */
712     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
713 
714     /* Return error status */
715     status =  HAL_ERROR;
716   }
717 
718   /* Release Lock */
719   __HAL_UNLOCK(hpcd);
720 
721   return status;
722 }
723 
724 /**
725   * @brief  Unregister the USB PCD Iso OUT incomplete Callback
726   *         USB PCD Iso OUT incomplete Callback is redirected
727   *         to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
728   * @param  hpcd PCD handle
729   * @retval HAL status
730   */
HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef * hpcd)731 HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
732 {
733   HAL_StatusTypeDef status = HAL_OK;
734 
735   /* Process locked */
736   __HAL_LOCK(hpcd);
737 
738   if (hpcd->State == HAL_PCD_STATE_READY)
739   {
740     hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback  */
741   }
742   else
743   {
744     /* Update the error code */
745     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
746 
747     /* Return error status */
748     status =  HAL_ERROR;
749   }
750 
751   /* Release Lock */
752   __HAL_UNLOCK(hpcd);
753 
754   return status;
755 }
756 
757 /**
758   * @brief  Register USB PCD Iso IN incomplete Callback
759   *         To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
760   * @param  hpcd PCD handle
761   * @param  pCallback pointer to the USB PCD Iso IN incomplete Callback function
762   * @retval HAL status
763   */
HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef * hpcd,pPCD_IsoInIncpltCallbackTypeDef pCallback)764 HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
765                                                       pPCD_IsoInIncpltCallbackTypeDef pCallback)
766 {
767   HAL_StatusTypeDef status = HAL_OK;
768 
769   if (pCallback == NULL)
770   {
771     /* Update the error code */
772     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
773 
774     return HAL_ERROR;
775   }
776 
777   /* Process locked */
778   __HAL_LOCK(hpcd);
779 
780   if (hpcd->State == HAL_PCD_STATE_READY)
781   {
782     hpcd->ISOINIncompleteCallback = pCallback;
783   }
784   else
785   {
786     /* Update the error code */
787     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
788 
789     /* Return error status */
790     status =  HAL_ERROR;
791   }
792 
793   /* Release Lock */
794   __HAL_UNLOCK(hpcd);
795 
796   return status;
797 }
798 
799 /**
800   * @brief  Unregister the USB PCD Iso IN incomplete Callback
801   *         USB PCD Iso IN incomplete Callback is redirected
802   *         to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
803   * @param  hpcd PCD handle
804   * @retval HAL status
805   */
HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef * hpcd)806 HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
807 {
808   HAL_StatusTypeDef status = HAL_OK;
809 
810   /* Process locked */
811   __HAL_LOCK(hpcd);
812 
813   if (hpcd->State == HAL_PCD_STATE_READY)
814   {
815     hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback  */
816   }
817   else
818   {
819     /* Update the error code */
820     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
821 
822     /* Return error status */
823     status =  HAL_ERROR;
824   }
825 
826   /* Release Lock */
827   __HAL_UNLOCK(hpcd);
828 
829   return status;
830 }
831 
832 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
833 
834 /**
835   * @}
836   */
837 
838 /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
839   *  @brief   Data transfers functions
840   *
841 @verbatim
842  ===============================================================================
843                       ##### IO operation functions #####
844  ===============================================================================
845     [..]
846     This subsection provides a set of functions allowing to manage the PCD data
847     transfers.
848 
849 @endverbatim
850   * @{
851   */
852 
853 /**
854   * @brief  Start the USB device
855   * @param  hpcd PCD handle
856   * @retval HAL status
857   */
HAL_PCD_Start(PCD_HandleTypeDef * hpcd)858 HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
859 {
860   __HAL_LOCK(hpcd);
861   __HAL_PCD_ENABLE(hpcd);
862 
863 #if defined (USB)
864   HAL_PCDEx_SetConnectionState(hpcd, 1U);
865 #endif /* defined (USB) */
866 
867   (void)USB_DevConnect(hpcd->Instance);
868   __HAL_UNLOCK(hpcd);
869 
870   return HAL_OK;
871 }
872 
873 /**
874   * @brief  Stop the USB device.
875   * @param  hpcd PCD handle
876   * @retval HAL status
877   */
HAL_PCD_Stop(PCD_HandleTypeDef * hpcd)878 HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
879 {
880   __HAL_LOCK(hpcd);
881   __HAL_PCD_DISABLE(hpcd);
882 
883 #if defined (USB)
884   HAL_PCDEx_SetConnectionState(hpcd, 0U);
885 #endif /* defined (USB) */
886 
887   (void)USB_DevDisconnect(hpcd->Instance);
888 
889 #if defined (USB_OTG_FS)
890   (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
891 #endif /* defined (USB_OTG_FS) */
892 
893   __HAL_UNLOCK(hpcd);
894 
895   return HAL_OK;
896 }
897 
898 #if defined (USB_OTG_FS)
899 /**
900   * @brief  Handles PCD interrupt request.
901   * @param  hpcd PCD handle
902   * @retval HAL status
903   */
HAL_PCD_IRQHandler(PCD_HandleTypeDef * hpcd)904 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
905 {
906   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
907   uint32_t USBx_BASE = (uint32_t)USBx;
908   USB_OTG_EPTypeDef *ep;
909   uint32_t i;
910   uint32_t ep_intr;
911   uint32_t epint;
912   uint32_t epnum;
913   uint32_t fifoemptymsk;
914   uint32_t temp;
915 
916   /* ensure that we are in device mode */
917   if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
918   {
919     /* avoid spurious interrupt */
920     if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
921     {
922       return;
923     }
924 
925     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
926     {
927       /* incorrect mode, acknowledge the interrupt */
928       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
929     }
930 
931     /* Handle RxQLevel Interrupt */
932     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
933     {
934       USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
935 
936       temp = USBx->GRXSTSP;
937 
938       ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
939 
940       if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
941       {
942         if ((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
943         {
944           (void)USB_ReadPacket(USBx, ep->xfer_buff,
945                                (uint16_t)((temp & USB_OTG_GRXSTSP_BCNT) >> 4));
946 
947           ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
948           ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
949         }
950       }
951       else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_SETUP_UPDT)
952       {
953         (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
954         ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
955       }
956       else
957       {
958         /* ... */
959       }
960       USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
961     }
962 
963     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
964     {
965       epnum = 0U;
966 
967       /* Read in the device interrupt bits */
968       ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
969 
970       while (ep_intr != 0U)
971       {
972         if ((ep_intr & 0x1U) != 0U)
973         {
974           epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
975 
976           if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
977           {
978             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
979             (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
980           }
981 
982           if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
983           {
984             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
985             /* Class B setup phase done for previous decoded setup */
986             (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
987           }
988 
989           if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
990           {
991             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
992           }
993 
994           /* Clear Status Phase Received interrupt */
995           if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
996           {
997             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
998           }
999 
1000           /* Clear OUT NAK interrupt */
1001           if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
1002           {
1003             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
1004           }
1005         }
1006         epnum++;
1007         ep_intr >>= 1U;
1008       }
1009     }
1010 
1011     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
1012     {
1013       /* Read in the device interrupt bits */
1014       ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
1015 
1016       epnum = 0U;
1017 
1018       while (ep_intr != 0U)
1019       {
1020         if ((ep_intr & 0x1U) != 0U) /* In ITR */
1021         {
1022           epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
1023 
1024           if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
1025           {
1026             fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
1027             USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1028 
1029             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
1030 
1031 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1032             hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
1033 #else
1034             HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
1035 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1036           }
1037           if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
1038           {
1039             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
1040           }
1041           if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
1042           {
1043             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
1044           }
1045           if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
1046           {
1047             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
1048           }
1049           if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
1050           {
1051             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
1052           }
1053           if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
1054           {
1055             (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
1056           }
1057         }
1058         epnum++;
1059         ep_intr >>= 1U;
1060       }
1061     }
1062 
1063     /* Handle Resume Interrupt */
1064     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
1065     {
1066       /* Clear the Remote Wake-up Signaling */
1067       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1068 
1069 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1070       hpcd->ResumeCallback(hpcd);
1071 #else
1072       HAL_PCD_ResumeCallback(hpcd);
1073 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1074 
1075       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
1076     }
1077 
1078     /* Handle Suspend Interrupt */
1079     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
1080     {
1081       if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
1082       {
1083 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1084         hpcd->SuspendCallback(hpcd);
1085 #else
1086         HAL_PCD_SuspendCallback(hpcd);
1087 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1088       }
1089       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
1090     }
1091     /* Handle Reset Interrupt */
1092     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
1093     {
1094       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1095       (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
1096 
1097       for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
1098       {
1099         USBx_INEP(i)->DIEPINT = 0xFB7FU;
1100         USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
1101         USBx_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
1102         USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
1103         USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
1104         USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
1105       }
1106       USBx_DEVICE->DAINTMSK |= 0x10001U;
1107 
1108       if (hpcd->Init.use_dedicated_ep1 != 0U)
1109       {
1110         USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
1111                                    USB_OTG_DOEPMSK_XFRCM |
1112                                    USB_OTG_DOEPMSK_EPDM;
1113 
1114         USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
1115                                   USB_OTG_DIEPMSK_XFRCM |
1116                                   USB_OTG_DIEPMSK_EPDM;
1117       }
1118       else
1119       {
1120         USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
1121                                 USB_OTG_DOEPMSK_XFRCM |
1122                                 USB_OTG_DOEPMSK_EPDM |
1123                                 USB_OTG_DOEPMSK_OTEPSPRM |
1124                                 USB_OTG_DOEPMSK_NAKM;
1125 
1126         USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
1127                                 USB_OTG_DIEPMSK_XFRCM |
1128                                 USB_OTG_DIEPMSK_EPDM;
1129       }
1130 
1131       /* Set Default Address to 0 */
1132       USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
1133 
1134       /* setup EP0 to receive SETUP packets */
1135       (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
1136 
1137       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
1138     }
1139 
1140     /* Handle Enumeration done Interrupt */
1141     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
1142     {
1143       (void)USB_ActivateSetup(hpcd->Instance);
1144       hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
1145 
1146       /* Set USB Turnaround time */
1147       (void)USB_SetTurnaroundTime(hpcd->Instance,
1148                                   HAL_RCC_GetHCLKFreq(),
1149                                   (uint8_t)hpcd->Init.speed);
1150 
1151 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1152       hpcd->ResetCallback(hpcd);
1153 #else
1154       HAL_PCD_ResetCallback(hpcd);
1155 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1156 
1157       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
1158     }
1159 
1160     /* Handle SOF Interrupt */
1161     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
1162     {
1163 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1164       hpcd->SOFCallback(hpcd);
1165 #else
1166       HAL_PCD_SOFCallback(hpcd);
1167 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1168 
1169       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
1170     }
1171 
1172     /* Handle Incomplete ISO IN Interrupt */
1173     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
1174     {
1175       /* Keep application checking the corresponding Iso IN endpoint
1176       causing the incomplete Interrupt */
1177       epnum = 0U;
1178 
1179 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1180       hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1181 #else
1182       HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1183 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1184 
1185       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
1186     }
1187 
1188     /* Handle Incomplete ISO OUT Interrupt */
1189     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
1190     {
1191       /* Keep application checking the corresponding Iso OUT endpoint
1192       causing the incomplete Interrupt */
1193       epnum = 0U;
1194 
1195 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1196       hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1197 #else
1198       HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1199 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1200 
1201       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
1202     }
1203 
1204     /* Handle Connection event Interrupt */
1205     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
1206     {
1207 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1208       hpcd->ConnectCallback(hpcd);
1209 #else
1210       HAL_PCD_ConnectCallback(hpcd);
1211 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1212 
1213       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
1214     }
1215 
1216     /* Handle Disconnection event Interrupt */
1217     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
1218     {
1219       temp = hpcd->Instance->GOTGINT;
1220 
1221       if ((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
1222       {
1223 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1224         hpcd->DisconnectCallback(hpcd);
1225 #else
1226         HAL_PCD_DisconnectCallback(hpcd);
1227 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1228       }
1229       hpcd->Instance->GOTGINT |= temp;
1230     }
1231   }
1232 }
1233 
1234 
1235 /**
1236   * @brief  Handles PCD Wakeup interrupt request.
1237   * @param  hpcd PCD handle
1238   * @retval HAL status
1239   */
HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef * hpcd)1240 void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
1241 {
1242   /* Clear EXTI pending Bit */
1243   __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG();
1244 }
1245 #endif /* defined (USB_OTG_FS) */
1246 
1247 #if defined (USB)
1248 /**
1249   * @brief  This function handles PCD interrupt request.
1250   * @param  hpcd PCD handle
1251   * @retval HAL status
1252   */
HAL_PCD_IRQHandler(PCD_HandleTypeDef * hpcd)1253 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
1254 {
1255   uint16_t store_ep[8];
1256   uint8_t i;
1257 
1258   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_CTR))
1259   {
1260     /* servicing of the endpoint correct transfer interrupt */
1261     /* clear of the CTR flag into the sub */
1262     (void)PCD_EP_ISR_Handler(hpcd);
1263   }
1264 
1265   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_RESET))
1266   {
1267     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
1268 
1269 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1270     hpcd->ResetCallback(hpcd);
1271 #else
1272     HAL_PCD_ResetCallback(hpcd);
1273 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1274 
1275     (void)HAL_PCD_SetAddress(hpcd, 0U);
1276   }
1277 
1278   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_PMAOVR))
1279   {
1280     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
1281   }
1282 
1283   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ERR))
1284   {
1285     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
1286   }
1287 
1288   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_WKUP))
1289   {
1290     hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_LP_MODE);
1291     hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
1292 
1293 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1294     hpcd->ResumeCallback(hpcd);
1295 #else
1296     HAL_PCD_ResumeCallback(hpcd);
1297 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1298 
1299     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
1300   }
1301 
1302   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SUSP))
1303   {
1304     /* WA: To Clear Wakeup flag if raised with suspend signal */
1305 
1306     /* Store Endpoint register */
1307     for (i = 0U; i < 8U; i++)
1308     {
1309       store_ep[i] = PCD_GET_ENDPOINT(hpcd->Instance, i);
1310     }
1311 
1312     /* FORCE RESET */
1313     hpcd->Instance->CNTR |= (uint16_t)(USB_CNTR_FRES);
1314 
1315     /* CLEAR RESET */
1316     hpcd->Instance->CNTR &= (uint16_t)(~USB_CNTR_FRES);
1317 
1318     /* wait for reset flag in ISTR */
1319     while ((hpcd->Instance->ISTR & USB_ISTR_RESET) == 0U)
1320     {
1321     }
1322 
1323     /* Clear Reset Flag */
1324     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
1325 
1326     /* Restore Registre */
1327     for (i = 0U; i < 8U; i++)
1328     {
1329       PCD_SET_ENDPOINT(hpcd->Instance, i, store_ep[i]);
1330     }
1331 
1332     /* Force low-power mode in the macrocell */
1333     hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
1334 
1335     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
1336     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
1337 
1338     hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LP_MODE;
1339 
1340 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1341     hpcd->SuspendCallback(hpcd);
1342 #else
1343     HAL_PCD_SuspendCallback(hpcd);
1344 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1345   }
1346 
1347   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_SOF))
1348   {
1349     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
1350 
1351 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1352     hpcd->SOFCallback(hpcd);
1353 #else
1354     HAL_PCD_SOFCallback(hpcd);
1355 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1356   }
1357 
1358   if (__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_ESOF))
1359   {
1360     /* clear ESOF flag in ISTR */
1361     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
1362   }
1363 }
1364 
1365 
1366 /**
1367   * @brief  Handles PCD Wakeup interrupt request.
1368   * @param  hpcd PCD handle
1369   * @retval HAL status
1370   */
HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef * hpcd)1371 void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
1372 {
1373   /* Clear EXTI pending Bit */
1374   __HAL_USB_WAKEUP_EXTI_CLEAR_FLAG();
1375 }
1376 #endif /* defined (USB) */
1377 
1378 /**
1379   * @brief  Data OUT stage callback.
1380   * @param  hpcd PCD handle
1381   * @param  epnum endpoint number
1382   * @retval None
1383   */
HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1384 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1385 {
1386   /* Prevent unused argument(s) compilation warning */
1387   UNUSED(hpcd);
1388   UNUSED(epnum);
1389 
1390   /* NOTE : This function should not be modified, when the callback is needed,
1391             the HAL_PCD_DataOutStageCallback could be implemented in the user file
1392    */
1393 }
1394 
1395 /**
1396   * @brief  Data IN stage callback
1397   * @param  hpcd PCD handle
1398   * @param  epnum endpoint number
1399   * @retval None
1400   */
HAL_PCD_DataInStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1401 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1402 {
1403   /* Prevent unused argument(s) compilation warning */
1404   UNUSED(hpcd);
1405   UNUSED(epnum);
1406 
1407   /* NOTE : This function should not be modified, when the callback is needed,
1408             the HAL_PCD_DataInStageCallback could be implemented in the user file
1409    */
1410 }
1411 /**
1412   * @brief  Setup stage callback
1413   * @param  hpcd PCD handle
1414   * @retval None
1415   */
HAL_PCD_SetupStageCallback(PCD_HandleTypeDef * hpcd)1416 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
1417 {
1418   /* Prevent unused argument(s) compilation warning */
1419   UNUSED(hpcd);
1420 
1421   /* NOTE : This function should not be modified, when the callback is needed,
1422             the HAL_PCD_SetupStageCallback could be implemented in the user file
1423    */
1424 }
1425 
1426 /**
1427   * @brief  USB Start Of Frame callback.
1428   * @param  hpcd PCD handle
1429   * @retval None
1430   */
HAL_PCD_SOFCallback(PCD_HandleTypeDef * hpcd)1431 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
1432 {
1433   /* Prevent unused argument(s) compilation warning */
1434   UNUSED(hpcd);
1435 
1436   /* NOTE : This function should not be modified, when the callback is needed,
1437             the HAL_PCD_SOFCallback could be implemented in the user file
1438    */
1439 }
1440 
1441 /**
1442   * @brief  USB Reset callback.
1443   * @param  hpcd PCD handle
1444   * @retval None
1445   */
HAL_PCD_ResetCallback(PCD_HandleTypeDef * hpcd)1446 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
1447 {
1448   /* Prevent unused argument(s) compilation warning */
1449   UNUSED(hpcd);
1450 
1451   /* NOTE : This function should not be modified, when the callback is needed,
1452             the HAL_PCD_ResetCallback could be implemented in the user file
1453    */
1454 }
1455 
1456 /**
1457   * @brief  Suspend event callback.
1458   * @param  hpcd PCD handle
1459   * @retval None
1460   */
HAL_PCD_SuspendCallback(PCD_HandleTypeDef * hpcd)1461 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
1462 {
1463   /* Prevent unused argument(s) compilation warning */
1464   UNUSED(hpcd);
1465 
1466   /* NOTE : This function should not be modified, when the callback is needed,
1467             the HAL_PCD_SuspendCallback could be implemented in the user file
1468    */
1469 }
1470 
1471 /**
1472   * @brief  Resume event callback.
1473   * @param  hpcd PCD handle
1474   * @retval None
1475   */
HAL_PCD_ResumeCallback(PCD_HandleTypeDef * hpcd)1476 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
1477 {
1478   /* Prevent unused argument(s) compilation warning */
1479   UNUSED(hpcd);
1480 
1481   /* NOTE : This function should not be modified, when the callback is needed,
1482             the HAL_PCD_ResumeCallback could be implemented in the user file
1483    */
1484 }
1485 
1486 /**
1487   * @brief  Incomplete ISO OUT callback.
1488   * @param  hpcd PCD handle
1489   * @param  epnum endpoint number
1490   * @retval None
1491   */
HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1492 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1493 {
1494   /* Prevent unused argument(s) compilation warning */
1495   UNUSED(hpcd);
1496   UNUSED(epnum);
1497 
1498   /* NOTE : This function should not be modified, when the callback is needed,
1499             the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
1500    */
1501 }
1502 
1503 /**
1504   * @brief  Incomplete ISO IN callback.
1505   * @param  hpcd PCD handle
1506   * @param  epnum endpoint number
1507   * @retval None
1508   */
HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1509 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1510 {
1511   /* Prevent unused argument(s) compilation warning */
1512   UNUSED(hpcd);
1513   UNUSED(epnum);
1514 
1515   /* NOTE : This function should not be modified, when the callback is needed,
1516             the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1517    */
1518 }
1519 
1520 /**
1521   * @brief  Connection event callback.
1522   * @param  hpcd PCD handle
1523   * @retval None
1524   */
HAL_PCD_ConnectCallback(PCD_HandleTypeDef * hpcd)1525 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
1526 {
1527   /* Prevent unused argument(s) compilation warning */
1528   UNUSED(hpcd);
1529 
1530   /* NOTE : This function should not be modified, when the callback is needed,
1531             the HAL_PCD_ConnectCallback could be implemented in the user file
1532    */
1533 }
1534 
1535 /**
1536   * @brief  Disconnection event callback.
1537   * @param  hpcd PCD handle
1538   * @retval None
1539   */
HAL_PCD_DisconnectCallback(PCD_HandleTypeDef * hpcd)1540 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
1541 {
1542   /* Prevent unused argument(s) compilation warning */
1543   UNUSED(hpcd);
1544 
1545   /* NOTE : This function should not be modified, when the callback is needed,
1546             the HAL_PCD_DisconnectCallback could be implemented in the user file
1547    */
1548 }
1549 
1550 /**
1551   * @}
1552   */
1553 
1554 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
1555   *  @brief   management functions
1556   *
1557 @verbatim
1558  ===============================================================================
1559                       ##### Peripheral Control functions #####
1560  ===============================================================================
1561     [..]
1562     This subsection provides a set of functions allowing to control the PCD data
1563     transfers.
1564 
1565 @endverbatim
1566   * @{
1567   */
1568 
1569 /**
1570   * @brief  Connect the USB device
1571   * @param  hpcd PCD handle
1572   * @retval HAL status
1573   */
HAL_PCD_DevConnect(PCD_HandleTypeDef * hpcd)1574 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
1575 {
1576   __HAL_LOCK(hpcd);
1577 
1578 #if defined (USB)
1579   HAL_PCDEx_SetConnectionState(hpcd, 1U);
1580 #endif /* defined (USB) */
1581 
1582   (void)USB_DevConnect(hpcd->Instance);
1583   __HAL_UNLOCK(hpcd);
1584 
1585   return HAL_OK;
1586 }
1587 
1588 /**
1589   * @brief  Disconnect the USB device.
1590   * @param  hpcd PCD handle
1591   * @retval HAL status
1592   */
HAL_PCD_DevDisconnect(PCD_HandleTypeDef * hpcd)1593 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
1594 {
1595   __HAL_LOCK(hpcd);
1596 
1597 #if defined (USB)
1598   HAL_PCDEx_SetConnectionState(hpcd, 0U);
1599 #endif /* defined (USB) */
1600 
1601   (void)USB_DevDisconnect(hpcd->Instance);
1602   __HAL_UNLOCK(hpcd);
1603 
1604   return HAL_OK;
1605 }
1606 
1607 /**
1608   * @brief  Set the USB Device address.
1609   * @param  hpcd PCD handle
1610   * @param  address new device address
1611   * @retval HAL status
1612   */
HAL_PCD_SetAddress(PCD_HandleTypeDef * hpcd,uint8_t address)1613 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
1614 {
1615   __HAL_LOCK(hpcd);
1616   hpcd->USB_Address = address;
1617   (void)USB_SetDevAddress(hpcd->Instance, address);
1618   __HAL_UNLOCK(hpcd);
1619 
1620   return HAL_OK;
1621 }
1622 /**
1623   * @brief  Open and configure an endpoint.
1624   * @param  hpcd PCD handle
1625   * @param  ep_addr endpoint address
1626   * @param  ep_mps endpoint max packet size
1627   * @param  ep_type endpoint type
1628   * @retval HAL status
1629   */
HAL_PCD_EP_Open(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint16_t ep_mps,uint8_t ep_type)1630 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
1631                                   uint16_t ep_mps, uint8_t ep_type)
1632 {
1633   HAL_StatusTypeDef  ret = HAL_OK;
1634   PCD_EPTypeDef *ep;
1635 
1636   if ((ep_addr & 0x80U) == 0x80U)
1637   {
1638     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1639     ep->is_in = 1U;
1640   }
1641   else
1642   {
1643     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1644     ep->is_in = 0U;
1645   }
1646 
1647   ep->num = ep_addr & EP_ADDR_MSK;
1648   ep->maxpacket = ep_mps;
1649   ep->type = ep_type;
1650 
1651   if (ep->is_in != 0U)
1652   {
1653     /* Assign a Tx FIFO */
1654     ep->tx_fifo_num = ep->num;
1655   }
1656   /* Set initial data PID. */
1657   if (ep_type == EP_TYPE_BULK)
1658   {
1659     ep->data_pid_start = 0U;
1660   }
1661 
1662   __HAL_LOCK(hpcd);
1663   (void)USB_ActivateEndpoint(hpcd->Instance, ep);
1664   __HAL_UNLOCK(hpcd);
1665 
1666   return ret;
1667 }
1668 
1669 /**
1670   * @brief  Deactivate an endpoint.
1671   * @param  hpcd PCD handle
1672   * @param  ep_addr endpoint address
1673   * @retval HAL status
1674   */
HAL_PCD_EP_Close(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1675 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1676 {
1677   PCD_EPTypeDef *ep;
1678 
1679   if ((ep_addr & 0x80U) == 0x80U)
1680   {
1681     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1682     ep->is_in = 1U;
1683   }
1684   else
1685   {
1686     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1687     ep->is_in = 0U;
1688   }
1689   ep->num   = ep_addr & EP_ADDR_MSK;
1690 
1691   __HAL_LOCK(hpcd);
1692   (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
1693   __HAL_UNLOCK(hpcd);
1694   return HAL_OK;
1695 }
1696 
1697 
1698 /**
1699   * @brief  Receive an amount of data.
1700   * @param  hpcd PCD handle
1701   * @param  ep_addr endpoint address
1702   * @param  pBuf pointer to the reception buffer
1703   * @param  len amount of data to be received
1704   * @retval HAL status
1705   */
HAL_PCD_EP_Receive(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)1706 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1707 {
1708   PCD_EPTypeDef *ep;
1709 
1710   ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1711 
1712   /*setup and start the Xfer */
1713   ep->xfer_buff = pBuf;
1714   ep->xfer_len = len;
1715   ep->xfer_count = 0U;
1716   ep->is_in = 0U;
1717   ep->num = ep_addr & EP_ADDR_MSK;
1718 
1719   if ((ep_addr & EP_ADDR_MSK) == 0U)
1720   {
1721     (void)USB_EP0StartXfer(hpcd->Instance, ep);
1722   }
1723   else
1724   {
1725     (void)USB_EPStartXfer(hpcd->Instance, ep);
1726   }
1727 
1728   return HAL_OK;
1729 }
1730 
1731 /**
1732   * @brief  Get Received Data Size
1733   * @param  hpcd PCD handle
1734   * @param  ep_addr endpoint address
1735   * @retval Data Size
1736   */
HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1737 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1738 {
1739   return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
1740 }
1741 /**
1742   * @brief  Send an amount of data
1743   * @param  hpcd PCD handle
1744   * @param  ep_addr endpoint address
1745   * @param  pBuf pointer to the transmission buffer
1746   * @param  len amount of data to be sent
1747   * @retval HAL status
1748   */
HAL_PCD_EP_Transmit(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)1749 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1750 {
1751   PCD_EPTypeDef *ep;
1752 
1753   ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1754 
1755   /*setup and start the Xfer */
1756   ep->xfer_buff = pBuf;
1757   ep->xfer_len = len;
1758 #if defined (USB)
1759   ep->xfer_fill_db = 1U;
1760   ep->xfer_len_db = len;
1761 #endif /* defined (USB) */
1762   ep->xfer_count = 0U;
1763   ep->is_in = 1U;
1764   ep->num = ep_addr & EP_ADDR_MSK;
1765 
1766   if ((ep_addr & EP_ADDR_MSK) == 0U)
1767   {
1768     (void)USB_EP0StartXfer(hpcd->Instance, ep);
1769   }
1770   else
1771   {
1772     (void)USB_EPStartXfer(hpcd->Instance, ep);
1773   }
1774 
1775   return HAL_OK;
1776 }
1777 
1778 /**
1779   * @brief  Set a STALL condition over an endpoint
1780   * @param  hpcd PCD handle
1781   * @param  ep_addr endpoint address
1782   * @retval HAL status
1783   */
HAL_PCD_EP_SetStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1784 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1785 {
1786   PCD_EPTypeDef *ep;
1787 
1788   if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
1789   {
1790     return HAL_ERROR;
1791   }
1792 
1793   if ((0x80U & ep_addr) == 0x80U)
1794   {
1795     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1796     ep->is_in = 1U;
1797   }
1798   else
1799   {
1800     ep = &hpcd->OUT_ep[ep_addr];
1801     ep->is_in = 0U;
1802   }
1803 
1804   ep->is_stall = 1U;
1805   ep->num = ep_addr & EP_ADDR_MSK;
1806 
1807   __HAL_LOCK(hpcd);
1808 
1809   (void)USB_EPSetStall(hpcd->Instance, ep);
1810 
1811   if ((ep_addr & EP_ADDR_MSK) == 0U)
1812   {
1813     (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
1814   }
1815 
1816   __HAL_UNLOCK(hpcd);
1817 
1818   return HAL_OK;
1819 }
1820 
1821 /**
1822   * @brief  Clear a STALL condition over in an endpoint
1823   * @param  hpcd PCD handle
1824   * @param  ep_addr endpoint address
1825   * @retval HAL status
1826   */
HAL_PCD_EP_ClrStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1827 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1828 {
1829   PCD_EPTypeDef *ep;
1830 
1831   if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
1832   {
1833     return HAL_ERROR;
1834   }
1835 
1836   if ((0x80U & ep_addr) == 0x80U)
1837   {
1838     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1839     ep->is_in = 1U;
1840   }
1841   else
1842   {
1843     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1844     ep->is_in = 0U;
1845   }
1846 
1847   ep->is_stall = 0U;
1848   ep->num = ep_addr & EP_ADDR_MSK;
1849 
1850   __HAL_LOCK(hpcd);
1851   (void)USB_EPClearStall(hpcd->Instance, ep);
1852   __HAL_UNLOCK(hpcd);
1853 
1854   return HAL_OK;
1855 }
1856 
1857 /**
1858   * @brief  Flush an endpoint
1859   * @param  hpcd PCD handle
1860   * @param  ep_addr endpoint address
1861   * @retval HAL status
1862   */
HAL_PCD_EP_Flush(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1863 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1864 {
1865   __HAL_LOCK(hpcd);
1866 
1867   if ((ep_addr & 0x80U) == 0x80U)
1868   {
1869     (void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
1870   }
1871   else
1872   {
1873     (void)USB_FlushRxFifo(hpcd->Instance);
1874   }
1875 
1876   __HAL_UNLOCK(hpcd);
1877 
1878   return HAL_OK;
1879 }
1880 
1881 /**
1882   * @brief  Activate remote wakeup signalling
1883   * @param  hpcd PCD handle
1884   * @retval HAL status
1885   */
HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1886 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1887 {
1888   return (USB_ActivateRemoteWakeup(hpcd->Instance));
1889 }
1890 
1891 /**
1892   * @brief  De-activate remote wakeup signalling.
1893   * @param  hpcd PCD handle
1894   * @retval HAL status
1895   */
HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1896 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1897 {
1898   return (USB_DeActivateRemoteWakeup(hpcd->Instance));
1899 }
1900 
1901 /**
1902   * @}
1903   */
1904 
1905 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1906   *  @brief   Peripheral State functions
1907   *
1908 @verbatim
1909  ===============================================================================
1910                       ##### Peripheral State functions #####
1911  ===============================================================================
1912     [..]
1913     This subsection permits to get in run-time the status of the peripheral
1914     and the data flow.
1915 
1916 @endverbatim
1917   * @{
1918   */
1919 
1920 /**
1921   * @brief  Return the PCD handle state.
1922   * @param  hpcd PCD handle
1923   * @retval HAL state
1924   */
HAL_PCD_GetState(PCD_HandleTypeDef * hpcd)1925 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1926 {
1927   return hpcd->State;
1928 }
1929 
1930 /**
1931   * @}
1932   */
1933 
1934 /**
1935   * @}
1936   */
1937 
1938 /* Private functions ---------------------------------------------------------*/
1939 /** @addtogroup PCD_Private_Functions
1940   * @{
1941   */
1942 #if defined (USB_OTG_FS)
1943 /**
1944   * @brief  Check FIFO for the next packet to be loaded.
1945   * @param  hpcd PCD handle
1946   * @param  epnum endpoint number
1947   * @retval HAL status
1948   */
PCD_WriteEmptyTxFifo(PCD_HandleTypeDef * hpcd,uint32_t epnum)1949 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
1950 {
1951   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1952   uint32_t USBx_BASE = (uint32_t)USBx;
1953   USB_OTG_EPTypeDef *ep;
1954   uint32_t len;
1955   uint32_t len32b;
1956   uint32_t fifoemptymsk;
1957 
1958   ep = &hpcd->IN_ep[epnum];
1959 
1960   if (ep->xfer_count > ep->xfer_len)
1961   {
1962     return HAL_ERROR;
1963   }
1964 
1965   len = ep->xfer_len - ep->xfer_count;
1966 
1967   if (len > ep->maxpacket)
1968   {
1969     len = ep->maxpacket;
1970   }
1971 
1972   len32b = (len + 3U) / 4U;
1973 
1974   while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
1975          (ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
1976   {
1977     /* Write the FIFO */
1978     len = ep->xfer_len - ep->xfer_count;
1979 
1980     if (len > ep->maxpacket)
1981     {
1982       len = ep->maxpacket;
1983     }
1984     len32b = (len + 3U) / 4U;
1985 
1986     (void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len);
1987 
1988     ep->xfer_buff  += len;
1989     ep->xfer_count += len;
1990   }
1991 
1992   if (ep->xfer_len <= ep->xfer_count)
1993   {
1994     fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
1995     USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1996   }
1997 
1998   return HAL_OK;
1999 }
2000 
2001 
2002 /**
2003   * @brief  process EP OUT transfer complete interrupt.
2004   * @param  hpcd PCD handle
2005   * @param  epnum endpoint number
2006   * @retval HAL status
2007   */
PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef * hpcd,uint32_t epnum)2008 static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2009 {
2010   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2011   uint32_t USBx_BASE = (uint32_t)USBx;
2012   uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);
2013   uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
2014 
2015   if (gSNPSiD == USB_OTG_CORE_ID_310A)
2016   {
2017     /* StupPktRcvd = 1 this is a setup packet */
2018     if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
2019     {
2020       CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2021     }
2022     else
2023     {
2024       if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
2025       {
2026         CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
2027       }
2028 
2029 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2030       hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2031 #else
2032       HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2033 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2034     }
2035   }
2036   else
2037   {
2038 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2039     hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2040 #else
2041     HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2042 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2043   }
2044 
2045   return HAL_OK;
2046 }
2047 
2048 
2049 /**
2050   * @brief  process EP OUT setup packet received interrupt.
2051   * @param  hpcd PCD handle
2052   * @param  epnum endpoint number
2053   * @retval HAL status
2054   */
PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef * hpcd,uint32_t epnum)2055 static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2056 {
2057   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2058   uint32_t USBx_BASE = (uint32_t)USBx;
2059   uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);
2060   uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
2061 
2062   if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
2063       ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
2064   {
2065     CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2066   }
2067 
2068   /* Inform the upper layer that a setup packet is available */
2069 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2070   hpcd->SetupStageCallback(hpcd);
2071 #else
2072   HAL_PCD_SetupStageCallback(hpcd);
2073 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2074 
2075   return HAL_OK;
2076 }
2077 #endif /* defined (USB_OTG_FS) */
2078 
2079 #if defined (USB)
2080 /**
2081   * @brief  This function handles PCD Endpoint interrupt request.
2082   * @param  hpcd PCD handle
2083   * @retval HAL status
2084   */
PCD_EP_ISR_Handler(PCD_HandleTypeDef * hpcd)2085 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
2086 {
2087   PCD_EPTypeDef *ep;
2088   uint16_t count, wIstr, wEPVal, TxByteNbre;
2089   uint8_t epindex;
2090 
2091   /* stay in loop while pending interrupts */
2092   while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
2093   {
2094     wIstr = hpcd->Instance->ISTR;
2095 
2096     /* extract highest priority endpoint number */
2097     epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
2098 
2099     if (epindex == 0U)
2100     {
2101       /* Decode and service control endpoint interrupt */
2102 
2103       /* DIR bit = origin of the interrupt */
2104       if ((wIstr & USB_ISTR_DIR) == 0U)
2105       {
2106         /* DIR = 0 */
2107 
2108         /* DIR = 0 => IN  int */
2109         /* DIR = 0 implies that (EP_CTR_TX = 1) always */
2110         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
2111         ep = &hpcd->IN_ep[0];
2112 
2113         ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
2114         ep->xfer_buff += ep->xfer_count;
2115 
2116         /* TX COMPLETE */
2117 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2118         hpcd->DataInStageCallback(hpcd, 0U);
2119 #else
2120         HAL_PCD_DataInStageCallback(hpcd, 0U);
2121 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2122 
2123         if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
2124         {
2125           hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
2126           hpcd->USB_Address = 0U;
2127         }
2128       }
2129       else
2130       {
2131         /* DIR = 1 */
2132 
2133         /* DIR = 1 & CTR_RX => SETUP or OUT int */
2134         /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
2135         ep = &hpcd->OUT_ep[0];
2136         wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
2137 
2138         if ((wEPVal & USB_EP_SETUP) != 0U)
2139         {
2140           /* Get SETUP Packet */
2141           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
2142 
2143           USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
2144                       ep->pmaadress, (uint16_t)ep->xfer_count);
2145 
2146           /* SETUP bit kept frozen while CTR_RX = 1 */
2147           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
2148 
2149           /* Process SETUP Packet*/
2150 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2151           hpcd->SetupStageCallback(hpcd);
2152 #else
2153           HAL_PCD_SetupStageCallback(hpcd);
2154 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2155         }
2156         else if ((wEPVal & USB_EP_CTR_RX) != 0U)
2157         {
2158           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
2159 
2160           /* Get Control Data OUT Packet */
2161           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
2162 
2163           if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
2164           {
2165             USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
2166                         ep->pmaadress, (uint16_t)ep->xfer_count);
2167 
2168             ep->xfer_buff += ep->xfer_count;
2169 
2170             /* Process Control Data OUT Packet */
2171 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2172             hpcd->DataOutStageCallback(hpcd, 0U);
2173 #else
2174             HAL_PCD_DataOutStageCallback(hpcd, 0U);
2175 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2176           }
2177 
2178           if ((PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0) & USB_EP_SETUP) == 0U)
2179           {
2180             PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
2181             PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
2182           }
2183         }
2184       }
2185     }
2186     else
2187     {
2188       /* Decode and service non control endpoints interrupt */
2189       /* process related endpoint register */
2190       wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
2191 
2192       if ((wEPVal & USB_EP_CTR_RX) != 0U)
2193       {
2194         /* clear int flag */
2195         PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
2196         ep = &hpcd->OUT_ep[epindex];
2197 
2198         /* OUT Single Buffering */
2199         if (ep->doublebuffer == 0U)
2200         {
2201           count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
2202 
2203           if (count != 0U)
2204           {
2205             USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
2206           }
2207         }
2208         else
2209         {
2210           /* manage double buffer bulk out */
2211           if (ep->type == EP_TYPE_BULK)
2212           {
2213             count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
2214           }
2215           else /* manage double buffer iso out */
2216           {
2217             /* free EP OUT Buffer */
2218             PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
2219 
2220             if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
2221             {
2222               /* read from endpoint BUF0Addr buffer */
2223               count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2224 
2225               if (count != 0U)
2226               {
2227                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2228               }
2229             }
2230             else
2231             {
2232               /* read from endpoint BUF1Addr buffer */
2233               count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2234 
2235               if (count != 0U)
2236               {
2237                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2238               }
2239             }
2240           }
2241         }
2242         /* multi-packet on the NON control OUT endpoint */
2243         ep->xfer_count += count;
2244         ep->xfer_buff += count;
2245 
2246         if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
2247         {
2248           /* RX COMPLETE */
2249 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2250           hpcd->DataOutStageCallback(hpcd, ep->num);
2251 #else
2252           HAL_PCD_DataOutStageCallback(hpcd, ep->num);
2253 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2254         }
2255         else
2256         {
2257           (void) USB_EPStartXfer(hpcd->Instance, ep);
2258         }
2259 
2260       }
2261 
2262       if ((wEPVal & USB_EP_CTR_TX) != 0U)
2263       {
2264         ep = &hpcd->IN_ep[epindex];
2265 
2266         /* clear int flag */
2267         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
2268 
2269         /* Manage all non bulk/isoc transaction Bulk Single Buffer Transaction */
2270         if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_CTRL) ||
2271            ((ep->type == EP_TYPE_BULK) && ((wEPVal & USB_EP_KIND) == 0U)))
2272         {
2273           /* multi-packet on the NON control IN endpoint */
2274           TxByteNbre = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
2275 
2276           if (ep->xfer_len > TxByteNbre)
2277           {
2278             ep->xfer_len -= TxByteNbre;
2279           }
2280           else
2281           {
2282             ep->xfer_len = 0U;
2283           }
2284 
2285           /* Zero Length Packet? */
2286           if (ep->xfer_len == 0U)
2287           {
2288             /* TX COMPLETE */
2289 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2290             hpcd->DataInStageCallback(hpcd, ep->num);
2291 #else
2292             HAL_PCD_DataInStageCallback(hpcd, ep->num);
2293 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2294           }
2295           else
2296           {
2297             /* Transfer is not yet Done */
2298             ep->xfer_buff += TxByteNbre;
2299             ep->xfer_count += TxByteNbre;
2300             (void)USB_EPStartXfer(hpcd->Instance, ep);
2301           }
2302         }
2303         /* Double Buffer Iso/bulk IN (bulk transfer Len > Ep_Mps) */
2304         else
2305         {
2306           (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
2307         }
2308       }
2309     }
2310   }
2311 
2312   return HAL_OK;
2313 }
2314 
2315 
2316 /**
2317   * @brief  Manage double buffer bulk out transaction from ISR
2318   * @param  hpcd PCD handle
2319   * @param  ep current endpoint handle
2320   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
2321   * @retval HAL status
2322   */
HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)2323 static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
2324                                       PCD_EPTypeDef *ep, uint16_t wEPVal)
2325 {
2326   uint16_t count;
2327 
2328   /* Manage Buffer0 OUT */
2329   if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2330   {
2331     /* Get count of received Data on buffer0 */
2332     count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2333 
2334     if (ep->xfer_len >= count)
2335     {
2336       ep->xfer_len -= count;
2337     }
2338     else
2339     {
2340       ep->xfer_len = 0U;
2341     }
2342 
2343     if (ep->xfer_len == 0U)
2344     {
2345       /* set NAK to OUT endpoint since double buffer is enabled */
2346       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2347     }
2348 
2349     /* Check if Buffer1 is in blocked sate which requires to toggle */
2350     if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2351     {
2352       PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
2353     }
2354 
2355     if (count != 0U)
2356     {
2357       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2358     }
2359   }
2360   /* Manage Buffer 1 DTOG_RX=0 */
2361   else
2362   {
2363     /* Get count of received data */
2364     count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2365 
2366     if (ep->xfer_len >= count)
2367     {
2368       ep->xfer_len -= count;
2369     }
2370     else
2371     {
2372       ep->xfer_len = 0U;
2373     }
2374 
2375     if (ep->xfer_len == 0U)
2376     {
2377       /* set NAK on the current endpoint */
2378       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2379     }
2380 
2381     /*Need to FreeUser Buffer*/
2382     if ((wEPVal & USB_EP_DTOG_TX) == 0U)
2383     {
2384       PCD_FreeUserBuffer(hpcd->Instance, ep->num, 0U);
2385     }
2386 
2387     if (count != 0U)
2388     {
2389       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2390     }
2391   }
2392 
2393   return count;
2394 }
2395 
2396 
2397 /**
2398   * @brief  Manage double buffer bulk IN transaction from ISR
2399   * @param  hpcd PCD handle
2400   * @param  ep current endpoint handle
2401   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
2402   * @retval HAL status
2403   */
HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)2404 static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
2405                                                 PCD_EPTypeDef *ep, uint16_t wEPVal)
2406 {
2407   uint32_t len;
2408   uint16_t TxByteNbre;
2409 
2410   /* Data Buffer0 ACK received */
2411   if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2412   {
2413     /* multi-packet on the NON control IN endpoint */
2414     TxByteNbre = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2415 
2416     if (ep->xfer_len > TxByteNbre)
2417     {
2418       ep->xfer_len -= TxByteNbre;
2419     }
2420     else
2421     {
2422       ep->xfer_len = 0U;
2423     }
2424     /* Transfer is completed */
2425     if (ep->xfer_len == 0U)
2426     {
2427       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2428       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2429 
2430       /* TX COMPLETE */
2431 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2432       hpcd->DataInStageCallback(hpcd, ep->num);
2433 #else
2434       HAL_PCD_DataInStageCallback(hpcd, ep->num);
2435 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2436 
2437       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2438       {
2439         PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
2440       }
2441     }
2442     else /* Transfer is not yet Done */
2443     {
2444       /* need to Free USB Buff */
2445       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2446       {
2447         PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
2448       }
2449 
2450       /* Still there is data to Fill in the next Buffer */
2451       if (ep->xfer_fill_db == 1U)
2452       {
2453         ep->xfer_buff += TxByteNbre;
2454         ep->xfer_count += TxByteNbre;
2455 
2456         /* Calculate the len of the new buffer to fill */
2457         if (ep->xfer_len_db >= ep->maxpacket)
2458         {
2459           len = ep->maxpacket;
2460           ep->xfer_len_db -= len;
2461         }
2462         else if (ep->xfer_len_db == 0U)
2463         {
2464           len = TxByteNbre;
2465           ep->xfer_fill_db = 0U;
2466         }
2467         else
2468         {
2469           ep->xfer_fill_db = 0U;
2470           len = ep->xfer_len_db;
2471           ep->xfer_len_db = 0U;
2472         }
2473 
2474         /* Write remaining Data to Buffer */
2475         /* Set the Double buffer counter for pma buffer1 */
2476         PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2477 
2478         /* Copy user buffer to USB PMA */
2479         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr0, (uint16_t)len);
2480       }
2481     }
2482   }
2483   else /* Data Buffer1 ACK received */
2484   {
2485     /* multi-packet on the NON control IN endpoint */
2486     TxByteNbre = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2487 
2488     if (ep->xfer_len >= TxByteNbre)
2489     {
2490       ep->xfer_len -= TxByteNbre;
2491     }
2492     else
2493     {
2494       ep->xfer_len = 0U;
2495     }
2496 
2497     /* Transfer is completed */
2498     if (ep->xfer_len == 0U)
2499     {
2500       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2501       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2502 
2503       /* TX COMPLETE */
2504 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2505       hpcd->DataInStageCallback(hpcd, ep->num);
2506 #else
2507       HAL_PCD_DataInStageCallback(hpcd, ep->num);
2508 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2509 
2510       /* need to Free USB Buff */
2511       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2512       {
2513         PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
2514       }
2515     }
2516     else /* Transfer is not yet Done */
2517     {
2518       /* need to Free USB Buff */
2519       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2520       {
2521         PCD_FreeUserBuffer(hpcd->Instance, ep->num, 1U);
2522       }
2523 
2524       /* Still there is data to Fill in the next Buffer */
2525       if (ep->xfer_fill_db == 1U)
2526       {
2527         ep->xfer_buff += TxByteNbre;
2528         ep->xfer_count += TxByteNbre;
2529 
2530         /* Calculate the len of the new buffer to fill */
2531         if (ep->xfer_len_db >= ep->maxpacket)
2532         {
2533           len = ep->maxpacket;
2534           ep->xfer_len_db -= len;
2535         }
2536         else if (ep->xfer_len_db == 0U)
2537         {
2538           len = TxByteNbre;
2539           ep->xfer_fill_db = 0U;
2540         }
2541         else
2542         {
2543           len = ep->xfer_len_db;
2544           ep->xfer_len_db = 0U;
2545           ep->xfer_fill_db = 0;
2546         }
2547 
2548         /* Set the Double buffer counter for pmabuffer1 */
2549         PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2550 
2551         /* Copy the user buffer to USB PMA */
2552         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr1, (uint16_t)len);
2553       }
2554     }
2555   }
2556 
2557   /*enable endpoint IN*/
2558   PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
2559 
2560   return HAL_OK;
2561 }
2562 
2563 #endif /* defined (USB) */
2564 
2565 /**
2566   * @}
2567   */
2568 #endif /* defined (USB) || defined (USB_OTG_FS) */
2569 #endif /* HAL_PCD_MODULE_ENABLED */
2570 
2571 /**
2572   * @}
2573   */
2574 
2575 /**
2576   * @}
2577   */
2578 
2579 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2580