Subversion Repositories DashDisplay

Rev

Rev 61 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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