Unique device identifiers for USB, firewire, and serial ports - macos

I am working on a project that involves the auto-detection of USB and firewire devices being plugged and unplugged from an OS X system. For a given device, the system needs to recognise a device when it is plugged in (no matter which port) and load a device-specific bundle to deal with it.
The key to making this work is obviously the unique identification of each device. I know that USB devices are identified by a combination of the vendor ID and product ID fields, but this does not provide a unique ID, only the "kind" of device. If I have two devices the same and I plug both of them in to the computer, I would like some way to distinguish them. Is there a general and reliable way to do this, perhaps using other fields in the USB descriptor?
A related question, how does this work for USB serial ports? Suppose I plug in two USB serial ports of the same make/model. OS X should give them unique inodes in the /dev tree. However, suppose it calls them /dev/usbserial1 and /dev/usbserial2. If I then unplug the ports and plug in only one one of them, will that port be given the same name as it previously had, or will it just get /dev/usbserial1 (since it is the only) port plugged in?
Same question for firewire devices, although I think firewire devices are supposed to have a 64-bit GUID. In this case I am looking for someone to verify that using the GUID for firewire device identification would be reliable. In other words, if I plugged in two separate cameras of the same make and model, would I expect them to have different GUIDs?
I know I could test some of these with the appropriate hardware, but I don't have multiple bits of hardware at this time, so I am hoping someone may know at least some of the answers to the above questions.

With luck, your USB devices should have unique serial numbers, in addition to the VID/PID combination. If you're enumerating IOUSBDevice objects, look at the USB Serial Number property.

On Windows, Microsoft remembers device-specific settings by:
the device's serial number (the iSerialNumber field in the USB device descriptor), if available
or otherwise, by the "path" to the device: its bus (i.e. what hub it's plugged into etc.) + USB VID and PID
Without serial numbers, USB devices are virtually indistinguishable. You could tell apart different USB disk drives, but for devices which have no non-volatile memory of any kind (and many USB devices fall into this category), they are just indistinguishable, so you just have to make the best effort to do what the user expects.

Related

Is there an easy way to get low-level data from a Mac USB serial port, from devices that do not show up in the /dev/ directory?

What I want to achieve is that I plug in a device, for example a mouse, but in general any device that outputs serial data via USB, and then either screen it in terminal, or store it in a file and, if possible, use python to do things with it.
As a concrete example, let's say I want access to the data from a trackpad plugged into a USB port on a macbook. When I run /dev/{tty,cu}.* in terminal, I get a bunch of devices, but none of them is the one I want. When I run ioreg -p IOUSB -l -b | grep -E "#|PortNum|USB Serial Number", I see that the device is plugged in, at a specific address (i.e. #14200000), as well as <class AppleUSBDevice, id 0x100002c38, registered, matched, active, busy 0 (10 ms), retain 14> and "PortNum" = 2.
Yes, the device is plugged in, no it does not show up in /dev/{tty,cu}.*. I don't want to have to write a device driver, I have heard that it is not the easiest thing to do. Are there any solutions for accessing low-level data from devices that don't show up in the /dev/ directory?
Devices showing up as /dev/tty... and /dev/cu... are devices implementing the asynchronous serial data communication protocol derived from RS-232. There used to be dedicated serial ports on computers. Today on a Mac, they are usually connected via USB.
Few USB devices implement the serial protocol. Instead they implement the HID protocol (keyboard, mouse etc.), USB mass storage protocol (external drives of all kind), USB ECM (for network adapters) or a custom protocol. Except for the ones with a custom protocol, macOS provides device drivers for all of them.
USB isn't a simple serial communication. Instead, devices configure several endpoints. Each endpoint uses a separate communication channel. Even USB CDC ACM for RS-232 like communication uses three endpoints. In addition, USB devices can pretend to be several devices at once. This is call composite device.
My understanding is that you want to observe and record USB communication. The main approaches are:
Use Wireshark. It is well known for observing and recording network traffic but it can do the same for USB. Unfortunately, with the ever tighter security on macOS, it isn't so easy to set up and probably doesn't work on Apple Silicon Macs anymore.
Use a dedicated USB protocol analyzer. They are very powerful and start at about USD 300.

Identify Windows USB Sounddevice by physical USB port connection

When I connect several USB audio devices using the default drivers I usually end up with some kind of friendly device description like "nn- USB Audio codec" or something else, so I have currently no unique property which refers to a specific hardware the e.g. manufacturer ID. I would like to ensure that in case of re-enumerating or replugging the hardware to a different port that my software will automatically identify the changed windows audio device which maps to this hardware. I there a possibility to gather further windows audio device information which can be used to determine the physical hardware ?
Maybe a little clarification is needed:
I have two or more USB audio devices, not necessarily same product or manufacturer. The audio connections have different purposes, so I want to ensure that I my software uses constantly the same physical audio devices for different tasks. This sometimes fails when a re-enumeration occurs ( sometimes without changing the physical USB port connections, it's a windows thing...)
Ideally I would distinguish them by an individual serial number, which usually is only available with storage devices. But what I can retrieve is the "physical" USB topology when I'm looking at the device with a tool such as USBDeview from Nir Sofer. There I have a property like "Hub 3, Port1". If I could map this to a sound device I get from audio audio api like "nn- USB Audio codec" as seen in the sound control panel I would be perfectly happy.
Edit2:
May be this[1] post helps here, but I still have to figure out how to get a USB Port <-> Windwos Sounddevice mapping.
[1]: Can the physical USB port be identified programatically for a device in Windows? "

USB composite Device instance IDs

I am developing a USB composite device. The composite device have 8 switches and one LED.
When I plugged the Composite device to PC,I could find five devices (each with same device ID but different instance IDs) in the HID section of Device Manager.
Why OS is showing multiple instances instead of One. Can anyone help me understand the concept?
As I recall 'composite device' is just a name in windows to mark that you have multiple devices on your USB line. There isn't a composite device class in the USB protocol. When you connect your USB device to your PC it communicates with all the devices contained in it and reports individually all their address and types. If you are missing some devices in your device manager it could be a driver issue or the device itself is broken. I don't know for sure but maybe there is a limit lower then it could be in theory in the windows hid host driver for the number of supported devices on a single line.

How do I reset USB devices using the Windows API?

Do you know a way to use the Windows XP API to reset the USB bus? In other words, I'd like the OS to kick out any USB devices that are currently connected, and then auto-detect everything anew.
I'm aware of devcon, and I suppose I could do system calls out to it, but I'm hoping for a direct call into the API.
From kernel mode: You can force a specific USB device to be re-connected, as if it was unplugged and replugged again, by sending an IOCTL_INTERNAL_USB_CYCLE_PORT to its PDO. (This can only be done from a kernel mode, e.g. through a helper driver.) This 'cycle' operation will cause a USB reset to occur, after which the device would be re-enumerated. For example, if the device comes back with a different USB device descriptor, a different driver may be matched for it.
From user mode: You can do this by ejecting the device through the CfgMgr API. For example, to go over all USB hubs and eject all devices:
Find all devices having device interface GUID_DEVINTERFACE_USB_HUB with SetupDiGetClassDevs(... DIGCF_DEVICEINTERFACE).
Enumerate over the returned device information set (SetupDiEnumDeviceInfo).
For each device, get the DevInst member:
Invoke CM_Get_Child(DevInst) and then CM_Get_Sibling repeatedly to go over all child nodes of the hub (i.e. the USB devices).
For each child node, call CM_Request_Device_Eject.
Well, use can use the Setup API (SetupDiXXX functions) to enumerate the USB devices in the system, and then call WinUsb_ResetPipe on each one, but I'm not sure if that's what you're looking for. It's been a while since I worked with USB devices, but as I recall, there is no standard way to reset a device (i.e. simulate a power off/power on cycle). If it's possible for a particular device, you'd have to send an appropriate IOCTL (using DeviceIOControl) to the driver. The IOCTL would vary from manufacturer to manufacturer.
It's possible to cycle the parent port on the USB hub the device is attached to, as well. This will result in, among other things, apparrent unplug/replug actions, as you will see a balloon popup when this occurs.
Much of this is poorly documented, and honestly, I've gotten the impression there are only a handful of people at Microsoft who really understand it well. The design decision I've made for future devices I design is that I intend to include watchdog functionality on both sides, as well as a device-side full reset function. That way, if the device figures out it is confused, it can just cut its own power for a second and fully reset, if the host can't communicate with it, it could do the same thing, and if the device thinks everything is fine but the host knows better, the host could order it to reset.
There are at least three APIs worth looking into for this problem: the Setup API, the Config Manager API, and various WMI extensions. However, be cautious about diving into WMI if you intend to use an Embedded XP target, as you will have to include a lot of other things in your OS image you might otherwise not need.
As far as I know, there is no way to do this - you can issue a command to have PnP rescan the bus for new devices, but that isn't the same as issuing a bus reset.
Furthermore, just because from a hardware perspective you issued a bus reset doesn't mean that Windows will remove the PDOs that represent the children of the hub and redetect them; the USB bus driver can (and does) do just what I describe (i.e. issue hardware bus resets without disturbing the device tree), and only after the device doesn't respond does it issue the surprise removal and yank it from the tree.

USB Debugging

I'm looking for a very specific USB device for debugging systems that may use USB but not with a regular computer (proprietary hardware). I want a device that has a USB host controller and two USB device connections. The device to be debugged is connected to the USB host controller and one of the device connections is connected to another device with it's own host controller on it. The the other device connection is connected to a pc. The point being that all USB data travelling through the device (from the device connected to the host controller to the device connected to the first device connection) is reported to the pc.
I'll happily write software to do the logging (in fact I want to) but I can't seem to find a board like this anywhere. Can anyone help?
I have an Ellisys USB analyser, which isn't exactly what you describe internally, but does sit between a peripheral and a host and use a separate PC to collect the data.
(i.e. it has two 'B' and one 'A' connectors on it.)
Excellent product, and very helpful company.
Sniffing the USB shouldn't be too hard if you have the right hardware. And that is the tricky question. I haven't seen anything that describes the USB breakout box that you want. However I can say that this is in the realm of the following two magazines:
Nuts and Volts
Circuit Cellar
If they don't have a USB breakout box project in their archives, then at least they will have advertisements for small cheap single board computers that would have multiple USB ports that you can use for buffering the signals and reporting it back to your PC.
Alternatively is it possible to just wire your PC up to the middle of your two devices and write a custom drive that echos data back and forth while sniffing off a stream for you?
Sorry for the long delay in my reply -- I checked out one of our USB developer's toolchain, and he uses a Beagle USB Sniffer. He seems happy with it.
You're looking for a USB device with two upstream outputs. I think according to the USB spec, this is not possible. You will have two USB hosts trying to send messages and control the USB devices at the same time.
What if you were to look for a device which allowed you to view the data going through a hub via something other than a usb output?
If you're building something custom, take a look at this USB chip site. The chips are programmable via a windows application. Once you define how you want it to operate, it's saved on an EPROM on the dev board ($30-$50).
Sorry if this isn't helpful!

Resources