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     uint8_t entity_id = 0U;
459     uint32_t length = 0U, ep = 0U;
460     void *temp;
461     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
462     usb_host_interface_t *interface_ptr = NULL;
463     usb_host_interface_t *ctrlInterface_ptr = NULL;
464     usb_host_transfer_t *transfer;
465     audio_descriptor_union_t ptr1;
466     usb_audio_2_0_ctrl_fu_desc_t *fu_ptr;
467     audio_descriptor_union_t ctrl_ptr;
468     usb_descriptor_endpoint_t *endpointDesc;
469     usb_audio_stream_spepific_as_intf_desc_t *as_general;
470 
471     if (classHandle == NULL)
472     {
473         return kStatus_USB_InvalidParameter;
474     }
475 
476     audioPtr->streamIntfHandle = interfaceHandle;
477 
478     status = USB_HostOpenDeviceInterface(audioPtr->deviceHandle, interfaceHandle);
479     if (status != kStatus_USB_Success)
480     {
481         return status;
482     }
483 
484     if (audioPtr->isoInPipe != NULL)
485     {
486         status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoInPipe, NULL);
487 
488         if (status != kStatus_USB_Success)
489         {
490 #ifdef HOST_ECHO
491             usb_echo("error when cancel pipe\r\n");
492 #endif
493         }
494     }
495 
496     if (audioPtr->isoOutPipe != NULL)
497     {
498         status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoOutPipe, NULL);
499 
500         if (status != kStatus_USB_Success)
501         {
502 #ifdef HOST_ECHO
503             usb_echo("error when cancel pipe\r\n");
504 #endif
505         }
506     }
507     /* open interface pipes */
508     interface_ptr = (usb_host_interface_t *)interfaceHandle;
509     ptr1.bufr     = interface_ptr->interfaceExtension;
510 
511     length = 0U;
512     while (length < interface_ptr->interfaceExtensionLength)
513     {
514         if ((ptr1.common->bDescriptorType == 0x04U) && (ptr1.interface->bAlternateSetting == alternateSetting))
515         {
516             interface_ptr->epCount = ptr1.interface->bNumEndpoints;
517             break;
518         }
519         ptr1.bufr += ptr1.common->bLength;
520         length += ptr1.common->bLength;
521     }
522     while (ep < interface_ptr->epCount)
523     {
524         if (ptr1.common->bDescriptorType == 0x24U)
525         {
526             temp = (void *)ptr1.bufr;
527             if (AUDIO_DEVICE_VERSION_01 == audioPtr->deviceAudioVersion)
528             {
529                 if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_AS_GENERAL)
530                 {
531                     audioPtr->asIntfDesc = temp;
532                 }
533                 else if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE)
534                 {
535                     audioPtr->formatTypeDesc = temp;
536                 }
537                 else
538                 {
539                     /*no action*/
540                 }
541             }
542             else if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
543             {
544                 if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_AS_GENERAL_20)
545                 {
546                     audioPtr->asIntfDesc = temp;
547                 }
548                 else if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE_20)
549                 {
550                     audioPtr->formatTypeDesc = temp;
551                 }
552                 else
553                 {
554                     /*no action*/
555                 }
556             }
557             else
558             {
559                 /*no action*/
560             }
561         }
562         else
563         {
564             /*no action*/
565         }
566 
567         if (ptr1.common->bDescriptorType == 0x05U)
568         {
569             uint32_t descLength = 0;
570             temp                = (void *)ptr1.bufr;
571             /*Bits 5..4: Usage Type,
572             00 = Data endpoint
573             01 = Feedback endpoint
574             10 = Implicit feedback Data endpoit, usb Spec 9.6*/
575             endpointDesc = (usb_descriptor_endpoint_t *)temp;
576             if (0x00U == ((endpointDesc->bmAttributes >> 4U) & 0x3U))
577             {
578                 interface_ptr->epList[ep].epDesc = (usb_descriptor_endpoint_t *)temp;
579                 audioPtr->isoEndpDesc            = (usb_descriptor_endpoint_t *)temp;
580             }
581             else if (0x01U == ((endpointDesc->bmAttributes >> 4U) & 0x3U))
582             {
583                 /*feedback endpoint*/
584             }
585             else
586             {
587                 /*TO DO*/
588             }
589 
590             descLength = ptr1.common->bLength;
591             ptr1.bufr += ptr1.common->bLength;
592 
593             if ((0x25U == ptr1.common->bDescriptorType))
594             {
595                 interface_ptr->epList[ep].epExtension       = ptr1.bufr;
596                 interface_ptr->epList[ep].epExtensionLength = ptr1.common->bLength;
597             }
598             else
599             {
600                 ptr1.bufr -= descLength;
601             }
602             ep++;
603         }
604         ptr1.bufr += ptr1.common->bLength;
605     }
606 
607     if (NULL != audioPtr->asIntfDesc)
608     {
609         as_general = (usb_audio_stream_spepific_as_intf_desc_t *)audioPtr->asIntfDesc;
610         entity_id = as_general->bterminallink;
611         ctrlInterface_ptr = (usb_host_interface_t *)audioPtr->controlIntfHandle;
612         ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
613         length = 0U;
614         /* find audio input or output terminal firstly bases on as general descriptor */
615         while (length < ctrlInterface_ptr->interfaceExtensionLength)
616         {
617             if (ctrl_ptr.common->bDescriptorType == 0x24U)
618             {
619                 temp = (void *)ctrl_ptr.bufr;
620                 if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_INPUT)
621                 {
622                     if ((audioPtr->itDesc == NULL) && (ctrl_ptr.common->bData[1] == entity_id))
623                     {
624                         audioPtr->itDesc = (void *)temp;
625                         break;
626                     }
627                 }
628                 else if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_OUTPUT)
629                 {
630                     if ((audioPtr->otDesc == NULL) && (ctrl_ptr.common->bData[1] == entity_id))
631                     {
632                         audioPtr->otDesc = (void *)temp;
633                         entity_id = ctrl_ptr.common->bData[5]; /* entity_id is fu or su id */
634                         break;
635                     }
636                 }
637                 else
638                 {
639                     /*no action*/
640                 }
641             }
642             ctrl_ptr.bufr += ctrl_ptr.common->bLength;
643             length += ctrl_ptr.common->bLength;
644         }
645 
646         if (NULL != audioPtr->itDesc)
647         {
648             ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
649             length = 0U;
650             while (length < ctrlInterface_ptr->interfaceExtensionLength)
651             {
652                 if (ctrl_ptr.common->bDescriptorType == 0x24U)
653                 {
654                     temp = (void *)ctrl_ptr.bufr;
655                     if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_FEATURE)
656                     {
657                         if ((audioPtr->fuDesc == NULL) && (ctrl_ptr.common->bData[2] == entity_id))
658                         {
659                             audioPtr->fuDesc = (void *)temp;
660                             break;
661                         }
662                     }
663                     else if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_MIXER)
664                     {
665                         if (audioPtr->fuDesc == NULL)
666                         {
667                             usb_audio_2_0_ctrl_mu_desc_t *mix_unit = (usb_audio_2_0_ctrl_mu_desc_t *)temp;
668                             for (uint8_t i = 0; i < mix_unit->bNrInPins; i++)
669                             {
670                                 if (entity_id == mix_unit->baSourceID[i])
671                                 {
672                                     /* save entity id for mix unit */
673                                     entity_id = mix_unit->bunitid;
674                                     break;
675                                 }
676                             }
677                         }
678                     }
679                     else
680                     {
681                         /*no action*/
682                     }
683                 }
684                 ctrl_ptr.bufr += ctrl_ptr.common->bLength;
685                 length += ctrl_ptr.common->bLength;
686             }
687 
688             if (NULL != audioPtr->fuDesc)
689             {
690                 ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
691                 length = 0U;
692                 fu_ptr= (usb_audio_2_0_ctrl_fu_desc_t *)audioPtr->fuDesc;
693                 while (length < ctrlInterface_ptr->interfaceExtensionLength)
694                 {
695                     if (ctrl_ptr.common->bDescriptorType == 0x24U)
696                     {
697                         temp = (void *)ctrl_ptr.bufr;
698                         if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_OUTPUT)
699                         {
700                             if ((audioPtr->otDesc == NULL) && (ctrl_ptr.common->bData[5] == fu_ptr->bunitid))
701                             {
702                                 audioPtr->otDesc = (void *)temp;
703                                 if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
704                                 {
705                                     entity_id = ctrl_ptr.common->bData[6]; /* clock source id */
706                                 }
707                                 break;
708                             }
709                         }
710                     }
711                     ctrl_ptr.bufr += ctrl_ptr.common->bLength;
712                     length += ctrl_ptr.common->bLength;
713                 }
714 
715                 if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
716                 {
717                     ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
718                     length = 0U;
719                     while (length < ctrlInterface_ptr->interfaceExtensionLength)
720                     {
721                         if (ctrl_ptr.common->bDescriptorType == 0x24U)
722                         {
723                             temp = (void *)ctrl_ptr.bufr;
724                             if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_CLOCK_SOURE)
725                             {
726                                 if ((audioPtr->clockSource == NULL) && (ctrl_ptr.common->bData[1] == entity_id))
727                                 {
728                                     audioPtr->clockSource = (void *)temp;
729                                     break;
730                                 }
731                             }
732                         }
733                         ctrl_ptr.bufr += ctrl_ptr.common->bLength;
734                         length += ctrl_ptr.common->bLength;
735                     }
736 
737                 }
738             }
739             else if (entity_id != as_general->bterminallink) /* entity_id is mix unit id */
740             {
741                 ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
742                 length = 0U;
743                 while (length < ctrlInterface_ptr->interfaceExtensionLength)
744                 {
745                     if (ctrl_ptr.common->bDescriptorType == 0x24U)
746                     {
747                         temp = (void *)ctrl_ptr.bufr;
748                         if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_FEATURE)
749                         {
750                             if ((audioPtr->fuDesc == NULL) && (ctrl_ptr.common->bData[2] == entity_id))
751                             {
752                                 audioPtr->fuDesc = (void *)temp;
753                                 entity_id = ctrl_ptr.common->bData[1]; /* entity_id is fu id */
754                                 break;
755                             }
756                         }
757                     }
758                     ctrl_ptr.bufr += ctrl_ptr.common->bLength;
759                     length += ctrl_ptr.common->bLength;
760 
761                 }
762 
763                 ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
764                 length = 0U;
765                 while (length < ctrlInterface_ptr->interfaceExtensionLength)
766                 {
767                     if (ctrl_ptr.common->bDescriptorType == 0x24U)
768                     {
769                         temp = (void *)ctrl_ptr.bufr;
770                         if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_OUTPUT)
771                         {
772                             if ((audioPtr->otDesc == NULL) && (ctrl_ptr.common->bData[5] == entity_id))
773                             {
774                                 audioPtr->otDesc = (void *)temp;
775                                 if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
776                                 {
777                                     entity_id = ctrl_ptr.common->bData[6]; /* clock source id */
778                                 }
779                                 break;
780                             }
781                         }
782                     }
783                     ctrl_ptr.bufr += ctrl_ptr.common->bLength;
784                     length += ctrl_ptr.common->bLength;
785                 }
786 
787                 if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
788                 {
789                     ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
790                     length = 0U;
791                     while (length < ctrlInterface_ptr->interfaceExtensionLength)
792                     {
793                         if (ctrl_ptr.common->bDescriptorType == 0x24U)
794                         {
795                             temp = (void *)ctrl_ptr.bufr;
796                             if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_CLOCK_SOURE)
797                             {
798                                 if ((audioPtr->clockSource == NULL) && (ctrl_ptr.common->bData[1] == entity_id))
799                                 {
800                                     audioPtr->clockSource = (void *)temp;
801                                     break;
802                                 }
803                             }
804                         }
805                         ctrl_ptr.bufr += ctrl_ptr.common->bLength;
806                         length += ctrl_ptr.common->bLength;
807                     }
808                 }
809             }
810             else
811             {
812                 /* no action */
813             }
814         }
815         else if (NULL != audioPtr->otDesc)
816         {
817             ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
818             length = 0U;
819             while (length < ctrlInterface_ptr->interfaceExtensionLength)
820             {
821                 if (ctrl_ptr.common->bDescriptorType == 0x24U)
822                 {
823                     temp = (void *)ctrl_ptr.bufr;
824                     if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_FEATURE)
825                     {
826                         if ((audioPtr->fuDesc == NULL) && (ctrl_ptr.common->bData[1] == entity_id)) /* entity_id is fu id */
827                         {
828                             audioPtr->fuDesc = (void *)temp;
829                             entity_id = ctrl_ptr.common->bData[2]; /* entity_id is it id */
830                             break;
831                         }
832                     }
833                     else if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_SELECTOR)
834                     {
835                         if ((audioPtr->fuDesc == NULL) && (ctrl_ptr.common->bData[1] == entity_id)) /* entity_id is su id */
836                         {
837                             entity_id = ctrl_ptr.common->bData[3]; /* entity_id is fu id */
838                             break;
839                         }
840                     }
841                     else
842                     {
843                         /* no action */
844                     }
845                 }
846                 ctrl_ptr.bufr += ctrl_ptr.common->bLength;
847                 length += ctrl_ptr.common->bLength;
848 
849             }
850 
851             if (NULL != audioPtr->fuDesc)
852             {
853                 ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
854                 length = 0U;
855                 while (length < ctrlInterface_ptr->interfaceExtensionLength)
856                 {
857                     if (ctrl_ptr.common->bDescriptorType == 0x24U)
858                     {
859                         temp = (void *)ctrl_ptr.bufr;
860                         if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_INPUT)
861                         {
862                             if ((audioPtr->itDesc == NULL) && (ctrl_ptr.common->bData[1] == entity_id)) /* entity_id is it id */
863                             {
864                                 audioPtr->itDesc = (void *)temp;
865                                 if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
866                                 {
867                                     entity_id = ctrl_ptr.common->bData[5]; /* entity_id is clock source id */
868                                 }
869                                 break;
870                             }
871                         }
872                     }
873                     ctrl_ptr.bufr += ctrl_ptr.common->bLength;
874                     length += ctrl_ptr.common->bLength;
875                 }
876 
877                 if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
878                 {
879                     if (NULL == audioPtr->itDesc)
880                     {
881                         return kStatus_USB_Error;
882                     }
883 
884                     ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
885                     length = 0U;
886                     while (length < ctrlInterface_ptr->interfaceExtensionLength)
887                     {
888                         if (ctrl_ptr.common->bDescriptorType == 0x24U)
889                         {
890                             temp = (void *)ctrl_ptr.bufr;
891                             if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_CLOCK_SOURE)
892                             {
893                                 if ((audioPtr->clockSource == NULL) && (ctrl_ptr.common->bData[1] == entity_id)) /* entity_id is clock source id */
894                                 {
895                                     audioPtr->clockSource = (void *)temp;
896                                     break;
897                                 }
898                             }
899                         }
900                         ctrl_ptr.bufr += ctrl_ptr.common->bLength;
901                         length += ctrl_ptr.common->bLength;
902                     }
903                 }
904 
905 
906             }
907             else
908             {
909                 ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
910                 length = 0U;
911                 while (length < ctrlInterface_ptr->interfaceExtensionLength)
912                 {
913                     if (ctrl_ptr.common->bDescriptorType == 0x24U)
914                     {
915                         temp = (void *)ctrl_ptr.bufr;
916                         if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_FEATURE)
917                         {
918                             if ((audioPtr->fuDesc == NULL) && (ctrl_ptr.common->bData[1] == entity_id)) /* entity_id is fu id */
919                             {
920                                 audioPtr->fuDesc = (void *)temp;
921                                 entity_id = ctrl_ptr.common->bData[2]; /* entity_id is it id */
922                                 break;
923                             }
924                         }
925                     }
926                     ctrl_ptr.bufr += ctrl_ptr.common->bLength;
927                     length += ctrl_ptr.common->bLength;
928                 }
929 
930                 if (NULL == audioPtr->fuDesc)
931                 {
932                     return kStatus_USB_Error;
933                 }
934 
935                 ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
936                 length = 0U;
937                 while (length < ctrlInterface_ptr->interfaceExtensionLength)
938                 {
939                     if (ctrl_ptr.common->bDescriptorType == 0x24U)
940                     {
941                         temp = (void *)ctrl_ptr.bufr;
942                         if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_INPUT)
943                         {
944                             if ((audioPtr->itDesc == NULL) && (ctrl_ptr.common->bData[1] == entity_id)) /* entity_id is it id */
945                             {
946                                 audioPtr->itDesc = (void *)temp;
947                                 if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
948                                 {
949                                     entity_id = ctrl_ptr.common->bData[5]; /* entity_id is clock source id */
950                                 }
951                                 break;
952                             }
953                         }
954                         ctrl_ptr.bufr += ctrl_ptr.common->bLength;
955                         length += ctrl_ptr.common->bLength;
956                     }
957                 }
958 
959                 if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
960                 {
961                     if (NULL == audioPtr->itDesc)
962                     {
963                         return kStatus_USB_Error;
964                     }
965 
966                     ctrl_ptr.bufr = ctrlInterface_ptr->interfaceExtension;
967                     length = 0U;
968                     while (length < ctrlInterface_ptr->interfaceExtensionLength)
969                     {
970                         if (ctrl_ptr.common->bDescriptorType == 0x24U)
971                         {
972                             temp = (void *)ctrl_ptr.bufr;
973                             if (ctrl_ptr.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_CLOCK_SOURE)
974                             {
975                                 if ((audioPtr->itDesc == NULL) && (ctrl_ptr.common->bData[1] == entity_id)) /* entity_id is clock source id */
976                                 {
977                                     audioPtr->clockSource = (void *)temp;
978                                     break;
979                                 }
980                             }
981                         }
982                         ctrl_ptr.bufr += ctrl_ptr.common->bLength;
983                         length += ctrl_ptr.common->bLength;
984                     }
985                 }
986             }
987         }
988     }
989     else
990     {
991         return kStatus_USB_Error;
992     }
993 
994     if (alternateSetting == 0U)
995     {
996         if (callbackFn != NULL)
997         {
998             status = _USB_HostAudioOpenInterface(audioPtr);
999             callbackFn(callbackParam, NULL, 0U, kStatus_USB_Success);
1000         }
1001     }
1002     else
1003     {
1004         if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
1005         {
1006 #ifdef HOST_ECHO
1007             usb_echo("error to get transfer\r\n");
1008 #endif
1009             return kStatus_USB_Error;
1010         }
1011         audioPtr->controlCallbackFn    = callbackFn;
1012         audioPtr->controlCallbackParam = callbackParam;
1013         /* initialize transfer */
1014         transfer->callbackFn                 = _USB_HostAudioSetInterfaceCallback;
1015         transfer->callbackParam              = audioPtr;
1016         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
1017         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
1018         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
1019             ((usb_host_interface_t *)audioPtr->streamIntfHandle)->interfaceDesc->bInterfaceNumber);
1020         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
1021         transfer->setupPacket->wLength = 0;
1022         transfer->transferBuffer       = NULL;
1023         transfer->transferLength       = 0;
1024         status                         = USB_HostSendSetup(audioPtr->hostHandle, audioPtr->controlPipe, transfer);
1025 
1026         if (status == kStatus_USB_Success)
1027         {
1028             audioPtr->controlTransfer = transfer;
1029         }
1030         else
1031         {
1032             (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
1033         }
1034     }
1035 
1036     return status;
1037 }
1038 
1039 /*!
1040  * @brief set audioclass control interface.
1041  *
1042  * This function bind the interface with the audio instance.
1043  *
1044  * @param classHandle        The class handle.
1045  * @param interfaceHandle          The interface handle.
1046  * @param alternateSetting  The alternate setting value.
1047  * @param callbackFn          This callback is called after this function completes.
1048  * @param callbackParam    The first parameter in the callback function.
1049  *
1050  * @retval kStatus_USB_Success         The device is initialized successfully.
1051  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1052  * @retval kStatus_USB_Busy           There is no idle transfer.
1053  * @retval kStatus_USB_Error          send transfer fail, please reference to USB_HostSendSetup.
1054  * @retval kStatus_USB_Busy           callback return status, there is no idle pipe.
1055  * @retval kStatus_USB_TransferStall  callback return status, the transfer is stall by device.
1056  * @retval kStatus_USB_Error          callback return status, open pipe fail, please reference to USB_HostOpenPipe.
1057  */
USB_HostAudioControlSetInterface(usb_host_class_handle classHandle,usb_host_interface_handle interfaceHandle,uint8_t alternateSetting,transfer_callback_t callbackFn,void * callbackParam)1058 usb_status_t USB_HostAudioControlSetInterface(usb_host_class_handle classHandle,
1059                                               usb_host_interface_handle interfaceHandle,
1060                                               uint8_t alternateSetting,
1061                                               transfer_callback_t callbackFn,
1062                                               void *callbackParam)
1063 {
1064     usb_status_t status;
1065     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
1066     usb_host_interface_t *interface_ptr;
1067     usb_host_transfer_t *transfer;
1068     audio_descriptor_union_t ptr1;
1069     void *temp;
1070     void *header;
1071     usb_audio_ctrl_common_header_desc_t *commonHeader;
1072     uint32_t length = 0U;
1073 
1074     if (classHandle == NULL)
1075     {
1076         return kStatus_USB_InvalidParameter;
1077     }
1078     audioPtr->controlIntfHandle = interfaceHandle;
1079     interface_ptr               = (usb_host_interface_t *)interfaceHandle;
1080 
1081     status = USB_HostOpenDeviceInterface(audioPtr->deviceHandle, interfaceHandle);
1082     if (status != kStatus_USB_Success)
1083     {
1084         return status;
1085     }
1086     ptr1.bufr = interface_ptr->interfaceExtension;
1087 
1088     length = 0U;
1089 
1090     while (length < interface_ptr->interfaceExtensionLength)
1091     {
1092         if (((interface_ptr->interfaceDesc->bDescriptorType == 0x04U) &&
1093              (interface_ptr->interfaceDesc->bAlternateSetting == alternateSetting)) ||
1094             ((ptr1.common->bDescriptorType == 0x04U) && (ptr1.interface->bAlternateSetting == alternateSetting)))
1095         {
1096             break;
1097         }
1098 
1099         ptr1.bufr += ptr1.common->bLength;
1100         length += ptr1.common->bLength;
1101     }
1102     while (length < interface_ptr->interfaceExtensionLength)
1103     {
1104         if (ptr1.common->bDescriptorType == 0x24U)
1105         {
1106             temp = (void *)ptr1.bufr;
1107             if (ptr1.common->bData[0] == USB_AUDIO_DESC_SUBTYPE_CS_HEADER)
1108             {
1109                 audioPtr->headerDesc         = (void *)temp;
1110                 commonHeader                 = (usb_audio_ctrl_common_header_desc_t *)temp;
1111                 header                       = (void *)&commonHeader->bcdcdc;
1112                 audioPtr->deviceAudioVersion = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(((uint8_t *)header));
1113             }
1114             else
1115             {
1116                 /*no action*/
1117             }
1118         }
1119         ptr1.bufr += ptr1.common->bLength;
1120         length += ptr1.common->bLength;
1121     }
1122 
1123     if (alternateSetting == 0U)
1124     {
1125         if (callbackFn != NULL)
1126         {
1127             callbackFn(callbackParam, NULL, 0U, kStatus_USB_Success);
1128         }
1129     }
1130     else
1131     {
1132         if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
1133         {
1134 #ifdef HOST_ECHO
1135             usb_echo("error to get transfer\r\n");
1136 #endif
1137             return kStatus_USB_Error;
1138         }
1139         audioPtr->controlCallbackFn    = callbackFn;
1140         audioPtr->controlCallbackParam = callbackParam;
1141         /* initialize transfer */
1142         transfer->callbackFn                 = _USB_HostAudioControlCallback;
1143         transfer->callbackParam              = audioPtr;
1144         transfer->setupPacket->bRequest      = USB_REQUEST_STANDARD_SET_INTERFACE;
1145         transfer->setupPacket->bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
1146         transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(
1147             ((usb_host_interface_t *)audioPtr->controlIntfHandle)->interfaceDesc->bInterfaceNumber);
1148         transfer->setupPacket->wValue  = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
1149         transfer->setupPacket->wLength = 0;
1150         transfer->transferBuffer       = NULL;
1151         transfer->transferLength       = 0;
1152         status                         = USB_HostSendSetup(audioPtr->hostHandle, audioPtr->controlPipe, transfer);
1153 
1154         if (status == kStatus_USB_Success)
1155         {
1156             audioPtr->controlTransfer = transfer;
1157         }
1158         else
1159         {
1160             (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
1161         }
1162     }
1163 
1164     return status;
1165 }
1166 
1167 /*!
1168  * @brief get pipe max packet size.
1169  *
1170  * @param classHandle the class handle.
1171  * @param pipeType    It's value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
1172  * USB_ENDPOINT_INTERRUPT.
1173  *                     Please reference to usb_spec.h
1174  * @param direction    pipe direction.
1175  *
1176  * @retval 0        The classHandle is NULL.
1177  * @retval max packet size.
1178  */
USB_HostAudioPacketSize(usb_host_class_handle classHandle,uint8_t pipeType,uint8_t direction)1179 uint16_t USB_HostAudioPacketSize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
1180 {
1181     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
1182     if (classHandle == NULL)
1183     {
1184         return 0U;
1185     }
1186 
1187     if (pipeType == USB_ENDPOINT_ISOCHRONOUS)
1188     {
1189         if (direction == USB_IN)
1190         {
1191             return audioPtr->inPacketSize;
1192         }
1193         else
1194         {
1195             return audioPtr->outPacketSize;
1196         }
1197     }
1198     return 0U;
1199 }
1200 
1201 /*!
1202  * @brief audio stream receive data.
1203  *
1204  * This function implements audioreceiving data.
1205  *
1206  * @param classHandle      The class handle.
1207  * @param buffer                The buffer pointer.
1208  * @param bufferLen          The buffer length.
1209  * @param callbackFn         This callback is called after this function completes.
1210  * @param callbackParam  The first parameter in the callback function.
1211  *
1212  * @retval kStatus_USB_Success          Receive request successfully.
1213  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1214  * @retval kStatus_USB_Busy               There is no idle transfer.
1215  * @retval kStatus_USB_Error              pipe is not initialized.
1216  *                                                       Or, send transfer fail, please reference to USB_HostRecv.
1217  */
USB_HostAudioStreamRecv(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLen,transfer_callback_t callbackFn,void * callbackParam)1218 usb_status_t USB_HostAudioStreamRecv(usb_host_class_handle classHandle,
1219                                      uint8_t *buffer,
1220                                      uint32_t bufferLen,
1221                                      transfer_callback_t callbackFn,
1222                                      void *callbackParam)
1223 {
1224     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
1225     usb_host_transfer_t *transfer;
1226 
1227     if (classHandle == NULL)
1228     {
1229         return kStatus_USB_InvalidHandle;
1230     }
1231 
1232     if (audioPtr->isoInPipe == NULL)
1233     {
1234         return kStatus_USB_Error;
1235     }
1236 
1237     if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
1238     {
1239 #ifdef HOST_ECHO
1240         usb_echo("error to get transfer\r\n");
1241 #endif
1242         return kStatus_USB_Error;
1243     }
1244     audioPtr->inCallbackFn    = callbackFn;
1245     audioPtr->inCallbackParam = callbackParam;
1246     transfer->transferBuffer  = buffer;
1247     transfer->transferLength  = bufferLen;
1248     transfer->callbackFn      = _USB_HostAudioStreamIsoInPipeCallback;
1249     transfer->callbackParam   = audioPtr;
1250 
1251     if (USB_HostRecv(audioPtr->hostHandle, audioPtr->isoInPipe, transfer) != kStatus_USB_Success)
1252     {
1253 #ifdef HOST_ECHO
1254         usb_echo("failed to USB_HostRecv\r\n");
1255 #endif
1256         (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
1257         return kStatus_USB_Error;
1258     }
1259 
1260     return kStatus_USB_Success;
1261 }
1262 
1263 /*!
1264  * @brief audio stream send data.
1265  *
1266  * This function implements audio sending data.
1267  *
1268  * @param classHandle      The class handle.
1269  * @param buffer                The buffer pointer.
1270  * @param bufferLen          The buffer length.
1271  * @param callbackFn         This callback is called after this function completes.
1272  * @param callbackParam  The first parameter in the callback function.
1273  *
1274  * @retval kStatus_USB_Success          Receive request successfully.
1275  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1276  * @retval kStatus_USB_Busy               There is no idle transfer.
1277  * @retval kStatus_USB_Error              pipe is not initialized.
1278  *                                                       Or, send transfer fail, please reference to USB_HostSend.
1279  */
USB_HostAudioStreamSend(usb_host_class_handle classHandle,uint8_t * buffer,uint32_t bufferLen,transfer_callback_t callbackFn,void * callbackParam)1280 usb_status_t USB_HostAudioStreamSend(usb_host_class_handle classHandle,
1281                                      uint8_t *buffer,
1282                                      uint32_t bufferLen,
1283                                      transfer_callback_t callbackFn,
1284                                      void *callbackParam)
1285 {
1286     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
1287     usb_host_transfer_t *transfer;
1288 
1289     if (classHandle == NULL)
1290     {
1291         return kStatus_USB_InvalidHandle;
1292     }
1293 
1294     if (audioPtr->isoOutPipe == NULL)
1295     {
1296         return kStatus_USB_Error;
1297     }
1298 
1299     if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
1300     {
1301 #ifdef HOST_ECHO
1302         usb_echo("error to get transfer\r\n");
1303 #endif
1304         return kStatus_USB_Error;
1305     }
1306     audioPtr->outCallbackFn    = callbackFn;
1307     audioPtr->outCallbackParam = callbackParam;
1308     transfer->transferBuffer   = buffer;
1309     transfer->transferLength   = bufferLen;
1310     transfer->callbackFn       = _USB_HostAudioStreamIsoOutPipeCallback;
1311     transfer->callbackParam    = audioPtr;
1312 
1313     if (USB_HostSend(audioPtr->hostHandle, audioPtr->isoOutPipe, transfer) != kStatus_USB_Success)
1314     {
1315 #ifdef HOST_ECHO
1316         usb_echo("failed to USB_HostSend\r\n");
1317 #endif
1318         (void)USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
1319         return kStatus_USB_Error;
1320     }
1321 
1322     return kStatus_USB_Success;
1323 }
1324 /*!
1325  * @brief get audio control current altsetting descriptor.
1326  *
1327  * This function implements get audio stream current altsetting descriptor.
1328  *
1329  * @param classHandle               The class handle.
1330  * @param DescriptorType            The descriptor type.
1331  * @param DescriptorSubType         The descriptor subtype, 0 for no subtype.
1332  * @param Descriptor                The pointer of descriptor pointer.
1333  *
1334  * @retval kStatus_USB_Success          Get audio stream current altsetting descriptor request successfully.
1335  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1336  *
1337  */
USB_HostAudioControlGetCurrentAltsettingSpecificDescriptors(usb_host_class_handle classHandle,uint32_t DescriptorType,uint32_t DescriptorSubType,void ** Descriptor)1338 usb_status_t USB_HostAudioControlGetCurrentAltsettingSpecificDescriptors(
1339 
1340     usb_host_class_handle classHandle, uint32_t DescriptorType, uint32_t DescriptorSubType, void **Descriptor)
1341 {
1342     audio_instance_t *audioPtr   = (audio_instance_t *)classHandle;
1343     usb_status_t status          = kStatus_USB_Error;
1344     uint32_t **descriptorPointer = (uint32_t **)Descriptor;
1345     if ((classHandle == NULL) || NULL == Descriptor)
1346     {
1347         return kStatus_USB_InvalidParameter;
1348     }
1349 
1350     if (USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE == DescriptorType)
1351     {
1352         if (AUDIO_DEVICE_VERSION_01 == audioPtr->deviceAudioVersion)
1353         {
1354             if (USB_AUDIO_DESC_SUBTYPE_CS_EXTENSION <= DescriptorSubType)
1355             {
1356                 /*descriptor type code bigger than EXTENSION is not support by audio 1.0*/
1357                 return kStatus_USB_InvalidParameter;
1358             }
1359         }
1360         switch (DescriptorSubType)
1361         {
1362             case USB_AUDIO_DESC_SUBTYPE_CS_HEADER:
1363                 *descriptorPointer = (uint32_t *)audioPtr->headerDesc;
1364                 status             = kStatus_USB_Success;
1365                 break;
1366             case USB_AUDIO_DESC_SUBTYPE_CS_INPUT:
1367                 *descriptorPointer = (uint32_t *)audioPtr->itDesc;
1368                 status             = kStatus_USB_Success;
1369                 break;
1370             case USB_AUDIO_DESC_SUBTYPE_CS_OUTPUT:
1371                 *descriptorPointer = (uint32_t *)audioPtr->otDesc;
1372                 status             = kStatus_USB_Success;
1373                 break;
1374             case USB_AUDIO_DESC_SUBTYPE_CS_FEATURE:
1375                 *descriptorPointer = (uint32_t *)audioPtr->fuDesc;
1376                 status             = kStatus_USB_Success;
1377                 break;
1378             default:
1379                 /*no action*/
1380                 break;
1381         }
1382     }
1383 
1384     return status;
1385 }
1386 /*!
1387  * @brief get audio control current altsetting descriptor.
1388  *
1389  * This function implements get audio stream current altsetting descriptor.
1390  *
1391  * @param classHandle               The class handle.
1392  * @param DescriptorType            The descriptor type.
1393  * @param DescriptorSubType         The descriptor subtype, default 0.
1394  * @param Descriptor                The pointer of descriptor pointer.
1395  *
1396  * @retval kStatus_USB_Success          Get audio stream current altsetting descriptor request successfully.
1397  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1398  *
1399  */
USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(usb_host_class_handle classHandle,uint32_t DescriptorType,uint32_t DescriptorSubType,void ** Descriptor)1400 usb_status_t USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors(
1401 
1402     usb_host_class_handle classHandle, uint32_t DescriptorType, uint32_t DescriptorSubType, void **Descriptor)
1403 {
1404     audio_instance_t *audioPtr   = (audio_instance_t *)classHandle;
1405     usb_status_t status          = kStatus_USB_Error;
1406     uint32_t **descriptorPointer = (uint32_t **)Descriptor;
1407     void *temp;
1408 
1409     if ((classHandle == NULL) || NULL == Descriptor)
1410     {
1411         return kStatus_USB_InvalidParameter;
1412     }
1413 
1414     if (USB_AUDIO_DESCRIPTOR_TYPE_CS_INTERFACE == DescriptorType)
1415     {
1416         if (AUDIO_DEVICE_VERSION_01 == audioPtr->deviceAudioVersion)
1417         {
1418             switch (DescriptorSubType)
1419             {
1420                 case USB_AUDIO_DESC_SUBTYPE_AS_GENERAL:
1421                     *descriptorPointer = (uint32_t *)audioPtr->asIntfDesc;
1422                     status             = kStatus_USB_Success;
1423                     break;
1424                 case USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE:
1425                     *descriptorPointer = (uint32_t *)audioPtr->formatTypeDesc;
1426                     status             = kStatus_USB_Success;
1427                     break;
1428                 default:
1429                     /*no action*/
1430                     break;
1431             }
1432         }
1433         else if (AUDIO_DEVICE_VERSION_02 == audioPtr->deviceAudioVersion)
1434         {
1435             switch (DescriptorSubType)
1436             {
1437                 case USB_AUDIO_DESC_SUBTYPE_AS_GENERAL_20:
1438                     *descriptorPointer = (uint32_t *)audioPtr->asIntfDesc;
1439                     status             = kStatus_USB_Success;
1440                     break;
1441                 case USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_TYPE_20:
1442                     *descriptorPointer = (uint32_t *)audioPtr->formatTypeDesc;
1443                     status             = kStatus_USB_Success;
1444                     break;
1445                 case USB_AUDIO_DESC_SUBTYPE_AS_FORMAT_ENCODER_20:
1446                     /*no action*/
1447                     break;
1448                 default:
1449                     /*no action*/
1450                     break;
1451             }
1452         }
1453         else
1454         {
1455             /*To DO*/
1456         }
1457     }
1458     else if (USB_DESCRIPTOR_TYPE_ENDPOINT == DescriptorType)
1459     {
1460         if (0x0U == DescriptorSubType)
1461         {
1462             /*iso data endpoint descriptor*/
1463             temp               = (void *)audioPtr->isoEndpDesc;
1464             *descriptorPointer = (uint32_t *)temp;
1465             status             = kStatus_USB_Success;
1466         }
1467         else
1468         {
1469             /*TO DO*/
1470         }
1471     }
1472     else
1473     {
1474         /*To DO*/
1475     }
1476 
1477     return status;
1478 }
1479 
1480 /*!
1481  * @brief get audio stream current altsetting descriptor.
1482  * @deprecated Do not use this function. It has been superceded by @ref
1483  * USB_HostAudioStreamGetCurrentAltsettingSpecificDescriptors.
1484  *
1485  * This function implements get audio stream current altsetting descriptor.
1486  *
1487  * @param classHandle               The class handle.
1488  * @param asIntfDesc                 The pointer of class specific AS interface descriptor.
1489  * @param formatTypeDesc       The pointer of format type descriptor.
1490  * @param isoEndpDesc    The pointer of specific iso endp descriptor.
1491  *
1492  * @retval kStatus_USB_Success          Get audio stream current altsetting descriptor request successfully.
1493  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
1494  *
1495  */
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)1496 usb_status_t USB_HostAudioStreamGetCurrentAltsettingDescriptors(
1497 
1498     usb_host_class_handle classHandle,
1499     usb_audio_stream_spepific_as_intf_desc_t **asIntfDesc,
1500     usb_audio_stream_format_type_desc_t **formatTypeDesc,
1501     usb_descriptor_endpoint_t **isoEndpDesc)
1502 {
1503     audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
1504 
1505     if (classHandle == NULL)
1506     {
1507         return kStatus_USB_InvalidHandle;
1508     }
1509     *asIntfDesc     = (usb_audio_stream_spepific_as_intf_desc_t *)audioPtr->asIntfDesc;
1510     *formatTypeDesc = (usb_audio_stream_format_type_desc_t *)audioPtr->formatTypeDesc;
1511     *isoEndpDesc    = (usb_descriptor_endpoint_t *)audioPtr->isoEndpDesc;
1512 
1513     return kStatus_USB_Success;
1514 }
1515 /*!
1516  * @brief usb audio set/get feature unit request.
1517  *
1518  * This function implements usb audio feature unit request.
1519  *
1520  * @param classHandle      The class handle.
1521  * @param csAndCn          The CS and CN or MCN for wValue field in setup Request.
1522  * @param cmdCode          The bRequest code in lower 8bit of lower word and get(1)/set(0) flag in higher 8bit of lower
1523  * word.
1524  * @param buf              The feature unit request buffer pointer.
1525  * @param callbackFn       This callback is called after this function completes.
1526  * @param callbackParam  The first parameter in the callback function.
1527  *
1528  * @retval kStatus_USB_Success            Feature unit request successfully.
1529  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
1530  * @retval kStatus_USB_Busy                There is no idle transfer.
1531  * @retval kStatus_USB_Error                Send transfer fail, please reference to USB_HostSendSetup.
1532  *
1533  */
USB_HostAudioGetSetFeatureUnitRequest(usb_host_class_handle classHandle,uint32_t csAndCn,uint32_t cmdCode,void * buf,uint32_t bufLen,transfer_callback_t callbackFn,void * callbackParam)1534 usb_status_t USB_HostAudioGetSetFeatureUnitRequest(usb_host_class_handle classHandle,
1535                                                    uint32_t csAndCn,
1536                                                    uint32_t cmdCode,
1537                                                    void *buf,
1538                                                    uint32_t bufLen,
1539                                                    transfer_callback_t callbackFn,
1540                                                    void *callbackParam)
1541 {
1542     audio_instance_t *if_ptr;
1543     uint8_t *bmacontrols = NULL;
1544     usb_audio_ctrl_common_fu_desc *fuDesc;
1545     uint16_t windex;
1546     uint8_t request;
1547     uint8_t atribute_index;
1548     uint16_t length = 0U;
1549     uint8_t typeRequest;
1550     uint8_t controlSelector;
1551 
1552     usb_status_t status = kStatus_USB_Error;
1553 
1554     if (classHandle == NULL)
1555     {
1556         return kStatus_USB_InvalidHandle;
1557     }
1558 
1559     if_ptr = (audio_instance_t *)classHandle;
1560 
1561     /* Check whether this attribute valid or not */
1562     if (if_ptr->fuDesc == NULL)
1563     {
1564         return kStatus_USB_Error;
1565     }
1566     fuDesc = (usb_audio_ctrl_common_fu_desc *)if_ptr->fuDesc;
1567     if (AUDIO_DEVICE_VERSION_01 == if_ptr->deviceAudioVersion)
1568     {
1569         windex         = (uint16_t)((uint16_t)((uint16_t)(fuDesc->fuDesc10.bunitid) << 8U) | (if_ptr->streamIfnum));
1570         atribute_index = (uint8_t)(fuDesc->fuDesc10.bcontrolsize * ((uint16_t)csAndCn & 0xFFU));
1571         /*Size of this descriptor, in bytes: 7+(ch+1)*n*/
1572         if (atribute_index < (fuDesc->fuDesc10.blength - 7U))
1573         {
1574             bmacontrols = &(fuDesc->fuDesc10.bcontrolsize);
1575         }
1576     }
1577     else if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1578     {
1579         windex = (uint16_t)((uint16_t)((uint16_t)(fuDesc->fuDesc20.bunitid) << 8U) | (if_ptr->streamIfnum));
1580         /*BmControl is 4byte, refer to *audio2.0 4.7.2.8 Size of this descriptor, in bytes: 6+(ch+1)*4*/
1581         atribute_index = (uint8_t)(4U * ((uint16_t)csAndCn & 0xFFU));
1582 
1583         if (atribute_index < (fuDesc->fuDesc20.blength - 6U))
1584         {
1585             bmacontrols = &(fuDesc->fuDesc20.bmaControls0[0]);
1586         }
1587     }
1588     else
1589     {
1590         /*TO DO*/
1591     }
1592     if (bmacontrols == NULL)
1593     {
1594         return kStatus_USB_Error;
1595     }
1596     request = (uint8_t)(((uint16_t)cmdCode & 0xFFU));
1597 
1598     controlSelector = (uint8_t)((uint16_t)(csAndCn >> 8) & 0xFFU);
1599     if (AUDIO_DEVICE_VERSION_01 == if_ptr->deviceAudioVersion)
1600     {
1601         /*control selector */
1602         switch (controlSelector)
1603         {
1604             /*note ,all the length is defined in audio1.0 Spec chapter 5.2.2.4.3*/
1605             case AUDIO_FU_MUTE:
1606                 status = kStatus_USB_Success;
1607                 length = 1U;
1608                 break;
1609             case AUDIO_FU_VOLUME:
1610                 status = kStatus_USB_Success;
1611                 length = 2U;
1612                 break;
1613             case AUDIO_FU_BASS:
1614                 /*TO DO*/
1615                 break;
1616             default:
1617                 /*no action*/
1618                 break;
1619         }
1620     }
1621     else if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1622     {
1623         if ((request != USB_AUDIO_CS_REQUEST_CODE_RANGE_20) && (request != USB_AUDIO_CS_REQUEST_CODE_CUR_20))
1624         {
1625             return kStatus_USB_Error;
1626         }
1627         switch (controlSelector)
1628         {
1629             /*note ,all the length is defined in audio2.0 Spec chapter 5.2.5.7*/
1630             case AUDIO_FU_MUTE:
1631 
1632                 if (bufLen != 1U)
1633                 {
1634                     return kStatus_USB_Error;
1635                 }
1636                 status = kStatus_USB_Success;
1637                 length = 1U;
1638                 break;
1639             case AUDIO_FU_VOLUME:
1640                 status = kStatus_USB_Success;
1641 
1642                 if (USB_AUDIO_CS_REQUEST_CODE_RANGE_20 == request)
1643                 {
1644                     /*the len for volume is 2+6*n*/
1645                     if (bufLen < 8U)
1646                     {
1647                         return kStatus_USB_Error;
1648                     }
1649                 }
1650                 else if (USB_AUDIO_CS_REQUEST_CODE_CUR_20 == request)
1651                 {
1652                     if (bufLen != 2U)
1653                     {
1654                         return kStatus_USB_Error;
1655                     }
1656                 }
1657                 else
1658                 {
1659                     /*TO DO*/
1660                 }
1661                 length = (uint16_t)bufLen;
1662 
1663                 break;
1664             case AUDIO_FU_BASS:
1665                 /*TO DO*/
1666                 break;
1667             default:
1668                 /*no action*/
1669                 break;
1670         }
1671     }
1672     else
1673     {
1674         /*TO DO*/
1675     }
1676 
1677     if (status != kStatus_USB_Success)
1678     {
1679         /*the request is not support*/
1680         return kStatus_USB_Error;
1681     }
1682     if (0U == ((uint16_t)(cmdCode >> 8U) & 0xFFU))
1683     {
1684         /*refer to audio Spec 2.0 chapter 5.2.2*/
1685         typeRequest = 0x21U;
1686     }
1687     else
1688     {
1689         typeRequest = 0xA1U;
1690     }
1691 
1692     status = _USB_HostAudioControl(classHandle, typeRequest, request, (uint16_t)csAndCn, windex, length, (uint8_t *)buf,
1693                                    callbackFn, callbackParam);
1694 
1695     return status;
1696 }
1697 /*!
1698  * @brief usb audio set/get feature unit request.
1699  *
1700  * This function implements usb audio feature unit request.
1701  *
1702  * @param classHandle      The class handle.
1703  * @param csAndCn          The CS and CN or MCN for wValue field in setup Request.
1704  * @param cmdCode          The bRequest code in lower 8bit of lower word and get(1)/set(0) flag in higher 8bit of lower
1705  word.
1706  * @param buf              The feature unit request buffer pointer.
1707 
1708  * @param callbackFn       This callback is called after this function completes.
1709  * @param callbackParam  The first parameter in the callback function.
1710  *
1711  * @retval kStatus_USB_Success            Feature unit request successfully.
1712  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
1713  * @retval kStatus_USB_Busy                There is no idle transfer.
1714  * @retval kStatus_USB_Error                Send transfer fail, please reference to USB_HostSendSetup.
1715  *
1716  */
USB_HostAudioGetSetClockSourceRequest(usb_host_class_handle classHandle,uint32_t csAndCn,uint32_t cmdCode,void * buf,uint32_t bufLen,transfer_callback_t callbackFn,void * callbackParam)1717 usb_status_t USB_HostAudioGetSetClockSourceRequest(usb_host_class_handle classHandle,
1718                                                    uint32_t csAndCn,
1719                                                    uint32_t cmdCode,
1720                                                    void *buf,
1721                                                    uint32_t bufLen,
1722                                                    transfer_callback_t callbackFn,
1723                                                    void *callbackParam)
1724 {
1725     audio_instance_t *if_ptr;
1726     usb_audio_2_0_ctrl_clock_source_desc_t *clockDesc;
1727     uint16_t windex;
1728     uint16_t controlSelector;
1729     uint8_t length = 0U;
1730     uint8_t typeRequest;
1731     uint8_t request;
1732 
1733     usb_status_t status = kStatus_USB_Error;
1734 
1735     if (classHandle == NULL)
1736     {
1737         return kStatus_USB_InvalidParameter;
1738     }
1739 
1740     if_ptr = (audio_instance_t *)classHandle;
1741 
1742     if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1743     {
1744         clockDesc = (usb_audio_2_0_ctrl_clock_source_desc_t *)if_ptr->clockSource;
1745         windex    = (uint16_t)((uint16_t)((uint16_t)(clockDesc->bClockID) << 8U) | (if_ptr->streamIfnum));
1746     }
1747     else
1748     {
1749         return kStatus_USB_Error;
1750     }
1751     request         = (uint8_t)(((uint16_t)cmdCode & 0xFFU));
1752     controlSelector = (uint8_t)((uint16_t)(csAndCn >> 8U) & 0xFFU);
1753 
1754     if (USB_AUDIO_CS_SAM_FREQ_CONTROL_20 == controlSelector)
1755     {
1756         /*note ,all the length is defined in audio2.0 Spec chapter 5.2.5.1.1*/
1757 
1758         if (USB_AUDIO_CS_REQUEST_CODE_RANGE_20 == request)
1759         {
1760             /*the len for volume is 2+6*n*/
1761             if (bufLen < 12U)
1762             {
1763                 return kStatus_USB_Error;
1764             }
1765             else
1766             {
1767                 length = (uint8_t)bufLen;
1768             }
1769         }
1770         else if (USB_AUDIO_CS_REQUEST_CODE_CUR_20 == request)
1771         {
1772             if (bufLen != 4U)
1773             {
1774                 return kStatus_USB_Error;
1775             }
1776             length = (uint8_t)bufLen;
1777         }
1778         else
1779         {
1780             return kStatus_USB_Error;
1781         }
1782         status = kStatus_USB_Success;
1783     }
1784     else if (USB_AUDIO_CS_CLOCK_VALID_CONTROL_20 == controlSelector)
1785     {
1786         status = kStatus_USB_Success;
1787         if (bufLen < 1U)
1788         {
1789             return kStatus_USB_Error;
1790         }
1791         length = 1U;
1792     }
1793     else
1794     {
1795         /**TO DO*/
1796     }
1797 
1798     if (status != kStatus_USB_Success)
1799     {
1800         /*the request is not support*/
1801         return kStatus_USB_Error;
1802     }
1803 
1804     if (0U == ((uint16_t)(cmdCode >> 8U) & 0xFFU))
1805     {
1806         /*refer to audio Spec 2.0 chapter 5.2.2*/
1807         typeRequest = 0x21U;
1808     }
1809     else
1810     {
1811         typeRequest = 0xA1U;
1812     }
1813 
1814     status = _USB_HostAudioControl(classHandle, typeRequest, request, (uint16_t)csAndCn, windex, length, (uint8_t *)buf,
1815                                    callbackFn, callbackParam);
1816 
1817     return status;
1818 }
1819 
1820 /*!
1821  * @brief usb audio feature unit request.
1822  * @deprecated Do not use this function. It has been superceded by @ref USB_HostAudioGetSetFeatureUnitRequest.
1823  *
1824  * This function implements usb audio feature unit request.
1825  *
1826  * @param classHandle      The class handle.
1827  * @param channelNo        The channel number of audio feature unit.
1828  * @param buf              The feature unit request buffer pointer.
1829  * @param cmdCode          The feature unit command code, for example USB_AUDIO_GET_CUR_MUTE etc.
1830  * @param callbackFn         This callback is called after this function completes.
1831  * @param callbackParam  The first parameter in the callback function.
1832  *
1833  * @retval kStatus_USB_Success            Feature unit request successfully.
1834  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
1835  * @retval kStatus_USB_Busy                There is no idle transfer.
1836  * @retval kStatus_USB_Error                Send transfer fail, please reference to USB_HostSendSetup.
1837  *
1838  */
USB_HostAudioFeatureUnitRequest(usb_host_class_handle classHandle,uint8_t channelNo,void * buf,uint32_t cmdCode,transfer_callback_t callbackFn,void * callbackParam)1839 usb_status_t USB_HostAudioFeatureUnitRequest(usb_host_class_handle classHandle,
1840                                              uint8_t channelNo,
1841                                              void *buf,
1842                                              uint32_t cmdCode,
1843                                              transfer_callback_t callbackFn,
1844                                              void *callbackParam)
1845 { /* Body */
1846     uint16_t windex;
1847     uint16_t request_value;
1848     audio_instance_t *if_ptr;
1849     usb_audio_request_t *p_feature_request;
1850     usb_audio_ctrl_fu_desc_t *fuDesc;
1851     uint8_t *bmacontrols = NULL;
1852     uint8_t atribute_index;
1853     usb_status_t status;
1854 
1855     if ((classHandle == NULL))
1856     {
1857         return kStatus_USB_InvalidHandle;
1858     }
1859 
1860     if_ptr = (audio_instance_t *)classHandle;
1861     if (AUDIO_DEVICE_VERSION_01 != if_ptr->deviceAudioVersion)
1862     {
1863         return kStatus_USB_Error;
1864     }
1865     /* pointer to command */
1866     p_feature_request = &(s_usbAudioFuRequests[(uint8_t)cmdCode & 0xfU]);
1867     /* get request value */
1868     request_value = (uint16_t)((uint16_t)((uint16_t)p_feature_request->requestValue << 8U) | channelNo);
1869 
1870     /* Check whether this attribute valid or not */
1871     if (if_ptr->fuDesc == NULL)
1872     {
1873         return kStatus_USB_Error;
1874     }
1875     fuDesc         = (usb_audio_ctrl_fu_desc_t *)if_ptr->fuDesc;
1876     windex         = (uint16_t)((uint16_t)((uint16_t)(fuDesc->bunitid) << 8U) | (if_ptr->streamIfnum));
1877     atribute_index = fuDesc->bcontrolsize * channelNo;
1878 
1879     if (atribute_index < (fuDesc->blength - 7U))
1880     {
1881         bmacontrols = &(fuDesc->bcontrolsize);
1882     }
1883 
1884     if (bmacontrols == NULL)
1885     {
1886         return kStatus_USB_Error;
1887     }
1888 
1889     status = _USB_HostAudioControl(classHandle, (p_feature_request->typeRequest | ((uint8_t)cmdCode & 0x80U)),
1890                                    (p_feature_request->codeRequest | ((uint8_t)cmdCode & 0x80U)), request_value, windex,
1891                                    p_feature_request->length, (uint8_t *)buf, callbackFn, callbackParam);
1892 
1893     return status;
1894 }
1895 /*!
1896  * @brief usb audio set/get endp unit request.
1897  *
1898  * This function implements usb audio feature unit request.
1899  *
1900  * @param classHandle      The class handle.
1901  * @param csAndCn          The CS for wValue field in setup Request.
1902  * @param cmdCode          The bRequest code in lower 8bit of lower word and get(1)/set(0) flag in higher 8bit of lower
1903  word.
1904  * @param buf              The feature unit request buffer pointer.
1905 
1906  * @param callbackFn       This callback is called after this function completes.
1907  * @param callbackParam  The first parameter in the callback function.
1908  *
1909  * @retval kStatus_USB_Success            Feature unit request successfully.
1910  * @retval kStatus_USB_InvalidHandle    The classHandle is NULL pointer.
1911  * @retval kStatus_USB_Busy                There is no idle transfer.
1912  * @retval kStatus_USB_Error                Send transfer fail, please reference to USB_HostSendSetup.
1913  *
1914  */
USB_HostAudioGetSetEndpointRequest(usb_host_class_handle classHandle,uint32_t csAndCn,uint32_t cmdCode,void * buf,uint32_t bufLen,transfer_callback_t callbackFn,void * callbackParam)1915 usb_status_t USB_HostAudioGetSetEndpointRequest(usb_host_class_handle classHandle,
1916                                                 uint32_t csAndCn,
1917                                                 uint32_t cmdCode,
1918                                                 void *buf,
1919                                                 uint32_t bufLen,
1920                                                 transfer_callback_t callbackFn,
1921                                                 void *callbackParam)
1922 {
1923     audio_instance_t *if_ptr;
1924     uint16_t windex;
1925     uint8_t request;
1926     uint8_t length = 0U;
1927     uint8_t typeRequest;
1928     uint8_t controlSelector;
1929 
1930     usb_status_t status = kStatus_USB_Error;
1931 
1932     if (classHandle == NULL)
1933     {
1934         return kStatus_USB_InvalidHandle;
1935     }
1936 
1937     if_ptr = (audio_instance_t *)classHandle;
1938 
1939     if (AUDIO_DEVICE_VERSION_01 == if_ptr->deviceAudioVersion)
1940     {
1941         if ((NULL == if_ptr->isoInPipe) && (NULL == if_ptr->isoOutPipe))
1942         {
1943             return kStatus_USB_InvalidParameter;
1944         }
1945         else if (NULL != if_ptr->isoInPipe)
1946         {
1947             windex = (((uint16_t)if_ptr->isoEpNum) | 0x80U);
1948         }
1949         else
1950         {
1951             windex = if_ptr->isoEpNum;
1952         }
1953     }
1954     else if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1955     {
1956         /*TO DO*/
1957     }
1958     else
1959     {
1960         /*TO DO*/
1961     }
1962 
1963     request = (uint8_t)(((uint16_t)cmdCode & 0xFFU));
1964 
1965     controlSelector = (uint8_t)((uint16_t)(csAndCn >> 8U) & 0xFFU);
1966     if (AUDIO_DEVICE_VERSION_01 == if_ptr->deviceAudioVersion)
1967     {
1968         /*control selector */
1969         /*note ,all the length is defined in audio1.0 Spec chapter 5.2.3.2.3*/
1970         if (USB_AUDIO_EP_CS_SAMPING_FREQ_CONTROL == controlSelector)
1971         {
1972             if (bufLen > 3U)
1973             {
1974                 /*fixed length*/
1975                 length = 3U;
1976                 status = kStatus_USB_Success;
1977             }
1978             else
1979             {
1980                 /*TO DO*/
1981             }
1982         }
1983         else if (USB_AUDIO_EP_CS_PINTCH_CONTROL == controlSelector)
1984         {
1985             /*TO DO*/
1986         }
1987         else
1988         {
1989             /*TO DO*/
1990         }
1991     }
1992     else if (AUDIO_DEVICE_VERSION_02 == if_ptr->deviceAudioVersion)
1993     {
1994         switch (controlSelector)
1995         {
1996             /*note ,all the length is defined in audio2.0 Spec chapter 5.2.6*/
1997             case USB_AUDIO_EP_CS_PINTCH_CONTROL_20:
1998                 /*TO DO*/
1999                 break;
2000             case USB_AUDIO_EP_CS_OVERRUN_CONTROL_20:
2001                 /*TO DO*/
2002                 break;
2003             case USB_AUDIO_EP_CS_UNDERRUN_CONTROL_20:
2004                 /*TO DO*/
2005                 break;
2006             default:
2007                 /*no action*/
2008                 break;
2009         }
2010     }
2011     else
2012     {
2013         /*TO DO*/
2014     }
2015 
2016     if (status != kStatus_USB_Success)
2017     {
2018         /*the request is not support*/
2019         return kStatus_USB_Error;
2020     }
2021     if (0U == ((uint16_t)(cmdCode >> 8U) & 0xFFU))
2022     {
2023         /*refer to audio Spec 2.0 chapter 5.2.2*/
2024         typeRequest = 0x22U;
2025     }
2026     else
2027     {
2028         typeRequest = 0xA2U;
2029     }
2030 
2031     status = _USB_HostAudioControl(classHandle, typeRequest, request, (uint16_t)csAndCn, windex, length, (uint8_t *)buf,
2032                                    callbackFn, callbackParam);
2033 
2034     return status;
2035 }
2036 /*!
2037  * @brief usb audio endpoint request.
2038  * @deprecated Do not use this function. It has been superceded by @ref USB_HostAudioGetSetEndpointRequest.
2039  *
2040  * This function implements usb audio endpoint request.
2041  *
2042  * @param classHandle      The class handle.
2043  * @param buf                    The feature unit buffer pointer.
2044  * @param cmdCode          The feature unit command code, for example USB_AUDIO_GET_CUR_PITCH etc .
2045  * @param callbackFn         This callback is called after this function completes.
2046  * @param callbackParam   The first parameter in the callback function.
2047  *
2048  * @retval kStatus_USB_Success          Endpoint request successfully.
2049  * @retval kStatus_USB_InvalidHandle  The classHandle is NULL pointer.
2050  * @retval kStatus_USB_Busy               There is no idle transfer.
2051  * @retval kStatus_USB_Error               Send transfer fail, please reference to USB_HostSendSetup.
2052  *
2053  */
USB_HostAudioEndpointRequest(usb_host_class_handle classHandle,void * buf,uint32_t cmdCode,transfer_callback_t callbackFn,void * callbackParam)2054 usb_status_t USB_HostAudioEndpointRequest(
2055     usb_host_class_handle classHandle, void *buf, uint32_t cmdCode, transfer_callback_t callbackFn, void *callbackParam)
2056 {
2057     uint8_t endp_num;
2058     usb_status_t status;
2059     uint16_t request_value;
2060     usb_audio_request_t *p_endpoint_request;
2061     audio_instance_t *audioPtr;
2062 
2063     if (classHandle == NULL)
2064     {
2065         return kStatus_USB_InvalidHandle;
2066     }
2067 
2068     audioPtr = (audio_instance_t *)classHandle;
2069     if (AUDIO_DEVICE_VERSION_01 != audioPtr->deviceAudioVersion)
2070     {
2071         return kStatus_USB_Error;
2072     }
2073     /* pointer to command */
2074     p_endpoint_request = &(s_usbAudioEpRequests[(uint8_t)cmdCode & 0xfU]);
2075     /* get request value */
2076     request_value = (uint16_t)((uint16_t)((uint16_t)p_endpoint_request->requestValue << 8U));
2077 
2078     /* Check whether this attribute valid or not */
2079     if (audioPtr->isoEndpDesc == NULL)
2080     {
2081         return kStatus_USB_Error;
2082     }
2083     if ((0U != audioPtr->isoEndpDesc->bmAttributes) && (0U != p_endpoint_request->controlMask))
2084     {
2085         status = kStatus_USB_Success;
2086     }
2087     else
2088     {
2089         status = kStatus_USB_InvalidRequest;
2090     }
2091 
2092     if (kStatus_USB_Success == status)
2093     {
2094         /* Any isochronous pipe is supported? */
2095         if ((NULL == audioPtr->isoInPipe) && (NULL == audioPtr->isoOutPipe))
2096         {
2097             return kStatus_USB_InvalidParameter;
2098         }
2099         else if (NULL != audioPtr->isoInPipe)
2100         {
2101             endp_num = (audioPtr->isoEpNum | 0x80U);
2102         }
2103         else
2104         {
2105             endp_num = audioPtr->isoEpNum;
2106         } /* Endif */
2107 
2108         status = _USB_HostAudioControl(classHandle, (p_endpoint_request->typeRequest | ((uint8_t)cmdCode & 0x80U)),
2109                                        (p_endpoint_request->codeRequest | ((uint8_t)cmdCode & 0x80U)), request_value,
2110                                        endp_num, p_endpoint_request->length, (uint8_t *)buf, callbackFn, callbackParam);
2111     }
2112 
2113     return status;
2114 }
2115 
USB_HostAudioSetStreamOutDataInterval(usb_host_class_handle classHandle,uint8_t intervalValue)2116 usb_status_t USB_HostAudioSetStreamOutDataInterval(usb_host_class_handle classHandle, uint8_t intervalValue)
2117 {
2118     audio_instance_t *audioPtr         = (audio_instance_t *)classHandle;
2119     usb_status_t status                = kStatus_USB_Error;
2120     uint8_t ep_index                   = 0U;
2121     usb_descriptor_endpoint_t *ep_desc = NULL;
2122     usb_host_interface_t *interface_ptr;
2123 
2124     if (classHandle == NULL)
2125     {
2126         return kStatus_USB_InvalidHandle;
2127     }
2128 
2129     if (audioPtr->isoOutPipe != NULL)
2130     {
2131         (void)USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoOutPipe);
2132         audioPtr->isoOutPipe = NULL;
2133     }
2134 
2135     /* open interface pipes */
2136     interface_ptr = (usb_host_interface_t *)audioPtr->streamIntfHandle;
2137     for (ep_index = 0U; ep_index < interface_ptr->epCount; ++ep_index)
2138     {
2139         ep_desc = interface_ptr->epList[ep_index].epDesc;
2140         if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
2141              USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
2142             ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_ISOCHRONOUS))
2143         {
2144             uint8_t intervalBackUp = ep_desc->bInterval;
2145             ep_desc->bInterval     = intervalValue;
2146             status                 = _USB_HostAudioInitEndpoint(audioPtr, ep_desc);
2147             ep_desc->bInterval     = intervalBackUp;
2148         }
2149     }
2150 
2151     return status;
2152 }
2153 #endif /* USB_HOST_CONFIG_AUDIO */
2154