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,579 @@
1
+/**
2
+  ******************************************************************************
3
+  * @file    usbd_msc.c
4
+  * @author  MCD Application Team
5
+  * @brief   This file provides all the MSC core functions.
6
+  *
7
+  ******************************************************************************
8
+  * @attention
9
+  *
10
+  * Copyright (c) 2015 STMicroelectronics.
11
+  * All rights reserved.
12
+  *
13
+  * This software is licensed under terms that can be found in the LICENSE file
14
+  * in the root directory of this software component.
15
+  * If no LICENSE file comes with this software, it is provided AS-IS.
16
+  *
17
+  ******************************************************************************
18
+  * @verbatim
19
+  *
20
+  *          ===================================================================
21
+  *                                MSC Class  Description
22
+  *          ===================================================================
23
+  *           This module manages the MSC class V1.0 following the "Universal
24
+  *           Serial Bus Mass Storage Class (MSC) Bulk-Only Transport (BOT) Version 1.0
25
+  *           Sep. 31, 1999".
26
+  *           This driver implements the following aspects of the specification:
27
+  *             - Bulk-Only Transport protocol
28
+  *             - Subclass : SCSI transparent command set (ref. SCSI Primary Commands - 3 (SPC-3))
29
+  *
30
+  *  @endverbatim
31
+  *
32
+  ******************************************************************************
33
+  */
34
+
35
+/* BSPDependencies
36
+- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
37
+- "stm32xxxxx_{eval}{discovery}_io.c"
38
+- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c"
39
+EndBSPDependencies */
40
+
41
+/* Includes ------------------------------------------------------------------*/
42
+#include "usbd_msc.h"
43
+
44
+
45
+/** @addtogroup STM32_USB_DEVICE_LIBRARY
46
+  * @{
47
+  */
48
+
49
+
50
+/** @defgroup MSC_CORE
51
+  * @brief Mass storage core module
52
+  * @{
53
+  */
54
+
55
+/** @defgroup MSC_CORE_Private_TypesDefinitions
56
+  * @{
57
+  */
58
+/**
59
+  * @}
60
+  */
61
+
62
+
63
+/** @defgroup MSC_CORE_Private_Defines
64
+  * @{
65
+  */
66
+
67
+/**
68
+  * @}
69
+  */
70
+
71
+
72
+/** @defgroup MSC_CORE_Private_Macros
73
+  * @{
74
+  */
75
+/**
76
+  * @}
77
+  */
78
+
79
+
80
+/** @defgroup MSC_CORE_Private_FunctionPrototypes
81
+  * @{
82
+  */
83
+uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
84
+uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx);
85
+uint8_t USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
86
+uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum);
87
+uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum);
88
+
89
+#ifndef USE_USBD_COMPOSITE
90
+uint8_t *USBD_MSC_GetHSCfgDesc(uint16_t *length);
91
+uint8_t *USBD_MSC_GetFSCfgDesc(uint16_t *length);
92
+uint8_t *USBD_MSC_GetOtherSpeedCfgDesc(uint16_t *length);
93
+uint8_t *USBD_MSC_GetDeviceQualifierDescriptor(uint16_t *length);
94
+#endif /* USE_USBD_COMPOSITE */
95
+/**
96
+  * @}
97
+  */
98
+
99
+
100
+/** @defgroup MSC_CORE_Private_Variables
101
+  * @{
102
+  */
103
+
104
+
105
+USBD_ClassTypeDef  USBD_MSC =
106
+{
107
+  USBD_MSC_Init,
108
+  USBD_MSC_DeInit,
109
+  USBD_MSC_Setup,
110
+  NULL, /*EP0_TxSent*/
111
+  NULL, /*EP0_RxReady*/
112
+  USBD_MSC_DataIn,
113
+  USBD_MSC_DataOut,
114
+  NULL, /*SOF */
115
+  NULL,
116
+  NULL,
117
+#ifdef USE_USBD_COMPOSITE
118
+  NULL,
119
+  NULL,
120
+  NULL,
121
+  NULL,
122
+#else
123
+  USBD_MSC_GetHSCfgDesc,
124
+  USBD_MSC_GetFSCfgDesc,
125
+  USBD_MSC_GetOtherSpeedCfgDesc,
126
+  USBD_MSC_GetDeviceQualifierDescriptor,
127
+#endif /* USE_USBD_COMPOSITE */
128
+};
129
+
130
+/* USB Mass storage device Configuration Descriptor */
131
+#ifndef USE_USBD_COMPOSITE
132
+/* USB Mass storage device Configuration Descriptor */
133
+/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
134
+__ALIGN_BEGIN static uint8_t USBD_MSC_CfgDesc[USB_MSC_CONFIG_DESC_SIZ]  __ALIGN_END =
135
+{
136
+  0x09,                                            /* bLength: Configuration Descriptor size */
137
+  USB_DESC_TYPE_CONFIGURATION,                     /* bDescriptorType: Configuration */
138
+  USB_MSC_CONFIG_DESC_SIZ,
139
+
140
+  0x00,
141
+  0x01,                                            /* bNumInterfaces: 1 interface */
142
+  0x01,                                            /* bConfigurationValue */
143
+  0x04,                                            /* iConfiguration */
144
+#if (USBD_SELF_POWERED == 1U)
145
+  0xC0,                                            /* bmAttributes: Bus Powered according to user configuration */
146
+#else
147
+  0x80,                                            /* bmAttributes: Bus Powered according to user configuration */
148
+#endif /* USBD_SELF_POWERED */
149
+  USBD_MAX_POWER,                                  /* MaxPower (mA) */
150
+
151
+  /********************  Mass Storage interface ********************/
152
+  0x09,                                            /* bLength: Interface Descriptor size */
153
+  0x04,                                            /* bDescriptorType: */
154
+  0x00,                                            /* bInterfaceNumber: Number of Interface */
155
+  0x00,                                            /* bAlternateSetting: Alternate setting */
156
+  0x02,                                            /* bNumEndpoints */
157
+  0x08,                                            /* bInterfaceClass: MSC Class */
158
+  0x06,                                            /* bInterfaceSubClass : SCSI transparent*/
159
+  0x50,                                            /* nInterfaceProtocol */
160
+  0x05,                                            /* iInterface: */
161
+  /********************  Mass Storage Endpoints ********************/
162
+  0x07,                                            /* Endpoint descriptor length = 7 */
163
+  0x05,                                            /* Endpoint descriptor type */
164
+  MSC_EPIN_ADDR,                                   /* Endpoint address (IN, address 1) */
165
+  0x02,                                            /* Bulk endpoint type */
166
+  LOBYTE(MSC_MAX_FS_PACKET),
167
+  HIBYTE(MSC_MAX_FS_PACKET),
168
+  0x00,                                            /* Polling interval in milliseconds */
169
+
170
+  0x07,                                            /* Endpoint descriptor length = 7 */
171
+  0x05,                                            /* Endpoint descriptor type */
172
+  MSC_EPOUT_ADDR,                                  /* Endpoint address (OUT, address 1) */
173
+  0x02,                                            /* Bulk endpoint type */
174
+  LOBYTE(MSC_MAX_FS_PACKET),
175
+  HIBYTE(MSC_MAX_FS_PACKET),
176
+  0x00                                             /* Polling interval in milliseconds */
177
+};
178
+
179
+/* USB Standard Device Descriptor */
180
+__ALIGN_BEGIN static uint8_t USBD_MSC_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC]  __ALIGN_END =
181
+{
182
+  USB_LEN_DEV_QUALIFIER_DESC,
183
+  USB_DESC_TYPE_DEVICE_QUALIFIER,
184
+  0x00,
185
+  0x02,
186
+  0x00,
187
+  0x00,
188
+  0x00,
189
+  MSC_MAX_FS_PACKET,
190
+  0x01,
191
+  0x00,
192
+};
193
+#endif /* USE_USBD_COMPOSITE */
194
+
195
+uint8_t MSCInEpAdd  = MSC_EPIN_ADDR;
196
+uint8_t MSCOutEpAdd = MSC_EPOUT_ADDR;
197
+
198
+/**
199
+  * @}
200
+  */
201
+
202
+
203
+/** @defgroup MSC_CORE_Private_Functions
204
+  * @{
205
+  */
206
+
207
+/**
208
+  * @brief  USBD_MSC_Init
209
+  *         Initialize  the mass storage configuration
210
+  * @param  pdev: device instance
211
+  * @param  cfgidx: configuration index
212
+  * @retval status
213
+  */
214
+uint8_t USBD_MSC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
215
+{
216
+  UNUSED(cfgidx);
217
+  USBD_MSC_BOT_HandleTypeDef *hmsc;
218
+
219
+  hmsc = (USBD_MSC_BOT_HandleTypeDef *)USBD_malloc(sizeof(USBD_MSC_BOT_HandleTypeDef));
220
+
221
+  if (hmsc == NULL)
222
+  {
223
+    pdev->pClassDataCmsit[pdev->classId] = NULL;
224
+    return (uint8_t)USBD_EMEM;
225
+  }
226
+
227
+  pdev->pClassDataCmsit[pdev->classId] = (void *)hmsc;
228
+  pdev->pClassData = pdev->pClassDataCmsit[pdev->classId];
229
+
230
+#ifdef USE_USBD_COMPOSITE
231
+  /* Get the Endpoints addresses allocated for this class instance */
232
+  MSCInEpAdd  = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
233
+  MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
234
+#endif /* USE_USBD_COMPOSITE */
235
+
236
+  if (pdev->dev_speed == USBD_SPEED_HIGH)
237
+  {
238
+    /* Open EP OUT */
239
+    (void)USBD_LL_OpenEP(pdev, MSCOutEpAdd, USBD_EP_TYPE_BULK, MSC_MAX_HS_PACKET);
240
+    pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 1U;
241
+
242
+    /* Open EP IN */
243
+    (void)USBD_LL_OpenEP(pdev, MSCInEpAdd, USBD_EP_TYPE_BULK, MSC_MAX_HS_PACKET);
244
+    pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 1U;
245
+  }
246
+  else
247
+  {
248
+    /* Open EP OUT */
249
+    (void)USBD_LL_OpenEP(pdev, MSCOutEpAdd, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET);
250
+    pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 1U;
251
+
252
+    /* Open EP IN */
253
+    (void)USBD_LL_OpenEP(pdev, MSCInEpAdd, USBD_EP_TYPE_BULK, MSC_MAX_FS_PACKET);
254
+    pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 1U;
255
+  }
256
+
257
+  /* Init the BOT  layer */
258
+  MSC_BOT_Init(pdev);
259
+
260
+  return (uint8_t)USBD_OK;
261
+}
262
+
263
+/**
264
+  * @brief  USBD_MSC_DeInit
265
+  *         DeInitialize  the mass storage configuration
266
+  * @param  pdev: device instance
267
+  * @param  cfgidx: configuration index
268
+  * @retval status
269
+  */
270
+uint8_t USBD_MSC_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
271
+{
272
+  UNUSED(cfgidx);
273
+
274
+#ifdef USE_USBD_COMPOSITE
275
+  /* Get the Endpoints addresses allocated for this class instance */
276
+  MSCInEpAdd  = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
277
+  MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
278
+#endif /* USE_USBD_COMPOSITE */
279
+
280
+  /* Close MSC EPs */
281
+  (void)USBD_LL_CloseEP(pdev, MSCOutEpAdd);
282
+  pdev->ep_out[MSCOutEpAdd & 0xFU].is_used = 0U;
283
+
284
+  /* Close EP IN */
285
+  (void)USBD_LL_CloseEP(pdev, MSCInEpAdd);
286
+  pdev->ep_in[MSCInEpAdd & 0xFU].is_used = 0U;
287
+
288
+  /* Free MSC Class Resources */
289
+  if (pdev->pClassDataCmsit[pdev->classId] != NULL)
290
+  {
291
+    /* De-Init the BOT layer */
292
+    MSC_BOT_DeInit(pdev);
293
+
294
+    (void)USBD_free(pdev->pClassDataCmsit[pdev->classId]);
295
+    pdev->pClassDataCmsit[pdev->classId]  = NULL;
296
+    pdev->pClassData = NULL;
297
+  }
298
+
299
+  return (uint8_t)USBD_OK;
300
+}
301
+/**
302
+  * @brief  USBD_MSC_Setup
303
+  *         Handle the MSC specific requests
304
+  * @param  pdev: device instance
305
+  * @param  req: USB request
306
+  * @retval status
307
+  */
308
+uint8_t USBD_MSC_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
309
+{
310
+  USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassDataCmsit[pdev->classId];
311
+  USBD_StatusTypeDef ret = USBD_OK;
312
+  uint16_t status_info = 0U;
313
+
314
+#ifdef USE_USBD_COMPOSITE
315
+  /* Get the Endpoints addresses allocated for this class instance */
316
+  MSCInEpAdd  = USBD_CoreGetEPAdd(pdev, USBD_EP_IN, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
317
+  MSCOutEpAdd = USBD_CoreGetEPAdd(pdev, USBD_EP_OUT, USBD_EP_TYPE_BULK, (uint8_t)pdev->classId);
318
+#endif /* USE_USBD_COMPOSITE */
319
+
320
+  if (hmsc == NULL)
321
+  {
322
+    return (uint8_t)USBD_FAIL;
323
+  }
324
+
325
+  switch (req->bmRequest & USB_REQ_TYPE_MASK)
326
+  {
327
+    /* Class request */
328
+    case USB_REQ_TYPE_CLASS:
329
+      switch (req->bRequest)
330
+      {
331
+        case BOT_GET_MAX_LUN:
332
+          if ((req->wValue  == 0U) && (req->wLength == 1U) &&
333
+              ((req->bmRequest & 0x80U) == 0x80U))
334
+          {
335
+            hmsc->max_lun = (uint32_t)((USBD_StorageTypeDef *)pdev->pUserData[pdev->classId])->GetMaxLun();
336
+            (void)USBD_CtlSendData(pdev, (uint8_t *)&hmsc->max_lun, 1U);
337
+          }
338
+          else
339
+          {
340
+            USBD_CtlError(pdev, req);
341
+            ret = USBD_FAIL;
342
+          }
343
+          break;
344
+
345
+        case BOT_RESET :
346
+          if ((req->wValue  == 0U) && (req->wLength == 0U) &&
347
+              ((req->bmRequest & 0x80U) != 0x80U))
348
+          {
349
+            MSC_BOT_Reset(pdev);
350
+          }
351
+          else
352
+          {
353
+            USBD_CtlError(pdev, req);
354
+            ret = USBD_FAIL;
355
+          }
356
+          break;
357
+
358
+        default:
359
+          USBD_CtlError(pdev, req);
360
+          ret = USBD_FAIL;
361
+          break;
362
+      }
363
+      break;
364
+    /* Interface & Endpoint request */
365
+    case USB_REQ_TYPE_STANDARD:
366
+      switch (req->bRequest)
367
+      {
368
+        case USB_REQ_GET_STATUS:
369
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
370
+          {
371
+            (void)USBD_CtlSendData(pdev, (uint8_t *)&status_info, 2U);
372
+          }
373
+          else
374
+          {
375
+            USBD_CtlError(pdev, req);
376
+            ret = USBD_FAIL;
377
+          }
378
+          break;
379
+
380
+        case USB_REQ_GET_INTERFACE:
381
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
382
+          {
383
+            (void)USBD_CtlSendData(pdev, (uint8_t *)&hmsc->interface, 1U);
384
+          }
385
+          else
386
+          {
387
+            USBD_CtlError(pdev, req);
388
+            ret = USBD_FAIL;
389
+          }
390
+          break;
391
+
392
+        case USB_REQ_SET_INTERFACE:
393
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
394
+          {
395
+            hmsc->interface = (uint8_t)(req->wValue);
396
+          }
397
+          else
398
+          {
399
+            USBD_CtlError(pdev, req);
400
+            ret = USBD_FAIL;
401
+          }
402
+          break;
403
+
404
+        case USB_REQ_CLEAR_FEATURE:
405
+          if (pdev->dev_state == USBD_STATE_CONFIGURED)
406
+          {
407
+            if (req->wValue == USB_FEATURE_EP_HALT)
408
+            {
409
+              /* Flush the FIFO */
410
+              (void)USBD_LL_FlushEP(pdev, (uint8_t)req->wIndex);
411
+
412
+              /* Handle BOT error */
413
+              MSC_BOT_CplClrFeature(pdev, (uint8_t)req->wIndex);
414
+            }
415
+          }
416
+          break;
417
+
418
+        default:
419
+          USBD_CtlError(pdev, req);
420
+          ret = USBD_FAIL;
421
+          break;
422
+      }
423
+      break;
424
+
425
+    default:
426
+      USBD_CtlError(pdev, req);
427
+      ret = USBD_FAIL;
428
+      break;
429
+  }
430
+
431
+  return (uint8_t)ret;
432
+}
433
+
434
+/**
435
+  * @brief  USBD_MSC_DataIn
436
+  *         handle data IN Stage
437
+  * @param  pdev: device instance
438
+  * @param  epnum: endpoint index
439
+  * @retval status
440
+  */
441
+uint8_t USBD_MSC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
442
+{
443
+  MSC_BOT_DataIn(pdev, epnum);
444
+
445
+  return (uint8_t)USBD_OK;
446
+}
447
+
448
+/**
449
+  * @brief  USBD_MSC_DataOut
450
+  *         handle data OUT Stage
451
+  * @param  pdev: device instance
452
+  * @param  epnum: endpoint index
453
+  * @retval status
454
+  */
455
+uint8_t USBD_MSC_DataOut(USBD_HandleTypeDef *pdev, uint8_t epnum)
456
+{
457
+  MSC_BOT_DataOut(pdev, epnum);
458
+
459
+  return (uint8_t)USBD_OK;
460
+}
461
+#ifndef USE_USBD_COMPOSITE
462
+/**
463
+  * @brief  USBD_MSC_GetHSCfgDesc
464
+  *         return configuration descriptor
465
+  * @param  length : pointer data length
466
+  * @retval pointer to descriptor buffer
467
+  */
468
+uint8_t *USBD_MSC_GetHSCfgDesc(uint16_t *length)
469
+{
470
+  USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
471
+  USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
472
+
473
+  if (pEpInDesc != NULL)
474
+  {
475
+    pEpInDesc->wMaxPacketSize = MSC_MAX_HS_PACKET;
476
+  }
477
+
478
+  if (pEpOutDesc != NULL)
479
+  {
480
+    pEpOutDesc->wMaxPacketSize = MSC_MAX_HS_PACKET;
481
+  }
482
+
483
+  *length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
484
+  return USBD_MSC_CfgDesc;
485
+}
486
+
487
+/**
488
+  * @brief  USBD_MSC_GetFSCfgDesc
489
+  *         return configuration descriptor
490
+  * @param  length : pointer data length
491
+  * @retval pointer to descriptor buffer
492
+  */
493
+uint8_t *USBD_MSC_GetFSCfgDesc(uint16_t *length)
494
+{
495
+  USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
496
+  USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
497
+
498
+  if (pEpInDesc != NULL)
499
+  {
500
+    pEpInDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
501
+  }
502
+
503
+  if (pEpOutDesc != NULL)
504
+  {
505
+    pEpOutDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
506
+  }
507
+
508
+  *length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
509
+  return USBD_MSC_CfgDesc;
510
+}
511
+
512
+/**
513
+  * @brief  USBD_MSC_GetOtherSpeedCfgDesc
514
+  *         return other speed configuration descriptor
515
+  * @param  length : pointer data length
516
+  * @retval pointer to descriptor buffer
517
+  */
518
+uint8_t *USBD_MSC_GetOtherSpeedCfgDesc(uint16_t *length)
519
+{
520
+  USBD_EpDescTypeDef *pEpInDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPIN_ADDR);
521
+  USBD_EpDescTypeDef *pEpOutDesc = USBD_GetEpDesc(USBD_MSC_CfgDesc, MSC_EPOUT_ADDR);
522
+
523
+  if (pEpInDesc != NULL)
524
+  {
525
+    pEpInDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
526
+  }
527
+
528
+  if (pEpOutDesc != NULL)
529
+  {
530
+    pEpOutDesc->wMaxPacketSize = MSC_MAX_FS_PACKET;
531
+  }
532
+
533
+  *length = (uint16_t)sizeof(USBD_MSC_CfgDesc);
534
+  return USBD_MSC_CfgDesc;
535
+}
536
+/**
537
+  * @brief  DeviceQualifierDescriptor
538
+  *         return Device Qualifier descriptor
539
+  * @param  length : pointer data length
540
+  * @retval pointer to descriptor buffer
541
+  */
542
+uint8_t *USBD_MSC_GetDeviceQualifierDescriptor(uint16_t *length)
543
+{
544
+  *length = (uint16_t)sizeof(USBD_MSC_DeviceQualifierDesc);
545
+
546
+  return USBD_MSC_DeviceQualifierDesc;
547
+}
548
+#endif /* USE_USBD_COMPOSITE */
549
+/**
550
+  * @brief  USBD_MSC_RegisterStorage
551
+  * @param  fops: storage callback
552
+  * @retval status
553
+  */
554
+uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, USBD_StorageTypeDef *fops)
555
+{
556
+  if (fops == NULL)
557
+  {
558
+    return (uint8_t)USBD_FAIL;
559
+  }
560
+
561
+  pdev->pUserData[pdev->classId] = fops;
562
+
563
+  return (uint8_t)USBD_OK;
564
+}
565
+
566
+/**
567
+  * @}
568
+  */
569
+
570
+
571
+/**
572
+  * @}
573
+  */
574
+
575
+
576
+/**
577
+  * @}
578
+  */
579
+