6

I have two USB device IDs, e.g. USB\VID_E4F1&PID_0661\00000115FA9CE7750000000000000000 and USB\VID_E4F1&PID_0661&MI_00\7&B5A5DDF&0&0000

How to verify device #2 is a direct child of device #1 (physically they’re different parts of the same USB composite device)?

In real-life scenarios it will be many of them connected to the same USB controller. Moreover, it's possible they'll be of the same maker and model. That's why I cant verify the VID, PID, and use Win32_USBControllerDevice WMI query to verify they're plugged into the same USB controller - I need to somehow verify the parent-child relation, not just the fact they're plugged into the same controller.

If it matters, I only need to support Windows 8+.

4
  • 1
    I'm no expert, but I think CM_Locate_DevNode, CM_Get_Parent, and CM_Get_Device_ID should do the trick. Commented Sep 24, 2014 at 4:55
  • @HarryJohnston you've forgot CM_Get_Device_ID_Size, but thanks a lot, it works like a charm! You should probably copy-paste your comment to the answer. Commented Sep 24, 2014 at 15:10
  • You tagged the question C#, but you accepted an answer that uses WINAPI... Shouldn't the c# tag be removed? Commented Jul 3, 2019 at 13:37
  • @gog As far as I remember, the project I was working at that time was 100% C#. It can consume WinAPI just fine, see e.g. pinvoke.net/default.aspx/setupapi/CM_Locate_DevNodeA%20.html Commented Jul 3, 2019 at 14:01

3 Answers 3

7

The PnP Configuration Manager API is your friend here:

Sign up to request clarification or add additional context in comments.

Comments

5

If you are able to use the new WinRT API You should take a look at the PnpObject class and namespace.

Here's a code example:

var propertiesToQuery = new List<string>() { 
    "System.ItemNameDisplay",
    "System.Devices.DeviceInstanceId",
    "System.Devices.Parent",
    "System.Devices.LocationPaths",
    "System.Devices.Children"
};

var id1 = @"USB\VID_E4F1&PID_0661\00000115FA9CE7750000000000000000";

var device1 = await PnpObject.FindAllAsync(PnpObjectType.Device, 
                                            propertiesToQuery, 
                                            "System.Devices.DeviceInstanceId:=\"" + id1 + "\"");

var id2 = @"USB\VID_E4F1&PID_0661&MI_00\7&B5A5DDF&0&0000";

var device2 = await PnpObject.FindAllAsync(PnpObjectType.Device, 
                                            propertiesToQuery, 
                                            "System.Devices.DeviceInstanceId:=\"" + id2 + "\"");


var parent1 = device1.Properties["System.Devices.Parent"] as string;
var parent2 = device2.Properties["System.Devices.Parent"] as string;

if (parent1 && parent1 == id2)
{
    WriteLine("Device 2 is parent of device 1");
}

if (parent2 && parent2 == id1)
{
    WriteLine("Device 11 is parent of device 2");
}

var child_ids = device1.Properties["System.Devices.Children"] as string[];

if (child_ids != null){
    foreach (var id in child_ids)
    {
        if (id == id2){
            WriteLine("Device 2 is child of device 1")
        }
    }
}

 child_ids = device2.Properties["System.Devices.Children"] as string[];

if (child_ids != null){
    foreach (var id in child_ids)
    {
        if (id == id1){
            WriteLine("Device 1 is child of device 2")
        }
    }
}

If this is not enough you can try going up or down the parent/children path.

You could also look at the System.Devices.LocationPaths property (which is an array of strings) and test if one is a prefix of the other.

Comments

-1

Extending the great answer by Harry Johnston:

Once you call CM_Locate_DevNode, you can get the parent Device Instance ID with a single function call:

#include <propkey.h>

// Get the Parent Device Property
DEVPROPTYPE propType;
wchar_t propBuf[MAX_DEVICE_ID_LEN] = {};
ULONG propBufSize = sizeof(propBuf);
CONFIGRET cres = CM_Get_DevNode_Property(devInst, (DEVPROPKEY*)&PKEY_Devices_Parent, &propType, (BYTE*)propBuf, &propBufSize, 0);
if (cres == CR_SUCCESS) {
    // propBuf now contains the Parent System Device ID!
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.