[fpc-pascal] How to list USB devices on Windows?

R0b0t1 r030t1 at gmail.com
Wed Jun 27 08:11:12 CEST 2018


On Wed, Jun 27, 2018 at 12:32 AM, Bo Berglund <bo.berglund at gmail.com> wrote:
> I am writing a class that interfaces to a specific USB device HID type
> and I would like to list all such devices currently connected to the
> PC (usin Windows).
>
> On Linux I can do this on the command line:
>
> $ lsusb
> Bus 001 Device 004: ID 07f2:0003 Microcomputer Applications, Inc.
> Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
> SMSC9512/9514 Fast Ethernet Adapter
> Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
> Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
>
> This gets me as the ID the vendorid:productid so I can scan for the
> interesting device type:
>
> $ lsusb | grep 07f2:
> Bus 001 Device 004: ID 07f2:0003 Microcomputer Applications, Inc.
>
> Is there some way I can do this on Windows so I can create a list of
> the device type I work with?
> Or is there an FPC command already?
>

I don't know if there exists any functions to do it in FPC, but the
function (C++) below is the start of what you want. As is it uses the
SetupAPI to return a vector of paths of a device type which could each
be given to CreateFile, generating a handle to interact with the
device using DeviceIoControl.

In your case you should call it with GUID_DEVINTERFACE_USB_DEVICE.
Refer to https://msdn.microsoft.com/en-us/library/windows/hardware/ff553412(v=vs.85).aspx
for the GUIDs of other device types. You may want to consider
GUID_DEVINTERFACE_HID. Look at initguid.h and usbiodef.h.

For USB devices the returned paths will contain the VID and PID in a
regular manner so you could parse them out. In general you likely want
to use the following functions:

1) SetupDiEnumDeviceInfo
2) SetupDiGetDevicePropertyKeys
3) SetupDiGetDevicePropery
4) SetupDiGetDeviceInterfacePropertyKeys
5) SetupDiGetDeviceInterfaceProperty

("Interfaces" are instances of a device on a physical link type and a
"class" or device is an instance of a device type which serves some
purpose. Some class GUIDs are obsolete.)

You should also reference the full set at
https://docs.microsoft.com/en-us/windows/desktop/devinst/setupapi-h.
Realize the SetupAPI was made to programmatically install drivers. It
may or may not contain the information you want. In my experience it
always has, but you may need to resort to querying a device with
IOCTLs (in your case USB hubs).

---

vector<wstring> enum_devices(
    _In_    const GUID Guid
)
{
    vector<wstring> r;

    int index = 0;
    HDEVINFO hDevInfo = SetupDiGetClassDevs(&Guid, NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    SP_DEVINFO_DATA DevInfoData;
    memset(&DevInfoData, 0, sizeof(SP_DEVINFO_DATA));
    DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

    while (SetupDiEnumDeviceInfo(hDevInfo, index, &DevInfoData)) {
        index++;

        int jndex = 0;
        SP_DEVICE_INTERFACE_DATA DevIntData;
        memset(&DevIntData, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
        DevIntData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

        while (SetupDiEnumDeviceInterfaces(
            hDevInfo,
            &DevInfoData, &Guid, jndex, &DevIntData
        )) {
            jndex++;

            // Get the size required for the structure.
            DWORD RequiredSize;
            SetupDiGetDeviceInterfaceDetail(
                hDevInfo, &DevIntData, NULL, NULL, &RequiredSize, NULL
            );

            PSP_DEVICE_INTERFACE_DETAIL_DATA pDevIntDetData =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(
                sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + RequiredSize
            );
            memset(pDevIntDetData, 0,
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + RequiredSize);
            pDevIntDetData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

            SetupDiGetDeviceInterfaceDetail(
                hDevInfo,
                &DevIntData,
                pDevIntDetData, RequiredSize,
                NULL,
                &DevInfoData
            );

            r.push_back(wstring(pDevIntDetData->DevicePath));
            free(pDevIntDetData);
        }
    }

    return r;
}

---

Cheers,
     R0b0t1



More information about the fpc-pascal mailing list