1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016,2019 - 2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_host_config.h"
10 #if ((defined USB_HOST_CONFIG_AUDIO) && (USB_HOST_CONFIG_AUDIO))
11 #include "usb_host.h"
12 #include "usb_host_audio.h"
13 
14 /*******************************************************************************
15  * Definitions
16  ******************************************************************************/
17 typedef union usb_audio_ctrl_common_fu_desc_t
18 {
19     usb_audio_ctrl_fu_desc_t fuDesc10;
20     usb_audio_2_0_ctrl_fu_desc_t fuDesc20;
21 } usb_audio_ctrl_common_fu_desc;
22 /*******************************************************************************
23  * Variables
24  ******************************************************************************/
25 
26 /* usb audio feature uint command request declaration */
27 static usb_audio_request_t s_usbAudioFuRequests[NUMBER_OF_FEATURE_COMMANDS] = {
28     /* Mute command request  */
29     {AUDIO_FU_MUTE_MASK, ITF_REQUEST, CUR_REQUEST, AUDIO_FU_MUTE, 1U},
30     /* Volume command request  */
31     {AUDIO_FU_VOLUME_MASK, ITF_REQUEST, CUR_REQUEST, AUDIO_FU_VOLUME, 2U},
32     {AUDIO_FU_VOLUME_MASK, ITF_REQUEST, MIN_REQUEST, AUDIO_FU_VOLUME, 2U},
33     {AUDIO_FU_VOLUME_MASK, ITF_REQUEST, MAX_REQUEST, AUDIO_FU_VOLUME, 2U},
34     {AUDIO_FU_VOLUME_MASK, ITF_REQUEST, RES_REQUEST, AUDIO_FU_VOLUME, 2U},
35 };
36 /* USB audio endpoint command declaration */
37 static usb_audio_request_t s_usbAudioEpRequests[NUMBER_OF_ENDPOINT_COMMANDS] = {
38     /* USB audio Pitch command request  */
39     {AUDIO_PITCH_MASK, EP_REQUEST, CUR_REQUEST, AUDIO_PITCH_CONTROL, 1U},
40 
41     /* USB audio Sampling frequency command request  */
42     {AUDIO_SAMPLING_FREQ_MASK, EP_REQUEST, CUR_REQUEST, AUDIO_SAMPLING_FREQ_CONTROL, 3U},
43     {AUDIO_SAMPLING_FREQ_MASK, EP_REQUEST, MIN_REQUEST, AUDIO_SAMPLING_FREQ_CONTROL, 3U},
44     {AUDIO_SAMPLING_FREQ_MASK, EP_REQUEST, MAX_REQUEST, AUDIO_SAMPLING_FREQ_CONTROL, 3U},
45     {AUDIO_SAMPLING_FREQ_MASK, EP_REQUEST, RES_REQUEST, AUDIO_SAMPLING_FREQ_CONTROL, 3U},
46 };
47 
48 /*******************************************************************************
49  * Code
50  ******************************************************************************/
51 /*!
52  * @brief initialize the audio instance.
53  *
54  * This function allocate the resource for audio instance.
55  *
56  * @param deviceHandle       The device handle.
57  * @param classHandlePtr return class handle.
58  *
59  * @retval kStatus_USB_Success        The device is initialized successfully.
60  * @retval kStatus_USB_AllocFail      Allocate memory fail.
61  */
USB_HostAudioInit(usb_device_handle deviceHandle,usb_host_class_handle * classHandlePtr)62 usb_status_t USB_HostAudioInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandlePtr)
63 {
64     audio_instance_t *audioPtr = (audio_instance_t *)OSA_MemoryAllocate(sizeof(audio_instance_t));
65     uint32_t info_value        = 0U;
66     uint32_t *temp;
67 
68     if (audioPtr == NULL)
69     {
70         return kStatus_USB_AllocFail;
71     }
72 
73     audioPtr->deviceHandle      = deviceHandle;
74     audioPtr->controlIntfHandle = NULL;
75     audioPtr->streamIntfHandle  = NULL;
76     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &info_value);
77     temp                 = (uint32_t *)info_value;
78     audioPtr->hostHandle = (usb_host_handle)temp;
79     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &info_value);
80     temp                  = (uint32_t *)info_value;
81     audioPtr->controlPipe = (usb_host_pipe_handle)temp;
82 
83     *classHandlePtr = audioPtr;
84     return kStatus_USB_Success;
85 }
86 
87 /*!
88  * @brief de-initialize the audio instance.
89  *
90  * This function release the resource for audio instance.
91  *
92  * @param deviceHandle   the device handle.
93  * @param classHandle the class handle.
94  *
95  * @retval kStatus_USB_Success        The device is de-initialized successfully.
96  */
USB_HostAudioDeinit(usb_device_handle deviceHandle,usb_host_class_handle classHandle)97 usb_status_t USB_HostAudioDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
98 {
99     usb_status_t status        = kStatus_USB_Success;
100     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
101 
102     if (deviceHandle == NULL)
103     {
104         return kStatus_USB_InvalidHandle;
105     }
106 
107     if (classHandle != NULL)
108     {
109         if (audioPtr->isoInPipe != NULL)
110         {
111             status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoInPipe, NULL);
112             if (status != kStatus_USB_Success)
113             {
114 #ifdef HOST_ECHO
115                 usb_echo("error when cancel pipe\r\n");
116 #endif
117             }
118             status = USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoInPipe);
119 
120             if (status != kStatus_USB_Success)
121             {
122 #ifdef HOST_ECHO
123                 usb_echo("error when close pipe\r\n");
124 #endif
125             }
126             audioPtr->isoInPipe = NULL;
127         }
128         if (audioPtr->isoOutPipe != NULL)
129         {
130             status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoOutPipe, NULL);
131             if (status != kStatus_USB_Success)
132             {
133 #ifdef HOST_ECHO
134                 usb_echo("error when cancel pipe\r\n");
135 #endif
136             }
137             status = USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoOutPipe);
138 
139             if (status != kStatus_USB_Success)
140             {
141 #ifdef HOST_ECHO
142                 usb_echo("error when close pipe\r\n");
143 #endif
144             }
145             audioPtr->isoOutPipe = NULL;
146         }
147         (void)USB_HostCloseDeviceInterface(deviceHandle, audioPtr->streamIntfHandle);
148 
149         if ((audioPtr->controlPipe != NULL) && (audioPtr->controlTransfer != NULL))
150         {
151             status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->controlPipe, audioPtr->controlTransfer);
152         }
153         (void)USB_HostCloseDeviceInterface(deviceHandle, audioPtr->controlIntfHandle);
154         OSA_MemoryFree(audioPtr);
155     }
156     else
157     {
158         (void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
159     }
160 
161     return status;
162 }
163 
164 /*!
165  * @brief audiostream iso in pipe transfer callback.
166  *
167  * @param param       callback parameter.
168  * @param transfer     callback transfer.
169  * @param status        transfer status.
170  */
_USB_HostAudioStreamIsoInPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)171 static void _USB_HostAudioStreamIsoInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
172 {
173     audio_instance_t *audioPtr = (audio_instance_t *)param;
174 
175     if (audioPtr->inCallbackFn != NULL)
176     {
177         /* callback function is initialized in USB_HostAudioStreamRecv */
178         audioPtr->inCallbackFn(audioPtr->inCallbackParam, transfer->transferBuffer, transfer->transferSofar, status);
179     }
180     (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
181 }
182 
183 /*!
184  * @brief audiostream iso out pipe transfer callback.
185  *
186  * @param param       callback parameter.
187  * @param transfer     callback transfer.
188  * @param status        transfer status.
189  */
_USB_HostAudioStreamIsoOutPipeCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)190 static void _USB_HostAudioStreamIsoOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
191 {
192     audio_instance_t *audioPtr = (audio_instance_t *)param;
193 
194     if (audioPtr->outCallbackFn != NULL)
195     {
196         /* callback function is initialized in USB_HostAudioStreamSend */
197         audioPtr->outCallbackFn(audioPtr->outCallbackParam, transfer->transferBuffer, transfer->transferSofar, status);
198     }
199     (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
200 }
201 
202 /*!
203  * @brief audiocontrol pipe transfer callback.
204  *
205  * @param param       callback parameter.
206  * @param transfer     callback transfer.
207  * @param status        transfer status.
208  */
_USB_HostAudioControlCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)209 static void _USB_HostAudioControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
210 {
211     audio_instance_t *audioPtr = (audio_instance_t *)param;
212 
213     audioPtr->controlTransfer = NULL;
214     if (audioPtr->controlCallbackFn != NULL)
215     {
216         /* callback to application, callback function is initialized in the _USB_HostAudioControl,
217         USB_HostAudioStreamSetInterface
218         or USB_HostAudioControlSetInterface, but is the same function */
219         audioPtr->controlCallbackFn(audioPtr->controlCallbackParam, transfer->transferBuffer, transfer->transferSofar,
220                                     status);
221     }
222     (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
223     audioPtr->isSetup = 0U;
224 }
225 
226 /*!
227  * @brief hid send control transfer common code.
228  *
229  * @param classHandle   the class handle.
230  * @param typeRequest   setup packet request type.
231  * @param request           setup packet request value.
232  * @param wvalue            setup packet wvalue value.
233  * @param windex            setup packet index value.
234  * @param wlength           setup packet wlength value.
235  * @param data                data buffer pointer will be transfer.
236  * @param callbackFn       this callback is called after this function completes.
237  * @param callbackParam the first parameter in the callback function.
238  *
239  * @return An error code or kStatus_USB_Success.
240  */
_USB_HostAudioControl(usb_host_class_handle classHandle,uint8_t typeRequest,uint8_t request,uint16_t wvalue,uint16_t windex,uint16_t wlength,uint8_t * data,transfer_callback_t callbackFn,void * callbackParam)241 static usb_status_t _USB_HostAudioControl(usb_host_class_handle classHandle,
242                                           uint8_t typeRequest,
243                                           uint8_t request,
244                                           uint16_t wvalue,
245                                           uint16_t windex,
246                                           uint16_t wlength,
247                                           uint8_t *data,
248                                           transfer_callback_t callbackFn,
249                                           void *callbackParam)
250 {
251     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
252     usb_host_transfer_t *transfer;
253 
254     if (classHandle == NULL)
255     {
256         return kStatus_USB_InvalidHandle;
257     }
258 
259     if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
260     {
261 #ifdef HOST_ECHO
262         usb_echo("error to get transfer\r\n");
263 #endif
264         return kStatus_USB_Error;
265     }
266     audioPtr->controlCallbackFn    = callbackFn;
267     audioPtr->controlCallbackParam = callbackParam;
268 
269     transfer->transferBuffer             = data;
270     transfer->transferLength             = wlength;
271     transfer->callbackFn                 = _USB_HostAudioControlCallback;
272     transfer->callbackParam              = audioPtr;
273     transfer->setupPacket->bmRequestType = typeRequest;
274     transfer->setupPacket->bRequest      = request;
275     transfer->setupPacket->wValue        = USB_SHORT_TO_LITTLE_ENDIAN(wvalue);
276     transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(windex);
277 
278     transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
279     audioPtr->isSetup              = 1;
280 
281     if (USB_HostSendSetup(audioPtr->hostHandle, audioPtr->controlPipe, transfer) != kStatus_USB_Success)
282     {
283 #ifdef HOST_ECHO
284         usb_echo("failed for USB_HostSendSetup\r\n");
285 #endif
286         (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
287         return kStatus_USB_Error;
288     }
289     audioPtr->controlTransfer = transfer;
290 
291     return kStatus_USB_Success;
292 }
293 
_USB_HostAudioInitEndpoint(audio_instance_t * audioPtr,usb_descriptor_endpoint_t * ep_desc)294 static usb_status_t _USB_HostAudioInitEndpoint(audio_instance_t *audioPtr, usb_descriptor_endpoint_t *ep_desc)
295 {
296     usb_host_pipe_init_t pipe_init;
297     usb_status_t status;
298 
299     pipe_init.devInstance     = audioPtr->deviceHandle;
300     pipe_init.pipeType        = USB_ENDPOINT_ISOCHRONOUS;
301     pipe_init.direction       = ((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >>
302                            USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
303     pipe_init.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
304     pipe_init.interval        = ep_desc->bInterval;
305     pipe_init.maxPacketSize   = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
306                                           USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
307     pipe_init.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
308                                            USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
309     pipe_init.nakCount        = USB_HOST_CONFIG_MAX_NAK;
310 
311     if (pipe_init.direction == USB_IN)
312     {
313         audioPtr->inPacketSize = pipe_init.maxPacketSize;
314         audioPtr->isoEpNum     = pipe_init.endpointAddress;
315         status                 = USB_HostOpenPipe(audioPtr->hostHandle, &audioPtr->isoInPipe, &pipe_init);
316     }
317     else
318     {
319         audioPtr->outPacketSize = pipe_init.maxPacketSize;
320         audioPtr->isoEpNum      = pipe_init.endpointAddress;
321         status                  = USB_HostOpenPipe(audioPtr->hostHandle, &audioPtr->isoOutPipe, &pipe_init);
322     }
323 
324     return status;
325 }
326 
327 /*!
328  * @brief audio open interface.
329  *
330  * @param audioPtr     audio instance pointer.
331  *
332  * @return kStatus_USB_Success or error codes.
333  */
_USB_HostAudioOpenInterface(audio_instance_t * audioPtr)334 static usb_status_t _USB_HostAudioOpenInterface(audio_instance_t *audioPtr)
335 {
336     usb_status_t status;
337     uint8_t ep_index                   = 0U;
338     usb_descriptor_endpoint_t *ep_desc = NULL;
339     usb_host_interface_t *interface_ptr;
340 
341     if (audioPtr->isoInPipe != NULL)
342     {
343         status = USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoInPipe);
344 
345         if (status != kStatus_USB_Success)
346         {
347 #ifdef HOST_ECHO
348             usb_echo("error when close pipe\r\n");
349 #endif
350         }
351         audioPtr->isoInPipe = NULL;
352     }
353     if (audioPtr->isoOutPipe != NULL)
354     {
355         status = USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoOutPipe);
356 
357         if (status != kStatus_USB_Success)
358         {
359 #ifdef HOST_ECHO
360             usb_echo("error when close pipe\r\n");
361 #endif
362         }
363         audioPtr->isoOutPipe = NULL;
364     }
365 
366     /* open interface pipes */
367     interface_ptr = (usb_host_interface_t *)audioPtr->streamIntfHandle;
368     for (ep_index = 0U; ep_index < interface_ptr->epCount; ++ep_index)
369     {
370         ep_desc = interface_ptr->epList[ep_index].epDesc;
371         if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
372              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
373             ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_ISOCHRONOUS))
374         {
375             status = _USB_HostAudioInitEndpoint(audioPtr, ep_desc);
376             if (status != kStatus_USB_Success)
377             {
378 #ifdef HOST_ECHO
379                 usb_echo("usb_host_audio_stream_set_interface fail to open pipe\r\n");
380 #endif
381                 return kStatus_USB_Error;
382             }
383         }
384         else if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
385                   USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
386                  ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_ISOCHRONOUS))
387         {
388             status = _USB_HostAudioInitEndpoint(audioPtr, ep_desc);
389             if (status != kStatus_USB_Success)
390             {
391 #ifdef HOST_ECHO
392                 usb_echo("usb_host_audio_stream_set_interface fail to open pipe\r\n");
393 #endif
394                 return kStatus_USB_Error;
395             }
396         }
397         else
398         {
399         }
400     }
401 
402     return kStatus_USB_Success;
403 }
404 
405 /*!
406  * @brief audio set interface callback, open pipes.
407  *
408  * @param param       callback parameter.
409  * @param transfer    callback transfer.
410  * @param status      transfer status.
411  */
_USB_HostAudioSetInterfaceCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)412 static void _USB_HostAudioSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
413 {
414     audio_instance_t *audioPtr = (audio_instance_t *)param;
415 
416     audioPtr->controlTransfer = NULL;
417     if (status == kStatus_USB_Success)
418     {
419         status = _USB_HostAudioOpenInterface(audioPtr);
420     }
421 
422     if (audioPtr->controlCallbackFn != NULL)
423     {
424         /* callback to application, callback function is initialized in the _USB_HostAudioControl,
425         USB_HostAudioStreamSetInterface
426         or USB_HostAudioControlSetInterface, but is the same function */
427         audioPtr->controlCallbackFn(audioPtr->controlCallbackParam, NULL, 0U, status);
428     }
429     (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
430 }
431 
432 /*!
433  * @brief set audioclass stream interface.
434  *
435  * This function bind the interface with the audio instance.
436  *
437  * @param classHandle        The class handle.
438  * @param interfaceHandle          The interface handle.
439  * @param alternateSetting  The alternate setting value.
440  * @param callbackFn          This callback is called after this function completes.
441  * @param callbackParam    The first parameter in the callback function.
442  *
443  * @retval kStatus_USB_Success         The device is initialized successfully.
444  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
445  * @retval kStatus_USB_Busy           There is no idle transfer.
446  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
447  * @retval kStatus_USB_Busy           callback return status, there is no idle pipe.
448  * @retval kStatus_USB_TransferStall  callback return status, the transfer is stall by device.
449  * @retval kStatus_USB_Error          callback return status, open pipe fail, please reference to USB_HostOpenPipe.
450  */
USB_HostAudioStreamSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)451 usb_status_t USB_HostAudioStreamSetInterface(usb_host_class_handle classHandle,
452                                              usb_host_interface_handle interfaceHandle,
453                                              uint8_t alternateSetting,
454                                              transfer_callback_t callbackFn,
455                                              void *callbackParam)
456 {
457     usb_status_t status;
458     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
459     usb_host_interface_t *interface_ptr;
460     usb_host_transfer_t *transfer;
461     audio_descriptor_union_t ptr1;
462     uint32_t length = 0U, ep = 0U;
463     void *temp;
464     usb_descriptor_endpoint_t *endpointDesc;
465     if (classHandle == NULL)
466     {
467         return kStatus_USB_InvalidParameter;
468     }
469 
470     audioPtr->streamIntfHandle = interfaceHandle;
471 
472     status = USB_HostOpenDeviceInterface(audioPtr->deviceHandle, interfaceHandle);
473     if (status != kStatus_USB_Success)
474     {
475         return status;
476     }
477 
478     if (audioPtr->isoInPipe != NULL)
479     {
480         status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoInPipe, NULL);
481 
482         if (status != kStatus_USB_Success)
483         {
484 #ifdef HOST_ECHO
485             usb_echo("error when cancel pipe\r\n");
486 #endif
487         }
488     }
489 
490     if (audioPtr->isoOutPipe != NULL)
491     {
492         status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoOutPipe, NULL);
493 
494         if (status != kStatus_USB_Success)
495         {
496 #ifdef HOST_ECHO
497             usb_echo("error when cancel pipe\r\n");
498 #endif
499         }
500     }
501     /* open interface pipes */
502     interface_ptr = (usb_host_interface_t *)interfaceHandle;
503     ptr1.bufr     = interface_ptr->interfaceExtension;
504 
505     length = 0U;
506     while (length < interface_ptr->interfaceExtensionLength)
507     {
508         if ((ptr1.common->bDescriptorType == 0x04U) && (ptr1.interface->bAlternateSetting == alternateSetting))
509         {
510             interface_ptr->epCount = ptr1.interface->bNumEndpoints;
511             break;
512         }
513         ptr1.bufr += ptr1.common->bLength;
514         length += ptr1.common->bLength;
515     }
516     while (ep < interface_ptr->epCount)
517     {
518         if (ptr1.common->bDescriptorType == 0x24U)
519         {
520             temp = (void *)ptr1.bufr;
521             if (AUDIO_DEVICE_VERSION_01 == audioPtr->deviceAudioVersion)
522             {
523                 if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_AS_GENERAL)
524                 {
525                     audioPtr->asIntfDesc = temp;
526                 }
527                 else if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE)
528                 {
529                     audioPtr->formatTypeDesc = temp;
530                 }
531                 else
532                 {
533                     /*no action*/
534                 }
535             }
536             else if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
537             {
538                 if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_AS_GENERAL_20)
539                 {
540                     audioPtr->asIntfDesc = temp;
541                 }
542                 else if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE_20)
543                 {
544                     audioPtr->formatTypeDesc = temp;
545                 }
546                 else
547                 {
548                     /*no action*/
549                 }
550             }
551             else
552             {
553                 /*no action*/
554             }
555         }
556         else
557         {
558             /*no action*/
559         }
560 
561         if (ptr1.common->bDescriptorType == 0x05U)
562         {
563             uint32_t descLength = 0;
564             temp                = (void *)ptr1.bufr;
565             /*Bits 5..4: Usage Type,
566             00 = Data endpoint
567             01 = Feedback endpoint
568             10 = Implicit feedback Data endpoit, usb Spec 9.6*/
569             endpointDesc = (usb_descriptor_endpoint_t *)temp;
570             if (0x00U == ((endpointDesc->bmAttributes >> 4U) & 0x3U))
571             {
572                 interface_ptr->epList[ep].epDesc = (usb_descriptor_endpoint_t *)temp;
573                 audioPtr->isoEndpDesc            = (usb_descriptor_endpoint_t *)temp;
574             }
575             else if (0x01U == ((endpointDesc->bmAttributes >> 4U) & 0x3U))
576             {
577                 /*feedback endpoint*/
578             }
579             else
580             {
581                 /*TO DO*/
582             }
583 
584             descLength = ptr1.common->bLength;
585             ptr1.bufr += ptr1.common->bLength;
586 
587             if ((0x25U == ptr1.common->bDescriptorType))
588             {
589                 interface_ptr->epList[ep].epExtension       = ptr1.bufr;
590                 interface_ptr->epList[ep].epExtensionLength = ptr1.common->bLength;
591             }
592             else
593             {
594                 ptr1.bufr -= descLength;
595             }
596             ep++;
597         }
598         ptr1.bufr += ptr1.common->bLength;
599     }
600 
601     if (alternateSetting == 0U)
602     {
603         if (callbackFn != NULL)
604         {
605             status = _USB_HostAudioOpenInterface(audioPtr);
606             callbackFn(callbackParam, NULL, 0U, kStatus_USB_Success);
607         }
608     }
609     else
610     {
611         if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
612         {
613 #ifdef HOST_ECHO
614             usb_echo("error to get transfer\r\n");
615 #endif
616             return kStatus_USB_Error;
617         }
618         audioPtr->controlCallbackFn    = callbackFn;
619         audioPtr->controlCallbackParam = callbackParam;
620         /* initialize transfer */
621         transfer->callbackFn                 = _USB_HostAudioSetInterfaceCallback;
622         transfer->callbackParam              = audioPtr;
623         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
624         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
625         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
626             ((usb_host_interface_t *)audioPtr->streamIntfHandle)->interfaceDesc->bInterfaceNumber);
627         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
628         transfer->setupPacket->wLength = 0;
629         transfer->transferBuffer       = NULL;
630         transfer->transferLength       = 0;
631         status                         = USB_HostSendSetup(audioPtr->hostHandle, audioPtr->controlPipe, transfer);
632 
633         if (status == kStatus_USB_Success)
634         {
635             audioPtr->controlTransfer = transfer;
636         }
637         else
638         {
639             (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
640         }
641     }
642 
643     return status;
644 }
645 
646 /*!
647  * @brief set audioclass control interface.
648  *
649  * This function bind the interface with the audio instance.
650  *
651  * @param classHandle        The class handle.
652  * @param interfaceHandle          The interface handle.
653  * @param alternateSetting  The alternate setting value.
654  * @param callbackFn          This callback is called after this function completes.
655  * @param callbackParam    The first parameter in the callback function.
656  *
657  * @retval kStatus_USB_Success         The device is initialized successfully.
658  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
659  * @retval kStatus_USB_Busy           There is no idle transfer.
660  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
661  * @retval kStatus_USB_Busy           callback return status, there is no idle pipe.
662  * @retval kStatus_USB_TransferStall  callback return status, the transfer is stall by device.
663  * @retval kStatus_USB_Error          callback return status, open pipe fail, please reference to USB_HostOpenPipe.
664  */
USB_HostAudioControlSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)665 usb_status_t USB_HostAudioControlSetInterface(usb_host_class_handle classHandle,
666                                               usb_host_interface_handle interfaceHandle,
667                                               uint8_t alternateSetting,
668                                               transfer_callback_t callbackFn,
669                                               void *callbackParam)
670 {
671     usb_status_t status;
672     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
673     usb_host_interface_t *interface_ptr;
674     usb_host_transfer_t *transfer;
675     audio_descriptor_union_t ptr1;
676     void *temp;
677     void *header;
678     usb_audio_ctrl_common_header_desc_t *commonHeader;
679     uint32_t length = 0U;
680 
681     if (classHandle == NULL)
682     {
683         return kStatus_USB_InvalidParameter;
684     }
685     audioPtr->controlIntfHandle = interfaceHandle;
686     interface_ptr               = (usb_host_interface_t *)interfaceHandle;
687 
688     status = USB_HostOpenDeviceInterface(audioPtr->deviceHandle, interfaceHandle);
689     if (status != kStatus_USB_Success)
690     {
691         return status;
692     }
693     ptr1.bufr = interface_ptr->interfaceExtension;
694 
695     length = 0U;
696 
697     while (length < interface_ptr->interfaceExtensionLength)
698     {
699         if (((interface_ptr->interfaceDesc->bDescriptorType == 0x04U) &&
700              (interface_ptr->interfaceDesc->bAlternateSetting == alternateSetting)) ||
701             ((ptr1.common->bDescriptorType == 0x04U) && (ptr1.interface->bAlternateSetting == alternateSetting)))
702         {
703             break;
704         }
705 
706         ptr1.bufr += ptr1.common->bLength;
707         length += ptr1.common->bLength;
708     }
709     while (length < interface_ptr->interfaceExtensionLength)
710     {
711         if (ptr1.common->bDescriptorType == 0x24U)
712         {
713             temp = (void *)ptr1.bufr;
714             if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_HEADER)
715             {
716                 audioPtr->headerDesc         = (void *)temp;
717                 commonHeader                 = (usb_audio_ctrl_common_header_desc_t *)temp;
718                 header                       = (void *)&commonHeader->bcdcdc;
719                 audioPtr->deviceAudioVersion = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(((uint8_t *)header));
720             }
721             else if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_INPUT)
722             {
723                 if (audioPtr->itDesc == NULL)
724                 {
725                     audioPtr->itDesc = (void *)temp;
726                 }
727             }
728             else if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_OUTPUT)
729             {
730                 if (audioPtr->otDesc == NULL)
731                 {
732                     audioPtr->otDesc = (void *)temp;
733                 }
734             }
735             else if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_FEATURE)
736             {
737                 if (audioPtr->fuDesc == NULL)
738                 {
739                     audioPtr->fuDesc = (void *)temp;
740                 }
741             }
742             else if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_CLOCK_SOURE)
743             {
744                 if (audioPtr->clockSource == NULL)
745                 {
746                     audioPtr->clockSource = (void *)temp;
747                 }
748             }
749             else
750             {
751                 /*no action*/
752             }
753         }
754         ptr1.bufr += ptr1.common->bLength;
755         length += ptr1.common->bLength;
756     }
757 
758     if (alternateSetting == 0U)
759     {
760         if (callbackFn != NULL)
761         {
762             callbackFn(callbackParam, NULL, 0U, kStatus_USB_Success);
763         }
764     }
765     else
766     {
767         if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
768         {
769 #ifdef HOST_ECHO
770             usb_echo("error to get transfer\r\n");
771 #endif
772             return kStatus_USB_Error;
773         }
774         audioPtr->controlCallbackFn    = callbackFn;
775         audioPtr->controlCallbackParam = callbackParam;
776         /* initialize transfer */
777         transfer->callbackFn                 = _USB_HostAudioControlCallback;
778         transfer->callbackParam              = audioPtr;
779         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
780         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
781         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
782             ((usb_host_interface_t *)audioPtr->controlIntfHandle)->interfaceDesc->bInterfaceNumber);
783         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
784         transfer->setupPacket->wLength = 0;
785         transfer->transferBuffer       = NULL;
786         transfer->transferLength       = 0;
787         status                         = USB_HostSendSetup(audioPtr->hostHandle, audioPtr->controlPipe, transfer);
788 
789         if (status == kStatus_USB_Success)
790         {
791             audioPtr->controlTransfer = transfer;
792         }
793         else
794         {
795             (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
796         }
797     }
798 
799     return status;
800 }
801 
802 /*!
803  * @brief get pipe max packet size.
804  *
805  * @param classHandle the class handle.
806  * @param pipeType    It's value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
807  * USB_ENDPOINT_INTERRUPT.
808  *                     Please reference to usb_spec.h
809  * @param direction    pipe direction.
810  *
811  * @retval 0        The classHandle is NULL.
812  * @retval max packet size.
813  */
USB_HostAudioPacketSize(usb_host_class_handle classHandle,uint8_t pipeType,uint8_t direction)814 uint16_t USB_HostAudioPacketSize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
815 {
816     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
817     if (classHandle == NULL)
818     {
819         return 0U;
820     }
821 
822     if (pipeType == USB_ENDPOINT_ISOCHRONOUS)
823     {
824         if (direction == USB_IN)
825         {
826             return audioPtr->inPacketSize;
827         }
828         else
829         {
830             return audioPtr->outPacketSize;
831         }
832     }
833     return 0U;
834 }
835 
836 /*!
837  * @brief audio stream receive data.
838  *
839  * This function implements audioreceiving data.
840  *
841  * @param classHandle      The class handle.
842  * @param buffer                The buffer pointer.
843  * @param bufferLen          The buffer length.
844  * @param callbackFn         This callback is called after this function completes.
845  * @param callbackParam  The first parameter in the callback function.
846  *
847  * @retval kStatus_USB_Success          Receive request successfully.
848  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
849  * @retval kStatus_USB_Busy               There is no idle transfer.
850  * @retval kStatus_USB_Error              pipe is not initialized.
851  *                                                       Or, send transfer fail, please reference to USB_HostRecv.
852  */
USB_HostAudioStreamRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLen,transfer_callback_t callbackFn,void * callbackParam)853 usb_status_t USB_HostAudioStreamRecv(usb_host_class_handle classHandle,
854                                      uint8_t *buffer,
855                                      uint32_t bufferLen,
856                                      transfer_callback_t callbackFn,
857                                      void *callbackParam)
858 {
859     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
860     usb_host_transfer_t *transfer;
861 
862     if (classHandle == NULL)
863     {
864         return kStatus_USB_InvalidHandle;
865     }
866 
867     if (audioPtr->isoInPipe == NULL)
868     {
869         return kStatus_USB_Error;
870     }
871 
872     if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
873     {
874 #ifdef HOST_ECHO
875         usb_echo("error to get transfer\r\n");
876 #endif
877         return kStatus_USB_Error;
878     }
879     audioPtr->inCallbackFn    = callbackFn;
880     audioPtr->inCallbackParam = callbackParam;
881     transfer->transferBuffer  = buffer;
882     transfer->transferLength  = bufferLen;
883     transfer->callbackFn      = _USB_HostAudioStreamIsoInPipeCallback;
884     transfer->callbackParam   = audioPtr;
885 
886     if (USB_HostRecv(audioPtr->hostHandle, audioPtr->isoInPipe, transfer) != kStatus_USB_Success)
887     {
888 #ifdef HOST_ECHO
889         usb_echo("failed to USB_HostRecv\r\n");
890 #endif
891         (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
892         return kStatus_USB_Error;
893     }
894 
895     return kStatus_USB_Success;
896 }
897 
898 /*!
899  * @brief audio stream send data.
900  *
901  * This function implements audio sending data.
902  *
903  * @param classHandle      The class handle.
904  * @param buffer                The buffer pointer.
905  * @param bufferLen          The buffer length.
906  * @param callbackFn         This callback is called after this function completes.
907  * @param callbackParam  The first parameter in the callback function.
908  *
909  * @retval kStatus_USB_Success          Receive request successfully.
910  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
911  * @retval kStatus_USB_Busy               There is no idle transfer.
912  * @retval kStatus_USB_Error              pipe is not initialized.
913  *                                                       Or, send transfer fail, please reference to USB_HostSend.
914  */
USB_HostAudioStreamSend(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLen,transfer_callback_t callbackFn,void * callbackParam)915 usb_status_t USB_HostAudioStreamSend(usb_host_class_handle classHandle,
916                                      uint8_t *buffer,
917                                      uint32_t bufferLen,
918                                      transfer_callback_t callbackFn,
919                                      void *callbackParam)
920 {
921     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
922     usb_host_transfer_t *transfer;
923 
924     if (classHandle == NULL)
925     {
926         return kStatus_USB_InvalidHandle;
927     }
928 
929     if (audioPtr->isoOutPipe == NULL)
930     {
931         return kStatus_USB_Error;
932     }
933 
934     if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
935     {
936 #ifdef HOST_ECHO
937         usb_echo("error to get transfer\r\n");
938 #endif
939         return kStatus_USB_Error;
940     }
941     audioPtr->outCallbackFn    = callbackFn;
942     audioPtr->outCallbackParam = callbackParam;
943     transfer->transferBuffer   = buffer;
944     transfer->transferLength   = bufferLen;
945     transfer->callbackFn       = _USB_HostAudioStreamIsoOutPipeCallback;
946     transfer->callbackParam    = audioPtr;
947 
948     if (USB_HostSend(audioPtr->hostHandle, audioPtr->isoOutPipe, transfer) != kStatus_USB_Success)
949     {
950 #ifdef HOST_ECHO
951         usb_echo("failed to USB_HostSend\r\n");
952 #endif
953         (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
954         return kStatus_USB_Error;
955     }
956 
957     return kStatus_USB_Success;
958 }
959 /*!
960  * @brief get audio control current altsetting descriptor.
961  *
962  * This function implements get audio stream current altsetting descriptor.
963  *
964  * @param classHandle               The class handle.
965  * @param DescriptorType            The descriptor type.
966  * @param DescriptorSubType         The descriptor subtype, 0 for no subtype.
967  * @param Descriptor                The pointer of descriptor pointer.
968  *
969  * @retval kStatus_USB_Success          Get audio stream current altsetting descriptor request successfully.
970  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
971  *
972  */
USB_HostAudioControlGetCurrentAltsettingSpecificDescriptors(usb_host_class_handle classHandle,uint32_t DescriptorType,uint32_t DescriptorSubType,void ** Descriptor)973 usb_status_t USB_HostAudioControlGetCurrentAltsettingSpecificDescriptors(
974 
975     usb_host_class_handle classHandle, uint32_t DescriptorType, uint32_t DescriptorSubType, void **Descriptor)
976 {
977     audio_instance_t *audioPtr   = (audio_instance_t *)classHandle;
978     usb_status_t status          = kStatus_USB_Error;
979     uint32_t **descriptorPointer = (uint32_t **)Descriptor;
980     if ((classHandle == NULL) || NULL == Descriptor)
981     {
982         return kStatus_USB_InvalidParameter;
983     }
984 
985     if (USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE == DescriptorType)
986     {
987         if (AUDIO_DEVICE_VERSION_01 == audioPtr->deviceAudioVersion)
988         {
989             if (USB_AUDIO_DESC_SUBTYPE_CS_EXTENSION <= DescriptorSubType)
990             {
991                 /*descriptor type code bigger than EXTENSION is not support by audio 1.0*/
992                 return kStatus_USB_InvalidParameter;
993             }
994         }
995         switch (DescriptorSubType)
996         {
997             case USB_AUDIO_DESC_SUBTYPE_CS_HEADER:
998                 *descriptorPointer = (uint32_t *)audioPtr->headerDesc;
999                 status             = kStatus_USB_Success;
1000                 break;
1001             case USB_AUDIO_DESC_SUBTYPE_CS_INPUT:
1002                 *descriptorPointer = (uint32_t *)audioPtr->itDesc;
1003                 status             = kStatus_USB_Success;
1004                 break;
1005             case USB_AUDIO_DESC_SUBTYPE_CS_OUTPUT:
1006                 *descriptorPointer = (uint32_t *)audioPtr->otDesc;
1007                 status             = kStatus_USB_Success;
1008                 break;
1009             case USB_AUDIO_DESC_SUBTYPE_CS_FEATURE:
1010                 *descriptorPointer = (uint32_t *)audioPtr->fuDesc;
1011                 status             = kStatus_USB_Success;
1012                 break;
1013             default:
1014                 /*no action*/
1015                 break;
1016         }
1017     }
1018 
1019     return status;
1020 }
1021 /*!
1022  * @brief get audio control current altsetting descriptor.
1023  *
1024  * This function implements get audio stream current altsetting descriptor.
1025  *
1026  * @param classHandle               The class handle.
1027  * @param DescriptorType            The descriptor type.
1028  * @param DescriptorSubType         The descriptor subtype, default 0.
1029  * @param Descriptor                The pointer of descriptor pointer.
1030  *
1031  * @retval kStatus_USB_Success          Get audio stream current altsetting descriptor request successfully.
1032  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1033  *
1034  */
USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(usb_host_class_handle classHandle,uint32_t DescriptorType,uint32_t DescriptorSubType,void ** Descriptor)1035 usb_status_t USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(
1036 
1037     usb_host_class_handle classHandle, uint32_t DescriptorType, uint32_t DescriptorSubType, void **Descriptor)
1038 {
1039     audio_instance_t *audioPtr   = (audio_instance_t *)classHandle;
1040     usb_status_t status          = kStatus_USB_Error;
1041     uint32_t **descriptorPointer = (uint32_t **)Descriptor;
1042     void *temp;
1043 
1044     if ((classHandle == NULL) || NULL == Descriptor)
1045     {
1046         return kStatus_USB_InvalidParameter;
1047     }
1048 
1049     if (USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE == DescriptorType)
1050     {
1051         if (AUDIO_DEVICE_VERSION_01 == audioPtr->deviceAudioVersion)
1052         {
1053             switch (DescriptorSubType)
1054             {
1055                 case USB_AUDIO_DESC_SUBTYPE_AS_GENERAL:
1056                     *descriptorPointer = (uint32_t *)audioPtr->asIntfDesc;
1057                     status             = kStatus_USB_Success;
1058                     break;
1059                 case USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE:
1060                     *descriptorPointer = (uint32_t *)audioPtr->formatTypeDesc;
1061                     status             = kStatus_USB_Success;
1062                     break;
1063                 default:
1064                     /*no action*/
1065                     break;
1066             }
1067         }
1068         else if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
1069         {
1070             switch (DescriptorSubType)
1071             {
1072                 case USB_AUDIO_DESC_SUBTYPE_AS_GENERAL_20:
1073                     *descriptorPointer = (uint32_t *)audioPtr->asIntfDesc;
1074                     status             = kStatus_USB_Success;
1075                     break;
1076                 case USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE_20:
1077                     *descriptorPointer = (uint32_t *)audioPtr->formatTypeDesc;
1078                     status             = kStatus_USB_Success;
1079                     break;
1080                 case USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_ENCODER_20:
1081                     /*no action*/
1082                     break;
1083                 default:
1084                     /*no action*/
1085                     break;
1086             }
1087         }
1088         else
1089         {
1090             /*To DO*/
1091         }
1092     }
1093     else if (USB_DESCRIPTOR_TYPE_ENDPOINT == DescriptorType)
1094     {
1095         if (0x0U == DescriptorSubType)
1096         {
1097             /*iso data endpoint descriptor*/
1098             temp               = (void *)audioPtr->isoEndpDesc;
1099             *descriptorPointer = (uint32_t *)temp;
1100             status             = kStatus_USB_Success;
1101         }
1102         else
1103         {
1104             /*TO DO*/
1105         }
1106     }
1107     else
1108     {
1109         /*To DO*/
1110     }
1111 
1112     return status;
1113 }
1114 
1115 /*!
1116  * @brief get audio stream current altsetting descriptor.
1117  * @deprecated Do not use this function. It has been superceded by @ref
1118  * USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors.
1119  *
1120  * This function implements get audio stream current altsetting descriptor.
1121  *
1122  * @param classHandle               The class handle.
1123  * @param asIntfDesc                 The pointer of class specific AS interface descriptor.
1124  * @param formatTypeDesc       The pointer of format type descriptor.
1125  * @param isoEndpDesc    The pointer of specific iso endp descriptor.
1126  *
1127  * @retval kStatus_USB_Success          Get audio stream current altsetting descriptor request successfully.
1128  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1129  *
1130  */
USB_HostAudioStreamGetCurrentAltsettingDescriptors(usb_host_class_handle classHandle,usb_audio_stream_spepific_as_intf_desc_t ** asIntfDesc,usb_audio_stream_format_type_desc_t ** formatTypeDesc,usb_descriptor_endpoint_t ** isoEndpDesc)1131 usb_status_t USB_HostAudioStreamGetCurrentAltsettingDescriptors(
1132 
1133     usb_host_class_handle classHandle,
1134     usb_audio_stream_spepific_as_intf_desc_t **asIntfDesc,
1135     usb_audio_stream_format_type_desc_t **formatTypeDesc,
1136     usb_descriptor_endpoint_t **isoEndpDesc)
1137 {
1138     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
1139 
1140     if (classHandle == NULL)
1141     {
1142         return kStatus_USB_InvalidHandle;
1143     }
1144     *asIntfDesc     = (usb_audio_stream_spepific_as_intf_desc_t *)audioPtr->asIntfDesc;
1145     *formatTypeDesc = (usb_audio_stream_format_type_desc_t *)audioPtr->formatTypeDesc;
1146     *isoEndpDesc    = (usb_descriptor_endpoint_t *)audioPtr->isoEndpDesc;
1147 
1148     return kStatus_USB_Success;
1149 }
1150 /*!
1151  * @brief usb audio set/get feature unit request.
1152  *
1153  * This function implements usb audio feature unit request.
1154  *
1155  * @param classHandle      The class handle.
1156  * @param csAndCn          The CS and CN or MCN for wValue field in setup Request.
1157  * @param cmdCode          The bRequest code in lower 8bit of lower word and get(1)/set(0) flag in higher 8bit of lower
1158  * word.
1159  * @param buf              The feature unit request buffer pointer.
1160  * @param callbackFn       This callback is called after this function completes.
1161  * @param callbackParam  The first parameter in the callback function.
1162  *
1163  * @retval kStatus_USB_Success            Feature unit request successfully.
1164  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
1165  * @retval kStatus_USB_Busy                There is no idle transfer.
1166  * @retval kStatus_USB_Error                Send transfer fail, please reference to USB_HostSendSetup.
1167  *
1168  */
USB_HostAudioGetSetFeatureUnitRequest(usb_host_class_handle classHandle,uint32_t csAndCn,uint32_t cmdCode,void * buf,uint32_t bufLen,transfer_callback_t callbackFn,void * callbackParam)1169 usb_status_t USB_HostAudioGetSetFeatureUnitRequest(usb_host_class_handle classHandle,
1170                                                    uint32_t csAndCn,
1171                                                    uint32_t cmdCode,
1172                                                    void *buf,
1173                                                    uint32_t bufLen,
1174                                                    transfer_callback_t callbackFn,
1175                                                    void *callbackParam)
1176 {
1177     audio_instance_t *if_ptr;
1178     uint8_t *bmacontrols = NULL;
1179     usb_audio_ctrl_common_fu_desc *fuDesc;
1180     uint16_t windex;
1181     uint8_t request;
1182     uint8_t atribute_index;
1183     uint16_t length = 0U;
1184     uint8_t typeRequest;
1185     uint8_t controlSelector;
1186 
1187     usb_status_t status = kStatus_USB_Error;
1188 
1189     if (classHandle == NULL)
1190     {
1191         return kStatus_USB_InvalidHandle;
1192     }
1193 
1194     if_ptr = (audio_instance_t *)classHandle;
1195 
1196     /* Check whether this attribute valid or not */
1197     if (if_ptr->fuDesc == NULL)
1198     {
1199         return kStatus_USB_Error;
1200     }
1201     fuDesc = (usb_audio_ctrl_common_fu_desc *)if_ptr->fuDesc;
1202     if (AUDIO_DEVICE_VERSION_01 == if_ptr->deviceAudioVersion)
1203     {
1204         windex         = (uint16_t)((uint16_t)((uint16_t)(fuDesc->fuDesc10.bunitid) << 8U) | (if_ptr->streamIfnum));
1205         atribute_index = (uint8_t)(fuDesc->fuDesc10.bcontrolsize * ((uint16_t)csAndCn & 0xFFU));
1206         /*Size of this descriptor, in bytes: 7+(ch+1)*n*/
1207         if (atribute_index < (fuDesc->fuDesc10.blength - 7U))
1208         {
1209             bmacontrols = &(fuDesc->fuDesc10.bcontrolsize);
1210         }
1211     }
1212     else if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1213     {
1214         windex = (uint16_t)((uint16_t)((uint16_t)(fuDesc->fuDesc20.bunitid) << 8U) | (if_ptr->streamIfnum));
1215         /*BmControl is 4byte, refer to *audio2.0 4.7.2.8 Size of this descriptor, in bytes: 6+(ch+1)*4*/
1216         atribute_index = (uint8_t)(4U * ((uint16_t)csAndCn & 0xFFU));
1217 
1218         if (atribute_index < (fuDesc->fuDesc20.blength - 6U))
1219         {
1220             bmacontrols = &(fuDesc->fuDesc20.bmaControls0[0]);
1221         }
1222     }
1223     else
1224     {
1225         /*TO DO*/
1226     }
1227     if (bmacontrols == NULL)
1228     {
1229         return kStatus_USB_Error;
1230     }
1231     request = (uint8_t)(((uint16_t)cmdCode & 0xFFU));
1232 
1233     controlSelector = (uint8_t)((uint16_t)(csAndCn >> 8) & 0xFFU);
1234     if (AUDIO_DEVICE_VERSION_01 == if_ptr->deviceAudioVersion)
1235     {
1236         /*control selector */
1237         switch (controlSelector)
1238         {
1239             /*note ,all the length is defined in audio1.0 Spec chapter 5.2.2.4.3*/
1240             case AUDIO_FU_MUTE:
1241                 status = kStatus_USB_Success;
1242                 length = 1U;
1243                 break;
1244             case AUDIO_FU_VOLUME:
1245                 status = kStatus_USB_Success;
1246                 length = 2U;
1247                 break;
1248             case AUDIO_FU_BASS:
1249                 /*TO DO*/
1250                 break;
1251             default:
1252                 /*no action*/
1253                 break;
1254         }
1255     }
1256     else if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1257     {
1258         if ((request != USB_AUDIO_CS_REQUEST_CODE_RANGE_20) && (request != USB_AUDIO_CS_REQUEST_CODE_CUR_20))
1259         {
1260             return kStatus_USB_Error;
1261         }
1262         switch (controlSelector)
1263         {
1264             /*note ,all the length is defined in audio2.0 Spec chapter 5.2.5.7*/
1265             case AUDIO_FU_MUTE:
1266 
1267                 if (bufLen != 1U)
1268                 {
1269                     return kStatus_USB_Error;
1270                 }
1271                 status = kStatus_USB_Success;
1272                 length = 1U;
1273                 break;
1274             case AUDIO_FU_VOLUME:
1275                 status = kStatus_USB_Success;
1276 
1277                 if (USB_AUDIO_CS_REQUEST_CODE_RANGE_20 == request)
1278                 {
1279                     /*the len for volume is 2+6*n*/
1280                     if (bufLen < 8U)
1281                     {
1282                         return kStatus_USB_Error;
1283                     }
1284                 }
1285                 else if (USB_AUDIO_CS_REQUEST_CODE_CUR_20 == request)
1286                 {
1287                     if (bufLen != 2U)
1288                     {
1289                         return kStatus_USB_Error;
1290                     }
1291                 }
1292                 else
1293                 {
1294                     /*TO DO*/
1295                 }
1296                 length = (uint16_t)bufLen;
1297 
1298                 break;
1299             case AUDIO_FU_BASS:
1300                 /*TO DO*/
1301                 break;
1302             default:
1303                 /*no action*/
1304                 break;
1305         }
1306     }
1307     else
1308     {
1309         /*TO DO*/
1310     }
1311 
1312     if (status != kStatus_USB_Success)
1313     {
1314         /*the request is not support*/
1315         return kStatus_USB_Error;
1316     }
1317     if (0U == ((uint16_t)(cmdCode >> 8U) & 0xFFU))
1318     {
1319         /*refer to audio Spec 2.0 chapter 5.2.2*/
1320         typeRequest = 0x21U;
1321     }
1322     else
1323     {
1324         typeRequest = 0xA1U;
1325     }
1326 
1327     status = _USB_HostAudioControl(classHandle, typeRequest, request, (uint16_t)csAndCn, windex, length, (uint8_t *)buf,
1328                                    callbackFn, callbackParam);
1329 
1330     return status;
1331 }
1332 /*!
1333  * @brief usb audio set/get feature unit request.
1334  *
1335  * This function implements usb audio feature unit request.
1336  *
1337  * @param classHandle      The class handle.
1338  * @param csAndCn          The CS and CN or MCN for wValue field in setup Request.
1339  * @param cmdCode          The bRequest code in lower 8bit of lower word and get(1)/set(0) flag in higher 8bit of lower
1340  word.
1341  * @param buf              The feature unit request buffer pointer.
1342 
1343  * @param callbackFn       This callback is called after this function completes.
1344  * @param callbackParam  The first parameter in the callback function.
1345  *
1346  * @retval kStatus_USB_Success            Feature unit request successfully.
1347  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
1348  * @retval kStatus_USB_Busy                There is no idle transfer.
1349  * @retval kStatus_USB_Error                Send transfer fail, please reference to USB_HostSendSetup.
1350  *
1351  */
USB_HostAudioGetSetClockSourceRequest(usb_host_class_handle classHandle,uint32_t csAndCn,uint32_t cmdCode,void * buf,uint32_t bufLen,transfer_callback_t callbackFn,void * callbackParam)1352 usb_status_t USB_HostAudioGetSetClockSourceRequest(usb_host_class_handle classHandle,
1353                                                    uint32_t csAndCn,
1354                                                    uint32_t cmdCode,
1355                                                    void *buf,
1356                                                    uint32_t bufLen,
1357                                                    transfer_callback_t callbackFn,
1358                                                    void *callbackParam)
1359 {
1360     audio_instance_t *if_ptr;
1361     usb_audio_2_0_ctrl_clock_source_desc_t *clockDesc;
1362     uint16_t windex;
1363     uint16_t controlSelector;
1364     uint8_t length = 0U;
1365     uint8_t typeRequest;
1366     uint8_t request;
1367 
1368     usb_status_t status = kStatus_USB_Error;
1369 
1370     if (classHandle == NULL)
1371     {
1372         return kStatus_USB_InvalidParameter;
1373     }
1374 
1375     if_ptr = (audio_instance_t *)classHandle;
1376 
1377     if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1378     {
1379         clockDesc = (usb_audio_2_0_ctrl_clock_source_desc_t *)if_ptr->clockSource;
1380         windex    = (uint16_t)((uint16_t)((uint16_t)(clockDesc->bClockID) << 8U) | (if_ptr->streamIfnum));
1381     }
1382     else
1383     {
1384         return kStatus_USB_Error;
1385     }
1386     request         = (uint8_t)(((uint16_t)cmdCode & 0xFFU));
1387     controlSelector = (uint8_t)((uint16_t)(csAndCn >> 8U) & 0xFFU);
1388 
1389     if (USB_AUDIO_CS_SAM_FREQ_CONTROL_20 == controlSelector)
1390     {
1391         /*note ,all the length is defined in audio2.0 Spec chapter 5.2.5.1.1*/
1392 
1393         if (USB_AUDIO_CS_REQUEST_CODE_RANGE_20 == request)
1394         {
1395             /*the len for volume is 2+6*n*/
1396             if (bufLen < 12U)
1397             {
1398                 return kStatus_USB_Error;
1399             }
1400             else
1401             {
1402                 length = (uint8_t)bufLen;
1403             }
1404         }
1405         else if (USB_AUDIO_CS_REQUEST_CODE_CUR_20 == request)
1406         {
1407             if (bufLen != 4U)
1408             {
1409                 return kStatus_USB_Error;
1410             }
1411             length = (uint8_t)bufLen;
1412         }
1413         else
1414         {
1415             return kStatus_USB_Error;
1416         }
1417         status = kStatus_USB_Success;
1418     }
1419     else if (USB_AUDIO_CS_CLOCK_VALID_CONTROL_20 == controlSelector)
1420     {
1421         status = kStatus_USB_Success;
1422         if (bufLen < 1U)
1423         {
1424             return kStatus_USB_Error;
1425         }
1426         length = 1U;
1427     }
1428     else
1429     {
1430         /**TO DO*/
1431     }
1432 
1433     if (status != kStatus_USB_Success)
1434     {
1435         /*the request is not support*/
1436         return kStatus_USB_Error;
1437     }
1438 
1439     if (0U == ((uint16_t)(cmdCode >> 8U) & 0xFFU))
1440     {
1441         /*refer to audio Spec 2.0 chapter 5.2.2*/
1442         typeRequest = 0x21U;
1443     }
1444     else
1445     {
1446         typeRequest = 0xA1U;
1447     }
1448 
1449     status = _USB_HostAudioControl(classHandle, typeRequest, request, (uint16_t)csAndCn, windex, length, (uint8_t *)buf,
1450                                    callbackFn, callbackParam);
1451 
1452     return status;
1453 }
1454 
1455 /*!
1456  * @brief usb audio feature unit request.
1457  * @deprecated Do not use this function. It has been superceded by @ref USB_HostAudioGetSetFeatureUnitRequest.
1458  *
1459  * This function implements usb audio feature unit request.
1460  *
1461  * @param classHandle      The class handle.
1462  * @param channelNo        The channel number of audio feature unit.
1463  * @param buf              The feature unit request buffer pointer.
1464  * @param cmdCode          The feature unit command code, for example USB_AUDIO_GET_CUR_MUTE etc.
1465  * @param callbackFn         This callback is called after this function completes.
1466  * @param callbackParam  The first parameter in the callback function.
1467  *
1468  * @retval kStatus_USB_Success            Feature unit request successfully.
1469  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
1470  * @retval kStatus_USB_Busy                There is no idle transfer.
1471  * @retval kStatus_USB_Error                Send transfer fail, please reference to USB_HostSendSetup.
1472  *
1473  */
USB_HostAudioFeatureUnitRequest(usb_host_class_handle classHandle,uint8_t channelNo,void * buf,uint32_t cmdCode,transfer_callback_t callbackFn,void * callbackParam)1474 usb_status_t USB_HostAudioFeatureUnitRequest(usb_host_class_handle classHandle,
1475                                              uint8_t channelNo,
1476                                              void *buf,
1477                                              uint32_t cmdCode,
1478                                              transfer_callback_t callbackFn,
1479                                              void *callbackParam)
1480 { /* Body */
1481     uint16_t windex;
1482     uint16_t request_value;
1483     audio_instance_t *if_ptr;
1484     usb_audio_request_t *p_feature_request;
1485     usb_audio_ctrl_fu_desc_t *fuDesc;
1486     uint8_t *bmacontrols = NULL;
1487     uint8_t atribute_index;
1488     usb_status_t status;
1489 
1490     if ((classHandle == NULL))
1491     {
1492         return kStatus_USB_InvalidHandle;
1493     }
1494 
1495     if_ptr = (audio_instance_t *)classHandle;
1496     if (AUDIO_DEVICE_VERSION_01 != if_ptr->deviceAudioVersion)
1497     {
1498         return kStatus_USB_Error;
1499     }
1500     /* pointer to command */
1501     p_feature_request = &(s_usbAudioFuRequests[(uint8_t)cmdCode & 0xfU]);
1502     /* get request value */
1503     request_value = (uint16_t)((uint16_t)((uint16_t)p_feature_request->requestValue << 8U) | channelNo);
1504 
1505     /* Check whether this attribute valid or not */
1506     if (if_ptr->fuDesc == NULL)
1507     {
1508         return kStatus_USB_Error;
1509     }
1510     fuDesc         = (usb_audio_ctrl_fu_desc_t *)if_ptr->fuDesc;
1511     windex         = (uint16_t)((uint16_t)((uint16_t)(fuDesc->bunitid) << 8U) | (if_ptr->streamIfnum));
1512     atribute_index = fuDesc->bcontrolsize * channelNo;
1513 
1514     if (atribute_index < (fuDesc->blength - 7U))
1515     {
1516         bmacontrols = &(fuDesc->bcontrolsize);
1517     }
1518 
1519     if (bmacontrols == NULL)
1520     {
1521         return kStatus_USB_Error;
1522     }
1523 
1524     status = _USB_HostAudioControl(classHandle, (p_feature_request->typeRequest | ((uint8_t)cmdCode & 0x80U)),
1525                                    (p_feature_request->codeRequest | ((uint8_t)cmdCode & 0x80U)), request_value, windex,
1526                                    p_feature_request->length, (uint8_t *)buf, callbackFn, callbackParam);
1527 
1528     return status;
1529 }
1530 /*!
1531  * @brief usb audio set/get endp unit request.
1532  *
1533  * This function implements usb audio feature unit request.
1534  *
1535  * @param classHandle      The class handle.
1536  * @param csAndCn          The CS for wValue field in setup Request.
1537  * @param cmdCode          The bRequest code in lower 8bit of lower word and get(1)/set(0) flag in higher 8bit of lower
1538  word.
1539  * @param buf              The feature unit request buffer pointer.
1540 
1541  * @param callbackFn       This callback is called after this function completes.
1542  * @param callbackParam  The first parameter in the callback function.
1543  *
1544  * @retval kStatus_USB_Success            Feature unit request successfully.
1545  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
1546  * @retval kStatus_USB_Busy                There is no idle transfer.
1547  * @retval kStatus_USB_Error                Send transfer fail, please reference to USB_HostSendSetup.
1548  *
1549  */
USB_HostAudioGetSetEndpointRequest(usb_host_class_handle classHandle,uint32_t csAndCn,uint32_t cmdCode,void * buf,uint32_t bufLen,transfer_callback_t callbackFn,void * callbackParam)1550 usb_status_t USB_HostAudioGetSetEndpointRequest(usb_host_class_handle classHandle,
1551                                                 uint32_t csAndCn,
1552                                                 uint32_t cmdCode,
1553                                                 void *buf,
1554                                                 uint32_t bufLen,
1555                                                 transfer_callback_t callbackFn,
1556                                                 void *callbackParam)
1557 {
1558     audio_instance_t *if_ptr;
1559     uint16_t windex;
1560     uint8_t request;
1561     uint8_t length = 0U;
1562     uint8_t typeRequest;
1563     uint8_t controlSelector;
1564 
1565     usb_status_t status = kStatus_USB_Error;
1566 
1567     if (classHandle == NULL)
1568     {
1569         return kStatus_USB_InvalidHandle;
1570     }
1571 
1572     if_ptr = (audio_instance_t *)classHandle;
1573 
1574     if (AUDIO_DEVICE_VERSION_01 == if_ptr->deviceAudioVersion)
1575     {
1576         if ((NULL == if_ptr->isoInPipe) && (NULL == if_ptr->isoOutPipe))
1577         {
1578             return kStatus_USB_InvalidParameter;
1579         }
1580         else if (NULL != if_ptr->isoInPipe)
1581         {
1582             windex = (((uint16_t)if_ptr->isoEpNum) | 0x80U);
1583         }
1584         else
1585         {
1586             windex = if_ptr->isoEpNum;
1587         }
1588     }
1589     else if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1590     {
1591         /*TO DO*/
1592     }
1593     else
1594     {
1595         /*TO DO*/
1596     }
1597 
1598     request = (uint8_t)(((uint16_t)cmdCode & 0xFFU));
1599 
1600     controlSelector = (uint8_t)((uint16_t)(csAndCn >> 8U) & 0xFFU);
1601     if (AUDIO_DEVICE_VERSION_01 == if_ptr->deviceAudioVersion)
1602     {
1603         /*control selector */
1604         /*note ,all the length is defined in audio1.0 Spec chapter 5.2.3.2.3*/
1605         if (USB_AUDIO_EP_CS_SAMPING_FREQ_CONTROL == controlSelector)
1606         {
1607             if (bufLen > 3U)
1608             {
1609                 /*fixed length*/
1610                 length = 3U;
1611                 status = kStatus_USB_Success;
1612             }
1613             else
1614             {
1615                 /*TO DO*/
1616             }
1617         }
1618         else if (USB_AUDIO_EP_CS_PINTCH_CONTROL == controlSelector)
1619         {
1620             /*TO DO*/
1621         }
1622         else
1623         {
1624             /*TO DO*/
1625         }
1626     }
1627     else if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1628     {
1629         switch (controlSelector)
1630         {
1631             /*note ,all the length is defined in audio2.0 Spec chapter 5.2.6*/
1632             case USB_AUDIO_EP_CS_PINTCH_CONTROL_20:
1633                 /*TO DO*/
1634                 break;
1635             case USB_AUDIO_EP_CS_OVERRUN_CONTROL_20:
1636                 /*TO DO*/
1637                 break;
1638             case USB_AUDIO_EP_CS_UNDERRUN_CONTROL_20:
1639                 /*TO DO*/
1640                 break;
1641             default:
1642                 /*no action*/
1643                 break;
1644         }
1645     }
1646     else
1647     {
1648         /*TO DO*/
1649     }
1650 
1651     if (status != kStatus_USB_Success)
1652     {
1653         /*the request is not support*/
1654         return kStatus_USB_Error;
1655     }
1656     if (0U == ((uint16_t)(cmdCode >> 8U) & 0xFFU))
1657     {
1658         /*refer to audio Spec 2.0 chapter 5.2.2*/
1659         typeRequest = 0x22U;
1660     }
1661     else
1662     {
1663         typeRequest = 0xA2U;
1664     }
1665 
1666     status = _USB_HostAudioControl(classHandle, typeRequest, request, (uint16_t)csAndCn, windex, length, (uint8_t *)buf,
1667                                    callbackFn, callbackParam);
1668 
1669     return status;
1670 }
1671 /*!
1672  * @brief usb audio endpoint request.
1673  * @deprecated Do not use this function. It has been superceded by @ref USB_HostAudioGetSetEndpointRequest.
1674  *
1675  * This function implements usb audio endpoint request.
1676  *
1677  * @param classHandle      The class handle.
1678  * @param buf                    The feature unit buffer pointer.
1679  * @param cmdCode          The feature unit command code, for example USB_AUDIO_GET_CUR_PITCH etc .
1680  * @param callbackFn         This callback is called after this function completes.
1681  * @param callbackParam   The first parameter in the callback function.
1682  *
1683  * @retval kStatus_USB_Success          Endpoint request successfully.
1684  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1685  * @retval kStatus_USB_Busy               There is no idle transfer.
1686  * @retval kStatus_USB_Error               Send transfer fail, please reference to USB_HostSendSetup.
1687  *
1688  */
USB_HostAudioEndpointRequest(usb_host_class_handle classHandle,void * buf,uint32_t cmdCode,transfer_callback_t callbackFn,void * callbackParam)1689 usb_status_t USB_HostAudioEndpointRequest(
1690     usb_host_class_handle classHandle, void *buf, uint32_t cmdCode, transfer_callback_t callbackFn, void *callbackParam)
1691 {
1692     uint8_t endp_num;
1693     usb_status_t status;
1694     uint16_t request_value;
1695     usb_audio_request_t *p_endpoint_request;
1696     audio_instance_t *audioPtr;
1697 
1698     if (classHandle == NULL)
1699     {
1700         return kStatus_USB_InvalidHandle;
1701     }
1702 
1703     audioPtr = (audio_instance_t *)classHandle;
1704     if (AUDIO_DEVICE_VERSION_01 != audioPtr->deviceAudioVersion)
1705     {
1706         return kStatus_USB_Error;
1707     }
1708     /* pointer to command */
1709     p_endpoint_request = &(s_usbAudioEpRequests[(uint8_t)cmdCode & 0xfU]);
1710     /* get request value */
1711     request_value = (uint16_t)((uint16_t)((uint16_t)p_endpoint_request->requestValue << 8U));
1712 
1713     /* Check whether this attribute valid or not */
1714     if (audioPtr->isoEndpDesc == NULL)
1715     {
1716         return kStatus_USB_Error;
1717     }
1718     if ((0U != audioPtr->isoEndpDesc->bmAttributes) && (0U != p_endpoint_request->controlMask))
1719     {
1720         status = kStatus_USB_Success;
1721     }
1722     else
1723     {
1724         status = kStatus_USB_InvalidRequest;
1725     }
1726 
1727     if (kStatus_USB_Success == status)
1728     {
1729         /* Any isochronous pipe is supported? */
1730         if ((NULL == audioPtr->isoInPipe) && (NULL == audioPtr->isoOutPipe))
1731         {
1732             return kStatus_USB_InvalidParameter;
1733         }
1734         else if (NULL != audioPtr->isoInPipe)
1735         {
1736             endp_num = (audioPtr->isoEpNum | 0x80U);
1737         }
1738         else
1739         {
1740             endp_num = audioPtr->isoEpNum;
1741         } /* Endif */
1742 
1743         status = _USB_HostAudioControl(classHandle, (p_endpoint_request->typeRequest | ((uint8_t)cmdCode & 0x80U)),
1744                                        (p_endpoint_request->codeRequest | ((uint8_t)cmdCode & 0x80U)), request_value,
1745                                        endp_num, p_endpoint_request->length, (uint8_t *)buf, callbackFn, callbackParam);
1746     }
1747 
1748     return status;
1749 }
1750 
USB_HostAudioSetStreamOutDataInterval(usb_host_class_handle classHandle,uint8_t intervalValue)1751 usb_status_t USB_HostAudioSetStreamOutDataInterval(usb_host_class_handle classHandle, uint8_t intervalValue)
1752 {
1753     audio_instance_t *audioPtr         = (audio_instance_t *)classHandle;
1754     usb_status_t status                = kStatus_USB_Error;
1755     uint8_t ep_index                   = 0U;
1756     usb_descriptor_endpoint_t *ep_desc = NULL;
1757     usb_host_interface_t *interface_ptr;
1758 
1759     if (classHandle == NULL)
1760     {
1761         return kStatus_USB_InvalidHandle;
1762     }
1763 
1764     if (audioPtr->isoOutPipe != NULL)
1765     {
1766         (void)USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoOutPipe);
1767         audioPtr->isoOutPipe = NULL;
1768     }
1769 
1770     /* open interface pipes */
1771     interface_ptr = (usb_host_interface_t *)audioPtr->streamIntfHandle;
1772     for (ep_index = 0U; ep_index < interface_ptr->epCount; ++ep_index)
1773     {
1774         ep_desc = interface_ptr->epList[ep_index].epDesc;
1775         if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
1776              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
1777             ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_ISOCHRONOUS))
1778         {
1779             uint8_t intervalBackUp = ep_desc->bInterval;
1780             ep_desc->bInterval     = intervalValue;
1781             status                 = _USB_HostAudioInitEndpoint(audioPtr, ep_desc);
1782             ep_desc->bInterval     = intervalBackUp;
1783         }
1784     }
1785 
1786     return status;
1787 }
1788 #endif /* USB_HOST_CONFIG_AUDIO */
1789