Is it possible to set up a USB audio device to look like more than one device? - usb

I'm working on a USB audio device based on the iMXRT1060 that currently can be configured as either a 2-spkr/2-mic device or a 6-channel mic-array. For either case, I can use "arecord -l" (on Linux host) to show the card/device information something like this:
card 1: Text [MoreText], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
This works fine, but my goal is to have this device show up as two virtual INPUT devices (device 0: 2-mic and device 1: 6-mic) something like this:
card 1: Text [MoreText], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: Text [MoreText], device 1: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
so that two different Linux programs can use ALSA to connect to the two different input devices independently. I've been assuming this is mostly just a matter of setting up the descriptor properly but since I haven't been able to do that for a few days, I'm now wondering if I'm trying to do something illegal in USB.
Any thoughts?

I'm answering my own question here...
Apparently as of UAC2, there is the notion of an "Audio Interface Collection".
Below is a snippet from the "USB Device Class Definition for Audio Device" document:
The collection of the single AudioControl interface and the
AudioStreaming and MIDIStreaming interfaces that belong to the same
audio function is called the Audio Interface Collection (AIC). A
device can have multiple Audio Interface Collections active at the
same time. These Collections are used to control multiple independent
audio functions located in the same composite device. An Audio
Interface Collection is described through the standard USB Interface
Association mechanism that expresses interface binding via the
Interface Association Descriptor (IAD).
The IAD is key to making this work, and I can say at this point that the descriptor with two IAD's (and the corresponding AIC) does in fact cause Linux to show two devices in a single audio card.

Related

USB hub and the identification of positions

I need to attach 8 devices of the same kind (RFID readers) to the 8 positions of the USB hub. I need to recognize which reader is not plugged-in. I also need to know which exact device sends the data (based on the physical location)
I am aware of "a path" related to an USB plug. However, I am still a newbie in the topic. Are the positions at the USB hub numbered always the same way, or are the numbers in the path assigned based on when the USB device is plugged in? In other words, can I tell whether a specific position at the USB hub is connected or not? Can I reliably determine which device sends the data based on the communication path?

How to query the serial number of a UVC camera?

I have two UVC cameras in a stereoscopic setup, controlled with a C++ MediaFoundation app. I need to uniquely identify them in order to assign left and right to each physical device. This camera model has a unique serial number in the USB descriptor. However I can't seem to find a way to get the serial number while enumerating using MediaFoundation.
The MF enumeration order of these cameras is not reliably in port order; 95% of the time, camera 1 is enumerated before camera 2, while on some machines, we get camera 2 before camera 1. So finding the serial number is very important.
Things I've tried:
MediaFoundation doesn't seem to provide a direct way to get the serial number at all
By querying the MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK attribute, you can get a USB symbolic link. The docs say this can be used to call SetupDiOpenDeviceInterface however this doesn't seem to be usable to get the serial number (or the USB descriptor) either.
WinUSB can be used to open some USB devices in a generic manner, so the USB descriptor might be accessible, but this method fails on these cameras also, after passing the handle from CreateFile.
IOCTL the lowest level method, apparently you can send a IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX to the hub device, with a port index, and it will return the descriptor from which you should be able to get the serial number. No idea how to get the hub device and port index from only the symlink though.
Related, but unresolved: How to get hardware ID when enumerating with Windows Media Foundation
I do not wish to reimplement half of the USBView example and enumerate the entire USB world just to get some specific info for a device for which I already have a handle.
Some symbolic links for USB devices can be parsed to extract the serial number, however in the case of composite devices (all the devices in question here) the symbolic link has the &MI_00# style format and does not contain the serial number in the symlink string. So it cannot simply be parsed out.
More generally, the Setup and related APIs in Win32 seem to make it easy to get information such as manufacturer, friendly name, and all sorts of other info. But serial number is conspicuously absent.
So how do you get the serial number associated with a MediaFoundation device instance?
You can do camera identification by USB port connection (Root-Hub-Port identifiers are the same if you don't connect new USB cards or hubs to the system)
Unfortunately StackOverflow doesn't give to attach images (I don't have good enough reputation).
I'll try to show data from debugger:
There is list of my available cameras
+Integrated_Webcam/R1.H2.P4/VID_1BCF&PID_2284&MI_00;
+HBVCAM FHD CAMERA/R4.H2.P4/VID_058F&PID_3821&MI_00;
+HD USB Camera/R5.H2.P5/VID_05A3&PID_9230&MI_00;
+Integrated_Webcam/R5.H2.P6/VID_1BCF&PID_2284&MI_00;
+Logitech HD Webcam C270/R1.H2.P1/VID_046D&PID_0825&MI_00;
Each string consists of Friendly camera name, Rx.Hx.Px camera connection port indexes, (i.e. Controller number"R"-Hub number"H"-Port number"P") and VID-PID-MI presentation string(vendor id, product id and interface number).
1st and 4th cameras are the same, but have different RHP indexes. These indexes I do use for camera identification.
I did USB enumerator which provides these indexes (I did this on the base of Microsoft USBView.exe application which is provided with sources in Windows SDK).
[1]: https://i.stack.imgur.com/6SQcS.png
Usually simple USB cameras (web cameras) doesn't have serial number or something like serial number is encoded inside USB instance ID. More expensive cameras have special drivers and you can read SN by driver.
I see only one way to know, what camera I do use now - by attached USB port. This port is unique... if you don't connect additional hubs or not insert additional USB interface cards in computer. There is USB enumeration process which provides Controller(Root)-Hub-Port enumeration indexes. I do use these indexes for camera identification.
Look on this dialog: you see 5 strings with 5 USB cameras descriptors. Each descriptor consists of "Friendly Camera Name", 3 enumeration indexes (Rx.Hx.Px) and camera vendor ID and product ID (VID and PID).
If I put different camera to the same port, my program will use this different camera. If several cameras of the same type are connected, I do differ between cameras by RHP indexes. For example, the first and the fourth camera in list are the same, but they have different
enter image description here

decoding captured HID over GATT traffic with usbpcap/wireshark

I'm trying to reverse-engineer a BLE device that uses USB HID over GATT to communicate with the host. I can capture the traffic using usbpcap, but when loading the results into wireshark, the packets seem to contain the bytes representing the data that is going over the air (i.e. device descriptor), but the packets are not decoded according to USBHID protocol. Everything is decoded as USB, and only contain URB_INTERRUPT_IN, URB_BULK in/out and URB_CONTROL_OUT, while I'm looking for things like GET DESCRIPTOR Request/Response DEVICE. Is there an extra step I can take to get the packets formatted and parsed correctly?
There are a few characteristics in use. You have one characteristic which contains the Report Map. This is usually only read once when the device is paired. This map contains the layout/specification of the data which is later sent through the Report notifications. This is mostly "copy-paste" the specification from the USB spec into BLE.
Now, when you run HID-over-GATT and your Bluetooth controller talks to the Host over USB, what you will see in usbpcap is the ACL data which contains L2CAP data, which contains GATT data, which in turn contains the Report data for HID. Then the Bluetooth stack on the host will decode this and feed it into the kernel's HID parser.
I would suggest you to instead connect your HID-over-GATT device to an Android phone and then take a look at the HCI snoop log what happens, which is decodable in Wireshark (but it won't parse your HID data).

How does an O.S. or a high level abstraction layer gain knowledge of the hardware using the device driver?

When reading about hardware/device independence this statement from wikipedia (http://en.wikipedia.org/wiki/Device_independence#Desktop_computing) states that:
The application software does not need to know anything about the hardware on which it was to be used. Instead it discovers the capabilities of the hardware through the standardized abstraction layer, and then use abstracted commands to control the hardware.
I wanted to know about the lower level interaction between the BIOS routine/device driver/HAL/OS and the device controller about discovering the hardware capabilities.
Kindly help me out to understand the communication between these entities that takes place which helps in hardware independence.
Hardware devices, normally, connect to the main controller through a standard bus of some kind.
For example - PCI, PEX, USB.
Each connected device on the bus will be allocated with a device #, bus #, function #, etc, by the bus controller.
Modern bus contollers either provide the main controller with the ability to perform a scan, or send an event when a device is hot plugged into the bus.
Per each discovered device, it is possible, using the bus controller standard commands (such as read/write registers of a device, by device ID, bus number, etc), to interrogate the device for details such as:
Manufacturer ID
Device ID
Class (controller / networking device / Human interface / imaging device / and so on)
Per bus type, all these details must be available in the same way for every connected HW device, thus enabling the OS to use an abstraction layer.
Once a device has been discovered and identified, the OS will call all the specific bus registered device drivers' probe function, which use the details mentioned above to decide if can handle it.
When a device driver probe succeeds, an instance of the driver is allocated and can be used directly by the application that needs to access the HW.
For example:
USB PC CAM connects to USB port. An event is sent to the main CPU by the USB bus controller. The CPU will use the standard USB bus controller functions to learn the manufacturer & device ID/s, device class, functions, etc, and will call all the USB registered device drivers probe functions.
If an appropriate device driver is installed (registered), it will successfully create an instance of the device and a video application (such as skype) can use it directly, through DLLs supplied by the driver SW.
Hope this helps.

USB host recognition

I'm developing an embedded USB device which needs to be available to two different hosts.
The first is a normal PC, where it will be used as a MSC (mass storage) device, and the second is a specific hardware which the USB device needs to comunicate with a CDC profile.
during the enumeration, the USB device send descriptor table where it declares its capabilities.
Is there a way in the enumeration process to know to which host the device was connected to ?
The simplest solution perhaps would be to implement a "USB Composite Device", where the single device presented both the MSC and CDC class interfaces simultaneously. The host PC would see both interfaces, but you could simply leave one unused. The "specific hardware" would probably simply ignore the MSC class if it had no support for it.