1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016, 2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_device_config.h"
10 #include "usb.h"
11 
12 #include "usb_device.h"
13 #include "usb_device_ch9.h"
14 #include "usb_device_class.h"
15 
16 #if ((defined(USB_DEVICE_CONFIG_NUM)) && (USB_DEVICE_CONFIG_NUM > 0U))
17 /* Include the class drivers according to the usb_device_config.h. */
18 #if ((defined(USB_DEVICE_CONFIG_HID)) && (USB_DEVICE_CONFIG_HID > 0U))
19 #include "usb_device_hid.h"
20 #endif
21 
22 #if ((defined(USB_DEVICE_CONFIG_CDC_ACM)) && (USB_DEVICE_CONFIG_CDC_ACM > 0U))
23 #include "usb_device_cdc_acm.h"
24 #endif
25 
26 #if ((defined(USB_DEVICE_CONFIG_MSC)) && (USB_DEVICE_CONFIG_MSC > 0U))
27 #include "usb_device_msc.h"
28 #endif
29 
30 #if ((defined(USB_DEVICE_CONFIG_MTP)) && (USB_DEVICE_CONFIG_MTP > 0U))
31 #include "usb_device_mtp.h"
32 #endif
33 
34 #if ((defined(USB_DEVICE_CONFIG_AUDIO)) && (USB_DEVICE_CONFIG_AUDIO > 0U))
35 #include "usb_device_audio.h"
36 #endif
37 
38 #if ((defined(USB_DEVICE_CONFIG_PHDC)) && (USB_DEVICE_CONFIG_PHDC > 0U))
39 #include "usb_device_phdc.h"
40 #endif
41 
42 #if ((defined(USB_DEVICE_CONFIG_VIDEO)) && (USB_DEVICE_CONFIG_VIDEO > 0U))
43 #include "usb_device_video.h"
44 #endif
45 
46 #if ((defined(USB_DEVICE_CONFIG_PRINTER)) && (USB_DEVICE_CONFIG_PRINTER > 0U))
47 #include "usb_device_printer.h"
48 #endif
49 
50 #if ((defined(USB_DEVICE_CONFIG_DFU)) && (USB_DEVICE_CONFIG_DFU > 0U))
51 #include "usb_device_dfu.h"
52 #endif
53 
54 #if ((defined(USB_DEVICE_CONFIG_CCID)) && (USB_DEVICE_CONFIG_CCID > 0U))
55 #include "usb_device_ccid.h"
56 #endif
57 
58 /*******************************************************************************
59  * Definitions
60  ******************************************************************************/
61 
62 /*******************************************************************************
63  * Prototypes
64  ******************************************************************************/
65 static usb_status_t USB_DeviceClassAllocateHandle(uint8_t controllerId, usb_device_common_class_struct_t **handle);
66 static usb_status_t USB_DeviceClassFreeHandle(uint8_t controllerId);
67 static usb_status_t USB_DeviceClassGetHandleByControllerId(uint8_t controllerId,
68                                                            usb_device_common_class_struct_t **handle);
69 static usb_status_t USB_DeviceClassGetHandleByDeviceHandle(usb_device_handle deviceHandle,
70                                                            usb_device_common_class_struct_t **handle);
71 
72 /*******************************************************************************
73  * Variables
74  ******************************************************************************/
75 
76 /* The device class driver list. */
77 static const usb_device_class_map_t s_UsbDeviceClassInterfaceMap[] = {
78 #if ((defined(USB_DEVICE_CONFIG_HID)) && (USB_DEVICE_CONFIG_HID > 0U))
79     {USB_DeviceHidInit, USB_DeviceHidDeinit, USB_DeviceHidEvent, kUSB_DeviceClassTypeHid},
80 #endif
81 
82 #if ((defined(USB_DEVICE_CONFIG_CDC_ACM)) && (USB_DEVICE_CONFIG_CDC_ACM > 0U))
83     {USB_DeviceCdcAcmInit, USB_DeviceCdcAcmDeinit, USB_DeviceCdcAcmEvent, kUSB_DeviceClassTypeCdc},
84 #endif
85 
86 #if ((defined(USB_DEVICE_CONFIG_MSC)) && (USB_DEVICE_CONFIG_MSC > 0U))
87     {USB_DeviceMscInit, USB_DeviceMscDeinit, USB_DeviceMscEvent, kUSB_DeviceClassTypeMsc},
88 #endif
89 
90 #if ((defined(USB_DEVICE_CONFIG_MTP)) && (USB_DEVICE_CONFIG_MTP > 0U))
91     {USB_DeviceMtpInit, USB_DeviceMtpDeinit, USB_DeviceMtpEvent, kUSB_DeviceClassTypeMtp},
92 #endif
93 
94 #if ((defined USB_DEVICE_CONFIG_AUDIO) && (USB_DEVICE_CONFIG_AUDIO > 0U))
95     {USB_DeviceAudioInit, USB_DeviceAudioDeinit, USB_DeviceAudioEvent, kUSB_DeviceClassTypeAudio},
96 #endif
97 
98 #if ((defined USB_DEVICE_CONFIG_PHDC) && (USB_DEVICE_CONFIG_PHDC > 0U))
99     {USB_DevicePhdcInit, USB_DevicePhdcDeinit, USB_DevicePhdcEvent, kUSB_DeviceClassTypePhdc},
100 #endif
101 
102 #if ((defined USB_DEVICE_CONFIG_VIDEO) && (USB_DEVICE_CONFIG_VIDEO > 0U))
103     {USB_DeviceVideoInit, USB_DeviceVideoDeinit, USB_DeviceVideoEvent, kUSB_DeviceClassTypeVideo},
104 #endif
105 
106 #if ((defined USB_DEVICE_CONFIG_PRINTER) && (USB_DEVICE_CONFIG_PRINTER > 0U))
107     {USB_DevicePrinterInit, USB_DevicePrinterDeinit, USB_DevicePrinterEvent, kUSB_DeviceClassTypePrinter},
108 #endif
109 
110 #if ((defined USB_DEVICE_CONFIG_DFU) && (USB_DEVICE_CONFIG_DFU > 0U))
111     {USB_DeviceDfuInit, USB_DeviceDfuDeinit, USB_DeviceDfuEvent, kUSB_DeviceClassTypeDfu},
112 #endif
113 
114 #if ((defined USB_DEVICE_CONFIG_CCID) && (USB_DEVICE_CONFIG_CCID > 0U))
115     {USB_DeviceCcidInit, USB_DeviceCcidDeinit, USB_DeviceCcidEvent, kUSB_DeviceClassTypeCcid},
116 #endif
117 
118     /* please make sure the following member is in the end of s_UsbDeviceClassInterfaceMap*/
119     {(usb_device_class_init_call_t)NULL, (usb_device_class_deinit_call_t)NULL, (usb_device_class_event_callback_t)NULL,
120      (usb_device_class_type_t)0},
121 };
122 
123 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_common_class_struct_t
124     s_UsbDeviceCommonClassStruct[USB_DEVICE_CONFIG_NUM];
125 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint8_t
126     s_UsbDeviceSetupBuffer[USB_DEVICE_CONFIG_NUM][USB_DATA_ALIGN_SIZE_MULTIPLE(USB_SETUP_PACKET_SIZE)];
127 
128 /*******************************************************************************
129  * Code
130  ******************************************************************************/
131 
132 /*!
133  * @brief Allocate a device common class handle.
134  *
135  * This function allocates a a device common class handle.
136  *
137  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
138  * @param handle          It is out parameter, is used to return pointer of the device common class handle to the
139  * caller.
140  *
141  * @retval kStatus_USB_Success              Get a device handle successfully.
142  * @retval kStatus_USB_Busy                 Cannot allocate a common class handle.
143  * @retval kStatus_USB_Error                The common class has been initialized.
144  */
USB_DeviceClassAllocateHandle(uint8_t controllerId,usb_device_common_class_struct_t ** handle)145 static usb_status_t USB_DeviceClassAllocateHandle(uint8_t controllerId, usb_device_common_class_struct_t **handle)
146 {
147     uint32_t count;
148     OSA_SR_ALLOC();
149 
150     OSA_ENTER_CRITICAL();
151     /* Check the controller is initialized or not. */
152     for (count = 0U; count < USB_DEVICE_CONFIG_NUM; count++)
153     {
154         if ((NULL != s_UsbDeviceCommonClassStruct[count].handle) &&
155             (controllerId == s_UsbDeviceCommonClassStruct[count].controllerId))
156         {
157             OSA_EXIT_CRITICAL();
158             return kStatus_USB_Error;
159         }
160     }
161     /* Get a free common class handle. */
162     for (count = 0U; count < USB_DEVICE_CONFIG_NUM; count++)
163     {
164         if (NULL == s_UsbDeviceCommonClassStruct[count].handle)
165         {
166             s_UsbDeviceCommonClassStruct[count].controllerId = controllerId;
167             s_UsbDeviceCommonClassStruct[count].setupBuffer  = s_UsbDeviceSetupBuffer[count];
168             *handle                                          = &s_UsbDeviceCommonClassStruct[count];
169             OSA_EXIT_CRITICAL();
170             return kStatus_USB_Success;
171         }
172     }
173 
174     OSA_EXIT_CRITICAL();
175     return kStatus_USB_Busy;
176 }
177 
178 /*!
179  * @brief Free a device common class handle.
180  *
181  * This function frees a device common class handle.
182  *
183  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
184  *
185  * @retval kStatus_USB_Success              Free device handle successfully.
186  * @retval kStatus_USB_InvalidParameter     The common class can not be found.
187  */
USB_DeviceClassFreeHandle(uint8_t controllerId)188 static usb_status_t USB_DeviceClassFreeHandle(uint8_t controllerId)
189 {
190     uint32_t count = 0U;
191     OSA_SR_ALLOC();
192 
193     OSA_ENTER_CRITICAL();
194     for (; count < USB_DEVICE_CONFIG_NUM; count++)
195     {
196         if ((NULL != s_UsbDeviceCommonClassStruct[count].handle) &&
197             (controllerId == s_UsbDeviceCommonClassStruct[count].controllerId))
198         {
199             s_UsbDeviceCommonClassStruct[count].handle       = NULL;
200             s_UsbDeviceCommonClassStruct[count].configList   = (usb_device_class_config_list_struct_t *)NULL;
201             s_UsbDeviceCommonClassStruct[count].controllerId = 0U;
202             OSA_EXIT_CRITICAL();
203             return kStatus_USB_Success;
204         }
205     }
206     OSA_EXIT_CRITICAL();
207 
208     return kStatus_USB_InvalidParameter;
209 }
210 
211 /*!
212  * @brief Get the device common class handle according to the controller id.
213  *
214  * This function gets the device common class handle according to the controller id.
215  *
216  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
217  * @param handle          It is out parameter, is used to return pointer of the device common class handle to the
218  * caller.
219  *
220  * @retval kStatus_USB_Success              Free device handle successfully.
221  * @retval kStatus_USB_InvalidParameter     The common class can not be found.
222  */
USB_DeviceClassGetHandleByControllerId(uint8_t controllerId,usb_device_common_class_struct_t ** handle)223 static usb_status_t USB_DeviceClassGetHandleByControllerId(uint8_t controllerId,
224                                                            usb_device_common_class_struct_t **handle)
225 {
226     uint32_t count = 0U;
227     OSA_SR_ALLOC();
228 
229     OSA_ENTER_CRITICAL();
230     for (; count < USB_DEVICE_CONFIG_NUM; count++)
231     {
232         if ((NULL != s_UsbDeviceCommonClassStruct[count].handle) &&
233             (controllerId == s_UsbDeviceCommonClassStruct[count].controllerId))
234         {
235             *handle = &s_UsbDeviceCommonClassStruct[count];
236             OSA_EXIT_CRITICAL();
237             return kStatus_USB_Success;
238         }
239     }
240     OSA_EXIT_CRITICAL();
241     return kStatus_USB_InvalidParameter;
242 }
243 
244 /*!
245  * @brief Get the device common class handle according to the device handle.
246  *
247  * This function gets the device common class handle according to the device handle.
248  *
249  * @param deviceHandle          The device handle, got from the USB_DeviceInit.
250  * @param handle                 It is out parameter, is used to return pointer of the device common class handle to the
251  * caller.
252  *
253  * @retval kStatus_USB_Success              Free device handle successfully.
254  * @retval kStatus_USB_InvalidParameter     The common class can not be found.
255  */
USB_DeviceClassGetHandleByDeviceHandle(usb_device_handle deviceHandle,usb_device_common_class_struct_t ** handle)256 static usb_status_t USB_DeviceClassGetHandleByDeviceHandle(usb_device_handle deviceHandle,
257                                                            usb_device_common_class_struct_t **handle)
258 {
259     uint32_t count = 0U;
260     OSA_SR_ALLOC();
261 
262     OSA_ENTER_CRITICAL();
263     for (; count < USB_DEVICE_CONFIG_NUM; count++)
264     {
265         if (deviceHandle == s_UsbDeviceCommonClassStruct[count].handle)
266         {
267             *handle = &s_UsbDeviceCommonClassStruct[count];
268             OSA_EXIT_CRITICAL();
269             return kStatus_USB_Success;
270         }
271     }
272     OSA_EXIT_CRITICAL();
273     return kStatus_USB_InvalidParameter;
274 }
275 
276 /*!
277  * @brief Get the device handle according to the controller id.
278  *
279  * This function gets the device handle according to the controller id.
280  *
281  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
282  * @param handle          It is out parameter, is used to return pointer of the device handle to the caller.
283  *
284  * @retval kStatus_USB_Success              Free device handle successfully.
285  * @retval kStatus_USB_InvalidParameter     The device handle not be found.
286  */
USB_DeviceClassGetDeviceHandle(uint8_t controllerId,usb_device_handle * handle)287 usb_status_t USB_DeviceClassGetDeviceHandle(uint8_t controllerId, usb_device_handle *handle)
288 {
289     uint32_t count = 0U;
290     OSA_SR_ALLOC();
291 
292     OSA_ENTER_CRITICAL();
293     for (; count < USB_DEVICE_CONFIG_NUM; count++)
294     {
295         if ((NULL != s_UsbDeviceCommonClassStruct[count].handle) &&
296             (controllerId == s_UsbDeviceCommonClassStruct[count].controllerId))
297         {
298             *handle = s_UsbDeviceCommonClassStruct[count].handle;
299             OSA_EXIT_CRITICAL();
300             return kStatus_USB_Success;
301         }
302     }
303     OSA_EXIT_CRITICAL();
304     return kStatus_USB_InvalidParameter;
305 }
306 
307 /*!
308  * @brief Handle the event passed to the class drivers.
309  *
310  * This function handles the event passed to the class drivers.
311  *
312  * @param handle          The device handle, got from the USB_DeviceInit.
313  * @param event           The event codes. Please refer to the enumeration usb_device_class_event_t.
314  * @param param           The param type is determined by the event code.
315  *
316  * @return A USB error code or kStatus_USB_Success.
317  * @retval kStatus_USB_Success              A valid request has been handled.
318  * @retval kStatus_USB_InvalidParameter     The device handle not be found.
319  * @retval kStatus_USB_InvalidRequest       The request is invalid, and the control pipe will be stalled by the caller.
320  */
USB_DeviceClassEvent(usb_device_handle handle,usb_device_class_event_t event,void * param)321 usb_status_t USB_DeviceClassEvent(usb_device_handle handle, usb_device_class_event_t event, void *param)
322 {
323     usb_device_common_class_struct_t *classHandle;
324     uint8_t mapIndex;
325     uint8_t classIndex;
326     usb_status_t errorReturn;
327     usb_status_t status = kStatus_USB_Error;
328 
329     if (NULL == param)
330     {
331         return kStatus_USB_InvalidParameter;
332     }
333 
334     /* Get the common class handle according to the device handle. */
335     errorReturn = USB_DeviceClassGetHandleByDeviceHandle(handle, &classHandle);
336     if (kStatus_USB_Success != errorReturn)
337     {
338         return kStatus_USB_InvalidParameter;
339     }
340 
341     for (classIndex = 0U; classIndex < classHandle->configList->count; classIndex++)
342     {
343         for (mapIndex = 0U; mapIndex < (ARRAY_SIZE(s_UsbDeviceClassInterfaceMap) - 1U); mapIndex++)
344         {
345             if (s_UsbDeviceClassInterfaceMap[mapIndex].type ==
346                 classHandle->configList->config[classIndex].classInfomation->type)
347             {
348                 /* Call class event callback of supported class */
349                 errorReturn = s_UsbDeviceClassInterfaceMap[mapIndex].classEventCallback(
350                     (void *)classHandle->configList->config[classIndex].classHandle, event, param);
351                 /* Return the error code kStatus_USB_InvalidRequest immediately, when a class returns
352                  * kStatus_USB_InvalidRequest. */
353                 if (kStatus_USB_InvalidRequest == errorReturn)
354                 {
355                     /* For composite device, it should return kStatus_USB_Success once a valid request has been handled
356                      */
357                     if (kStatus_USB_Success == status)
358                     {
359                         return kStatus_USB_Success;
360                     }
361                     return kStatus_USB_InvalidRequest;
362                 }
363                 /* For composite device, save kStatus_USB_Success status once a valid request has been handled */
364                 if (kStatus_USB_Success == errorReturn)
365                 {
366                     status = kStatus_USB_Success;
367                 }
368                 break;
369             }
370         }
371     }
372 
373     return status;
374 }
375 
376 /*!
377  * @brief Handle the common class callback.
378  *
379  * This function handles the common class callback.
380  *
381  * @param handle          The device handle, got from the USB_DeviceInit.
382  * @param event           The event codes. Please refer to the enumeration usb_device_event_t.
383  * @param param           The param type is determined by the event code.
384  *
385  * @return A USB error code or kStatus_USB_Success.
386  */
USB_DeviceClassCallback(usb_device_handle handle,uint32_t event,void * param)387 usb_status_t USB_DeviceClassCallback(usb_device_handle handle, uint32_t event, void *param)
388 {
389     usb_device_common_class_struct_t *classHandle;
390     usb_status_t status;
391 
392     /* Get the common class handle according to the device handle. */
393     status = USB_DeviceClassGetHandleByDeviceHandle(handle, &classHandle);
394     if (kStatus_USB_Success != status)
395     {
396         return status;
397     }
398 
399     if ((uint32_t)kUSB_DeviceEventBusReset == event)
400     {
401 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
402         if ((kStatus_USB_Success != USB_DeviceControlPipeInit(handle, classHandle)) ||
403             (kStatus_USB_Success != USB_DeviceClassEvent(handle, kUSB_DeviceClassEventDeviceReset, classHandle)))
404         {
405             return kStatus_USB_Error;
406         }
407 #else
408         /* Initialize the control pipes */
409         (void)USB_DeviceControlPipeInit(handle, classHandle);
410 
411         /* Notify the classes the USB bus reset signal detected. */
412         (void)USB_DeviceClassEvent(handle, kUSB_DeviceClassEventDeviceReset, classHandle);
413 #endif
414     }
415 
416     /* Call the application device callback function. deviceCallback is from the second parameter of
417        USB_DeviceClassInit */
418     status = classHandle->configList->deviceCallback(handle, event, param);
419     return status;
420 }
421 
422 /*!
423  * @brief Initialize the common class and the supported classes.
424  *
425  * This function is used to initialize the common class and the supported classes.
426  *
427  * @param[in] controllerId   The controller id of the USB IP. Please refer to the enumeration #usb_controller_index_t.
428  * @param[in] configList     The class configurations. The pointer must point to the global variable.
429  *                           Please refer to the structure #usb_device_class_config_list_struct_t.
430  * @param[out] handle        It is out parameter, is used to return pointer of the device handle to the caller.
431  *                           The value of parameter is a pointer points the device handle, and this design is used to
432  *                           make simple device align with composite device. For composite device, there are many
433  *                           kinds of class handle, but there is only one device handle. So the handle points to
434  *                           a device instead of a class. And the class handle can be got from the
435  *                           #usb_device_class_config_struct_t::classHandle after the function successfully.
436  *
437  * @return A USB error code or kStatus_USB_Success.
438  */
USB_DeviceClassInit(uint8_t controllerId,usb_device_class_config_list_struct_t * configList,usb_device_handle * handle)439 usb_status_t USB_DeviceClassInit(
440     uint8_t controllerId,                              /*!< [IN] Controller ID */
441     usb_device_class_config_list_struct_t *configList, /*!< [IN] Pointer to class configuration list */
442     usb_device_handle *handle                          /*!< [OUT] Pointer to the device handle */
443 )
444 {
445     usb_device_common_class_struct_t *classHandle;
446     usb_status_t error;
447     uint8_t mapIndex;
448     uint8_t classIndex;
449 
450     if ((NULL == handle) || (NULL == configList) || ((usb_device_callback_t)NULL == configList->deviceCallback))
451     {
452         return kStatus_USB_InvalidParameter;
453     }
454 
455     /* Allocate a common class driver handle. */
456     error = USB_DeviceClassAllocateHandle(controllerId, &classHandle);
457     if (kStatus_USB_Success != error)
458     {
459         return error;
460     }
461     /* Save the configuration list */
462     classHandle->configList = configList;
463 
464     /* Initialize the device stack. */
465     error = USB_DeviceInit(controllerId, USB_DeviceClassCallback, &classHandle->handle);
466 
467     if (kStatus_USB_Success != error)
468     {
469 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
470         if (((kStatus_USB_Success != USB_DeviceDeinit(classHandle->handle))) ||
471             (kStatus_USB_Success != USB_DeviceClassFreeHandle(controllerId)))
472         {
473             return kStatus_USB_Error;
474         }
475 #else
476         (void)USB_DeviceDeinit(classHandle->handle);
477         (void)USB_DeviceClassFreeHandle(controllerId);
478 #endif
479         return error;
480     }
481 
482     /* Initialize the all supported classes according to the configuration list. */
483     for (classIndex = 0U; classIndex < classHandle->configList->count; classIndex++)
484     {
485         for (mapIndex = 0U; mapIndex < (sizeof(s_UsbDeviceClassInterfaceMap) / sizeof(usb_device_class_map_t));
486              mapIndex++)
487         {
488             if (classHandle->configList->config[classIndex].classInfomation->type ==
489                 s_UsbDeviceClassInterfaceMap[mapIndex].type)
490             {
491 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
492                 error = s_UsbDeviceClassInterfaceMap[mapIndex].classInit(
493                     controllerId, &classHandle->configList->config[classIndex],
494                     &classHandle->configList->config[classIndex].classHandle);
495                 if (kStatus_USB_Success != error)
496                 {
497                     return error;
498                 }
499 #else
500                 (void)s_UsbDeviceClassInterfaceMap[mapIndex].classInit(
501                     controllerId, &classHandle->configList->config[classIndex],
502                     &classHandle->configList->config[classIndex].classHandle);
503 #endif
504             }
505         }
506     }
507 
508     *handle = classHandle->handle;
509     return error;
510 }
511 
512 /*!
513  * @brief De-initialize the common class and the supported classes.
514  *
515  * This function is used to de-initialize the common class and the supported classes.
516  *
517  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
518  *
519  * @return A USB error code or kStatus_USB_Success.
520  */
USB_DeviceClassDeinit(uint8_t controllerId)521 usb_status_t USB_DeviceClassDeinit(uint8_t controllerId /*!< [IN] Controller ID */
522 )
523 {
524     usb_device_common_class_struct_t *classHandle;
525     usb_status_t error;
526     uint8_t mapIndex;
527     uint8_t classIndex;
528 
529     /* Get the common class handle according to the controller id. */
530     error = USB_DeviceClassGetHandleByControllerId(controllerId, &classHandle);
531 
532     if (kStatus_USB_Success != error)
533     {
534         return error;
535     }
536 
537     /* De-initialize the all supported classes according to the configuration list. */
538     for (classIndex = 0U; classIndex < classHandle->configList->count; classIndex++)
539     {
540         for (mapIndex = 0U; mapIndex < (sizeof(s_UsbDeviceClassInterfaceMap) / sizeof(usb_device_class_map_t));
541              mapIndex++)
542         {
543             if (classHandle->configList->config[classIndex].classInfomation->type ==
544                 s_UsbDeviceClassInterfaceMap[mapIndex].type)
545             {
546 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
547                 error = s_UsbDeviceClassInterfaceMap[mapIndex].classDeinit(
548                     classHandle->configList->config[classIndex].classHandle);
549                 if (kStatus_USB_Success != error)
550                 {
551                     return error;
552                 }
553 #else
554                 (void)s_UsbDeviceClassInterfaceMap[mapIndex].classDeinit(
555                     classHandle->configList->config[classIndex].classHandle);
556 #endif
557             }
558         }
559     }
560 
561     /* De-initialize the USB device stack. */
562     error = USB_DeviceDeinit(classHandle->handle);
563     if (kStatus_USB_Success == error)
564     {
565         /* Free the common class handle. */
566 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
567         if (kStatus_USB_Success != USB_DeviceClassFreeHandle(controllerId))
568         {
569             return kStatus_USB_Error;
570         }
571 #else
572         (void)USB_DeviceClassFreeHandle(controllerId);
573 #endif
574     }
575     return error;
576 }
577 
578 /*!
579  * @brief Get the USB bus speed.
580  *
581  * This function is used to get the USB bus speed.
582  *
583  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
584  * @param speed           It is an OUT parameter, return current speed of the controller.
585  *
586  * @return A USB error code or kStatus_USB_Success.
587  */
USB_DeviceClassGetSpeed(uint8_t controllerId,uint8_t * speed)588 usb_status_t USB_DeviceClassGetSpeed(uint8_t controllerId, /*!< [IN] Controller ID */
589                                      uint8_t *speed        /*!< [OUT] Current speed */
590 )
591 {
592     usb_device_common_class_struct_t *classHandle;
593     usb_status_t error;
594 
595     /* Get the common class handle according to the controller id. */
596     error = USB_DeviceClassGetHandleByControllerId(controllerId, &classHandle);
597 
598     if (kStatus_USB_Success != error)
599     {
600         return error;
601     }
602 
603     /* Get the current speed. */
604     error = USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusSpeed, speed);
605 
606     return error;
607 }
608 
609 #if defined(USB_DEVICE_CONFIG_GET_SOF_COUNT) && (USB_DEVICE_CONFIG_GET_SOF_COUNT > 0U)
610 /*!
611  * @brief Get the USB SOF count.
612  *
613  * This function is used to get the USB SOF count.
614  *
615  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
616  * @param currentFrameCount           It is an OUT parameter, return current sof count of the controller.
617  *                                    HS: micro frame count, FS: frame count
618  *
619  * @return A USB error code or kStatus_USB_Success.
620  */
USB_DeviceClassGetCurrentFrameCount(uint8_t controllerId,uint32_t * currentFrameCount)621 usb_status_t USB_DeviceClassGetCurrentFrameCount(uint8_t controllerId,       /*!< [IN] Controller ID */
622                                                  uint32_t *currentFrameCount /*!< [OUT] Current frame count */
623 )
624 {
625     usb_device_common_class_struct_t *classHandle;
626     usb_status_t error;
627 
628     /* Get the common class handle according to the controller id. */
629     error = USB_DeviceClassGetHandleByControllerId(controllerId, &classHandle);
630 
631     if (kStatus_USB_Success != error)
632     {
633         return error;
634     }
635 
636     /* Get the current frame count. */
637     error = USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusGetCurrentFrameCount, currentFrameCount);
638 
639     return error;
640 }
641 #endif /* USB_DEVICE_CONFIG_GET_SOF_COUNT */
642 
643 #endif /* USB_DEVICE_CONFIG_NUM */
644