Subversion Repositories DashDisplay

Rev

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