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