none
How to enumerate all connected USB devices' device path, without a specific GUID? RRS feed

  • Question

  • I'm trying to use the SetupDi functions to enumerate all connected device's device path but I've hit a snag. This is the device path used to communicate to devices through CreateFile().

    Everything goes fine until I reach SetupDiGetDeviceInterface. This function requires an interface GUID however I'm not specifically looking for a particular interface. 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".


    Question:

    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
    }








    Tuesday, December 18, 2012 5:40 AM

Answers

  • I retract my last post and submit this as the new answer:

    According to this MSDN article, the GUID {A5DCBF10-6530-11D2-901F-00C04FB951ED} will list all attached USB devices. I've just tried it out and it works like a charm. This generates a list similar to the connected devices seen in USB View.

    • Marked as answer by Engineer Dan Wednesday, December 19, 2012 2:28 AM
    Wednesday, December 19, 2012 2:28 AM

All replies

  • What bigger problem are you trying to solve?

    by device path, do you mean the pnp identity? Or a filename you can pass to CreateFile?


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, December 18, 2012 6:23 AM
  • I'm looking for the filename to pass to CreateFile.

    Interface GUID will not always be guaranteed to be the same, and the program needs to be able to search for and connect to a USB with a user-specified VID/PID.

    Tuesday, December 18, 2012 6:32 AM
  • and once you open a file, what io are you going to send? there is a reason that there is no generic device interface guid which gives you a file handle to any device. the guid represents an io contract (supported ioctls, read, write, etc). if you don't know the guid, you don't know the contract, and thus, don't know what to do with that handle once you open it.  What does the user except you to do with any set of random VID/PID specified pairs?

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    • Marked as answer by Engineer Dan Wednesday, December 19, 2012 12:22 AM
    • Unmarked as answer by Engineer Dan Wednesday, December 19, 2012 2:28 AM
    Tuesday, December 18, 2012 6:27 PM
  • I've marked your last reply as the answer because it occurs to me that there is no way you can connect to an arbitrary device without a specific interface GUID.

    Although GUID's have their place, you'd think a VID/PID pair which is guaranteed to be unique for every device is good enough for an OS to assign a driver. My personal opinion is that in this case, this is an unnecessary burden to the hardware developer.

    Wednesday, December 19, 2012 12:21 AM
  • I retract my last post and submit this as the new answer:

    According to this MSDN article, the GUID {A5DCBF10-6530-11D2-901F-00C04FB951ED} will list all attached USB devices. I've just tried it out and it works like a charm. This generates a list similar to the connected devices seen in USB View.

    • Marked as answer by Engineer Dan Wednesday, December 19, 2012 2:28 AM
    Wednesday, December 19, 2012 2:28 AM
  • The guid does not necessarily mean you can open a handle. for instance, it will fail to open a handle to any hid device fdo. What will you do with the handle once opened? You won't know which ioctls to send.

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.


    Wednesday, December 19, 2012 3:48 AM