1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016 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 #include "usb_device.h"
12 
13 #include "usb_device_class.h"
14 
15 #if ((defined(USB_DEVICE_CONFIG_AUDIO)) && (USB_DEVICE_CONFIG_AUDIO > 0U))
16 #include "usb_device_audio.h"
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*******************************************************************************
23  * Prototypes
24  ******************************************************************************/
25 static usb_status_t USB_DeviceAudioAllocateHandle(usb_device_audio_struct_t **handle);
26 static usb_status_t USB_DeviceAudioFreeHandle(usb_device_audio_struct_t *handle);
27 usb_status_t USB_DeviceAudioInterruptIn(usb_device_handle handle,
28                                         usb_device_endpoint_callback_message_struct_t *message,
29                                         void *callbackParam);
30 usb_status_t USB_DeviceAudioIsochronousIn(usb_device_handle handle,
31                                           usb_device_endpoint_callback_message_struct_t *message,
32                                           void *callbackParam);
33 usb_status_t USB_DeviceAudioIsochronousOut(usb_device_handle handle,
34                                            usb_device_endpoint_callback_message_struct_t *message,
35                                            void *callbackParam);
36 usb_status_t USB_DeviceAudioStreamEndpointsInit(usb_device_audio_struct_t *audioHandle);
37 usb_status_t USB_DeviceAudioStreamEndpointsDeinit(usb_device_audio_struct_t *audioHandle);
38 usb_status_t USB_DeviceAudioControlEndpointsInit(usb_device_audio_struct_t *audioHandle);
39 usb_status_t USB_DeviceAudioControlEndpointsDeinit(usb_device_audio_struct_t *audioHandle);
40 usb_status_t USB_DeviceAudioGetCurAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
41                                                    usb_device_control_request_struct_t *controlRequest);
42 usb_status_t USB_DeviceAudioSetCurAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
43                                                    usb_device_control_request_struct_t *controlRequest);
44 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
45 usb_status_t USB_DeviceAudioGetRangeAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
46                                                      usb_device_control_request_struct_t *controlRequest);
47 usb_status_t USB_DeviceAudioGetClockSource(usb_device_audio_struct_t *audioHandle,
48                                            usb_device_control_request_struct_t *controlRequest);
49 usb_status_t USB_DeviceAudioSetClockSource(usb_device_audio_struct_t *audioHandle,
50                                            usb_device_control_request_struct_t *controlRequest);
51 #else
52 usb_status_t USB_DeviceAudioGetMinAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
53                                                    usb_device_control_request_struct_t *controlRequest);
54 usb_status_t USB_DeviceAudioGetMaxAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
55                                                    usb_device_control_request_struct_t *controlRequest);
56 usb_status_t USB_DeviceAudioGetResAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
57                                                    usb_device_control_request_struct_t *controlRequest);
58 usb_status_t USB_DeviceAudioSetMinAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
59                                                    usb_device_control_request_struct_t *controlRequest);
60 usb_status_t USB_DeviceAudioSetMaxAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
61                                                    usb_device_control_request_struct_t *controlRequest);
62 usb_status_t USB_DeviceAudioSetResAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
63                                                    usb_device_control_request_struct_t *controlRequest);
64 #endif
65 usb_status_t USB_DeviceAudioSetFeatureUnit(usb_device_audio_struct_t *audioHandle,
66                                            usb_device_control_request_struct_t *controlRequest);
67 usb_status_t USB_DeviceAudioSetRequestEndpoint(usb_device_audio_struct_t *audioHandle,
68                                                usb_device_control_request_struct_t *controlRequest);
69 usb_status_t USB_DeviceAudioGetRequestEndpoint(usb_device_audio_struct_t *audioHandle,
70                                                usb_device_control_request_struct_t *controlRequest);
71 usb_status_t USB_DeviceAudioSetControlTerminal(usb_device_audio_struct_t *audioHandle,
72                                                usb_device_control_request_struct_t *controlRequest,
73                                                uint8_t terminal_type);
74 usb_status_t USB_DeviceAudioGetControlTerminal(usb_device_audio_struct_t *audioHandle,
75                                                usb_device_control_request_struct_t *controlRequest,
76                                                uint8_t terminal_type);
77 usb_status_t USB_DeviceAudioGetFeatureUnit(usb_device_audio_struct_t *audioHandle,
78                                            usb_device_control_request_struct_t *controlRequest);
79 usb_status_t USB_DeviceAudioSetRequestInterface(usb_device_audio_struct_t *audioHandle,
80                                                 usb_device_control_request_struct_t *controlRequest);
81 usb_status_t USB_DeviceAudioGetRequestInterface(usb_device_audio_struct_t *audioHandle,
82                                                 usb_device_control_request_struct_t *controlRequest);
83 
84 /*******************************************************************************
85  * Variables
86  ******************************************************************************/
87 
USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE)88 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_device_audio_struct_t
89     s_UsbDeviceAudioHandle[USB_DEVICE_CONFIG_AUDIO];
90 
91 /*******************************************************************************
92  * Code
93  ******************************************************************************/
94 
95 /*!
96  * @brief Allocate a device audio class handle.
97  *
98  * This function allocates a device audio class handle.
99  *
100  * @param handle          It is out parameter, is used to return pointer of the device audio class handle to the caller.
101  *
102  * @retval kStatus_USB_Success              Get a device audio class handle successfully.
103  * @retval kStatus_USB_Busy                 Cannot allocate a device audio class handle.
104  */
105 static usb_status_t USB_DeviceAudioAllocateHandle(usb_device_audio_struct_t **handle)
106 {
107     uint32_t count;
108     OSA_SR_ALLOC();
109 
110     OSA_ENTER_CRITICAL();
111     for (count = 0; count < USB_DEVICE_CONFIG_AUDIO; count++)
112     {
113         if (NULL == s_UsbDeviceAudioHandle[count].handle)
114         {
115             *handle = &s_UsbDeviceAudioHandle[count];
116             OSA_EXIT_CRITICAL();
117             return kStatus_USB_Success;
118         }
119     }
120     OSA_EXIT_CRITICAL();
121     return kStatus_USB_Busy;
122 }
123 
124 /*!
125  * @brief Free a device audio class handle.
126  *
127  * This function frees a device audio class handle.
128  *
129  * @param handle          The device audio class handle.
130  *
131  * @retval kStatus_USB_Success              Free device audio class handle successfully.
132  */
USB_DeviceAudioFreeHandle(usb_device_audio_struct_t * handle)133 static usb_status_t USB_DeviceAudioFreeHandle(usb_device_audio_struct_t *handle)
134 {
135     OSA_SR_ALLOC();
136 
137     OSA_ENTER_CRITICAL();
138     handle->handle           = NULL;
139     handle->configStruct     = (usb_device_class_config_struct_t *)NULL;
140     handle->configuration    = 0U;
141     handle->controlAlternate = 0U;
142     handle->streamAlternate  = 0U;
143     OSA_EXIT_CRITICAL();
144     return kStatus_USB_Success;
145 }
146 
147 /*!
148  * @brief Interrupt IN endpoint callback function.
149  *
150  * This callback function is used to notify uplayer the transfser result of a transfer.
151  * This callback pointer is passed when the interrupt IN pipe initialized.
152  *
153  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
154  * @param message         The result of the interrupt IN pipe transfer.
155  * @param callbackParam  The parameter for this callback. It is same with
156  * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the audio class handle.
157  *
158  * @return A USB error code or kStatus_USB_Success.
159  */
USB_DeviceAudioInterruptIn(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)160 usb_status_t USB_DeviceAudioInterruptIn(usb_device_handle handle,
161                                         usb_device_endpoint_callback_message_struct_t *message,
162                                         void *callbackParam)
163 {
164     usb_device_audio_struct_t *audioHandle;
165     usb_status_t error = kStatus_USB_Error;
166 
167     /* Get the audio class handle */
168     audioHandle = (usb_device_audio_struct_t *)callbackParam;
169 
170     if (NULL == audioHandle)
171     {
172         return kStatus_USB_InvalidHandle;
173     }
174 
175     if ((NULL != audioHandle->configStruct) && (NULL != audioHandle->configStruct->classCallback))
176     {
177         /* Notify the application control data sent by calling the audio class callback.
178         classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
179         it is from the second parameter of classInit */
180         error = audioHandle->configStruct->classCallback((class_handle_t)audioHandle,
181                                                          kUSB_DeviceAudioEventControlSendResponse, message);
182     }
183 
184     return error;
185 }
186 
187 /*!
188  * @brief ISO IN endpoint callback function.
189  *
190  * This callback function is used to notify uplayer the transfser result of a transfer.
191  * This callback pointer is passed when the ISO IN pipe initialized.
192  *
193  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
194  * @param message         The result of the ISO IN pipe transfer.
195  * @param callbackParam  The parameter for this callback. It is same with
196  * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the audio class handle.
197  *
198  * @return A USB error code or kStatus_USB_Success.
199  */
USB_DeviceAudioIsochronousIn(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)200 usb_status_t USB_DeviceAudioIsochronousIn(usb_device_handle handle,
201                                           usb_device_endpoint_callback_message_struct_t *message,
202                                           void *callbackParam)
203 {
204     usb_device_audio_struct_t *audioHandle;
205     usb_status_t status = kStatus_USB_Error;
206 
207     /* Get the audio class handle */
208     audioHandle = (usb_device_audio_struct_t *)callbackParam;
209     if (NULL == audioHandle)
210     {
211         return kStatus_USB_InvalidHandle;
212     }
213     audioHandle->streamInPipeBusy = 0U;
214     if ((NULL != audioHandle->configStruct) && (NULL != audioHandle->configStruct->classCallback))
215     {
216         /* Notify the application stream data sent by calling the audio class callback.
217         classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
218         it is from the second parameter of classInit */
219         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle,
220                                                           kUSB_DeviceAudioEventStreamSendResponse, message);
221     }
222 
223     return status;
224 }
225 
226 /*!
227  * @brief ISO OUT endpoint callback function.
228  *
229  * This callback function is used to notify uplayer the transfser result of a transfer.
230  * This callback pointer is passed when the ISO OUT pipe initialized.
231  *
232  * @param handle          The device handle. It equals the value returned from USB_DeviceInit.
233  * @param message         The result of the ISO OUT pipe transfer.
234  * @param callbackParam  The parameter for this callback. It is same with
235  * usb_device_endpoint_callback_struct_t::callbackParam. In the class, the value is the audio class handle.
236  *
237  * @return A USB error code or kStatus_USB_Success.
238  */
USB_DeviceAudioIsochronousOut(usb_device_handle handle,usb_device_endpoint_callback_message_struct_t * message,void * callbackParam)239 usb_status_t USB_DeviceAudioIsochronousOut(usb_device_handle handle,
240                                            usb_device_endpoint_callback_message_struct_t *message,
241                                            void *callbackParam)
242 {
243     usb_device_audio_struct_t *audioHandle;
244     usb_status_t status = kStatus_USB_Error;
245 
246     /* Get the audio class handle */
247     audioHandle = (usb_device_audio_struct_t *)callbackParam;
248     if (NULL == audioHandle)
249     {
250         return kStatus_USB_InvalidHandle;
251     }
252     audioHandle->streamOutPipeBusy = 0U;
253 
254     if ((NULL != audioHandle->configStruct) && (NULL != audioHandle->configStruct->classCallback))
255     {
256         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
257         it is from the second parameter of classInit */
258         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle,
259                                                           kUSB_DeviceAudioEventStreamRecvResponse, message);
260     }
261     return status;
262 }
263 
264 /*!
265  * @brief Initialize the stream endpoints of the audio class.
266  *
267  * This callback function is used to initialize the stream endpoints of the audio class.
268  *
269  * @param audioHandle          The device audio class handle. It equals the value returned from
270  * usb_device_class_config_struct_t::classHandle.
271  *
272  * @return A USB error code or kStatus_USB_Success.
273  */
USB_DeviceAudioStreamEndpointsInit(usb_device_audio_struct_t * audioHandle)274 usb_status_t USB_DeviceAudioStreamEndpointsInit(usb_device_audio_struct_t *audioHandle)
275 {
276     usb_device_interface_list_t *interfaceList;
277     usb_device_interface_struct_t *interface = (usb_device_interface_struct_t *)NULL;
278     usb_status_t status                      = kStatus_USB_Error;
279     uint8_t count;
280     uint8_t index;
281 
282     /* Check the configuration is valid or not. */
283     if (0U == audioHandle->configuration)
284     {
285         return status;
286     }
287 
288     /* Check the configuration is valid or not. */
289     if (audioHandle->configuration > audioHandle->configStruct->classInfomation->configurations)
290     {
291         return status;
292     }
293 
294     if (NULL == audioHandle->configStruct->classInfomation->interfaceList)
295     {
296         return status;
297     }
298 
299     /* Get the interface list of the new configuration. */
300     interfaceList = &audioHandle->configStruct->classInfomation->interfaceList[audioHandle->configuration - 1U];
301 
302     /* Find stream interface by using the alternate setting of the interface. */
303     for (count = 0U; count < interfaceList->count; count++)
304     {
305         if ((USB_DEVICE_CONFIG_AUDIO_CLASS_CODE == interfaceList->interfaces[count].classCode) &&
306             (USB_DEVICE_AUDIO_STREAM_SUBCLASS == interfaceList->interfaces[count].subclassCode))
307         {
308             for (index = 0; index < interfaceList->interfaces[count].count; index++)
309             {
310                 if (interfaceList->interfaces[count].interface[index].alternateSetting == audioHandle->streamAlternate)
311                 {
312                     interface = &interfaceList->interfaces[count].interface[index];
313                     break;
314                 }
315             }
316             audioHandle->streamInterfaceNumber = interfaceList->interfaces[count].interfaceNumber;
317             break;
318         }
319     }
320     if (NULL == interface)
321     {
322         return status;
323     }
324     /* Keep new stream interface handle. */
325     audioHandle->streamInterfaceHandle = interface;
326 
327     /* Initialize the endpoints of the new interface. */
328     for (count = 0U; count < interface->endpointList.count; count++)
329     {
330         usb_device_endpoint_init_struct_t epInitStruct;
331         usb_device_endpoint_callback_struct_t epCallback;
332         epInitStruct.zlt             = 0U;
333         epInitStruct.interval        = interface->endpointList.endpoint[count].interval;
334         epInitStruct.endpointAddress = interface->endpointList.endpoint[count].endpointAddress;
335         epInitStruct.maxPacketSize   = interface->endpointList.endpoint[count].maxPacketSize;
336         epInitStruct.transferType    = interface->endpointList.endpoint[count].transferType;
337 
338         if ((USB_ENDPOINT_ISOCHRONOUS == (epInitStruct.transferType & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK)) &&
339             (USB_IN == ((epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
340                         USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)))
341         {
342             epCallback.callbackFn = USB_DeviceAudioIsochronousIn;
343         }
344         else
345         {
346             epCallback.callbackFn = USB_DeviceAudioIsochronousOut;
347         }
348         epCallback.callbackParam = audioHandle;
349 
350         status = USB_DeviceInitEndpoint(audioHandle->handle, &epInitStruct, &epCallback);
351     }
352     return status;
353 }
354 
355 /*!
356  * @brief De-initialize the stream endpoints of the audio class.
357  *
358  * This callback function is used to de-initialize the stream endpoints of the audio class.
359  *
360  * @param audioHandle          The device audio class handle. It equals the value returned from
361  * usb_device_class_config_struct_t::classHandle.
362  *
363  * @return A USB error code or kStatus_USB_Success.
364  */
USB_DeviceAudioStreamEndpointsDeinit(usb_device_audio_struct_t * audioHandle)365 usb_status_t USB_DeviceAudioStreamEndpointsDeinit(usb_device_audio_struct_t *audioHandle)
366 {
367     usb_status_t status = kStatus_USB_Error;
368     usb_device_endpoint_callback_message_struct_t message;
369     uint8_t count;
370 
371     if (NULL == audioHandle->streamInterfaceHandle)
372     {
373         return status;
374     }
375     /* De-initialize all stream endpoints of the interface */
376     for (count = 0U; count < audioHandle->streamInterfaceHandle->endpointList.count; count++)
377     {
378         status = USB_DeviceDeinitEndpoint(
379             audioHandle->handle, audioHandle->streamInterfaceHandle->endpointList.endpoint[count].endpointAddress);
380     }
381 
382     for (count = 0U; count < audioHandle->streamInterfaceHandle->endpointList.count; count++)
383     {
384         if ((audioHandle->streamInterfaceHandle->endpointList.endpoint[count].endpointAddress &
385              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
386                 USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT ==
387             USB_IN)
388         {
389             if (0U != audioHandle->streamInPipeBusy)
390             {
391                 message.length = USB_CANCELLED_TRANSFER_LENGTH;
392 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
393                 status = USB_DeviceAudioIsochronousIn(audioHandle->handle, &message, audioHandle);
394 #else
395                 (void)USB_DeviceAudioIsochronousIn(audioHandle->handle, &message, audioHandle);
396 #endif
397             }
398         }
399         else
400         {
401             if (0U != audioHandle->streamOutPipeBusy)
402             {
403                 message.length = USB_CANCELLED_TRANSFER_LENGTH;
404 #if (defined(USB_DEVICE_CONFIG_RETURN_VALUE_CHECK) && (USB_DEVICE_CONFIG_RETURN_VALUE_CHECK > 0U))
405                 status = USB_DeviceAudioIsochronousOut(audioHandle->handle, &message, audioHandle);
406 #else
407                 (void)USB_DeviceAudioIsochronousOut(audioHandle->handle, &message, audioHandle);
408 #endif
409             }
410         }
411     }
412 
413     audioHandle->streamInterfaceHandle = NULL;
414     return status;
415 }
416 
417 /*!
418  * @brief Initialize the control endpoints of the audio class.
419  *
420  * This callback function is used to initialize the control endpoints of the audio class.
421  *
422  * @param audioHandle          The device audio class handle. It equals the value returned from
423  * usb_device_class_config_struct_t::classHandle.
424  *
425  * @return A USB error code or kStatus_USB_Success.
426  */
USB_DeviceAudioControlEndpointsInit(usb_device_audio_struct_t * audioHandle)427 usb_status_t USB_DeviceAudioControlEndpointsInit(usb_device_audio_struct_t *audioHandle)
428 {
429     usb_device_interface_list_t *interfaceList;
430     usb_device_interface_struct_t *interface = (usb_device_interface_struct_t *)NULL;
431     usb_status_t status                      = kStatus_USB_Error;
432     uint8_t count;
433     uint8_t index;
434 
435     /* Check the configuration is valid or not. */
436     if (0U == audioHandle->configuration)
437     {
438         return status;
439     }
440 
441     /* Check the configuration is valid or not. */
442     if (audioHandle->configuration > audioHandle->configStruct->classInfomation->configurations)
443     {
444         return status;
445     }
446 
447     if (NULL == audioHandle->configStruct->classInfomation->interfaceList)
448     {
449         return status;
450     }
451 
452     /* Get the control interface list of the new configuration. */
453     interfaceList = &audioHandle->configStruct->classInfomation->interfaceList[audioHandle->configuration - 1U];
454 
455     /* Find control interface by using the alternate setting of the interface. */
456     for (count = 0U; count < interfaceList->count; count++)
457     {
458         if ((USB_DEVICE_CONFIG_AUDIO_CLASS_CODE == interfaceList->interfaces[count].classCode) &&
459             (USB_DEVICE_AUDIO_CONTROL_SUBCLASS == interfaceList->interfaces[count].subclassCode))
460         {
461             for (index = 0U; index < interfaceList->interfaces[count].count; index++)
462             {
463                 if (interfaceList->interfaces[count].interface[index].alternateSetting == audioHandle->controlAlternate)
464                 {
465                     interface = &interfaceList->interfaces[count].interface[index];
466                     break;
467                 }
468             }
469             audioHandle->controlInterfaceNumber = interfaceList->interfaces[count].interfaceNumber;
470             break;
471         }
472     }
473     if (NULL == interface)
474     {
475         return status;
476     }
477     /* Keep new control interface handle. */
478     audioHandle->controlInterfaceHandle = interface;
479 
480     /* Initialize the control endpoints of the new interface. */
481     for (count = 0U; count < interface->endpointList.count; count++)
482     {
483         usb_device_endpoint_init_struct_t epInitStruct;
484         usb_device_endpoint_callback_struct_t epCallback;
485         epInitStruct.zlt             = 0U;
486         epInitStruct.interval        = interface->endpointList.endpoint[count].interval;
487         epInitStruct.endpointAddress = interface->endpointList.endpoint[count].endpointAddress;
488         epInitStruct.maxPacketSize   = interface->endpointList.endpoint[count].maxPacketSize;
489         epInitStruct.transferType    = interface->endpointList.endpoint[count].transferType;
490 
491         if ((USB_ENDPOINT_INTERRUPT == (epInitStruct.transferType & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK)) &&
492             (USB_IN == ((epInitStruct.endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
493                         USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)))
494         {
495             epCallback.callbackFn = USB_DeviceAudioInterruptIn;
496         }
497         else
498         {
499             continue;
500         }
501         epCallback.callbackParam = audioHandle;
502 
503         status = USB_DeviceInitEndpoint(audioHandle->handle, &epInitStruct, &epCallback);
504     }
505     return status;
506 }
507 
508 /*!
509  * @brief De-initialize the control endpoints of the audio class.
510  *
511  * This callback function is used to de-initialize the control endpoints of the audio class.
512  *
513  * @param audioHandle          The device audio class handle. It equals the value returned from
514  * usb_device_class_config_struct_t::classHandle.
515  *
516  * @return A USB error code or kStatus_USB_Success.
517  */
USB_DeviceAudioControlEndpointsDeinit(usb_device_audio_struct_t * audioHandle)518 usb_status_t USB_DeviceAudioControlEndpointsDeinit(usb_device_audio_struct_t *audioHandle)
519 {
520     usb_status_t status = kStatus_USB_Error;
521     uint8_t count;
522 
523     if (NULL == audioHandle->controlInterfaceHandle)
524     {
525         return status;
526     }
527     /* De-initialize all control endpoints of the interface */
528     for (count = 0U; count < audioHandle->controlInterfaceHandle->endpointList.count; count++)
529     {
530         status = USB_DeviceDeinitEndpoint(
531             audioHandle->handle, audioHandle->controlInterfaceHandle->endpointList.endpoint[count].endpointAddress);
532     }
533     audioHandle->controlInterfaceHandle = NULL;
534     return status;
535 }
536 
537 /*!
538  * @brief Handle the audio device GET CUR control feature unit request.
539  *
540  * This callback function provides flexibility to add class and vendor specific requests
541  *
542  * @param audioHandle          The device audio class handle. It equals the value returned from
543  * usb_device_class_config_struct_t::classHandle.
544  * @param controlRequest       The pointer of the control request structure.
545  *
546  * @return A USB error code or kStatus_USB_Success.
547  */
USB_DeviceAudioGetCurAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)548 usb_status_t USB_DeviceAudioGetCurAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
549                                                    usb_device_control_request_struct_t *controlRequest)
550 {
551     usb_status_t status     = kStatus_USB_InvalidRequest;
552     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
553     uint32_t audioCommand   = 0U;
554 
555     /* Select GET CUR request Control Feature Unit Module */
556     switch (controlSelector)
557     {
558         case USB_DEVICE_AUDIO_FU_MUTE_CONTROL_SELECTOR:
559             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_MUTE_CONTROL;
560             break;
561         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
562             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_VOLUME_CONTROL;
563             break;
564         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
565             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_BASS_CONTROL;
566             break;
567         case USB_DEVICE_AUDIO_FU_MID_CONTROL_SELECTOR:
568             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_MID_CONTROL;
569             break;
570         case USB_DEVICE_AUDIO_FU_TREBLE_CONTROL_SELECTOR:
571             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_TREBLE_CONTROL;
572             break;
573         case USB_DEVICE_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL_SELECTOR:
574             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_GRAPHIC_EQUALIZER_CONTROL;
575             break;
576         case USB_DEVICE_AUDIO_FU_AUTOMATIC_GAIN_CONTROL_SELECTOR:
577             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_AUTOMATIC_GAIN_CONTROL;
578             break;
579         case USB_DEVICE_AUDIO_FU_DELAY_CONTROL_SELECTOR:
580             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_DELAY_CONTROL;
581             break;
582         case USB_DEVICE_AUDIO_FU_BASS_BOOST_CONTROL_SELECTOR:
583             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_BASS_BOOST_CONTROL;
584             break;
585         case USB_DEVICE_AUDIO_FU_LOUDNESS_CONTROL_SELECTOR:
586             audioCommand = USB_DEVICE_AUDIO_FU_GET_CUR_LOUDNESS_CONTROL;
587             break;
588         default:
589             /*no action*/
590             break;
591     }
592     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
593         (NULL != audioHandle->configStruct->classCallback))
594     {
595         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
596         it is from the second parameter of classInit */
597         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
598     }
599 
600     return status;
601 }
602 
603 /*!
604  * @brief Handle the audio device SET CUR control feature unit request.
605  *
606  * This callback function provides flexibility to add class and vendor specific requests
607  *
608  * @param audioHandle          The device audio class handle. It equals the value returned from
609  * usb_device_class_config_struct_t::classHandle.
610  * @param controlRequest       The pointer of the control request structure.
611  *
612  * @return A USB error code or kStatus_USB_Success.
613  */
USB_DeviceAudioSetCurAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)614 usb_status_t USB_DeviceAudioSetCurAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
615                                                    usb_device_control_request_struct_t *controlRequest)
616 {
617     usb_status_t status     = kStatus_USB_InvalidRequest;
618     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08U) & 0xFFU);
619     uint32_t audioCommand   = 0;
620 
621     /* Select SET CUR request Control Feature Unit Module */
622     switch (controlSelector)
623     {
624         case USB_DEVICE_AUDIO_FU_MUTE_CONTROL_SELECTOR:
625             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_MUTE_CONTROL;
626             break;
627         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
628             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_VOLUME_CONTROL;
629             break;
630         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
631             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_BASS_CONTROL;
632             break;
633         case USB_DEVICE_AUDIO_FU_MID_CONTROL_SELECTOR:
634             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_MID_CONTROL;
635             break;
636         case USB_DEVICE_AUDIO_FU_TREBLE_CONTROL_SELECTOR:
637             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_TREBLE_CONTROL;
638             break;
639         case USB_DEVICE_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL_SELECTOR:
640             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_GRAPHIC_EQUALIZER_CONTROL;
641             break;
642         case USB_DEVICE_AUDIO_FU_AUTOMATIC_GAIN_CONTROL_SELECTOR:
643             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_AUTOMATIC_GAIN_CONTROL;
644             break;
645         case USB_DEVICE_AUDIO_FU_DELAY_CONTROL_SELECTOR:
646             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_DELAY_CONTROL;
647             break;
648         case USB_DEVICE_AUDIO_FU_BASS_BOOST_CONTROL_SELECTOR:
649             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_BASS_BOOST_CONTROL;
650             break;
651         case USB_DEVICE_AUDIO_FU_LOUDNESS_CONTROL_SELECTOR:
652             audioCommand = USB_DEVICE_AUDIO_FU_SET_CUR_LOUDNESS_CONTROL;
653             break;
654         default:
655             /*no action*/
656             break;
657     }
658     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
659         (NULL != audioHandle->configStruct->classCallback))
660     {
661         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
662         it is from the second parameter of classInit */
663         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
664     }
665     return status;
666 }
667 
668 /*!
669  * @brief Handle the audio device GET feature unit request.
670  *
671  * This callback function provides flexibility to add class and vendor specific requests
672  *
673  * @param audioHandle          The device audio class handle. It equals the value returned from
674  * usb_device_class_config_struct_t::classHandle.
675  * @param controlRequest       The pointer of the control request structure.
676  *
677  * @return A USB error code or kStatus_USB_Success.
678  */
USB_DeviceAudioGetFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)679 usb_status_t USB_DeviceAudioGetFeatureUnit(usb_device_audio_struct_t *audioHandle,
680                                            usb_device_control_request_struct_t *controlRequest)
681 {
682     usb_status_t status = kStatus_USB_InvalidRequest;
683 
684     /* Select GET request Control Feature Unit Module */
685     switch (controlRequest->setup->bRequest)
686     {
687 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
688         case USB_DEVICE_AUDIO_CUR_REQUEST:
689             status = USB_DeviceAudioGetCurAudioFeatureUnit(audioHandle, controlRequest);
690             break;
691         case USB_DEVICE_AUDIO_RANGE_REQUEST:
692             status = USB_DeviceAudioGetRangeAudioFeatureUnit(audioHandle, controlRequest);
693             break;
694         default:
695             /*no action*/
696             break;
697 #else
698         case USB_DEVICE_AUDIO_GET_CUR_REQUEST:
699             status = USB_DeviceAudioGetCurAudioFeatureUnit(audioHandle, controlRequest);
700             break;
701         case USB_DEVICE_AUDIO_GET_MIN_REQUEST:
702             status = USB_DeviceAudioGetMinAudioFeatureUnit(audioHandle, controlRequest);
703             break;
704         case USB_DEVICE_AUDIO_GET_MAX_REQUEST:
705             status = USB_DeviceAudioGetMaxAudioFeatureUnit(audioHandle, controlRequest);
706             break;
707         case USB_DEVICE_AUDIO_GET_RES_REQUEST:
708             status = USB_DeviceAudioGetResAudioFeatureUnit(audioHandle, controlRequest);
709             break;
710         default:
711             /*no action*/
712             break;
713 #endif
714     }
715     return status;
716 }
717 
718 /*!
719  * @brief Handle the audio device SET feature unit request.
720  *
721  * This callback function provides flexibility to add class and vendor specific requests
722  *
723  * @param audioHandle          The device audio class handle. It equals the value returned from
724  * usb_device_class_config_struct_t::classHandle.
725  * @param controlRequest       The pointer of the control request structure.
726  *
727  * @return A USB error code or kStatus_USB_Success.
728  */
USB_DeviceAudioSetFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)729 usb_status_t USB_DeviceAudioSetFeatureUnit(usb_device_audio_struct_t *audioHandle,
730                                            usb_device_control_request_struct_t *controlRequest)
731 {
732     usb_status_t status = kStatus_USB_InvalidRequest;
733     /* Select SET request Control Feature Unit Module */
734     switch (controlRequest->setup->bRequest)
735     {
736 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
737         case USB_DEVICE_AUDIO_CUR_REQUEST:
738             status = USB_DeviceAudioSetCurAudioFeatureUnit(audioHandle, controlRequest);
739             break;
740         case USB_DEVICE_AUDIO_RANGE_REQUEST:
741             break;
742         default:
743             /*no action*/
744             break;
745 #else
746         case USB_DEVICE_AUDIO_SET_CUR_REQUEST:
747             status = USB_DeviceAudioSetCurAudioFeatureUnit(audioHandle, controlRequest);
748             break;
749         case USB_DEVICE_AUDIO_SET_MIN_REQUEST:
750             status = USB_DeviceAudioSetMinAudioFeatureUnit(audioHandle, controlRequest);
751             break;
752         case USB_DEVICE_AUDIO_SET_MAX_REQUEST:
753             status = USB_DeviceAudioSetMaxAudioFeatureUnit(audioHandle, controlRequest);
754             break;
755         case USB_DEVICE_AUDIO_SET_RES_REQUEST:
756             status = USB_DeviceAudioSetResAudioFeatureUnit(audioHandle, controlRequest);
757             break;
758         default:
759             /*no action*/
760             break;
761 #endif
762     }
763     return status;
764 }
765 
766 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
767 /*!
768  * @brief Handle the audio device GET RANGE control feature unit request.
769  *
770  * This callback function provides flexibility to add class and vendor specific requests
771  *
772  * @param audioHandle          The device audio class handle. It equals the value returned from
773  * usb_device_class_config_struct_t::classHandle.
774  * @param controlRequest       The pointer of the control request structure.
775  *
776  * @return A USB error code or kStatus_USB_Success.
777  */
USB_DeviceAudioGetRangeAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)778 usb_status_t USB_DeviceAudioGetRangeAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
779                                                      usb_device_control_request_struct_t *controlRequest)
780 {
781     usb_status_t status     = kStatus_USB_InvalidRequest;
782     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
783     uint32_t audioCommand   = 0U;
784 
785     /* Select GET RANGE request Control Feature Unit Module */
786     switch (controlSelector)
787     {
788         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
789             audioCommand = USB_DEVICE_AUDIO_FU_GET_RANGE_VOLUME_CONTROL;
790             break;
791         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
792             break;
793         default:
794             /*no action*/
795             break;
796     }
797 
798     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
799         (NULL != audioHandle->configStruct->classCallback))
800     {
801         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
802         it is from the second parameter of classInit */
803         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
804     }
805 
806     return status;
807 }
808 
809 /*!
810  * @brief Handle the audio device GET Clock Source control feature unit request.
811  *
812  * This callback function provides flexibility to add class and vendor specific requests
813  *
814  * @param audioHandle          The device audio class handle. It equals the value returned from
815  * usb_device_class_config_struct_t::classHandle.
816  * @param controlRequest       The pointer of the control request structure.
817  *
818  * @return A USB error code or kStatus_USB_Success.
819  */
USB_DeviceAudioGetClockSource(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)820 usb_status_t USB_DeviceAudioGetClockSource(usb_device_audio_struct_t *audioHandle,
821                                            usb_device_control_request_struct_t *controlRequest)
822 {
823     usb_status_t status     = kStatus_USB_InvalidRequest;
824     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
825     uint32_t audioCommand   = 0;
826     /* Select GET request Control Clock Source Module */
827     switch (controlRequest->setup->bRequest)
828     {
829         case USB_DEVICE_AUDIO_CUR_REQUEST:
830             switch (controlSelector)
831             {
832                 case USB_DEVICE_AUDIO_CS_SAM_FREQ_CONTROL_SELECTOR:
833                     audioCommand = USB_DEVICE_AUDIO_CS_GET_CUR_SAMPLING_FREQ_CONTROL;
834                     break;
835                 case USB_DEVICE_AUDIO_CS_CLOCK_VALID_CONTROL_SELECTOR:
836                     audioCommand = USB_DEVICE_AUDIO_CS_GET_CUR_CLOCK_VALID_CONTROL;
837                     break;
838                 default:
839                     /*no action*/
840                     break;
841             }
842             break;
843         case USB_DEVICE_AUDIO_RANGE_REQUEST:
844             switch (controlSelector)
845             {
846                 case USB_DEVICE_AUDIO_CS_SAM_FREQ_CONTROL_SELECTOR:
847                     audioCommand = USB_DEVICE_AUDIO_CS_GET_RANGE_SAMPLING_FREQ_CONTROL;
848                     break;
849                 default:
850                     /*no action*/
851                     break;
852             }
853             break;
854         default:
855             /*no action*/
856             break;
857     }
858 
859     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
860         (NULL != audioHandle->configStruct->classCallback))
861     {
862         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
863         it is from the second parameter of classInit */
864         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
865     }
866     return status;
867 }
868 
869 /*!
870  * @brief Handle the audio device SET Clock Source control feature unit request.
871  *
872  * This callback function provides flexibility to add class and vendor specific requests
873  *
874  * @param audioHandle          The device audio class handle. It equals the value returned from
875  * usb_device_class_config_struct_t::classHandle.
876  * @param controlRequest       The pointer of the control request structure.
877  *
878  * @return A USB error code or kStatus_USB_Success.
879  */
USB_DeviceAudioSetClockSource(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)880 usb_status_t USB_DeviceAudioSetClockSource(usb_device_audio_struct_t *audioHandle,
881                                            usb_device_control_request_struct_t *controlRequest)
882 {
883     usb_status_t status     = kStatus_USB_InvalidRequest;
884     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
885     uint32_t audioCommand   = 0;
886     /* Select SET request Control Clock Source Module */
887     switch (controlRequest->setup->bRequest)
888     {
889         case USB_DEVICE_AUDIO_CUR_REQUEST:
890             switch (controlSelector)
891             {
892                 case USB_DEVICE_AUDIO_CS_SAM_FREQ_CONTROL_SELECTOR:
893                     audioCommand = USB_DEVICE_AUDIO_CS_SET_CUR_SAMPLING_FREQ_CONTROL;
894                     break;
895                 case USB_DEVICE_AUDIO_CS_CLOCK_VALID_CONTROL_SELECTOR:
896                     audioCommand = USB_DEVICE_AUDIO_CS_SET_CUR_CLOCK_VALID_CONTROL;
897                     break;
898                 default:
899                     /*no action*/
900                     break;
901             }
902             break;
903         case USB_DEVICE_AUDIO_RANGE_REQUEST:
904             break;
905         default:
906             /*no action*/
907             break;
908     }
909     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
910         (NULL != audioHandle->configStruct->classCallback))
911     {
912         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
913         it is from the second parameter of classInit */
914         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
915     }
916     return status;
917 }
918 
919 #else
920 
921 /*!
922  * @brief Handle the audio device set minimum volume/control feature unit request.
923  *
924  * This callback function provides flexibility to add class and vendor specific requests
925  *
926  * @param audioHandle          The device audio class handle. It equals the value returned from
927  * usb_device_class_config_struct_t::classHandle.
928  * @param controlRequest       The pointer of the control request structure.
929  *
930  * @return A USB error code or kStatus_USB_Success.
931  */
USB_DeviceAudioSetMinAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)932 usb_status_t USB_DeviceAudioSetMinAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
933                                                    usb_device_control_request_struct_t *controlRequest)
934 {
935     usb_status_t status     = kStatus_USB_InvalidRequest;
936     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
937     uint32_t audioCommand   = 0U;
938 
939     /* Select SET MIN request Control Feature Unit Module */
940     switch (controlSelector)
941     {
942         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
943             audioCommand = USB_DEVICE_AUDIO_FU_SET_MIN_VOLUME_CONTROL;
944             break;
945         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
946             audioCommand = USB_DEVICE_AUDIO_FU_SET_MIN_BASS_CONTROL;
947             break;
948         case USB_DEVICE_AUDIO_FU_MID_CONTROL_SELECTOR:
949             audioCommand = USB_DEVICE_AUDIO_FU_SET_MIN_MID_CONTROL;
950             break;
951         case USB_DEVICE_AUDIO_FU_TREBLE_CONTROL_SELECTOR:
952             audioCommand = USB_DEVICE_AUDIO_FU_SET_MIN_TREBLE_CONTROL;
953             break;
954         case USB_DEVICE_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL_SELECTOR:
955             audioCommand = USB_DEVICE_AUDIO_FU_SET_MIN_GRAPHIC_EQUALIZER_CONTROL;
956             break;
957         case USB_DEVICE_AUDIO_FU_DELAY_CONTROL_SELECTOR:
958             audioCommand = USB_DEVICE_AUDIO_FU_SET_MIN_DELAY_CONTROL;
959             break;
960         default:
961             /*no action*/
962             break;
963     }
964     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
965         (NULL != audioHandle->configStruct->classCallback))
966     {
967         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
968         it is from the second parameter of classInit */
969         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
970     }
971 
972     return status;
973 }
974 
975 /*!
976  * @brief Handle the audio device maximum volume/control feature unit request.
977  *
978  * This callback function provides flexibility to add class and vendor specific requests
979  *
980  * @param audioHandle          The device audio class handle. It equals the value returned from
981  * usb_device_class_config_struct_t::classHandle.
982  * @param controlRequest       The pointer of the control request structure.
983  *
984  * @return A USB error code or kStatus_USB_Success.
985  */
USB_DeviceAudioSetMaxAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)986 usb_status_t USB_DeviceAudioSetMaxAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
987                                                    usb_device_control_request_struct_t *controlRequest)
988 {
989     usb_status_t status     = kStatus_USB_InvalidRequest;
990     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
991     uint32_t audioCommand   = 0;
992 
993     /* Select SET MAX request Control Feature Unit Module */
994     switch (controlSelector)
995     {
996         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
997             audioCommand = USB_DEVICE_AUDIO_FU_SET_MAX_VOLUME_CONTROL;
998             break;
999         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
1000             audioCommand = USB_DEVICE_AUDIO_FU_SET_MAX_BASS_CONTROL;
1001             break;
1002         case USB_DEVICE_AUDIO_FU_MID_CONTROL_SELECTOR:
1003             audioCommand = USB_DEVICE_AUDIO_FU_SET_MAX_MID_CONTROL;
1004             break;
1005         case USB_DEVICE_AUDIO_FU_TREBLE_CONTROL_SELECTOR:
1006             audioCommand = USB_DEVICE_AUDIO_FU_SET_MAX_TREBLE_CONTROL;
1007             break;
1008         case USB_DEVICE_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL_SELECTOR:
1009             audioCommand = USB_DEVICE_AUDIO_FU_SET_MAX_GRAPHIC_EQUALIZER_CONTROL;
1010             break;
1011         case USB_DEVICE_AUDIO_FU_DELAY_CONTROL_SELECTOR:
1012             audioCommand = USB_DEVICE_AUDIO_FU_SET_MAX_DELAY_CONTROL;
1013             break;
1014         default:
1015             /*no action*/
1016             break;
1017     }
1018     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1019         (NULL != audioHandle->configStruct->classCallback))
1020     {
1021         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1022         it is from the second parameter of classInit */
1023         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1024     }
1025 
1026     return status;
1027 }
1028 
1029 /*!
1030  * @brief Handle the audio device set res volume/control feature unit request.
1031  *
1032  * This callback function provides flexibility to add class and vendor specific requests
1033  *
1034  * @param audioHandle          The device audio class handle. It equals the value returned from
1035  * usb_device_class_config_struct_t::classHandle.
1036  * @param controlRequest       The pointer of the control request structure.
1037  *
1038  * @return A USB error code or kStatus_USB_Success.
1039  */
USB_DeviceAudioSetResAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)1040 usb_status_t USB_DeviceAudioSetResAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
1041                                                    usb_device_control_request_struct_t *controlRequest)
1042 {
1043     usb_status_t status     = kStatus_USB_InvalidRequest;
1044     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
1045     uint32_t audioCommand   = 0;
1046 
1047     /* Select SET RES request Control Feature Unit Module */
1048     switch (controlSelector)
1049     {
1050         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
1051             audioCommand = USB_DEVICE_AUDIO_FU_SET_RES_VOLUME_CONTROL;
1052             break;
1053         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
1054             audioCommand = USB_DEVICE_AUDIO_FU_SET_RES_BASS_CONTROL;
1055             break;
1056         case USB_DEVICE_AUDIO_FU_MID_CONTROL_SELECTOR:
1057             audioCommand = USB_DEVICE_AUDIO_FU_SET_RES_MID_CONTROL;
1058             break;
1059         case USB_DEVICE_AUDIO_FU_TREBLE_CONTROL_SELECTOR:
1060             audioCommand = USB_DEVICE_AUDIO_FU_SET_RES_TREBLE_CONTROL;
1061             break;
1062         case USB_DEVICE_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL_SELECTOR:
1063             audioCommand = USB_DEVICE_AUDIO_FU_SET_RES_GRAPHIC_EQUALIZER_CONTROL;
1064             break;
1065         case USB_DEVICE_AUDIO_FU_DELAY_CONTROL_SELECTOR:
1066             audioCommand = USB_DEVICE_AUDIO_FU_SET_RES_DELAY_CONTROL;
1067             break;
1068         default:
1069             /*no action*/
1070             break;
1071     }
1072     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1073         (NULL != audioHandle->configStruct->classCallback))
1074     {
1075         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1076         it is from the second parameter of classInit */
1077         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1078     }
1079     return status;
1080 }
1081 
1082 /*!
1083  * @brief Handle the audio device GET MIN control feature unit request.
1084  *
1085  * This callback function provides flexibility to add class and vendor specific requests
1086  *
1087  * @param audioHandle          The device audio class handle. It equals the value returned from
1088  * usb_device_class_config_struct_t::classHandle.
1089  * @param controlRequest       The pointer of the control request structure.
1090  *
1091  * @return A USB error code or kStatus_USB_Success.
1092  */
USB_DeviceAudioGetMinAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)1093 usb_status_t USB_DeviceAudioGetMinAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
1094                                                    usb_device_control_request_struct_t *controlRequest)
1095 {
1096     usb_status_t status     = kStatus_USB_InvalidRequest;
1097     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
1098     uint32_t audioCommand   = 0U;
1099 
1100     /* Select GET MIN request Control Feature Unit Module */
1101     switch (controlSelector)
1102     {
1103         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
1104             audioCommand = USB_DEVICE_AUDIO_FU_GET_MIN_VOLUME_CONTROL;
1105             break;
1106         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
1107             audioCommand = USB_DEVICE_AUDIO_FU_GET_MIN_BASS_CONTROL;
1108             break;
1109         case USB_DEVICE_AUDIO_FU_MID_CONTROL_SELECTOR:
1110             audioCommand = USB_DEVICE_AUDIO_FU_GET_MIN_MID_CONTROL;
1111             break;
1112         case USB_DEVICE_AUDIO_FU_TREBLE_CONTROL_SELECTOR:
1113             audioCommand = USB_DEVICE_AUDIO_FU_GET_MIN_TREBLE_CONTROL;
1114             break;
1115         case USB_DEVICE_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL_SELECTOR:
1116             audioCommand = USB_DEVICE_AUDIO_FU_GET_MIN_GRAPHIC_EQUALIZER_CONTROL;
1117             break;
1118         case USB_DEVICE_AUDIO_FU_DELAY_CONTROL_SELECTOR:
1119             audioCommand = USB_DEVICE_AUDIO_FU_GET_MIN_DELAY_CONTROL;
1120             break;
1121         default:
1122             /* no action*/
1123             break;
1124     }
1125     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1126         (NULL != audioHandle->configStruct->classCallback))
1127     {
1128         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1129         it is from the second parameter of classInit */
1130         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1131     }
1132     return status;
1133 }
1134 
1135 /*!
1136  * @brief Handle the audio device GET MAX control feature unit request.
1137  *
1138  * This callback function provides flexibility to add class and vendor specific requests
1139  *
1140  * @param audioHandle          The device audio class handle. It equals the value returned from
1141  * usb_device_class_config_struct_t::classHandle.
1142  * @param controlRequest       The pointer of the control request structure.
1143  *
1144  * @return A USB error code or kStatus_USB_Success.
1145  */
USB_DeviceAudioGetMaxAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)1146 usb_status_t USB_DeviceAudioGetMaxAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
1147                                                    usb_device_control_request_struct_t *controlRequest)
1148 {
1149     usb_status_t status     = kStatus_USB_InvalidRequest;
1150     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
1151     uint32_t audioCommand   = 0U;
1152 
1153     /* Select GET MAX request Control Feature Unit Module */
1154     switch (controlSelector)
1155     {
1156         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
1157             audioCommand = USB_DEVICE_AUDIO_FU_GET_MAX_VOLUME_CONTROL;
1158             break;
1159         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
1160             audioCommand = USB_DEVICE_AUDIO_FU_GET_MAX_BASS_CONTROL;
1161             break;
1162         case USB_DEVICE_AUDIO_FU_MID_CONTROL_SELECTOR:
1163             audioCommand = USB_DEVICE_AUDIO_FU_GET_MAX_MID_CONTROL;
1164             break;
1165         case USB_DEVICE_AUDIO_FU_TREBLE_CONTROL_SELECTOR:
1166             audioCommand = USB_DEVICE_AUDIO_FU_GET_MAX_TREBLE_CONTROL;
1167             break;
1168         case USB_DEVICE_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL_SELECTOR:
1169             audioCommand = USB_DEVICE_AUDIO_FU_GET_MAX_GRAPHIC_EQUALIZER_CONTROL;
1170             break;
1171         case USB_DEVICE_AUDIO_FU_DELAY_CONTROL_SELECTOR:
1172             audioCommand = USB_DEVICE_AUDIO_FU_GET_MAX_DELAY_CONTROL;
1173             break;
1174         default:
1175             /*no action*/
1176             break;
1177     }
1178     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1179         (NULL != audioHandle->configStruct->classCallback))
1180     {
1181         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1182         it is from the second parameter of classInit */
1183         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1184     }
1185     return status;
1186 }
1187 
1188 /*!
1189  * @brief Handle the audio device GET RES control feature unit request.
1190  *
1191  * This callback function provides flexibility to add class and vendor specific requests
1192  *
1193  * @param audioHandle          The device audio class handle. It equals the value returned from
1194  * usb_device_class_config_struct_t::classHandle.
1195  * @param controlRequest       The pointer of the control request structure.
1196  *
1197  * @return A USB error code or kStatus_USB_Success.
1198  */
USB_DeviceAudioGetResAudioFeatureUnit(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)1199 usb_status_t USB_DeviceAudioGetResAudioFeatureUnit(usb_device_audio_struct_t *audioHandle,
1200                                                    usb_device_control_request_struct_t *controlRequest)
1201 {
1202     usb_status_t status     = kStatus_USB_InvalidRequest;
1203     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
1204     uint32_t audioCommand   = 0U;
1205 
1206     /* Select GET RES request Control Feature Unit Module */
1207     switch (controlSelector)
1208     {
1209         case USB_DEVICE_AUDIO_FU_VOLUME_CONTROL_SELECTOR:
1210             audioCommand = USB_DEVICE_AUDIO_FU_GET_RES_VOLUME_CONTROL;
1211             break;
1212         case USB_DEVICE_AUDIO_FU_BASS_CONTROL_SELECTOR:
1213             audioCommand = USB_DEVICE_AUDIO_FU_GET_RES_BASS_CONTROL;
1214             break;
1215         case USB_DEVICE_AUDIO_FU_MID_CONTROL_SELECTOR:
1216             audioCommand = USB_DEVICE_AUDIO_FU_GET_RES_MID_CONTROL;
1217             break;
1218         case USB_DEVICE_AUDIO_FU_TREBLE_CONTROL_SELECTOR:
1219             audioCommand = USB_DEVICE_AUDIO_FU_GET_RES_TREBLE_CONTROL;
1220             break;
1221         case USB_DEVICE_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL_SELECTOR:
1222             audioCommand = USB_DEVICE_AUDIO_FU_GET_RES_GRAPHIC_EQUALIZER_CONTROL;
1223             break;
1224         case USB_DEVICE_AUDIO_FU_DELAY_CONTROL_SELECTOR:
1225             audioCommand = USB_DEVICE_AUDIO_FU_GET_RES_DELAY_CONTROL;
1226             break;
1227         default:
1228             /*no action*/
1229             break;
1230     }
1231     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1232         (NULL != audioHandle->configStruct->classCallback))
1233     {
1234         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1235            it is from the second parameter of classInit*/
1236         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1237     }
1238 
1239     return status;
1240 }
1241 #endif /* !USB_DEVICE_CONFIG_AUDIO_CLASS_2_0 */
1242 
1243 /*!
1244  * @brief Handle the audio device SET request endpoint.
1245  *
1246  * This callback function provides flexibility to add class and vendor specific requests
1247  *
1248  * @param audioHandle          The device audio class handle. It equals the value returned from
1249  * usb_device_class_config_struct_t::classHandle.
1250  * @param controlRequest       The pointer of the control request structure.
1251  *
1252  * @return A USB error code or kStatus_USB_Success.
1253  */
USB_DeviceAudioSetRequestEndpoint(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)1254 usb_status_t USB_DeviceAudioSetRequestEndpoint(usb_device_audio_struct_t *audioHandle,
1255                                                usb_device_control_request_struct_t *controlRequest)
1256 {
1257     usb_status_t status     = kStatus_USB_InvalidRequest;
1258     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
1259     uint32_t audioCommand   = 0;
1260 
1261     /* Select SET request Control for endpoint */
1262     switch (controlRequest->setup->bRequest)
1263     {
1264 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
1265         case USB_DEVICE_AUDIO_CUR_REQUEST:
1266             switch (controlSelector)
1267             {
1268                 case USB_DEVICE_AUDIO_EP_PITCH_CONTROL_SELECTOR_AUDIO20:
1269                     audioCommand = USB_DEVICE_AUDIO_EP_SET_CUR_PITCH_CONTROL_AUDIO20;
1270                     break;
1271                 default:
1272                     /*no action*/
1273                     break;
1274             }
1275             break;
1276         default:
1277             /*no action*/
1278             break;
1279 #else
1280         case USB_DEVICE_AUDIO_SET_CUR_REQUEST:
1281             switch (controlSelector)
1282             {
1283                 case USB_DEVICE_AUDIO_EP_SAMPLING_FREQ_CONTROL_SELECTOR:
1284                     audioCommand = USB_DEVICE_AUDIO_EP_SET_CUR_SAMPLING_FREQ_CONTROL;
1285                     break;
1286                 case USB_DEVICE_AUDIO_EP_PITCH_CONTROL_SELECTOR:
1287                     audioCommand = USB_DEVICE_AUDIO_EP_SET_CUR_PITCH_CONTROL;
1288                     break;
1289                 default:
1290                     /*no action*/
1291                     break;
1292             }
1293             break;
1294         case USB_DEVICE_AUDIO_SET_MIN_REQUEST:
1295             switch (controlSelector)
1296             {
1297                 case USB_DEVICE_AUDIO_EP_SAMPLING_FREQ_CONTROL_SELECTOR:
1298                     audioCommand = USB_DEVICE_AUDIO_EP_SET_MIN_SAMPLING_FREQ_CONTROL;
1299                     break;
1300                 default:
1301                     /*no action*/
1302                     break;
1303             }
1304             break;
1305         case USB_DEVICE_AUDIO_SET_MAX_REQUEST:
1306             switch (controlSelector)
1307             {
1308                 case USB_DEVICE_AUDIO_EP_SAMPLING_FREQ_CONTROL_SELECTOR:
1309                     audioCommand = USB_DEVICE_AUDIO_EP_SET_MAX_SAMPLING_FREQ_CONTROL;
1310                     break;
1311                 default:
1312                     /*no action*/
1313                     break;
1314             }
1315             break;
1316         case USB_DEVICE_AUDIO_SET_RES_REQUEST:
1317             switch (controlSelector)
1318             {
1319                 case USB_DEVICE_AUDIO_EP_SAMPLING_FREQ_CONTROL_SELECTOR:
1320                     audioCommand = USB_DEVICE_AUDIO_EP_SET_RES_SAMPLING_FREQ_CONTROL;
1321                     break;
1322                 default:
1323                     /*no action*/
1324                     break;
1325             }
1326             break;
1327 
1328         default:
1329             /*no action*/
1330             break;
1331 #endif /* USB_DEVICE_CONFIG_AUDIO_CLASS_2_0 */
1332     }
1333     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1334         (NULL != audioHandle->configStruct->classCallback))
1335     {
1336         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1337         it is from the second parameter of classInit */
1338         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1339     }
1340     return status;
1341 }
1342 
1343 /*!
1344  * @brief Handle the audio device GET request endpoint.
1345  *
1346  * This callback function provides flexibility to add class and vendor specific requests
1347  *
1348  * @param audioHandle          The device audio class handle. It equals the value returned from
1349  * usb_device_class_config_struct_t::classHandle.
1350  * @param controlRequest       The pointer of the control request structure.
1351  *
1352  * @return A USB error code or kStatus_USB_Success.
1353  */
USB_DeviceAudioGetRequestEndpoint(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)1354 usb_status_t USB_DeviceAudioGetRequestEndpoint(usb_device_audio_struct_t *audioHandle,
1355                                                usb_device_control_request_struct_t *controlRequest)
1356 {
1357     usb_status_t status     = kStatus_USB_InvalidRequest;
1358     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
1359     uint32_t audioCommand   = 0;
1360     /* Select GET request Control for endpoint */
1361     switch (controlRequest->setup->bRequest)
1362     {
1363 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
1364         case USB_DEVICE_AUDIO_CUR_REQUEST:
1365             switch (controlSelector)
1366             {
1367                 case USB_DEVICE_AUDIO_EP_DATA_OVERRUN_CONTROL_SELECTOR:
1368                     audioCommand = USB_DEVICE_AUDIO_EP_GET_CUR_DATA_OVERRUN_CONTROL;
1369                     break;
1370                 case USB_DEVICE_AUDIO_EP_DATA_UNDERRUN_CONTROL_SELECTOR:
1371                     audioCommand = USB_DEVICE_AUDIO_EP_GET_CUR_DATA_UNDERRUN_CONTROL;
1372                     break;
1373                 default:
1374                     /*no action*/
1375                     break;
1376             }
1377             break;
1378         default:
1379             /*no action*/
1380             break;
1381 #else
1382         case USB_DEVICE_AUDIO_GET_CUR_REQUEST:
1383             switch (controlSelector)
1384             {
1385                 case USB_DEVICE_AUDIO_EP_SAMPLING_FREQ_CONTROL_SELECTOR:
1386                     audioCommand = USB_DEVICE_AUDIO_EP_GET_CUR_SAMPLING_FREQ_CONTROL;
1387                     break;
1388                 default:
1389                     /*no action*/
1390                     break;
1391             }
1392             break;
1393         case USB_DEVICE_AUDIO_GET_MIN_REQUEST:
1394             switch (controlSelector)
1395             {
1396                 case USB_DEVICE_AUDIO_EP_SAMPLING_FREQ_CONTROL_SELECTOR:
1397                     audioCommand = USB_DEVICE_AUDIO_EP_GET_MIN_SAMPLING_FREQ_CONTROL;
1398                     break;
1399                 default:
1400                     /*no action*/
1401                     break;
1402             }
1403             break;
1404         case USB_DEVICE_AUDIO_GET_MAX_REQUEST:
1405             switch (controlSelector)
1406             {
1407                 case USB_DEVICE_AUDIO_EP_SAMPLING_FREQ_CONTROL_SELECTOR:
1408 
1409                     audioCommand = USB_DEVICE_AUDIO_EP_GET_MAX_SAMPLING_FREQ_CONTROL;
1410                     break;
1411                 default:
1412                     /*no action*/
1413                     break;
1414             }
1415             break;
1416         case USB_DEVICE_AUDIO_GET_RES_REQUEST:
1417             switch (controlSelector)
1418             {
1419                 case USB_DEVICE_AUDIO_EP_SAMPLING_FREQ_CONTROL_SELECTOR:
1420                     audioCommand = USB_DEVICE_AUDIO_EP_GET_RES_SAMPLING_FREQ_CONTROL;
1421 
1422                     break;
1423                 default:
1424                     /*no action*/
1425                     break;
1426             }
1427             break;
1428         default:
1429             /*no action*/
1430             break;
1431 #endif
1432     }
1433     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1434         (NULL != audioHandle->configStruct->classCallback))
1435     {
1436         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1437         it is from the second parameter of classInit */
1438         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1439     }
1440     return status;
1441 }
1442 
1443 /*!
1444  * @brief Handle the audio device GET control terminal request.
1445  *
1446  * This callback function provides flexibility to add class and vendor specific requests
1447  *
1448  * @param audioHandle          The device audio class handle. It equals the value returned from
1449  * usb_device_class_config_struct_t::classHandle.
1450  * @param controlRequest       The pointer of the control request structure.
1451  *
1452  * @return A USB error code or kStatus_USB_Success.
1453  */
USB_DeviceAudioGetControlTerminal(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest,uint8_t terminal_type)1454 usb_status_t USB_DeviceAudioGetControlTerminal(usb_device_audio_struct_t *audioHandle,
1455                                                usb_device_control_request_struct_t *controlRequest,
1456                                                uint8_t terminal_type)
1457 {
1458     usb_status_t status     = kStatus_USB_InvalidRequest;
1459     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
1460     uint32_t audioCommand   = 0;
1461     /* Select GET request Control for endpoint */
1462     switch (controlRequest->setup->bRequest)
1463     {
1464 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
1465         case USB_DEVICE_AUDIO_CUR_REQUEST:
1466             switch (controlSelector)
1467             {
1468                 case USB_DEVICE_AUDIO_TE_COPY_PROTECT_CONTROL:
1469                     if (USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_INPUT_TERMINAL == terminal_type)
1470                     {
1471                         audioCommand = USB_DEVICE_AUDIO_TE_GET_CUR_COPY_PROTECT_CONTROL;
1472                     }
1473                     else
1474                     {
1475                         /* Input Terminals only support the Get Terminal Copy Protect Control request */
1476                     }
1477                     break;
1478                 case USB_DEVICE_AUDIO_TE_CONNECTOR_CONTROL:
1479                     audioCommand = USB_DEVICE_AUDIO_TE_GET_CUR_CONNECTOR_CONTROL;
1480                     break;
1481                 case USB_DEVICE_AUDIO_TE_OVERLOAD_CONTROL:
1482                     audioCommand = USB_DEVICE_AUDIO_TE_GET_CUR_OVERLOAD_CONTROL;
1483                     break;
1484                 default:
1485                     /*no action*/
1486                     break;
1487             }
1488             break;
1489         default:
1490             /*no action*/
1491             break;
1492 #else
1493         case USB_DEVICE_AUDIO_GET_CUR_REQUEST:
1494             switch (controlSelector)
1495             {
1496                 case USB_DEVICE_AUDIO_TE_COPY_PROTECT_CONTROL:
1497                     if (USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_INPUT_TERMINAL == terminal_type)
1498                     {
1499                         audioCommand = USB_DEVICE_AUDIO_TE_GET_CUR_COPY_PROTECT_CONTROL;
1500                     }
1501                     else
1502                     {
1503                         /* Input Terminals only support the Get Terminal Copy Protect Control request */
1504                     }
1505                     break;
1506                 default:
1507                     /*no action*/
1508                     break;
1509             }
1510             break;
1511         default:
1512             /*no action*/
1513             break;
1514 #endif
1515     }
1516 
1517     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1518         (NULL != audioHandle->configStruct->classCallback))
1519     {
1520         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1521         it is from the second parameter of classInit */
1522         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1523     }
1524 
1525     return status;
1526 }
1527 
1528 /*!
1529  * @brief Handle the audio device SET control terminal request.
1530  *
1531  * This callback function provides flexibility to add class and vendor specific requests
1532  *
1533  * @param audioHandle          The device audio class handle. It equals the value returned from
1534  * usb_device_class_config_struct_t::classHandle.
1535  * @param controlRequest       The pointer of the control request structure.
1536  * @param terminal_type        The terminal type:: input terminal or output terminal
1537  *
1538  * @return A USB error code, kStatus_USB_Success or kStatus_USB_InvalidRequest.
1539  */
USB_DeviceAudioSetControlTerminal(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest,uint8_t terminal_type)1540 usb_status_t USB_DeviceAudioSetControlTerminal(usb_device_audio_struct_t *audioHandle,
1541                                                usb_device_control_request_struct_t *controlRequest,
1542                                                uint8_t terminal_type)
1543 {
1544     usb_status_t status     = kStatus_USB_InvalidRequest;
1545     uint8_t controlSelector = (uint8_t)((controlRequest->setup->wValue >> 0x08) & 0xFFU);
1546     uint32_t audioCommand   = 0;
1547     /* Select GET request Control for endpoint */
1548     switch (controlRequest->setup->bRequest)
1549     {
1550 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
1551         case USB_DEVICE_AUDIO_CUR_REQUEST:
1552             switch (controlSelector)
1553             {
1554                 case USB_DEVICE_AUDIO_TE_COPY_PROTECT_CONTROL:
1555                     if (USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_OUTPUT_TERMINAL == terminal_type)
1556                     {
1557                         audioCommand = USB_DEVICE_AUDIO_TE_SET_CUR_COPY_PROTECT_CONTROL;
1558                     }
1559                     else
1560                     {
1561                         /* Output Terminals only support the Set Terminal Copy Protect Control request */
1562                     }
1563                     break;
1564                 default:
1565                     /*no action*/
1566                     break;
1567             }
1568             break;
1569         default:
1570             /*no action*/
1571             break;
1572 #else
1573         case USB_DEVICE_AUDIO_SET_CUR_REQUEST:
1574             switch (controlSelector)
1575             {
1576                 case USB_DEVICE_AUDIO_TE_COPY_PROTECT_CONTROL:
1577                     if (USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_OUTPUT_TERMINAL == terminal_type)
1578                     {
1579                         audioCommand = USB_DEVICE_AUDIO_TE_SET_CUR_COPY_PROTECT_CONTROL;
1580                     }
1581                     else
1582                     {
1583                         /* Output Terminals only support the Set Terminal Copy Protect Control request */
1584                     }
1585                     break;
1586                 default:
1587                     /*no action*/
1588                     break;
1589             }
1590             break;
1591         default:
1592             /*no action*/
1593             break;
1594 #endif
1595     }
1596 
1597     if ((0U != audioCommand) && (NULL != audioHandle->configStruct) &&
1598         (NULL != audioHandle->configStruct->classCallback))
1599     {
1600         /* classCallback is initialized in classInit of s_UsbDeviceClassInterfaceMap,
1601         it is from the second parameter of classInit */
1602         status = audioHandle->configStruct->classCallback((class_handle_t)audioHandle, audioCommand, controlRequest);
1603     }
1604 
1605     return status;
1606 }
1607 
1608 /*!
1609  * @brief Handle the audio device set request interface.
1610  *
1611  * This callback function provides flexibility to add class and vendor specific requests
1612  *
1613  * @param audioHandle          The device audio class handle. It equals the value returned from
1614  * usb_device_class_config_struct_t::classHandle.
1615  * @param controlRequest       The pointer of the control request structure.
1616  *
1617  * @return A USB error code or kStatus_USB_Success.
1618  */
USB_DeviceAudioSetRequestInterface(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)1619 usb_status_t USB_DeviceAudioSetRequestInterface(usb_device_audio_struct_t *audioHandle,
1620                                                 usb_device_control_request_struct_t *controlRequest)
1621 {
1622     uint32_t i;
1623     usb_device_audio_entities_struct_t *entity_list;
1624     usb_status_t status = kStatus_USB_Error;
1625     uint8_t entityId    = (uint8_t)(controlRequest->setup->wIndex >> 0x08);
1626 
1627     entity_list = (usb_device_audio_entities_struct_t *)audioHandle->controlInterfaceHandle->classSpecific;
1628     for (i = 0; i < entity_list->count; i++)
1629     {
1630         if (entityId == entity_list->entity[i].entityId)
1631         {
1632             switch (entity_list->entity[i].entityType)
1633             {
1634                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_OUTPUT_TERMINAL:
1635                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_INPUT_TERMINAL:
1636                     /*Select SET Request Control Input Terminal Module */
1637                     status = USB_DeviceAudioSetControlTerminal(audioHandle, controlRequest,
1638                                                                entity_list->entity[i].entityType);
1639                     break;
1640                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_FEATURE_UNIT:
1641                     /* Select SET request Control Feature Unit Module */
1642                     status = USB_DeviceAudioSetFeatureUnit(audioHandle, controlRequest);
1643                     break;
1644 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
1645                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_CLOCK_SOURCE_UNIT:
1646                     /* Select SET request Control Clock Source Module */
1647                     status = USB_DeviceAudioSetClockSource(audioHandle, controlRequest);
1648                     break;
1649                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_CLOCK_SELECTOR_UNIT:
1650                     /* Select SET request Control Clock Selector Module */
1651                     status = kStatus_USB_InvalidRequest;
1652                     break;
1653                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_CLOCK_MULTIPLIER_UNIT:
1654                     /* Select SET request Control Clock multiplier Module */
1655                     status = kStatus_USB_InvalidRequest;
1656                     break;
1657 #endif
1658                 default:
1659                     status = kStatus_USB_InvalidRequest;
1660                     break;
1661             }
1662         }
1663     }
1664     return status;
1665 }
1666 
1667 /*!
1668  * @brief Handle the audio device get request interface.
1669  *
1670  * This callback function provides flexibility to add class and vendor specific requests
1671  *
1672  * @param audioHandle          The device audio class handle. It equals the value returned from
1673  * usb_device_class_config_struct_t::classHandle.
1674  * @param controlRequest       The pointer of the control request structure.
1675  *
1676  * @return A USB error code or kStatus_USB_Success.
1677  */
USB_DeviceAudioGetRequestInterface(usb_device_audio_struct_t * audioHandle,usb_device_control_request_struct_t * controlRequest)1678 usb_status_t USB_DeviceAudioGetRequestInterface(usb_device_audio_struct_t *audioHandle,
1679                                                 usb_device_control_request_struct_t *controlRequest)
1680 {
1681     uint32_t i;
1682     usb_device_audio_entities_struct_t *entity_list;
1683     usb_status_t status = kStatus_USB_Error;
1684     uint8_t entityId    = (uint8_t)(controlRequest->setup->wIndex >> 0x08);
1685 
1686     entity_list = (usb_device_audio_entities_struct_t *)audioHandle->controlInterfaceHandle->classSpecific;
1687     for (i = 0; i < entity_list->count; i++)
1688     {
1689         if (entityId == entity_list->entity[i].entityId)
1690         {
1691             switch (entity_list->entity[i].entityType)
1692             {
1693                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_INPUT_TERMINAL:
1694                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_OUTPUT_TERMINAL:
1695                     status = USB_DeviceAudioGetControlTerminal(audioHandle, controlRequest,
1696                                                                entity_list->entity[i].entityType);
1697                     break;
1698                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_FEATURE_UNIT:
1699                     status = USB_DeviceAudioGetFeatureUnit(audioHandle, controlRequest);
1700                     break;
1701 #if (USB_DEVICE_CONFIG_AUDIO_CLASS_2_0)
1702                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_CLOCK_SOURCE_UNIT:
1703                     /* Select SET request Control Clock Source Module */
1704                     status = USB_DeviceAudioGetClockSource(audioHandle, controlRequest);
1705                     break;
1706                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_CLOCK_SELECTOR_UNIT:
1707                     /* Select SET request Control Clock Select Module */
1708                     status = kStatus_USB_InvalidRequest;
1709                     break;
1710                 case USB_DESCRIPTOR_SUBTYPE_AUDIO_CONTROL_CLOCK_MULTIPLIER_UNIT:
1711                     /* Select SET request Control Clock Multiplier Module */
1712                     status = kStatus_USB_InvalidRequest;
1713                     break;
1714 #endif
1715                 default:
1716                     status = kStatus_USB_InvalidRequest;
1717                     break;
1718             }
1719         }
1720     }
1721     return status;
1722 }
1723 
1724 /*!
1725  * @brief Handle the event passed to the audio class.
1726  *
1727  * This function handles the event passed to the audio class.
1728  *
1729  * @param handle          The audio class handle, got from the usb_device_class_config_struct_t::classHandle.
1730  * @param event           The event codes. Please refer to the enumeration usb_device_class_event_t.
1731  * @param param           The param type is determined by the event code.
1732  *
1733  * @return A USB error code or kStatus_USB_Success.
1734  * @retval kStatus_USB_Success              Free device handle successfully.
1735  * @retval kStatus_USB_InvalidParameter     The device handle not be found.
1736  * @retval kStatus_USB_InvalidRequest       The request is invalid, and the control pipe will be stalled by the caller.
1737  */
USB_DeviceAudioEvent(void * handle,uint32_t event,void * param)1738 usb_status_t USB_DeviceAudioEvent(void *handle, uint32_t event, void *param)
1739 {
1740     usb_device_audio_struct_t *audioHandle;
1741     usb_status_t error = kStatus_USB_Error;
1742     uint16_t interfaceAlternate;
1743     uint8_t *temp8;
1744     uint8_t alternate;
1745     uint32_t count;
1746     usb_device_class_event_t eventCode = (usb_device_class_event_t)event;
1747     if ((NULL == param) || (NULL == handle))
1748     {
1749         return kStatus_USB_InvalidHandle;
1750     }
1751 
1752     /* Get the audio class handle. */
1753     audioHandle = (usb_device_audio_struct_t *)handle;
1754 
1755     switch (eventCode)
1756     {
1757         case kUSB_DeviceClassEventDeviceReset:
1758             /* Bus reset, clear the configuration. */
1759             audioHandle->configuration     = 0U;
1760             audioHandle->streamOutPipeBusy = 0U;
1761             audioHandle->streamInPipeBusy  = 0U;
1762             error                          = kStatus_USB_Success;
1763             break;
1764         case kUSB_DeviceClassEventSetConfiguration:
1765             /* Get the new configuration. */
1766             temp8 = ((uint8_t *)param);
1767             if (NULL == audioHandle->configStruct)
1768             {
1769                 break;
1770             }
1771             if (*temp8 == audioHandle->configuration)
1772             {
1773                 error = kStatus_USB_Success;
1774                 break;
1775             }
1776             /* De-initialize the endpoints when current configuration is none zero. */
1777             if (0U != audioHandle->configuration)
1778             {
1779                 error = USB_DeviceAudioControlEndpointsDeinit(audioHandle);
1780                 error = USB_DeviceAudioStreamEndpointsDeinit(audioHandle);
1781             }
1782             /* Save new configuration. */
1783             audioHandle->configuration = *temp8;
1784             /* Clear the alternate setting value. */
1785             audioHandle->controlAlternate = 0U;
1786             /* Clear the alternate setting value. */
1787             audioHandle->streamAlternate        = 0U;
1788             audioHandle->controlInterfaceHandle = NULL;
1789             audioHandle->streamInterfaceHandle  = NULL;
1790             /* Initialize the control endpoints of the new current configuration by using the alternate setting 0. */
1791             error = USB_DeviceAudioControlEndpointsInit(audioHandle);
1792             /* Initialize the stream endpoints of the new current configuration by using the alternate setting 0. */
1793             error = USB_DeviceAudioStreamEndpointsInit(audioHandle);
1794             break;
1795         case kUSB_DeviceClassEventSetInterface:
1796             if (NULL == audioHandle->configStruct)
1797             {
1798                 break;
1799             }
1800             /* Get the new alternate setting of the interface */
1801             interfaceAlternate = *((uint16_t *)param);
1802             /* Get the alternate setting value */
1803             alternate = (uint8_t)(interfaceAlternate & 0xFFU);
1804 
1805             /* Whether the interface belongs to the class. */
1806             if (audioHandle->controlInterfaceNumber == ((uint8_t)(interfaceAlternate >> 8U)))
1807             {
1808                 /* When the interface is control interface. */
1809                 /* Only handle new alternate setting. */
1810                 if (alternate == audioHandle->controlAlternate)
1811                 {
1812                     error = kStatus_USB_Success;
1813                     break;
1814                 }
1815                 /* De-initialize old endpoints */
1816                 error                         = USB_DeviceAudioControlEndpointsDeinit(audioHandle);
1817                 audioHandle->controlAlternate = alternate;
1818                 /* Initialize new endpoints */
1819                 error = USB_DeviceAudioControlEndpointsInit(audioHandle);
1820             }
1821             else if (audioHandle->streamInterfaceNumber == ((uint8_t)(interfaceAlternate >> 8U)))
1822             {
1823                 /* When the interface is stream interface. */
1824                 /* Only handle new alternate setting. */
1825                 if (alternate == audioHandle->streamAlternate)
1826                 {
1827                     error = kStatus_USB_Success;
1828                     break;
1829                 }
1830                 /* De-initialize old endpoints */
1831                 error                        = USB_DeviceAudioStreamEndpointsDeinit(audioHandle);
1832                 audioHandle->streamAlternate = alternate;
1833                 /* Initialize new endpoints */
1834                 error = USB_DeviceAudioStreamEndpointsInit(audioHandle);
1835             }
1836             else
1837             {
1838                 /*no action*/
1839             }
1840             break;
1841         case kUSB_DeviceClassEventSetEndpointHalt:
1842             if (NULL == audioHandle->configStruct)
1843             {
1844                 break;
1845             }
1846             /* Get the endpoint address */
1847             temp8 = ((uint8_t *)param);
1848             if (NULL != audioHandle->controlInterfaceHandle)
1849             {
1850                 for (count = 0U; count < audioHandle->controlInterfaceHandle->endpointList.count; count++)
1851                 {
1852                     if (*temp8 == audioHandle->controlInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1853                     {
1854                         /* Only stall the endpoint belongs to control interface of the class */
1855                         error = USB_DeviceStallEndpoint(audioHandle->handle, *temp8);
1856                     }
1857                 }
1858             }
1859             if (NULL != audioHandle->streamInterfaceHandle)
1860             {
1861                 for (count = 0U; count < audioHandle->streamInterfaceHandle->endpointList.count; count++)
1862                 {
1863                     if (*temp8 == audioHandle->streamInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1864                     {
1865                         /* Only stall the endpoint belongs to stream interface of the class */
1866                         error = USB_DeviceStallEndpoint(audioHandle->handle, *temp8);
1867                     }
1868                 }
1869             }
1870             break;
1871         case kUSB_DeviceClassEventClearEndpointHalt:
1872             if (NULL == audioHandle->configStruct)
1873             {
1874                 break;
1875             }
1876             /* Get the endpoint address */
1877             temp8 = ((uint8_t *)param);
1878             if (NULL != audioHandle->controlInterfaceHandle)
1879             {
1880                 for (count = 0U; count < audioHandle->controlInterfaceHandle->endpointList.count; count++)
1881                 {
1882                     if (*temp8 == audioHandle->controlInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1883                     {
1884                         /* Only un-stall the endpoint belongs to control interface of the class */
1885                         error = USB_DeviceUnstallEndpoint(audioHandle->handle, *temp8);
1886                     }
1887                 }
1888             }
1889             if (NULL != audioHandle->streamInterfaceHandle)
1890             {
1891                 for (count = 0U; count < audioHandle->streamInterfaceHandle->endpointList.count; count++)
1892                 {
1893                     if (*temp8 == audioHandle->streamInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1894                     {
1895                         /* Only un-stall the endpoint belongs to stream interface of the class */
1896                         error = USB_DeviceUnstallEndpoint(audioHandle->handle, *temp8);
1897                     }
1898                 }
1899             }
1900             break;
1901         case kUSB_DeviceClassEventClassRequest:
1902         {
1903             /* Handle the audio class specific request. */
1904             usb_device_control_request_struct_t *controlRequest = (usb_device_control_request_struct_t *)param;
1905             uint8_t interfaceOrEndpoint                         = (uint8_t)controlRequest->setup->wIndex;
1906 
1907             if ((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) ==
1908                 USB_REQUEST_TYPE_RECIPIENT_ENDPOINT)
1909             {
1910                 if ((NULL == audioHandle->controlInterfaceHandle) || (NULL == audioHandle->streamInterfaceHandle))
1911                 {
1912                     break; /* return error */
1913                 }
1914                 for (count = 0U; count < audioHandle->controlInterfaceHandle->endpointList.count; count++)
1915                 {
1916                     if (interfaceOrEndpoint ==
1917                         audioHandle->controlInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1918                     {
1919                         break;
1920                     }
1921                 }
1922                 if (count == audioHandle->controlInterfaceHandle->endpointList.count)
1923                 {
1924                     for (count = 0U; count < audioHandle->streamInterfaceHandle->endpointList.count; count++)
1925                     {
1926                         if (interfaceOrEndpoint ==
1927                             audioHandle->streamInterfaceHandle->endpointList.endpoint[count].endpointAddress)
1928                         {
1929                             break;
1930                         }
1931                     }
1932                     if (count == audioHandle->streamInterfaceHandle->endpointList.count)
1933                     {
1934                         break; /* return error */
1935                     }
1936                 }
1937                 error = kStatus_USB_InvalidRequest;
1938                 switch (controlRequest->setup->bmRequestType)
1939                 {
1940                     case USB_DEVICE_AUDIO_SET_REQUEST_ENDPOINT:
1941                         error = USB_DeviceAudioSetRequestEndpoint(audioHandle, controlRequest);
1942                         break;
1943                     case USB_DEVICE_AUDIO_GET_REQUEST_ENDPOINT:
1944                         error = USB_DeviceAudioGetRequestEndpoint(audioHandle, controlRequest);
1945                         break;
1946                     default:
1947                         /*no action*/
1948                         break;
1949                 }
1950             }
1951             else if ((controlRequest->setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) ==
1952                      USB_REQUEST_TYPE_RECIPIENT_INTERFACE)
1953             {
1954                 if (audioHandle->controlInterfaceNumber == interfaceOrEndpoint)
1955                 {
1956                     error = kStatus_USB_InvalidRequest;
1957                     switch (controlRequest->setup->bmRequestType)
1958                     {
1959                         case USB_DEVICE_AUDIO_SET_REQUEST_INTERFACE:
1960                             error = USB_DeviceAudioSetRequestInterface(audioHandle, controlRequest);
1961                             break;
1962                         case USB_DEVICE_AUDIO_GET_REQUEST_INTERFACE:
1963                             error = USB_DeviceAudioGetRequestInterface(audioHandle, controlRequest);
1964                             break;
1965                         default:
1966                             /*no action*/
1967                             break;
1968                     }
1969                 }
1970             }
1971             else
1972             {
1973                 /* no action */
1974             }
1975         }
1976         break;
1977         default:
1978             /*no action*/
1979             break;
1980     }
1981     return error;
1982 }
1983 
1984 /*!
1985  * @brief Initialize the audio class.
1986  *
1987  * This function is used to initialize the audio class.
1988  *
1989  * @param controllerId   The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
1990  * @param config          The class configuration information.
1991  * @param handle          It is out parameter, is used to return pointer of the audio class handle to the caller.
1992  *
1993  * @return A USB error code or kStatus_USB_Success.
1994  */
USB_DeviceAudioInit(uint8_t controllerId,usb_device_class_config_struct_t * config,class_handle_t * handle)1995 usb_status_t USB_DeviceAudioInit(uint8_t controllerId, usb_device_class_config_struct_t *config, class_handle_t *handle)
1996 {
1997     usb_device_audio_struct_t *audioHandle;
1998     usb_status_t error = kStatus_USB_Error;
1999 
2000     /* Allocate a audio class handle. */
2001     error = USB_DeviceAudioAllocateHandle(&audioHandle);
2002 
2003     if (kStatus_USB_Success != error)
2004     {
2005         return error;
2006     }
2007 
2008     /* Get the device handle according to the controller id. */
2009     error = USB_DeviceClassGetDeviceHandle(controllerId, &audioHandle->handle);
2010 
2011     if (kStatus_USB_Success != error)
2012     {
2013         return error;
2014     }
2015 
2016     if (NULL == audioHandle->handle)
2017     {
2018         return kStatus_USB_InvalidHandle;
2019     }
2020     /* Save the configuration of the class. */
2021     audioHandle->configStruct = config;
2022     /* Clear the configuration value. */
2023     audioHandle->configuration    = 0U;
2024     audioHandle->streamAlternate  = 0xffU;
2025     audioHandle->controlAlternate = 0xffU;
2026 
2027     *handle = (class_handle_t)audioHandle;
2028     return error;
2029 }
2030 
2031 /*!
2032  * @brief De-initialize the device audio class.
2033  *
2034  * The function de-initializes the device audio class.
2035  *
2036  * @param handle The ccid class handle got from usb_device_class_config_struct_t::classHandle.
2037  *
2038  * @return A USB error code or kStatus_USB_Success.
2039  */
USB_DeviceAudioDeinit(class_handle_t handle)2040 usb_status_t USB_DeviceAudioDeinit(class_handle_t handle)
2041 {
2042     usb_device_audio_struct_t *audioHandle;
2043     usb_status_t error = kStatus_USB_Error;
2044 
2045     audioHandle = (usb_device_audio_struct_t *)handle;
2046 
2047     if (NULL == audioHandle)
2048     {
2049         return kStatus_USB_InvalidHandle;
2050     }
2051     error = USB_DeviceAudioStreamEndpointsDeinit(audioHandle);
2052     error = USB_DeviceAudioControlEndpointsDeinit(audioHandle);
2053     (void)USB_DeviceAudioFreeHandle(audioHandle);
2054     return error;
2055 }
2056 
2057 /*!
2058  * @brief Send data through a specified endpoint.
2059  *
2060  * The function is used to send data through a specified endpoint.
2061  * The function calls USB_DeviceSendRequest internally.
2062  *
2063  * @param handle The audio class handle got from usb_device_class_config_struct_t::classHandle.
2064  * @param endpointAddress Endpoint index.
2065  * @param buffer The memory address to hold the data need to be sent.
2066  * @param length The data length need to be sent.
2067  *
2068  * @return A USB error code or kStatus_USB_Success.
2069  *
2070  * @note The return value just means if the sending request is successful or not; the transfer done is notified by
2071  * usb_device_audio_stream_in or usb_device_audio_control_in.
2072  * Currently, only one transfer request can be supported for one specific endpoint.
2073  * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
2074  * should implement a queue in the application level.
2075  * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
2076  * callback).
2077  */
USB_DeviceAudioSend(class_handle_t handle,uint8_t ep,uint8_t * buffer,uint32_t length)2078 usb_status_t USB_DeviceAudioSend(class_handle_t handle, uint8_t ep, uint8_t *buffer, uint32_t length)
2079 {
2080     usb_device_audio_struct_t *audioHandle;
2081     usb_status_t error = kStatus_USB_Error;
2082 
2083     if (NULL == handle)
2084     {
2085         return kStatus_USB_InvalidHandle;
2086     }
2087     audioHandle = (usb_device_audio_struct_t *)handle;
2088 
2089     if (0U != audioHandle->streamInPipeBusy)
2090     {
2091         return kStatus_USB_Busy;
2092     }
2093     audioHandle->streamInPipeBusy = 1U;
2094 
2095     error = USB_DeviceSendRequest(audioHandle->handle, ep, buffer, length);
2096     if (kStatus_USB_Success != error)
2097     {
2098         audioHandle->streamInPipeBusy = 0U;
2099     }
2100     return error;
2101 }
2102 
2103 /*!
2104  * @brief Receive data through a specified endpoint.
2105  *
2106  * The function is used to receive data through a specified endpoint.
2107  * The function calls USB_DeviceRecvRequest internally.
2108  *
2109  * @param handle The audio class handle got from usb_device_class_config_struct_t::classHandle.
2110  * @param endpointAddress Endpoint index.
2111  * @param buffer The memory address to save the received data.
2112  * @param length The data length want to be received.
2113  *
2114  * @return A USB error code or kStatus_USB_Success.
2115  *
2116  * @note The return value just means if the receiving request is successful or not; the transfer done is notified by
2117  * usb_device_audio_stream_out.
2118  * Currently, only one transfer request can be supported for one specific endpoint.
2119  * If there is a specific requirement to support multiple transfer requests for one specific endpoint, the application
2120  * should implement a queue in the application level.
2121  * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint
2122  * callback).
2123  */
USB_DeviceAudioRecv(class_handle_t handle,uint8_t ep,uint8_t * buffer,uint32_t length)2124 usb_status_t USB_DeviceAudioRecv(class_handle_t handle, uint8_t ep, uint8_t *buffer, uint32_t length)
2125 {
2126     usb_device_audio_struct_t *audioHandle;
2127     usb_status_t error = kStatus_USB_Error;
2128 
2129     if (NULL == handle)
2130     {
2131         return kStatus_USB_InvalidHandle;
2132     }
2133     audioHandle = (usb_device_audio_struct_t *)handle;
2134 
2135     if (0U != audioHandle->streamOutPipeBusy)
2136     {
2137         return kStatus_USB_Busy;
2138     }
2139     audioHandle->streamOutPipeBusy = 1U;
2140 
2141     error = USB_DeviceRecvRequest(audioHandle->handle, ep, buffer, length);
2142     if (kStatus_USB_Success != error)
2143     {
2144         audioHandle->streamOutPipeBusy = 0U;
2145     }
2146     return error;
2147 }
2148 
2149 #endif
2150