Audio USB descriptor confusion...

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Audio USB descriptor confusion...

Jump to solution
2,799 Views
EdSutter
Senior Contributor II

The more I dig into USB descriptors the more confused I get...
I'm working on a multi-channel USB audio device (6-mic/2-spkr).

I started walking through the entire set of descriptors as they exist
in usb_device_composite_hid_audio_unified_lite, comparing them to the
USB specification. The goal simply to understand the construction of
each descriptor so I can modify them as needed. Right at the top I find
a stumbling point...

According to section 4.2 of the spec ("USB Device Class Definition for
Audio Devices")...

For both composite devices and audio-only devices, the device descriptor
must indicate that class information is to be found at the interface
level. Therefore, the bDeviceClass, bDeviceSubClass and bDeviceProtocol
fields of the device descriptor must contain the values 0xEF, 0x02, and
0x01 respectively so that enumeration software looks down at the interface
level to determine the Interface Class and to also ensure that IAD-aware
enumeration software gets loaded.

But, when I look at the descriptor in usb_device_descriptor.c, it uses
USB_DEVICE_CLASS, USB_DEVICE_SUBCLASS & USB DEVICE_PROTOCOL
all of which are #defines set to zero. The output of "lsusb -v" of my
device plugged into a Linux box shows:

Bus 001 Device 023: ID 1fc9:00a4 NXP Semiconductors
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0

So it appears to be doing what the spec says, however its not using
the values mentioned in the spec (0xEF, 0x02, 0x01). Further, when I
change those three values to match the spec lsusb seems confused...

Bus 001 Device 027: ID 1fc9:00a4 NXP Semiconductors
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 239 Miscellaneous Device
bDeviceSubClass 2 ?
bDeviceProtocol 1 Interface Association

And I have problems with my running application. Can anyone
explain what I am missing? Is anyone aware of any "USB Audio"
forums that would deal with these kinds of questions?

Tx

Labels (1)
Tags (2)
0 Kudos
1 Solution
2,634 Views
EdSutter
Senior Contributor II

I've done sufficient testing to verify that the above configuration I mention (using 2 IADs) does properly create two unique devices  from Linux's point of view and all audio streams have been verified both individually and simultaneously. 

Now, going back to the original question in this post...

When I set up the device descriptor with 0xEF, 0x02, 0x01 as described in the USB spec, things work fine despite the fact that lsusb still shows the output shown in the original post.

This may be due to the fact that I am running Ubuntu 16.04.4 LTS, so maybe a newer version would clean that up.

 

View solution in original post

6 Replies
2,657 Views
EdSutter
Senior Contributor II

Well I've learned a bit more since original conversation...

According to the spec, and IAD defines a grouping of audio interfaces into something called an AIC (Audio Interface Cluster).  The AIC has one control interface and zero or more streaming interfaces.  

The trick (for me) was realizing that all I really needed to do was to create two clusters; hence two IADs.  Each IAD/IAC group then apparently is seen by Linux as a "device" within a "card".  So, with two IADs in my system I now have two devices (plughw:1,0 and plughw:1,1), each of which can be accessed by independent processes on Linux.

Then under the covers my codec/SAI driver code will deal with splitting the interfaces into two virtually isolated devices (a 6-channel mic array and a 2-in/2-out audio speakerphone with AEC).

As of this writing I've confirmed that Linux does in-fact see two devices when the descriptor is configured as mentioned above; but I have not implemented the code to really confirm that all this will work.  Once I do that, I'll post one more time and this topic will be closed!  

Thanks much to @gusarambula and @mjbcswitzerland for the input...

2,635 Views
EdSutter
Senior Contributor II

I've done sufficient testing to verify that the above configuration I mention (using 2 IADs) does properly create two unique devices  from Linux's point of view and all audio streams have been verified both individually and simultaneously. 

Now, going back to the original question in this post...

When I set up the device descriptor with 0xEF, 0x02, 0x01 as described in the USB spec, things work fine despite the fact that lsusb still shows the output shown in the original post.

This may be due to the fact that I am running Ubuntu 16.04.4 LTS, so maybe a newer version would clean that up.

 

2,791 Views
gusarambula
NXP TechSupport
NXP TechSupport

Hello EdSutter,

I couldn’t find any forum that’s focused to USB Audio at this level, and there seems to be little troubleshooting information on this regard.

It seems that the descriptor on the SDK example uses Device Class as 0 to simplify things, as an actual implementation would ideally require using the classes defined by the USB-IF (which again, ironically, do not have a public forum or communities to inquiry about these matters)

The 0xEF, 0x02, 0x01 values would be correct for the Interface Association Descriptor, which from what I understand would allow to have one descriptor describing two or more interfaces that are associated with a single device function. For example, a data interface and a control interface.

https://usb.org/sites/default/files/iadclasscode_r10.pdf

It could be that the example on the SDK do not use this feature and thus switching to the IAD configuration leads to problems when Linux enumerate the device.

Application Note 11018 (link below) is not using an i.MXRT but it may help if you are working with Audio. (Their descriptor does use the device class as 0XEF)

https://www.nxp.com/docs/en/application-note/AN11018.pdf

Regards,
Gustavo

2,784 Views
EdSutter
Senior Contributor II

Hi @gusarambula ,

Thanks for your detailed reply.  

I will have to experiment with the IAD till I make things work; because apparently the device descriptor should be set to 0xEF, 0x02, 0x01.  If/when I get it working I will post back to resolve this...

Ed

0 Kudos
2,778 Views
mjbcswitzerland
Specialist V

Hi Ed

I can confirm that 0xef, 0x02, 0x01 is an Interface Association Descriptor, which is commonly used (and needed) when USB-CDC with multiple VCOM interfaces is used. It allows multiple interfaces to be defined in a composite device which are in turn made up of their own multiple interfaces.
The Interface Association Descriptor can also be used when only one interface is used, although it is a bit redundant in that case.

0x00, 0x00, 0x00 is used to specify that the class is specified at the interface level (as you know).

Although very simple in comparison to your required configuration I have attached a diagram showing the configuration that I have recently used for a stereo ultrasonic microphone which helps with general audio class construction understanding.

In the case of a more complicated device with multiple audio interfaces the device level would use an Interface Association Descriptor instead and then there would be multiple interfaces configurations (like a tree under the configuration descriptor), each with its own Interface Association Descriptor. Each branch in itself is then in fact simple since it is describing just one item as in the single item case in the diagram.

I don't now about the specification extract since I have seen typical USB audio parts (like Logitec headset) using the 0,0,0 so it maybe shouldn't take it too literally. On the other hand, as noted for USB-CDC, one can always use an IAD at the device level if one wants to be finicky as it doesn't hurt either.

Personally I find the USB specs difficult to interpret since you already need to understand how the class in question works before it starts to make sense and find it most intuitive to record the enumeration of existing (quality) references and copy it - then do some educated guesses at why they are doing some of the things they do and change them to suit - depending on the effect the guess was close and if not try something else until the operation is suitable. At the end go back to the specs (which finally start to become partly understandable) to clear up anything that may work but not be fully according to the guides.

Regards

Mark
USB device and host developer for the uTasker project

2,768 Views
EdSutter
Senior Contributor II

Hey Mark,

I've got most of the snippets of this project working individually, soon I have to merge them into one composite device; hence my reason for starting with the composite unified audio example.  My hardware is just one 6-in/8-out codec, but I have to configure it to look like a 6 channel mic array running in parallel with a simple speaker-phone type device with echo cancellation and noise reduction.  So one of the mic channels will be pulling double duty running as the nth channel of the mic array, but also feeding into an echo canceller.

This is my first USB device (aside from being my first '1060) project, so its been interesting to say the least.  Similar to your comments below, I just read some, and attempt some code, then re-read some and change some code, and the iterations continue.  I figure about the time I finish this I'll understand the puzzle pieces the way I should have at the start. 

Thanks for the diagram, I will take a look and reply if needed...

Regards,

Ed

0 Kudos