Windows HID USB设备C#API替代

时间:2019-06-30 18:35:55

标签: c# c winapi usb hid

我在为自己的键盘编写测试应用程序(WPF,C#、. NET 4.7)时遇到了一个问题。键盘通过USB连接,并显示为键盘类型的HID设备。现在,我想向键盘发送一些数据(配置,背光信息等)。

在键盘端有一个ARM微控制器,它使用键盘的HID-Report-Descriptor进行初始化,其中包含一个额外的OUTPUT标签,用于将某些配置数据发送到键盘。 (4个字节)

这是MCU的当前报告描述符:

__ALIGN_BEGIN static uint8_t 
JKP_HID_ReportDesc_FS[USBD_JKP_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)

    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs) ; Modifier Byte (1 byte)

    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs) ; Reserved Byte (1 byte)

    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x05, 0x08,                    //   USAGE_PAGE (LEDs)
    0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs) ; LED Report
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x03,                    //   REPORT_SIZE (3)
    0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs) ; LED Report Padding (LEDs 1 byte)

    0x95, USBD_JKP_HID_REPORT_KEY_ROLLOVER, //   REPORT_COUNT (USBD_JKP_HID_REPORT_KEY_ROLLOVER)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs) ; Key Arrays (6 bytes)

    0x06, 0x00, 0xff,              //   USAGE_PAGE(Vendor Defined Page 1)
    0x09, 0x01,                    //   USAGE(Venor Usage 1)
    0x15, 0x00,                    //   LOGICAL_MINIMUM(0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM(255)
    0x75, 0x08,                    //   REPORT_SIZE(8)
    0x95, 0x04,                    //   REPORT_COUNT(4)
    0x91, 0x02,                    //   OUTPUT(Data,Var,Abs) ; JKP Config Info (4 bytes)

    0xc0                           // END_COLLECTION
};

在PC上,我有一个WPF应用程序,它是用C#编写的,并使用Windows.Devices.HumanInterfaceDevice API。

这是WPF应用程序的代码:

Console.WriteLine("Init HID Device Write...");

byte[] data = new byte[] { 0x00, 0xaa, 0xaa, 0xaa, 0xaa};


string device_selector = HidDevice.GetDeviceSelector(0x01, 0x06, 1155, 1024);
var devices = await DeviceInformation.FindAllAsync(device_selector);
if (devices.Any())
{
    Console.WriteLine("HID Devices Found: " + devices.Count);
    DeviceInformation devinfo = devices[0];
    Console.WriteLine($"HID Selected Device Info: ID: {devinfo.Id}, Name: {devinfo.Name}");
    HidDevice device = await HidDevice.FromIdAsync(devinfo.Id, Windows.Storage.FileAccessMode.ReadWrite);
    if (device != null)
    {
        Console.WriteLine("HID Device writing...");
        HidOutputReport report = device.CreateOutputReport(2);
        DataWriter dataWriter = new DataWriter();
        dataWriter.WriteBytes(data);
        report.Data = dataWriter.DetachBuffer();

        await device.SendOutputReportAsync(report);

    }
    else
    {
        Console.WriteLine("Failed to open HID device.");
    }
}
else
{
    Console.WriteLine("No devices found.");
}

尽管找到了键盘设备,但Windows.Devices.HumanInterfaceDevice API阻止了与键盘型HID设备的所有连接。

Windows API是否有支持此类连接的替代方法?

我已经尝试过HIDSharp和hidlibrary。另外,我也不想使用USB复合设备。

谢谢。

1 个答案:

答案 0 :(得分:0)

在Windows上,您无法与具有键盘用法(具有0x01使用情况页面和0x06使用情况ID)的HID设备进行通信,因为它们是由RIM(原始输入管理器)以互斥模式打开的。这是针对键盘记录程序的安全措施。 参见https://docs.microsoft.com/windows-hardware/drivers/hid/hid-architecture#hid-clients-supported-in-windows

作为一种解决方法,我建议您在HID描述符的0xFF00使用页面(特定于供应商)内添加另一个顶级集合,并在其中发送\接收您的自定义数据。这样,系统HID驱动程序将创建两个设备接口-一个用于键盘(无法读取/写入),另一个用于自定义设备的使用(可从应用程序中自由使用)。 参见https://docs.microsoft.com/windows-hardware/drivers/hid/top-level-collections