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