Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

windows - How to enumerate all connected USB devices' device path?

I'm trying to use the SetupDi functions to enumerate all connected USB devices' device path. The device path is the path used in CreateFile() so I can communicate with the device.

However, SetupDiGetDeviceInterface requires an interface GUID but I'm not specifically looking for a particular interface (other than all connected USBs). This part has been commented as /* ??? */ in the source below.

Attempted Solutions:

I've tried to supply GUID_DEVCLASS_UNKNOWN = {0x4d36e97e, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}; but this threw a "no more interfaces" error.

I've also tried to supply deviceInfoData.ClassGuid into SetupDiGetDeviceInterface but I get the same error as above, "no more interfaces".

Questions:

Is there a general interface class which will cover all USB devices? (HID, generic, etc.)

Or is there an alternate function which will give me the path to the device? (Instread of the SP_DEVICE_INTERFACE_DETAIL_DATA structure returned by SetupDiGetDeviceInterfaceDetail).

Source:

HDEVINFO deviceInfoList
SP_DEVINFO_DATA deviceInfoData;
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL;
DWORD requiredLength = 0;
char *hardwareID = 0;

// Retrieve a list of all present devices
deviceInfoList = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES);

if (deviceInfoList == INVALID_HANDLE_VALUE) {
    SetupDiDestroyDeviceInfoList(deviceInfoList);
    return false;
}

// Iterate over the list
for (DWORD i = 0; SetupDiEnumDeviceInfo(deviceInfoList, i, &deviceInfoData); i++) {
    if (deviceInterfaceDetailData) LocalFree(deviceInterfaceDetailData);

    requiredLength = 0;

    SetupDiGetDeviceRegistryProperty(deviceInfoList, &deviceInfoData, SPDRP_HARDWAREID, &DataT, NULL, 0, &requiredLength);

    if (requiredLength <= 0) {
        SetupDiDestroyDeviceInfoList(deviceInfoList);
        return false;
    }

    hardwareID = new char[requiredLength]();

    SetupDiGetDeviceRegistryProperty(deviceInfoList, &deviceInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)hardwareID, requiredLength, NULL);

    // Parse hardwareID for vendor ID and product ID

    delete hardwareID;
    hardwareID = 0;

    deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

    // Requires an interface GUID, for which I have none to specify
    if (!SetupDiEnumDeviceInterfaces(deviceInfoList, &deviceInfoData, /* ??? */, 0, &deviceInterfaceData)) {
        SetupDiDestroyDeviceInfoList(deviceInfoList);
        return false;
    }

    if (!SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInterfaceData, NULL, 0, &requiredLength, NULL)) {
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER && requiredLength > 0) {
            deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, requiredLength);

            if (!deviceInterfaceDetailData) {
                SetupDiDestroyDeviceInfoList(deviceInfoList);
                return false;
            }
        } else {
            SetupDiDestroyDeviceInfoList(deviceInfoList);
            return false;
        }
    }

    deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

    if (!SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInterfaceData, deviceInterfaceDetailData, requiredLength, NULL, &deviceInfoData)) {
        SetupDiDestroyDeviceInfoList(deviceInfoList);
        return false;
    }

    SetupDiDestroyDeviceInfoList(deviceInfoList);

    // deviceInterfaceDetailData->DevicePath yields the device path
}
like image 864
Daniel Avatar asked Dec 18 '12 06:12

Daniel


People also ask

How can I tell which USB port is which device is using?

Use the Device Manager to determine if your computer has USB 1.1, 2.0, or 3.0 ports: Open the Device Manager. In the "Device Manager" window, click the + (plus sign) next to Universal Serial Bus controllers. You will see a list of the USB ports installed on your computer.

Where is the USB path in Windows?

Finding the Device Path Parameters using Device ManagerOpen the properties for a USB device and click on the 'Details' tab. Select the 'Device Instance Path' property from the combo box to display the device instance path which shares the components of the device path used for CreateFile().


1 Answers

MSDN says that there's a generic USB device interface class named GUID_DEVINTERFACE_USB_DEVICE with the GUID {A5DCBF10-6530-11D2-901F-00C04FB951ED}:

The system-supplied USB hub driver registers instances of GUID_DEVINTERFACE_USB_DEVICE to notify the system and applications of the presence of USB devices that are attached to a USB hub.

Here's a code example that seems to do what you want to do, using the DEVINTERFACE_USB_DEVICE GUID.

like image 128
Michael Avatar answered Oct 31 '22 22:10

Michael