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