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