Why is my USB device sometimes creating another entry in the windows (7&10) registry? - windows

What can cause a USB device to have double entries for the same device in the registry?
How are the numbers following the "9&" derived (see below), i.e., 3406C40F and 2D6B958A, in case this is a hint to what is causing this problem.
My guess is that possibly the device reports itself differently during enumeration, possibly a different configuration and/or device descriptor.
Details of the test that causes this problem:
I am running a USB plug/unplug enumeration test where every time I plug in the device I verify various things to make sure that the enumeration is correct. This cycle is repeated 1000's of times. This a development test.
Upon enumeration, the test uses devcon.exe to verify some things about the collections. For some unknown reason, after some number of enumerations, the numbers associated with the collections is changing. Further investigation shows what appears to be two entries in the registry for the same device with these same numbers.
\9&3406C40F is the number at the beginning of the test associated with each collection
and some time later after several hundred enumerations it changes, in this case to
\9&2D6B958A
initial enumeration
2020-09-18 16:09:22,066 main INFO =========> devcon.exe "find HID"\vid_047F* <=========
HID\VID_047F&PID_015D&MI_03&COL05\9&3406C40F&0&0004 : HID-compliant device
HID\VID_047F&PID_015D&MI_03&COL01\9&3406C40F&0&0000 : HID-compliant device
HID\VID_047F&PID_015D&MI_03&COL02\9&3406C40F&0&0001 : HID-compliant device
HID\VID_047F&PID_015D&MI_03&COL03\9&3406C40F&0&0002 : HID-compliant consumer control device
HID\VID_047F&PID_015D&MI_03&COL04\9&3406C40F&0&0003 : HID-compliant device
several hundred enumerations later,
HID\VID_047F&PID_015D&MI_03&COL01\9&2D6B958A&0&0000 :HID-compliant device
HID\VID_047F&PID_015D&MI_03&COL02\9&2D6B958A&0&0001 :HID-compliant device
HID\VID_047F&PID_015D&MI_03&COL03\9&2D6B958A&0&0002 :HID-compliant consumer control device
HID\VID_047F&PID_015D&MI_03&COL04\9&2D6B958A&0&0003 :HID-compliant device
HID\VID_047F&PID_015D&MI_03&COL05\9&2D6B958A&0&0004 :HID-compliant device
I've run this test for millions of cycles on other devices but I have never seen this problem before. It is happening on win7 and win10.
Any help would be very appreciated! thx!

It's a device bug. The device is intermittently not reporting it's serial number so the OS creates a new entry with a different LUID (locally unique ID).

Related

How to identify a HID after it's moved to a different port on Windows

I'm on Windows and am trying to store calibration data for game controllers connected via USB and am trying to find a value which uniquely identifies them in a port independent way.
There is the HidD_GetSerialNumberString function but i've read here that it's uncommon for devices to have serial numbers and indeed when i try to read one f.e. from a PS4 controller HidD_GetSerialNumberString returns FALSE and GetLastError returns ERROR_INVALID_PARAMETER.
Is there any other data available which can be accessed to achieve this?
You can try to use instance ID for your HID device (call CM_Get_Device_Interface_Property with device interface path and DEVPKEY_Device_InstanceId property and use string after last & char). It should be unique and persistent per system restarts. But it is not guaranteed if serial number is not provided (in this case instance ID will be different if device is plugged into different usb port)...
More info on this here: https://stackoverflow.com/a/56885175/1795050

A driver has enumerated two child PDO's that returned identical Device ID's

I have a kmdf bus driver PCI\VEN_XXXX&DEV_XXXX that creates two statically enumerated PDOs with serial numbers: 217 and 218; one for each Ethernet port. The PDO hardware id is ROOT\MY_NIC_PORT so I can install a NDIS Miniport driver on them.
The bus driver passes SDV and Verifier; but, on reboot two more PDOs get enumerated. On the next reboot I get a duplicate pdo crash.
The toaster example used the device class guid as part of the hardware id. When I tried that my NIC ports no longer showed up in device manager.
Any debug suggestion or work around idea would be appreciated?
pnpCaps.LockSupported = WdfFalse;
pnpCaps.EjectSupported = WdfTrue;
pnpCaps.Removable = WdfTrue;
pnpCaps.DockDevice = WdfFalse;
pnpCaps.UniqueID = WdfTrue;
pnpCaps.SilentInstall = WdfTrue;
pnpCaps.SurpriseRemovalOK = WdfTrue;
pnpCaps.HardwareDisabled = WdfFalse;
pnpCaps.NoDisplayInUI = WdfFalse;
pnpCaps.Address = SerialNo;
pnpCaps.UINumber = SerialNo;
************************************************************
Driver Verifier detected violation:
A driver has enumerated two child PDO's that returned identical Device
ID's.
CulpritAddress = FFFFF8025ED309C4, DeviceObject1 = FFFFE3882FB2F300,
DeviceObject2 = FFFFE3882EBF88D0.
************************************************************
There are a few versions of the toaster bus sample -- assuming you started with this one, then note that it saves its list of child PDOs in the registry. My guess is that your driver is both loading PDOs from the registry, and trying to dynamically create some too.
Set a breakpoint on your driver's version of Bus_PlugInDevice, and see how often it's getting called. Make sure it's never getting called 2x with the same Instance ID.
To clear up a bit of the naming thing: a device setup class is a GUID that is totally unrelated to its hardware ID. For NICs that want to interoperate with the OS's networking stack, you must use the NET setup class, {4d36e972-e325-11ce-bfc1-08002be10318}. You can put anything you want into your hardware ID. I don't really encourage you to put "ROOT\" in there, since that could be confused with a root-enumerated device (which your devices are not). Instead, you can use "yourcompany_yourdevice\port1" as a hardware ID.
While you're thinking about naming things, there are a few things to note about hardware IDs:
Once you assign a HWID, it's rather difficult to change it in a future driver update, without breaking customers who had already installed your device. So get it right the first time.
Once you assign an Instance ID, don't change or reuse it for the lifetime of the device. Otherwise you'll cause this bugcheck, or cause IP addresses to bounce around / get reset. The OS ultimately uses the Instance ID to figure out which NIC port to bind an IP address to.
Think about what happens if someone plugs 2 of your device into a system. Make sure your Instance ID is unique across all ports. You can do this by encoding into the Instance ID the PCI device serial number (if it has one) or by falling back to the PCI bus:device:function.
Don't lump together different types of hardware under the same hardware ID. For example, if the deluxe version of your device supports checksum offload, but the regular version does not -- you should use 2 different hardware IDs for these two different devices. Otherwise it gets difficult to write a single INF that has keywords for both.

How to identify PC (motherboard) in win32 api? [duplicate]

How to uniquely identify computer (mainboard) using C#(.Net/Mono, local application)?
Edition. We can identify mainboard in .Net using something like this (see Get Unique System Identifiers in C#):
using System.Management;
...
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_MotherboardDevice");
...
But unfortunately Mono does not support System.Management. How to do it under Mono for Linux? - I don't know :(
Write a function that takes a few unique hardware parameters as input and generates a hash out of them.
For example, Windows activation looks at the following hardware characteristics:
Display Adapter
SCSI Adapter
IDE Adapter (effectively the motherboard)
Network Adapter (NIC) and its MAC Address
RAM Amount Range (i.e., 0-64mb, 64-128mb, etc.)
Processor Type
Processor Serial Number
Hard Drive Device
Hard Drive Volume Serial Number (VSN)
CD-ROM / CD-RW / DVD-ROM
You can pick up a few of them to generate your unique computer identifier.
Please see: Get Unique System Identifiers in C#
You realistically have MotherboardID, CPUID, Disk Serial and MAC address, from experience none of them are 100%.
Our stats show
Disk serial Is missing 0.1 %
MAC Is missing 1.3 %
Motherboard ID Is missing 30 %
CPUID Is missing 99 %
0.04% of machines tested yielded no information, we couldn't even read the computer name. It maybe that these were some kind of virtual PC, HyperV or VMWare instance, or maybe just very locked down? In any case your design has to be able to cope with these cases.
Disk serial is the most reliable, but easy to change, mac can be changed and depending on the filtering applied when reading it can change if device drivers are added (hyperv, wireshark etc).
Motherboard and CPUID sometimes return values that are invalid "NONE", "AAAA..", "XXXX..." etc.
You should also note that these functions can be very slow to call (they may take a few seconds even on a fast PC), so it may be worth kicking them off on a background thread as early as possible, you ideally don't want to be blocking on them.
Try this:
http://carso-owen.blogspot.com/2007/02/how-to-get-my-motherboard-serial-number.html
Personally though, I'd go with hard drive serial number. If a mainboard dies and is replaced, that PC isn't valid any more. If the HDD drive is replaced, it doesn't matter too much because the software was on it.
Of course, on the other hand, if the HDD is just moved elsewhere, the information goes with it, so you might want to look at a combination of serial numbers, depending what you want it for.
How about the MAC address of the network card?

Is the PNPDeviceID unique

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)

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