Subversion Repositories DashDisplay

Rev

Rev 61 | Details | Compare with Previous | Last modification | View Log | RSS feed

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