Browse code

Add source code of the firmware for the IO Board

Pawel Jablonski authored on 05/06/2023 17:01:27
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,1221 @@
1
+/**
2
+  ******************************************************************************
3
+  * @file    usbd_core.c
4
+  * @author  MCD Application Team
5
+  * @brief   This file provides all the USBD core functions.
6
+  ******************************************************************************
7
+  * @attention
8
+  *
9
+  * Copyright (c) 2015 STMicroelectronics.
10
+  * All rights reserved.
11
+  *
12
+  * This software is licensed under terms that can be found in the LICENSE file
13
+  * in the root directory of this software component.
14
+  * If no LICENSE file comes with this software, it is provided AS-IS.
15
+  *
16
+  ******************************************************************************
17
+  */
18
+
19
+/* Includes ------------------------------------------------------------------*/
20
+#include "usbd_core.h"
21
+
22
+#ifdef USE_USBD_COMPOSITE
23
+#include "usbd_composite_builder.h"
24
+#endif /* USE_USBD_COMPOSITE */
25
+
26
+/** @addtogroup STM32_USBD_DEVICE_LIBRARY
27
+  * @{
28
+  */
29
+
30
+
31
+/** @defgroup USBD_CORE
32
+  * @brief usbd core module
33
+  * @{
34
+  */
35
+
36
+/** @defgroup USBD_CORE_Private_TypesDefinitions
37
+  * @{
38
+  */
39
+
40
+/**
41
+  * @}
42
+  */
43
+
44
+
45
+/** @defgroup USBD_CORE_Private_Defines
46
+  * @{
47
+  */
48
+
49
+/**
50
+  * @}
51
+  */
52
+
53
+
54
+/** @defgroup USBD_CORE_Private_Macros
55
+  * @{
56
+  */
57
+
58
+/**
59
+  * @}
60
+  */
61
+
62
+
63
+/** @defgroup USBD_CORE_Private_FunctionPrototypes
64
+  * @{
65
+  */
66
+
67
+/**
68
+  * @}
69
+  */
70
+
71
+/** @defgroup USBD_CORE_Private_Variables
72
+  * @{
73
+  */
74
+
75
+/**
76
+  * @}
77
+  */
78
+
79
+
80
+/** @defgroup USBD_CORE_Private_Functions
81
+  * @{
82
+  */
83
+
84
+/**
85
+  * @brief  USBD_Init
86
+  *         Initializes the device stack and load the class driver
87
+  * @param  pdev: device instance
88
+  * @param  pdesc: Descriptor structure address
89
+  * @param  id: Low level core index
90
+  * @retval None
91
+  */
92
+USBD_StatusTypeDef USBD_Init(USBD_HandleTypeDef *pdev,
93
+                             USBD_DescriptorsTypeDef *pdesc, uint8_t id)
94
+{
95
+  USBD_StatusTypeDef ret;
96
+
97
+  /* Check whether the USB Host handle is valid */
98
+  if (pdev == NULL)
99
+  {
100
+#if (USBD_DEBUG_LEVEL > 1U)
101
+    USBD_ErrLog("Invalid Device handle");
102
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
103
+    return USBD_FAIL;
104
+  }
105
+
106
+#ifdef USE_USBD_COMPOSITE
107
+  /* Parse the table of classes in use */
108
+  for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
109
+  {
110
+    /* Unlink previous class*/
111
+    pdev->pClass[i] = NULL;
112
+    pdev->pUserData[i] = NULL;
113
+
114
+    /* Set class as inactive */
115
+    pdev->tclasslist[i].Active = 0;
116
+    pdev->NumClasses = 0;
117
+    pdev->classId = 0;
118
+  }
119
+#else
120
+  /* Unlink previous class*/
121
+  pdev->pClass[0] = NULL;
122
+  pdev->pUserData[0] = NULL;
123
+#endif /* USE_USBD_COMPOSITE */
124
+
125
+  pdev->pConfDesc = NULL;
126
+
127
+  /* Assign USBD Descriptors */
128
+  if (pdesc != NULL)
129
+  {
130
+    pdev->pDesc = pdesc;
131
+  }
132
+
133
+  /* Set Device initial State */
134
+  pdev->dev_state = USBD_STATE_DEFAULT;
135
+  pdev->id = id;
136
+
137
+  /* Initialize low level driver */
138
+  ret = USBD_LL_Init(pdev);
139
+
140
+  return ret;
141
+}
142
+
143
+/**
144
+  * @brief  USBD_DeInit
145
+  *         Re-Initialize the device library
146
+  * @param  pdev: device instance
147
+  * @retval status: status
148
+  */
149
+USBD_StatusTypeDef USBD_DeInit(USBD_HandleTypeDef *pdev)
150
+{
151
+  USBD_StatusTypeDef ret;
152
+
153
+  /* Disconnect the USB Device */
154
+  (void)USBD_LL_Stop(pdev);
155
+
156
+  /* Set Default State */
157
+  pdev->dev_state = USBD_STATE_DEFAULT;
158
+
159
+#ifdef USE_USBD_COMPOSITE
160
+  /* Parse the table of classes in use */
161
+  for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
162
+  {
163
+    /* Check if current class is in use */
164
+    if ((pdev->tclasslist[i].Active) == 1U)
165
+    {
166
+      if (pdev->pClass[i] != NULL)
167
+      {
168
+        pdev->classId = i;
169
+        /* Free Class Resources */
170
+        pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config);
171
+      }
172
+    }
173
+  }
174
+#else
175
+  /* Free Class Resources */
176
+  if (pdev->pClass[0] != NULL)
177
+  {
178
+    pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
179
+  }
180
+
181
+  pdev->pUserData[0] = NULL;
182
+
183
+#endif /* USE_USBD_COMPOSITE */
184
+
185
+  /* Free Device descriptors resources */
186
+  pdev->pDesc = NULL;
187
+  pdev->pConfDesc = NULL;
188
+
189
+  /* DeInitialize low level driver */
190
+  ret = USBD_LL_DeInit(pdev);
191
+
192
+  return ret;
193
+}
194
+
195
+/**
196
+  * @brief  USBD_RegisterClass
197
+  *         Link class driver to Device Core.
198
+  * @param  pDevice : Device Handle
199
+  * @param  pclass: Class handle
200
+  * @retval USBD Status
201
+  */
202
+USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass)
203
+{
204
+  uint16_t len = 0U;
205
+
206
+  if (pclass == NULL)
207
+  {
208
+#if (USBD_DEBUG_LEVEL > 1U)
209
+    USBD_ErrLog("Invalid Class handle");
210
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
211
+    return USBD_FAIL;
212
+  }
213
+
214
+  /* link the class to the USB Device handle */
215
+  pdev->pClass[0] = pclass;
216
+
217
+  /* Get Device Configuration Descriptor */
218
+#ifdef USE_USB_HS
219
+  if (pdev->pClass[pdev->classId]->GetHSConfigDescriptor != NULL)
220
+  {
221
+    pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetHSConfigDescriptor(&len);
222
+  }
223
+#else /* Default USE_USB_FS */
224
+  if (pdev->pClass[pdev->classId]->GetFSConfigDescriptor != NULL)
225
+  {
226
+    pdev->pConfDesc = (void *)pdev->pClass[pdev->classId]->GetFSConfigDescriptor(&len);
227
+  }
228
+#endif /* USE_USB_FS */
229
+
230
+  /* Increment the NumClasses */
231
+  pdev->NumClasses ++;
232
+
233
+  return USBD_OK;
234
+}
235
+
236
+#ifdef USE_USBD_COMPOSITE
237
+/**
238
+  * @brief  USBD_RegisterClassComposite
239
+  *         Link class driver to Device Core.
240
+  * @param  pdev : Device Handle
241
+  * @param  pclass: Class handle
242
+  * @param  classtype: Class type
243
+  * @param  EpAddr: Endpoint Address handle
244
+  * @retval USBD Status
245
+  */
246
+USBD_StatusTypeDef  USBD_RegisterClassComposite(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass,
247
+                                                USBD_CompositeClassTypeDef classtype, uint8_t *EpAddr)
248
+{
249
+  USBD_StatusTypeDef   ret = USBD_OK;
250
+  uint16_t len = 0U;
251
+
252
+  if ((pdev->classId < USBD_MAX_SUPPORTED_CLASS) && (pdev->NumClasses < USBD_MAX_SUPPORTED_CLASS))
253
+  {
254
+    if ((uint32_t)pclass != 0U)
255
+    {
256
+      /* Link the class to the USB Device handle */
257
+      pdev->pClass[pdev->classId] = pclass;
258
+      ret = USBD_OK;
259
+
260
+      pdev->tclasslist[pdev->classId].EpAdd = EpAddr;
261
+
262
+      /* Call the composite class builder */
263
+      (void)USBD_CMPSIT_AddClass(pdev, pclass, classtype, 0);
264
+
265
+      /* Increment the ClassId for the next occurrence */
266
+      pdev->classId ++;
267
+      pdev->NumClasses ++;
268
+    }
269
+    else
270
+    {
271
+#if (USBD_DEBUG_LEVEL > 1U)
272
+      USBD_ErrLog("Invalid Class handle");
273
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
274
+      ret = USBD_FAIL;
275
+    }
276
+  }
277
+
278
+  if (ret == USBD_OK)
279
+  {
280
+    /* Get Device Configuration Descriptor */
281
+#ifdef USE_USB_HS
282
+    pdev->pConfDesc = USBD_CMPSIT.GetHSConfigDescriptor(&len);
283
+#else /* Default USE_USB_FS */
284
+    pdev->pConfDesc = USBD_CMPSIT.GetFSConfigDescriptor(&len);
285
+#endif /* USE_USB_FS */
286
+  }
287
+
288
+  return ret;
289
+}
290
+
291
+/**
292
+  * @brief  USBD_UnRegisterClassComposite
293
+  *         UnLink all composite class drivers from Device Core.
294
+  * @param  pDevice : Device Handle
295
+  * @retval USBD Status
296
+  */
297
+USBD_StatusTypeDef  USBD_UnRegisterClassComposite(USBD_HandleTypeDef *pdev)
298
+{
299
+  USBD_StatusTypeDef   ret = USBD_FAIL;
300
+  uint8_t idx1;
301
+  uint8_t idx2;
302
+
303
+  /* Unroll all activated classes */
304
+  for (idx1 = 0; idx1 < pdev->NumClasses; idx1++)
305
+  {
306
+    /* Check if the class correspond to the requested type and if it is active */
307
+    if (pdev->tclasslist[idx1].Active == 1U)
308
+    {
309
+      /* Set the new class ID */
310
+      pdev->classId = idx1;
311
+
312
+      /* Free resources used by the selected class */
313
+      if (pdev->pClass[pdev->classId] != NULL)
314
+      {
315
+        /* Free Class Resources */
316
+        if (pdev->pClass[pdev->classId]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
317
+        {
318
+#if (USBD_DEBUG_LEVEL > 1U)
319
+          USBD_ErrLog("Class DeInit didn't succeed!, can't unregister selected class");
320
+#endif /* (USBD_DEBUG_LEVEL > 1U) */
321
+
322
+          ret = USBD_FAIL;
323
+        }
324
+      }
325
+
326
+      /* Free the class pointer */
327
+      pdev->pClass[pdev->classId] = NULL;
328
+
329
+      /* Free the class location in classes table and reset its parameters to zero */
330
+      pdev->tclasslist[pdev->classId].ClassType = CLASS_TYPE_NONE;
331
+      pdev->tclasslist[pdev->classId].ClassId = 0U;
332
+      pdev->tclasslist[pdev->classId].Active = 0U;
333
+      pdev->tclasslist[pdev->classId].NumEps = 0U;
334
+      pdev->tclasslist[pdev->classId].NumIf = 0U;
335
+      pdev->tclasslist[pdev->classId].CurrPcktSze = 0U;
336
+
337
+      for (idx2 = 0U; idx2 < USBD_MAX_CLASS_ENDPOINTS; idx2++)
338
+      {
339
+        pdev->tclasslist[pdev->classId].Eps[idx2].add = 0U;
340
+        pdev->tclasslist[pdev->classId].Eps[idx2].type = 0U;
341
+        pdev->tclasslist[pdev->classId].Eps[idx2].size = 0U;
342
+        pdev->tclasslist[pdev->classId].Eps[idx2].is_used = 0U;
343
+      }
344
+
345
+      for (idx2 = 0U; idx2 < USBD_MAX_CLASS_INTERFACES; idx2++)
346
+      {
347
+        pdev->tclasslist[pdev->classId].Ifs[idx2] = 0U;
348
+      }
349
+    }
350
+  }
351
+
352
+  /* Reset the configuration descriptor */
353
+  (void)USBD_CMPST_ClearConfDesc(pdev);
354
+
355
+  /* Reset the class ID and number of classes */
356
+  pdev->classId = 0U;
357
+  pdev->NumClasses = 0U;
358
+
359
+  return ret;
360
+}
361
+
362
+
363
+#endif /* USE_USBD_COMPOSITE */
364
+
365
+/**
366
+  * @brief  USBD_Start
367
+  *         Start the USB Device Core.
368
+  * @param  pdev: Device Handle
369
+  * @retval USBD Status
370
+  */
371
+USBD_StatusTypeDef USBD_Start(USBD_HandleTypeDef *pdev)
372
+{
373
+#ifdef USE_USBD_COMPOSITE
374
+  pdev->classId = 0U;
375
+#endif /* USE_USBD_COMPOSITE */
376
+
377
+  /* Start the low level driver  */
378
+  return USBD_LL_Start(pdev);
379
+}
380
+
381
+/**
382
+  * @brief  USBD_Stop
383
+  *         Stop the USB Device Core.
384
+  * @param  pdev: Device Handle
385
+  * @retval USBD Status
386
+  */
387
+USBD_StatusTypeDef USBD_Stop(USBD_HandleTypeDef *pdev)
388
+{
389
+  /* Disconnect USB Device */
390
+  (void)USBD_LL_Stop(pdev);
391
+
392
+  /* Free Class Resources */
393
+#ifdef USE_USBD_COMPOSITE
394
+  /* Parse the table of classes in use */
395
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
396
+  {
397
+    /* Check if current class is in use */
398
+    if ((pdev->tclasslist[i].Active) == 1U)
399
+    {
400
+      if (pdev->pClass[i] != NULL)
401
+      {
402
+        pdev->classId = i;
403
+        /* Free Class Resources */
404
+        (void)pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config);
405
+      }
406
+    }
407
+  }
408
+
409
+  /* Reset the class ID */
410
+  pdev->classId = 0U;
411
+#else
412
+  if (pdev->pClass[0] != NULL)
413
+  {
414
+    (void)pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config);
415
+  }
416
+#endif /* USE_USBD_COMPOSITE */
417
+
418
+  return USBD_OK;
419
+}
420
+
421
+/**
422
+  * @brief  USBD_RunTestMode
423
+  *         Launch test mode process
424
+  * @param  pdev: device instance
425
+  * @retval status
426
+  */
427
+USBD_StatusTypeDef USBD_RunTestMode(USBD_HandleTypeDef *pdev)
428
+{
429
+#ifdef USBD_HS_TESTMODE_ENABLE
430
+  USBD_StatusTypeDef ret;
431
+
432
+  /* Run USB HS test mode */
433
+  ret = USBD_LL_SetTestMode(pdev, pdev->dev_test_mode);
434
+
435
+  return ret;
436
+#else
437
+  /* Prevent unused argument compilation warning */
438
+  UNUSED(pdev);
439
+
440
+  return USBD_OK;
441
+#endif /* USBD_HS_TESTMODE_ENABLE */
442
+}
443
+
444
+/**
445
+  * @brief  USBD_SetClassConfig
446
+  *        Configure device and start the interface
447
+  * @param  pdev: device instance
448
+  * @param  cfgidx: configuration index
449
+  * @retval status
450
+  */
451
+
452
+USBD_StatusTypeDef USBD_SetClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
453
+{
454
+  USBD_StatusTypeDef ret = USBD_OK;
455
+
456
+#ifdef USE_USBD_COMPOSITE
457
+  /* Parse the table of classes in use */
458
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
459
+  {
460
+    /* Check if current class is in use */
461
+    if ((pdev->tclasslist[i].Active) == 1U)
462
+    {
463
+      if (pdev->pClass[i] != NULL)
464
+      {
465
+        pdev->classId = i;
466
+        /* Set configuration  and Start the Class*/
467
+        if (pdev->pClass[i]->Init(pdev, cfgidx) != 0U)
468
+        {
469
+          ret = USBD_FAIL;
470
+        }
471
+      }
472
+    }
473
+  }
474
+#else
475
+  if (pdev->pClass[0] != NULL)
476
+  {
477
+    /* Set configuration and Start the Class */
478
+    ret = (USBD_StatusTypeDef)pdev->pClass[0]->Init(pdev, cfgidx);
479
+  }
480
+#endif /* USE_USBD_COMPOSITE */
481
+
482
+  return ret;
483
+}
484
+
485
+/**
486
+  * @brief  USBD_ClrClassConfig
487
+  *         Clear current configuration
488
+  * @param  pdev: device instance
489
+  * @param  cfgidx: configuration index
490
+  * @retval status: USBD_StatusTypeDef
491
+  */
492
+USBD_StatusTypeDef USBD_ClrClassConfig(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
493
+{
494
+  USBD_StatusTypeDef ret = USBD_OK;
495
+
496
+#ifdef USE_USBD_COMPOSITE
497
+  /* Parse the table of classes in use */
498
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
499
+  {
500
+    /* Check if current class is in use */
501
+    if ((pdev->tclasslist[i].Active) == 1U)
502
+    {
503
+      if (pdev->pClass[i] != NULL)
504
+      {
505
+        pdev->classId = i;
506
+        /* Clear configuration  and De-initialize the Class process */
507
+        if (pdev->pClass[i]->DeInit(pdev, cfgidx) != 0U)
508
+        {
509
+          ret = USBD_FAIL;
510
+        }
511
+      }
512
+    }
513
+  }
514
+#else
515
+  /* Clear configuration  and De-initialize the Class process */
516
+  if (pdev->pClass[0]->DeInit(pdev, cfgidx) != 0U)
517
+  {
518
+    ret = USBD_FAIL;
519
+  }
520
+#endif /* USE_USBD_COMPOSITE */
521
+
522
+  return ret;
523
+}
524
+
525
+
526
+/**
527
+  * @brief  USBD_LL_SetupStage
528
+  *         Handle the setup stage
529
+  * @param  pdev: device instance
530
+  * @retval status
531
+  */
532
+USBD_StatusTypeDef USBD_LL_SetupStage(USBD_HandleTypeDef *pdev, uint8_t *psetup)
533
+{
534
+  USBD_StatusTypeDef ret;
535
+
536
+  USBD_ParseSetupRequest(&pdev->request, psetup);
537
+
538
+  pdev->ep0_state = USBD_EP0_SETUP;
539
+
540
+  pdev->ep0_data_len = pdev->request.wLength;
541
+
542
+  switch (pdev->request.bmRequest & 0x1FU)
543
+  {
544
+    case USB_REQ_RECIPIENT_DEVICE:
545
+      ret = USBD_StdDevReq(pdev, &pdev->request);
546
+      break;
547
+
548
+    case USB_REQ_RECIPIENT_INTERFACE:
549
+      ret = USBD_StdItfReq(pdev, &pdev->request);
550
+      break;
551
+
552
+    case USB_REQ_RECIPIENT_ENDPOINT:
553
+      ret = USBD_StdEPReq(pdev, &pdev->request);
554
+      break;
555
+
556
+    default:
557
+      ret = USBD_LL_StallEP(pdev, (pdev->request.bmRequest & 0x80U));
558
+      break;
559
+  }
560
+
561
+  return ret;
562
+}
563
+
564
+/**
565
+  * @brief  USBD_LL_DataOutStage
566
+  *         Handle data OUT stage
567
+  * @param  pdev: device instance
568
+  * @param  epnum: endpoint index
569
+  * @param  pdata: data pointer
570
+  * @retval status
571
+  */
572
+USBD_StatusTypeDef USBD_LL_DataOutStage(USBD_HandleTypeDef *pdev,
573
+                                        uint8_t epnum, uint8_t *pdata)
574
+{
575
+  USBD_EndpointTypeDef *pep;
576
+  USBD_StatusTypeDef ret = USBD_OK;
577
+  uint8_t idx;
578
+
579
+  if (epnum == 0U)
580
+  {
581
+    pep = &pdev->ep_out[0];
582
+
583
+    if (pdev->ep0_state == USBD_EP0_DATA_OUT)
584
+    {
585
+      if (pep->rem_length > pep->maxpacket)
586
+      {
587
+        pep->rem_length -= pep->maxpacket;
588
+
589
+        (void)USBD_CtlContinueRx(pdev, pdata, MIN(pep->rem_length, pep->maxpacket));
590
+      }
591
+      else
592
+      {
593
+        /* Find the class ID relative to the current request */
594
+        switch (pdev->request.bmRequest & 0x1FU)
595
+        {
596
+          case USB_REQ_RECIPIENT_DEVICE:
597
+            /* Device requests must be managed by the first instantiated class
598
+               (or duplicated by all classes for simplicity) */
599
+            idx = 0U;
600
+            break;
601
+
602
+          case USB_REQ_RECIPIENT_INTERFACE:
603
+            idx = USBD_CoreFindIF(pdev, LOBYTE(pdev->request.wIndex));
604
+            break;
605
+
606
+          case USB_REQ_RECIPIENT_ENDPOINT:
607
+            idx = USBD_CoreFindEP(pdev, LOBYTE(pdev->request.wIndex));
608
+            break;
609
+
610
+          default:
611
+            /* Back to the first class in case of doubt */
612
+            idx = 0U;
613
+            break;
614
+        }
615
+
616
+        if (idx < USBD_MAX_SUPPORTED_CLASS)
617
+        {
618
+          /* Setup the class ID and route the request to the relative class function */
619
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
620
+          {
621
+            if (pdev->pClass[idx]->EP0_RxReady != NULL)
622
+            {
623
+              pdev->classId = idx;
624
+              pdev->pClass[idx]->EP0_RxReady(pdev);
625
+            }
626
+          }
627
+        }
628
+
629
+        (void)USBD_CtlSendStatus(pdev);
630
+      }
631
+    }
632
+    else
633
+    {
634
+#if 0
635
+      if (pdev->ep0_state == USBD_EP0_STATUS_OUT)
636
+      {
637
+        /*
638
+          * STATUS PHASE completed, update ep0_state to idle
639
+          */
640
+        pdev->ep0_state = USBD_EP0_IDLE;
641
+        (void)USBD_LL_StallEP(pdev, 0U);
642
+      }
643
+#endif
644
+    }
645
+  }
646
+  else
647
+  {
648
+    /* Get the class index relative to this interface */
649
+    idx = USBD_CoreFindEP(pdev, (epnum & 0x7FU));
650
+
651
+    if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
652
+    {
653
+      /* Call the class data out function to manage the request */
654
+      if (pdev->dev_state == USBD_STATE_CONFIGURED)
655
+      {
656
+        if (pdev->pClass[idx]->DataOut != NULL)
657
+        {
658
+          pdev->classId = idx;
659
+          ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataOut(pdev, epnum);
660
+        }
661
+      }
662
+      if (ret != USBD_OK)
663
+      {
664
+        return ret;
665
+      }
666
+    }
667
+  }
668
+
669
+  return USBD_OK;
670
+}
671
+
672
+/**
673
+  * @brief  USBD_LL_DataInStage
674
+  *         Handle data in stage
675
+  * @param  pdev: device instance
676
+  * @param  epnum: endpoint index
677
+  * @retval status
678
+  */
679
+USBD_StatusTypeDef USBD_LL_DataInStage(USBD_HandleTypeDef *pdev,
680
+                                       uint8_t epnum, uint8_t *pdata)
681
+{
682
+  USBD_EndpointTypeDef *pep;
683
+  USBD_StatusTypeDef ret;
684
+  uint8_t idx;
685
+
686
+  if (epnum == 0U)
687
+  {
688
+    pep = &pdev->ep_in[0];
689
+
690
+    if (pdev->ep0_state == USBD_EP0_DATA_IN)
691
+    {
692
+      if (pep->rem_length > pep->maxpacket)
693
+      {
694
+        pep->rem_length -= pep->maxpacket;
695
+
696
+        (void)USBD_CtlContinueSendData(pdev, pdata, pep->rem_length);
697
+
698
+        /* Prepare endpoint for premature end of transfer */
699
+        (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
700
+      }
701
+      else
702
+      {
703
+        /* last packet is MPS multiple, so send ZLP packet */
704
+        if ((pep->maxpacket == pep->rem_length) &&
705
+            (pep->total_length >= pep->maxpacket) &&
706
+            (pep->total_length < pdev->ep0_data_len))
707
+        {
708
+          (void)USBD_CtlContinueSendData(pdev, NULL, 0U);
709
+          pdev->ep0_data_len = 0U;
710
+
711
+          /* Prepare endpoint for premature end of transfer */
712
+          (void)USBD_LL_PrepareReceive(pdev, 0U, NULL, 0U);
713
+        }
714
+        else
715
+        {
716
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
717
+          {
718
+            if (pdev->pClass[0]->EP0_TxSent != NULL)
719
+            {
720
+              pdev->classId = 0U;
721
+              pdev->pClass[0]->EP0_TxSent(pdev);
722
+            }
723
+          }
724
+          (void)USBD_LL_StallEP(pdev, 0x80U);
725
+          (void)USBD_CtlReceiveStatus(pdev);
726
+        }
727
+      }
728
+    }
729
+    else
730
+    {
731
+#if 0
732
+      if ((pdev->ep0_state == USBD_EP0_STATUS_IN) ||
733
+          (pdev->ep0_state == USBD_EP0_IDLE))
734
+      {
735
+        (void)USBD_LL_StallEP(pdev, 0x80U);
736
+      }
737
+#endif
738
+    }
739
+
740
+    if (pdev->dev_test_mode != 0U)
741
+    {
742
+      (void)USBD_RunTestMode(pdev);
743
+      pdev->dev_test_mode = 0U;
744
+    }
745
+  }
746
+  else
747
+  {
748
+    /* Get the class index relative to this interface */
749
+    idx = USBD_CoreFindEP(pdev, ((uint8_t)epnum | 0x80U));
750
+
751
+    if (((uint16_t)idx != 0xFFU) && (idx < USBD_MAX_SUPPORTED_CLASS))
752
+    {
753
+      /* Call the class data out function to manage the request */
754
+      if (pdev->dev_state == USBD_STATE_CONFIGURED)
755
+      {
756
+        if (pdev->pClass[idx]->DataIn != NULL)
757
+        {
758
+          pdev->classId = idx;
759
+          ret = (USBD_StatusTypeDef)pdev->pClass[idx]->DataIn(pdev, epnum);
760
+
761
+          if (ret != USBD_OK)
762
+          {
763
+            return ret;
764
+          }
765
+        }
766
+      }
767
+    }
768
+  }
769
+
770
+  return USBD_OK;
771
+}
772
+
773
+/**
774
+  * @brief  USBD_LL_Reset
775
+  *         Handle Reset event
776
+  * @param  pdev: device instance
777
+  * @retval status
778
+  */
779
+
780
+USBD_StatusTypeDef USBD_LL_Reset(USBD_HandleTypeDef *pdev)
781
+{
782
+  USBD_StatusTypeDef ret = USBD_OK;
783
+
784
+  /* Upon Reset call user call back */
785
+  pdev->dev_state = USBD_STATE_DEFAULT;
786
+  pdev->ep0_state = USBD_EP0_IDLE;
787
+  pdev->dev_config = 0U;
788
+  pdev->dev_remote_wakeup = 0U;
789
+  pdev->dev_test_mode = 0U;
790
+
791
+#ifdef USE_USBD_COMPOSITE
792
+  /* Parse the table of classes in use */
793
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
794
+  {
795
+    /* Check if current class is in use */
796
+    if ((pdev->tclasslist[i].Active) == 1U)
797
+    {
798
+      if (pdev->pClass[i] != NULL)
799
+      {
800
+        pdev->classId = i;
801
+        /* Clear configuration  and De-initialize the Class process*/
802
+
803
+        if (pdev->pClass[i]->DeInit != NULL)
804
+        {
805
+          if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK)
806
+          {
807
+            ret = USBD_FAIL;
808
+          }
809
+        }
810
+      }
811
+    }
812
+  }
813
+#else
814
+
815
+  if (pdev->pClass[0] != NULL)
816
+  {
817
+    if (pdev->pClass[0]->DeInit != NULL)
818
+    {
819
+      if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != USBD_OK)
820
+      {
821
+        ret = USBD_FAIL;
822
+      }
823
+    }
824
+  }
825
+#endif /* USE_USBD_COMPOSITE */
826
+
827
+  /* Open EP0 OUT */
828
+  (void)USBD_LL_OpenEP(pdev, 0x00U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
829
+  pdev->ep_out[0x00U & 0xFU].is_used = 1U;
830
+
831
+  pdev->ep_out[0].maxpacket = USB_MAX_EP0_SIZE;
832
+
833
+  /* Open EP0 IN */
834
+  (void)USBD_LL_OpenEP(pdev, 0x80U, USBD_EP_TYPE_CTRL, USB_MAX_EP0_SIZE);
835
+  pdev->ep_in[0x80U & 0xFU].is_used = 1U;
836
+
837
+  pdev->ep_in[0].maxpacket = USB_MAX_EP0_SIZE;
838
+
839
+  return ret;
840
+}
841
+
842
+/**
843
+  * @brief  USBD_LL_SetSpeed
844
+  *         Handle Reset event
845
+  * @param  pdev: device instance
846
+  * @retval status
847
+  */
848
+USBD_StatusTypeDef USBD_LL_SetSpeed(USBD_HandleTypeDef *pdev,
849
+                                    USBD_SpeedTypeDef speed)
850
+{
851
+  pdev->dev_speed = speed;
852
+
853
+  return USBD_OK;
854
+}
855
+
856
+/**
857
+  * @brief  USBD_LL_Suspend
858
+  *         Handle Suspend event
859
+  * @param  pdev: device instance
860
+  * @retval status
861
+  */
862
+
863
+USBD_StatusTypeDef USBD_LL_Suspend(USBD_HandleTypeDef *pdev)
864
+{
865
+  pdev->dev_old_state = pdev->dev_state;
866
+  pdev->dev_state = USBD_STATE_SUSPENDED;
867
+
868
+  return USBD_OK;
869
+}
870
+
871
+/**
872
+  * @brief  USBD_LL_Resume
873
+  *         Handle Resume event
874
+  * @param  pdev: device instance
875
+  * @retval status
876
+  */
877
+
878
+USBD_StatusTypeDef USBD_LL_Resume(USBD_HandleTypeDef *pdev)
879
+{
880
+  if (pdev->dev_state == USBD_STATE_SUSPENDED)
881
+  {
882
+    pdev->dev_state = pdev->dev_old_state;
883
+  }
884
+
885
+  return USBD_OK;
886
+}
887
+
888
+/**
889
+  * @brief  USBD_LL_SOF
890
+  *         Handle SOF event
891
+  * @param  pdev: device instance
892
+  * @retval status
893
+  */
894
+
895
+USBD_StatusTypeDef USBD_LL_SOF(USBD_HandleTypeDef *pdev)
896
+{
897
+  /* The SOF event can be distributed for all classes that support it */
898
+  if (pdev->dev_state == USBD_STATE_CONFIGURED)
899
+  {
900
+#ifdef USE_USBD_COMPOSITE
901
+    /* Parse the table of classes in use */
902
+    for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
903
+    {
904
+      /* Check if current class is in use */
905
+      if ((pdev->tclasslist[i].Active) == 1U)
906
+      {
907
+        if (pdev->pClass[i] != NULL)
908
+        {
909
+          if (pdev->pClass[i]->SOF != NULL)
910
+          {
911
+            pdev->classId = i;
912
+            (void)pdev->pClass[i]->SOF(pdev);
913
+          }
914
+        }
915
+      }
916
+    }
917
+#else
918
+    if (pdev->pClass[0] != NULL)
919
+    {
920
+      if (pdev->pClass[0]->SOF != NULL)
921
+      {
922
+        (void)pdev->pClass[0]->SOF(pdev);
923
+      }
924
+    }
925
+#endif /* USE_USBD_COMPOSITE */
926
+  }
927
+
928
+  return USBD_OK;
929
+}
930
+
931
+/**
932
+  * @brief  USBD_LL_IsoINIncomplete
933
+  *         Handle iso in incomplete event
934
+  * @param  pdev: device instance
935
+  * @retval status
936
+  */
937
+USBD_StatusTypeDef USBD_LL_IsoINIncomplete(USBD_HandleTypeDef *pdev,
938
+                                           uint8_t epnum)
939
+{
940
+  if (pdev->pClass[pdev->classId] == NULL)
941
+  {
942
+    return USBD_FAIL;
943
+  }
944
+
945
+  if (pdev->dev_state == USBD_STATE_CONFIGURED)
946
+  {
947
+    if (pdev->pClass[pdev->classId]->IsoINIncomplete != NULL)
948
+    {
949
+      (void)pdev->pClass[pdev->classId]->IsoINIncomplete(pdev, epnum);
950
+    }
951
+  }
952
+
953
+  return USBD_OK;
954
+}
955
+
956
+/**
957
+  * @brief  USBD_LL_IsoOUTIncomplete
958
+  *         Handle iso out incomplete event
959
+  * @param  pdev: device instance
960
+  * @retval status
961
+  */
962
+USBD_StatusTypeDef USBD_LL_IsoOUTIncomplete(USBD_HandleTypeDef *pdev,
963
+                                            uint8_t epnum)
964
+{
965
+  if (pdev->pClass[pdev->classId] == NULL)
966
+  {
967
+    return USBD_FAIL;
968
+  }
969
+
970
+  if (pdev->dev_state == USBD_STATE_CONFIGURED)
971
+  {
972
+    if (pdev->pClass[pdev->classId]->IsoOUTIncomplete != NULL)
973
+    {
974
+      (void)pdev->pClass[pdev->classId]->IsoOUTIncomplete(pdev, epnum);
975
+    }
976
+  }
977
+
978
+  return USBD_OK;
979
+}
980
+
981
+/**
982
+  * @brief  USBD_LL_DevConnected
983
+  *         Handle device connection event
984
+  * @param  pdev: device instance
985
+  * @retval status
986
+  */
987
+USBD_StatusTypeDef USBD_LL_DevConnected(USBD_HandleTypeDef *pdev)
988
+{
989
+  /* Prevent unused argument compilation warning */
990
+  UNUSED(pdev);
991
+
992
+  return USBD_OK;
993
+}
994
+
995
+/**
996
+  * @brief  USBD_LL_DevDisconnected
997
+  *         Handle device disconnection event
998
+  * @param  pdev: device instance
999
+  * @retval status
1000
+  */
1001
+USBD_StatusTypeDef USBD_LL_DevDisconnected(USBD_HandleTypeDef *pdev)
1002
+{
1003
+  USBD_StatusTypeDef   ret = USBD_OK;
1004
+
1005
+  /* Free Class Resources */
1006
+  pdev->dev_state = USBD_STATE_DEFAULT;
1007
+
1008
+#ifdef USE_USBD_COMPOSITE
1009
+  /* Parse the table of classes in use */
1010
+  for (uint32_t i = 0; i < USBD_MAX_SUPPORTED_CLASS; i++)
1011
+  {
1012
+    /* Check if current class is in use */
1013
+    if ((pdev->tclasslist[i].Active) == 1U)
1014
+    {
1015
+      if (pdev->pClass[i] != NULL)
1016
+      {
1017
+        pdev->classId = i;
1018
+        /* Clear configuration  and De-initialize the Class process*/
1019
+        if (pdev->pClass[i]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
1020
+        {
1021
+          ret = USBD_FAIL;
1022
+        }
1023
+      }
1024
+    }
1025
+  }
1026
+#else
1027
+  if (pdev->pClass[0] != NULL)
1028
+  {
1029
+    if (pdev->pClass[0]->DeInit(pdev, (uint8_t)pdev->dev_config) != 0U)
1030
+    {
1031
+      ret = USBD_FAIL;
1032
+    }
1033
+  }
1034
+#endif /* USE_USBD_COMPOSITE */
1035
+
1036
+  return ret;
1037
+}
1038
+
1039
+/**
1040
+  * @brief  USBD_CoreFindIF
1041
+  *         return the class index relative to the selected interface
1042
+  * @param  pdev: device instance
1043
+  * @param  index : selected interface number
1044
+  * @retval index of the class using the selected interface number. OxFF if no class found.
1045
+  */
1046
+uint8_t USBD_CoreFindIF(USBD_HandleTypeDef *pdev, uint8_t index)
1047
+{
1048
+#ifdef USE_USBD_COMPOSITE
1049
+  /* Parse the table of classes in use */
1050
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
1051
+  {
1052
+    /* Check if current class is in use */
1053
+    if ((pdev->tclasslist[i].Active) == 1U)
1054
+    {
1055
+      /* Parse all interfaces listed in the current class */
1056
+      for (uint32_t j = 0U; j < pdev->tclasslist[i].NumIf; j++)
1057
+      {
1058
+        /* Check if requested Interface matches the current class interface */
1059
+        if (pdev->tclasslist[i].Ifs[j] == index)
1060
+        {
1061
+          if (pdev->pClass[i]->Setup != NULL)
1062
+          {
1063
+            return (uint8_t)i;
1064
+          }
1065
+        }
1066
+      }
1067
+    }
1068
+  }
1069
+
1070
+  return 0xFFU;
1071
+#else
1072
+  UNUSED(pdev);
1073
+  UNUSED(index);
1074
+
1075
+  return 0x00U;
1076
+#endif /* USE_USBD_COMPOSITE */
1077
+}
1078
+
1079
+/**
1080
+  * @brief  USBD_CoreFindEP
1081
+  *         return the class index relative to the selected endpoint
1082
+  * @param  pdev: device instance
1083
+  * @param  index : selected endpoint number
1084
+  * @retval index of the class using the selected endpoint number. 0xFF if no class found.
1085
+  */
1086
+uint8_t USBD_CoreFindEP(USBD_HandleTypeDef *pdev, uint8_t index)
1087
+{
1088
+#ifdef USE_USBD_COMPOSITE
1089
+  /* Parse the table of classes in use */
1090
+  for (uint32_t i = 0U; i < USBD_MAX_SUPPORTED_CLASS; i++)
1091
+  {
1092
+    /* Check if current class is in use */
1093
+    if ((pdev->tclasslist[i].Active) == 1U)
1094
+    {
1095
+      /* Parse all endpoints listed in the current class */
1096
+      for (uint32_t j = 0U; j < pdev->tclasslist[i].NumEps; j++)
1097
+      {
1098
+        /* Check if requested endpoint matches the current class endpoint */
1099
+        if (pdev->tclasslist[i].Eps[j].add == index)
1100
+        {
1101
+          if (pdev->pClass[i]->Setup != NULL)
1102
+          {
1103
+            return (uint8_t)i;
1104
+          }
1105
+        }
1106
+      }
1107
+    }
1108
+  }
1109
+
1110
+  return 0xFFU;
1111
+#else
1112
+  UNUSED(pdev);
1113
+  UNUSED(index);
1114
+
1115
+  return 0x00U;
1116
+#endif /* USE_USBD_COMPOSITE */
1117
+}
1118
+
1119
+#ifdef USE_USBD_COMPOSITE
1120
+/**
1121
+  * @brief  USBD_CoreGetEPAdd
1122
+  *         Get the endpoint address relative to a selected class
1123
+  * @param  pdev: device instance
1124
+  * @param  ep_dir: USBD_EP_IN or USBD_EP_OUT
1125
+  * @param  ep_type: USBD_EP_TYPE_CTRL, USBD_EP_TYPE_ISOC, USBD_EP_TYPE_BULK or USBD_EP_TYPE_INTR
1126
+  * @param  ClassId: The Class ID
1127
+  * @retval Address of the selected endpoint or 0xFFU if no endpoint found.
1128
+  */
1129
+uint8_t USBD_CoreGetEPAdd(USBD_HandleTypeDef *pdev, uint8_t ep_dir, uint8_t ep_type, uint8_t ClassId)
1130
+{
1131
+  uint8_t idx;
1132
+
1133
+  /* Find the EP address in the selected class table */
1134
+  for (idx = 0; idx < pdev->tclasslist[ClassId].NumEps; idx++)
1135
+  {
1136
+    if (((pdev->tclasslist[ClassId].Eps[idx].add & USBD_EP_IN) == ep_dir) && \
1137
+        (pdev->tclasslist[ClassId].Eps[idx].type == ep_type) && \
1138
+        (pdev->tclasslist[ClassId].Eps[idx].is_used != 0U))
1139
+    {
1140
+      return (pdev->tclasslist[ClassId].Eps[idx].add);
1141
+    }
1142
+  }
1143
+
1144
+  /* If reaching this point, then no endpoint was found */
1145
+  return 0xFFU;
1146
+}
1147
+#endif /* USE_USBD_COMPOSITE */
1148
+
1149
+/**
1150
+  * @brief  USBD_GetEpDesc
1151
+  *         This function return the Endpoint descriptor
1152
+  * @param  pdev: device instance
1153
+  * @param  pConfDesc:  pointer to Bos descriptor
1154
+  * @param  EpAddr:  endpoint address
1155
+  * @retval pointer to video endpoint descriptor
1156
+  */
1157
+void *USBD_GetEpDesc(uint8_t *pConfDesc, uint8_t EpAddr)
1158
+{
1159
+  USBD_DescHeaderTypeDef *pdesc = (USBD_DescHeaderTypeDef *)(void *)pConfDesc;
1160
+  USBD_ConfigDescTypeDef *desc = (USBD_ConfigDescTypeDef *)(void *)pConfDesc;
1161
+  USBD_EpDescTypeDef *pEpDesc = NULL;
1162
+  uint16_t ptr;
1163
+
1164
+  if (desc->wTotalLength > desc->bLength)
1165
+  {
1166
+    ptr = desc->bLength;
1167
+
1168
+    while (ptr < desc->wTotalLength)
1169
+    {
1170
+      pdesc = USBD_GetNextDesc((uint8_t *)pdesc, &ptr);
1171
+
1172
+      if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
1173
+      {
1174
+        pEpDesc = (USBD_EpDescTypeDef *)(void *)pdesc;
1175
+
1176
+        if (pEpDesc->bEndpointAddress == EpAddr)
1177
+        {
1178
+          break;
1179
+        }
1180
+        else
1181
+        {
1182
+          pEpDesc = NULL;
1183
+        }
1184
+      }
1185
+    }
1186
+  }
1187
+
1188
+  return (void *)pEpDesc;
1189
+}
1190
+
1191
+/**
1192
+  * @brief  USBD_GetNextDesc
1193
+  *         This function return the next descriptor header
1194
+  * @param  buf: Buffer where the descriptor is available
1195
+  * @param  ptr: data pointer inside the descriptor
1196
+  * @retval next header
1197
+  */
1198
+USBD_DescHeaderTypeDef *USBD_GetNextDesc(uint8_t *pbuf, uint16_t *ptr)
1199
+{
1200
+  USBD_DescHeaderTypeDef *pnext = (USBD_DescHeaderTypeDef *)(void *)pbuf;
1201
+
1202
+  *ptr += pnext->bLength;
1203
+  pnext = (USBD_DescHeaderTypeDef *)(void *)(pbuf + pnext->bLength);
1204
+
1205
+  return (pnext);
1206
+}
1207
+
1208
+/**
1209
+  * @}
1210
+  */
1211
+
1212
+
1213
+/**
1214
+  * @}
1215
+  */
1216
+
1217
+
1218
+/**
1219
+  * @}
1220
+  */
1221
+