Subversion Repositories FuelGauge

Rev

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

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