在没有 libusb 的情况下在 C# 中获取 USB 设备描述符?

Getting the USB Device Descriptor in C# without libusb?

我想读取 USB 串行端口的设备描述符(不仅仅是 VID/PID -- 主要是为了获取 bcdDevice、iProduct 和 iManufacturer),这样我就可以知道 USB 串行端口是否能够完成我想要它做的事情(我们在现场有几个调制解调器,其中一个在半双工时更可靠)。

我不想使用 libusbdotnet,因为我不希望我的用户必须提前弄清楚要过滤什么才能获得我感兴趣的端口。

我知道如何用 C 来做;查看 USBView 应用程序,我们将需要使用 SetupAPI 来枚举控制器 (SetupDiEnumDeviceInfo),然后是集线器,然后使用 IOCTL 查询集线器以获取每个端口上的内容。

我想我必须这样做,因为我无法找出来自 COM13 -> \.\USB#ROOT_HUB30#4&2a9d917a&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8 的映射}.. 是否有 better/easier 方法来获取我需要的 ioctl 文件名,而不是遍历所有文件并过滤它们?

我也试过将 usbview 应用程序制作成 C DLL 并尝试围绕它制作一个包装器,但我无法让我自己开发的 DLL 正确编译...

我尝试从 usbview 将其添加到 enum.c 作为起点

typedef struct
{
    PSTR Name;
    PSTR path;
    int port;
} USBDevice;

USBDevice USBDevices[255] = { 0 };
int ndevices;

    extern __declspec(dllexport) int GetDevices(PSTR filter)
    {
        //Enumerate it all and filter for "COM%"
        //Store the data in the USBDevice array.
    }

    extern __declspec(dllexport) PSTR DeviceName(int i)
    {
        return USBDevices[i].Name;
    }

    extern __declspec(dllexport) PSTR DevicePath(int i)
    {
        return USBDevices[i].path;
    }

    extern __declspec(dllexport) void FreeList(void)
    {
        char* foo;
        int i;

        for (i = 0; i<ndevices; i++)
        {
            free(USBDevices[i].Name);
            free(USBDevices[i].path);
        }

        ndevices = 0;
    }

    extern __declspec(dllexport) PUSB_COMMON_DESCRIPTOR GetDevuceInfo(PSTR path, int port)
    {
        //I didn't want to figure out how to marshal this.
    }

    extern __declspec(dllexport) PSTR GetDevuceInfoValue(PSTR path,int port, int selector)
    {
        //Open Hub, send IOCTL to it, get data, filter that, return the interesting bit.
    }

但是我无法将生成的 DLL 加载到我的 C# 项目中(它在 运行 时崩溃 - 甚至在 window 出现之前)。查看DLL,似乎是垃圾(遍历DLL导致walker崩溃)。所以...我不确定我在那里做错了什么,所以我打算将 enum.c 翻译成 C# pinvoke 风格并使用它,但它看起来像 很多 的工作,特别是如果有更简单的方法来获取 COM14 -> \.\USB#ROOT_HUB30#4&2a9d917a&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8} [Port1] link...

所以...我还有很多工作要做,还是有更简单的方法来获取 linkage(我已经从注册表中尝试过,但似乎没有有映射)。

看起来批准的方式(EnumerateDevices,CM_GetParent,Munge 到一个有效路径,然后要求集线器获取数据)。我已经编写了一个 C 程序来完成这些肮脏的工作,而且它的工作原理非常棒。我想我会把它包装在一个 DLL 中,然后 post 它到 CodeProject。

警告...即使您执行了 DeviceIOControl,windows也不会重新查询您的设备。它只会在插件中查询您的设备。

但至少你 可以 找到 "Manufacturer String" 这样你就可以从所有插入的相似端口中分辨出你的 USB 端口。再一次,你可以得到来自 SetupAPI,所以...我不知道它真正给你带来了什么。