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