Is the PNPDeviceID unique - wmi-query

I wonder if the PNPDeviceID of an USB drive is unique (at least for a charge of identical devices) and if the ID does not change.

As far as I know -- No. For example, "USBSTOR\DISK&VEN_LG&PROD_USB_DRIVE&REV_1100\AA04012700014149&0" - is a device id of a usb stick. For all such given usb sticks device id will be the same. But Windows adds an instance id of device ("&0"), so it can distinguish them. If you plug two same usb sticks the device id of each of them will be different, for example: USBSTOR\DISK&VEN_LG&PROD_USB_DRIVE&REV_1100\AA04012700014149&0 USBSTOR\DISK&VEN_LG&PROD_USB_DRIVE&REV_1100\AA04012700014149&1
P.S. Sometimes Windows doesn't add instance of a device, if another same device isn't plugged. (I don't know why)

Related

Getting USB data for OS X /dev/tty.* entry

I am trying to (programatically in Java, though running external scripts is a possibility) get the USB idProduct, idVendor and ideally the string descriptors for the manufacturer and product for a USB device.
The device has (and it is all I am provided with in the beginning) a /dev/tty.usbmodem entry, and I need some way to reliably map that back to the USB information, but I can't find anything that relates one to the other (or rather I don't know where to look).
The device in question has the /dev entry of:
crw-rw-rw- 1 root wheel 10, 2 18 Jul 15:08 /dev/tty.usbmodem9f31
system_profiler gives me the following USB information for the device:
<dict>
<key>_name</key>
<string>Stk500v2</string>
<key>a_product_id</key>
<string>0xa662</string>
<key>b_vendor_id</key>
<string>0x0403 (Future Technology Devices International Limited)</string>
<key>c_bcd_device</key>
<string> 1.80</string>
<key>e_device_speed</key>
<string>full_speed</string>
<key>f_manufacturer</key>
<string>www.cpustick.com</string>
<key>g_location_id</key>
<string>0x9f300000</string>
<key>h_bus_power</key>
<string>500</string>
<key>j_bus_power_used</key>
<string>500</string>
</dict>
I can see the prefix of 0x9f3 for the g_location_id matching the start of the dev entry's suffix of 9f31, but I don't know a) how reliable that would be, and b) what the "1" would represent at the end, and how that would be affected by having multiple of the same device on the same bus, and how you would differentiate between them.
I have other devices I need to do this with as well, and they don't all follow the same naming rules. One of them uses the USB serial number field for the suffix. Other potential ones (that I don't have control over at all) could do it differently again I guess.
So basically I need some way of mapping the textual device name /dev/tty.whatever to a physical USB device entry that I can then pull the data I need from. On Linux I do it by traversing the /sys tree from /sys/class/tty through to /sys/devices/pci...blahblah/usb[x]/wherever but I can find no similar facility on OS X.
You can use IOKit to get the USB vendor ID and product ID of a serial port on Mac OS X.
Also, there is a library called libserialport that you could use:
http://sigrok.org/wiki/Libserialport

Windows HID Device Name Format

There are various ways to retrieve the Windows "Device Name" of a HID device, GetRawInputDeviceInfo with RIDI_DEVICENAME being one way to do it.
Given the example name:
\?\HID#VID_FEED&PID_DEAD#6&3559c8ea&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}
I'm wondering if there is any documentation whatsoever on what is what in this string?
\?\HID#VID_AAAA&PID_BBBB#C&DDDDDD&E&FFFF#{GUID}
So the obvious ones are A(VID), B(PID) and the GUID on the end. What I'm wondering is what EXACTLY are C, D, E and F?
It seems that C and D are unique even if you plug in two of the exact same HID devices which is great for my problem, but I'd feel more comfortable if I could know exactly how this is determined on a per OS basis, or at least that it follows some known format.
I have been googling like a madman trying to figure this out, am I missing something obvious?
Thanks in advance
According to a similar MSDN post, the value represents a unique device instance ID:
the device instance ID is unique and constant for the physical
location the device is plugged into, but it is also opaque and should
not be parsed. that means it can be used for string comparison, but
not for interpretation.
It is actually device interface instance id (symbolic link name). And yes, its unique and persists across system restart. Some details also here.
You can use CM_Get_Device_Interface_Property or SetupDiGetDeviceInterfaceProperty on interface instance id with DEVPKEY_Device_InstanceId to get device instance id (one device can have multiple interfaces).
In your example - you have a HID device. Its device id format is described here.
Info on general USB devices id format is here.
After you have device instance id you can use CM_Get_DevNode_Property or SetupDiGetDeviceProperty with DEVPKEY_NAME to get localized friendly name of a device (which is shown in Device Manager).
To sum up:
\\?\HID#VID_203A&PID_FFFC&MI_01#7&2de99099&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd} - is device interface id (also referred as "device interface path" or "device name" in docs). This is path in virtual device file system.
{378de44c-56ef-11d1-bc8c-00a0c91405dd} - device interface class guid (GUID_DEVINTERFACE_MOUSE in this case. It determines which IOCTLs can be called on this device. IOCTL_MOUSE_QUERY_ATTRIBUTES in this case)
HID\VID_203A&PID_FFFC&MI_01\7&2de99099&0&0000 - is device instance id
NOTE: exact device interface id format is not documented, each device interface can generate file name it want. I don't recommend you to parse it - it could be changed in later Windows version, better aquire device instance id - it is documents at least.

how to parse USB Device Instance ID (DIID)?

I want to know how "Device Instance ID" is made or how to parse it.
Take the following string as an example:
USB\VID_093A&PID_2700&MI_00\6&2703A67B&0&0000
As per my knowledge:
USB tells that this is a USB device
VID_093A indicates its vendor ID
similarly, PID_2700 is the product ID
However, I don't know about the rest.
MI is for multiple interfaces. A composite device has several interfaces.
6&2703A67B&0&0000 is the Instance ID.
The 6 at the beginning corresponds to the device node depth.
0 are root devices (e.g. volmgr, acpi_hal, they have Root\ prefix)
1 are acpi_hal devices (e.g. acpi (uses PNP0C08\0 instead of vid/pid/1), they have ACPI_HAL\ prefix)
2 are acpi devices (e.g. root pci bus controller (uses PNP0A08\0 instead of vid/pid/2), they have ACPI\ prefix)
3 are pci devices (e.g. xhci controller, they have PCI\ prefix)
4 are xhci devices (e.g. root hub, they have IUSB3\ prefix)
5+ are hub devices (e.g. usbccgp FDOs for composite devices, ubstor for storage etc., they have USB\ prefix)
6+ are usbstor devices (disk FDOs, USBSTOR\ prefix) or usbccgp composite interfaces (e.g. hidusb FDOs for input devices, USB\ prefix and have an MI)
7+ are endpoints (kbdhid FDOs for keyboards, mouhid FDOs for mice, HID\ prefix and have an MI)
The ID 2703A67B is an ID assigned by the parent. The xhci controller assigns the same one to all its root hubs; the separate hubs are identified by the value after the final ampersand, which is a simple incremental value. The root hub gives its child devices an ID that is the same across all devices and reboots; the separate devices are identified by the value after the final ampersand, again an incremental value. A composite device gives its children an ID that changes based on what hub/port it is plugged into; the separate interfaces are identified by the value after the final ampersand. An interface gives its children endpoints an ID that changes based on what hub/port it is plugged into; the separate endpoints are identified by the value after the final ampersand.
I can confirm that the ID that a hub assigns to its children changes if the hub is plugged into a different port on the root hub or a different hub altogether. I wrote '+' to indicate the presence of possible nested hubs. The PCI bus could also be nested and have a child bus (via PCIe to PCI bridge or PCIe root port aka. a PCIe to PCIe bridge), but I decided to leave that out. A root port is just a PCI device, basically a bridge/controller to a bus with only one slot (or more slots if the lanes are configured on the port to be split up), with a PCI\ prefix, and the child device will also have a PCI\ prefix.
By that token, the ID that the xHCI controller assigns probably depends on the PCI slot, and the ID the PCI bus controller assigns is probably dependent on what port the subordinate bus controller is connected to or whether it is the root controller.
This is why it installs drivers again when you insert a device into another port (unless it has a serial number). The drivers are considered installed when there is a registry entry for the DIID. The USB device will have a separate entry for each port and root hub combination they're plugged into. The composite device interfaces will have a separate entry for each port and root hub as well, as will the endpoints.
If the device has a serial number, which is uncommon, then the instance ID will be the serial number, and this will be the same regardless of where it is plugged into the system. If a composite device has a serial number instance ID then its interfaces probably have the same instance ID as that because the MI in the Device ID tells them apart. The endpoints are unlikely to have their own serial numbers and probably use the regular instance ID scheme.
Well, you really cant. This is the response from Microsoft regarding the same..
the device instance ID should be treated as opaque. if you want the VID/PID, query for the hardware and/or compa IDs and parse those. the hardware IDs are not considered opaque (but you still have to assume new hardware IDs will show up, so you need to detect the pattern you want to parse and have proactive code that handles other types of formats).
source: http://social.msdn.microsoft.com/Forums/en-US/4ff692bc-97c9-4943-b1ee-ec4f098e3b14/how-to-detect-sim-card-change-or-imsi-change-programatically-in-windows-phone-8?forum=wpdevelop
The Microsoft Device Instance ID page explains well how a Device Instance ID string is composed.
This page explains how a USB Identifier string (which composes the Device ID part of a Device Instance ID) is created.
Specifically, for your example:
USB\VID_093A&PID_2700&MI_00 is the Device ID, and
6&2703A67B&0&0000 is the Instance ID
Moreover, the Device ID tells you that:
USB\: this is a device under the USB enumerator
VID_093A: Pixart, Inc. manufactured this USB Device (you can find the USB Vendor ID list here)
PID_2700: this is the Product ID
MI_00: This is a Multiple Interface USB Device

Get property of driver's parent (or ancestor)

I have a driver for a USB-attached custom SCSI device which implements some vendor-specific commands. Each USB device hosts more than one SCSI LUN. This is working quite happily, but there is a problem with grouping SCSI LUNs according to device, as from the IOSCSILogicalUnitNub level down (which my driver inherits from), there are no identifying features which link the LUNs together (there are SCSI Logical Unit Numbers, but these collide for every new device; they all have a unit 0x0).
I'd like to do something like link them all according to the USB locationID field (or any other unique key), but I don't know how to get at the parent USB devices given only the io_service_t of the matching SCSI drivers. This would also be better to be done on the application side, rather than in the driver, as the application needs to keep track of which service has which LUNs and was opened by which instance of the handler.
The hierarchy in the IO Registry is:
MyUSB-SCSI Device#fd130000
|-IOUSBCompositeDriver
|-Mass Storage Class Interface#0 (has location ID 0xfd130000)
|-IOUSBMassStorageClass
|-IOSCSILogicalUnitNub#0 (has SCSI LUN number, unique in this device, but not globally)
| |-com_Company_driver_MyDriver (my driver)
| |-IOBlockStorageServices
| |-Manuf Device Media (these are strings from the device firmware)
| |-IOMediaBSDClient
|
|-IOSCSILogicalUnitNub#0
|-com_Company_driver_MyDriver
|-IOBlockStorageServices
|-Manuf Device Media
|-IOMediaBSDClient
If your device's io_service_t is in the variable _device, then the code would look like:
CFTypeRef _thing_you_want = IORegistryEntrySearchCFProperty(_device, kIOServicePlane, CFSTR("locationID"), NULL, kIORegistryIterateParents);
Go here for more info:
http://developer.apple.com/library/mac/#documentation/devicedrivers/conceptual/AccessingHardware/AH_IOKitLib_API/AH_IOKitLib_API.html

I have 2 identical HID USB devices, each one has it's own control program, how can each program know which HID device is theres?

Is there a way to assign one HID device to a program and then another identical HID device to another program without each of them grabbing randomly the first HID device they enumerate? I'd need some kind of unique identifier. Is there such thing? On windows xp/vista/7.
The port is your default enumeration value. Configure your code to allow explicit specification of the port.
Depending on a uuid of a device is probably not going to give you the results you expect in the long run.

Resources