【问题标题】:Application Communicating with Keyboard应用程序与键盘通信
【发布时间】:2014-05-07 11:41:34
【问题描述】:

我创建了自己的可配置键盘设备(我可以更改任何键的代码)。 现在我正在尝试编写 C# 应用程序,它将与此设备进行通信,但我遇到了问题。

键盘设备报告描述符:

//Keyboard
0x05, 0x01,   // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,   // USAGE (Keyboard)
    0xa1, 0x01,   // COLLECTION (Application)
    0x85, 0x01,   //   REPORT_ID (1)
    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)
    0x95, 0x01,   //   REPORT_COUNT (1)
    0x75, 0x08,   //   REPORT_SIZE (8)
    0x81, 0x03,   //   INPUT (Cnst,Var,Abs)
    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)
    0x95, 0x01,   //   REPORT_COUNT (1)
    0x75, 0x03,   //   REPORT_SIZE (3)
    0x91, 0x03,   //   OUTPUT (Cnst,Var,Abs)
    0x95, 0x06,   //   REPORT_COUNT (6)
    0x75, 0x08,   //   REPORT_SIZE (8)
    0x15, 0x00,   //   LOGICAL_MINIMUM (0)
    0x25, 0xFF,   //   LOGICAL_MAXIMUM (255) //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)
0xc0,         // END_COLLECTION
/*65*/

//Device Configuration
0x06, 0xFF, 0xA0,  // USAGE_PAGE (Vendor-Defined)
    0x09, 0x01,    // USAGE (Vendor-Defined)
    0xA1, 0x01,    // COLLECTION (Application)
    0x85, 0x02,    // REPORT_ID (2)

    0x09, 0x03,    // USAGE (Vendor-Defined)
    0x15, 0x00,    // LOGICAL_MINIMUM (0)
    0x26, 0x00, 0xFF, // LOGICAL_MAXIMUM (255)
    0x95, 0x2D,    // REPORT_COUNT (45)
    0x75, 0x08,    // REPORT_SIZE (8)
    0x81, 0x02,    // Input (Data, Variable, Absolute)

    0x09, 0x04,    // USAGE (Vendor-Defined)
    0x15, 0x00,    // LOGICAL_MINIMUM (0)
    0x26, 0x00, 0xFF, // LOGICAL_MAXIMUM (255)
    0x95, 0x2D,    // REPORT_COUNT (45)
    0x75, 0x08,    // REPORT_SIZE (8)
    0x91, 0x02,    // Output (Data, Variable, Absolute)

    0x09, 0x05,    // USAGE (Vendor-Defined)
    0x15, 0x00,    // LOGICAL_MINIMUM (0)
    0x26, 0x00, 0xFF, // LOGICAL_MAXIMUM (255)
    0x95, 0x2D,    // REPORT_COUNT (45)
    0x75, 0x08,    // REPORT_SIZE (8)
    0xB1, 0x02,    // Feature (Data, Variable, Absolute)
0xc0,          //   END_COLLECTION

部分 C# 代码(我正在使用 HIDLibrary):

    Device = HidDevices.Enumerate(VendorID, ProductID).FirstOrDefault();

    if (Device == null)
    {
        return;
    }
    //Open Device
    Device.OpenDevice();
    //if( Device.IsOpen == false )
    //  return;
    Device.Inserted += DeviceAttachedHandler;
    Device.Removed += DeviceRemovedHandler;
    Device.MonitorDeviceEvents = true;


    //Handle Reports
    KeyMapRequest(); //Fill Buffer with KeyMapRequest
    HidReport report = Device.CreateReport();
    report.ReportId = 2;
    report.Data = USBBuffer;

    succeed = Device.WriteReport(report, 10);
    Device.ReadReport(OnReport);
    LastDataEventDate = DateTime.Now;
    while ((DateTime.Now - LastDataEventDate).TotalMilliseconds < 100)
    {
    }

键盘工作正常,但应用程序无法与设备通信。 “Device.IsOpen”始终为“假”。 但是,当我使用“Report_ID (1)”(键盘部分)从 Report Descriptor 部分中删除时,“Device.IsOpen”为“true”,并且通信工作正常。

Windows 是否负责阻止通信?我该如何处理? 或者我在描述符中有一些错误?

【问题讨论】:

    标签: c# keyboard usb hid


    【解决方案1】:

    我认为这种行为可能是不正确的 LOGICAL_MAXIMUM 规范的副作用。您不小心编码了 -256 而不是 255。当我使用 hidrdd 解码您的声明时,它会输出:

    /*
    06 FFA0      (GLOBAL) USAGE_PAGE         0xA0FF Reserved 
    09 01        (LOCAL)  USAGE              0xA0FF0001  
    A1 01        (MAIN)   COLLECTION         0x01 Application (Usage=0xA0FF0001: Page=Reserved, Usage=, Type=) <-- Warning: USAGE type should be CA (Application)
    85 02          (GLOBAL) REPORT_ID          0x02 (2) 
    09 03          (LOCAL)  USAGE              0xA0FF0003  
    15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
    26 00FF        (GLOBAL) LOGICAL_MAXIMUM    0xFF00 (-256) 
    95 2D          (GLOBAL) REPORT_COUNT       0x2D (45) Number of fields 
    75 08          (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
    81 02          (MAIN)   INPUT              0x00000002 (45 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap  <-- Error: REPORT_SIZE (8) is too small for LOGICAL_MAXIMUM (-256) which needs 9 bits. <-- Error: LOGICAL_MAXIMUM (-256) is less than LOGICAL_MINIMUM (0)
    09 04          (LOCAL)  USAGE              0xA0FF0004  
    15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
    26 00FF        (GLOBAL) LOGICAL_MAXIMUM    0xFF00 (-256) <-- Redundant: LOGICAL_MAXIMUM is already -256
    95 2D          (GLOBAL) REPORT_COUNT       0x2D (45) Number of fields <-- Redundant: REPORT_COUNT is already 45
    75 08          (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
    91 02          (MAIN)   OUTPUT             0x00000002 (45 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap  <-- Error: REPORT_SIZE (8) is too small for LOGICAL_MAXIMUM (-256) which needs 9 bits. <-- Error: LOGICAL_MAXIMUM (-256) is less than LOGICAL_MINIMUM (0)
    09 05          (LOCAL)  USAGE              0xA0FF0005  
    15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
    26 00FF        (GLOBAL) LOGICAL_MAXIMUM    0xFF00 (-256) <-- Redundant: LOGICAL_MAXIMUM is already -256
    95 2D          (GLOBAL) REPORT_COUNT       0x2D (45) Number of fields <-- Redundant: REPORT_COUNT is already 45
    75 08          (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
    B1 02          (MAIN)   FEATURE            0x00000002 (45 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap  <-- Error: REPORT_SIZE (8) is too small for LOGICAL_MAXIMUM (-256) which needs 9 bits. <-- Error: LOGICAL_MAXIMUM (-256) is less than LOGICAL_MINIMUM (0)
    C0           (MAIN)   END_COLLECTION     Application
    */
    

    在 HID 报告描述符中,您需要按 Little-Endian 顺序对值进行编码。这也适用于 USAGE_PAGE (我已经更正了下面的示例)。

    顺便说一句,您不需要重复 LOGICAL_MINIMUM、LOGICAL_MAXIMUM、REPORT_COUNT 或 REPORT_SIZE 值,因为它们都是 GLOBAL 项 - 所以只有在它们的值发生变化时才需要指定它们(因为解析器会扫描它们)。尝试指定:

    /*
    06 A0FF      (GLOBAL) USAGE_PAGE         0xFFA0 Vendor-defined 
    09 01        (LOCAL)  USAGE              0xFFA00001  
    A1 01        (MAIN)   COLLECTION         0x01 Application (Usage=0xFFA00001: Page=Vendor-defined, Usage=, Type=)
    85 02          (GLOBAL) REPORT_ID          0x02 (2) 
    09 03          (LOCAL)  USAGE              0xFFA00003  
    15 00          (GLOBAL) LOGICAL_MINIMUM    0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0
    26 FF00        (GLOBAL) LOGICAL_MAXIMUM    0x00FF (255) 
    95 2D          (GLOBAL) REPORT_COUNT       0x2D (45) Number of fields 
    75 08          (GLOBAL) REPORT_SIZE        0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8
    81 02          (MAIN)   INPUT              0x00000002 (45 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
    09 04          (LOCAL)  USAGE              0xFFA00004  
    91 02          (MAIN)   OUTPUT             0x00000002 (45 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
    09 05          (LOCAL)  USAGE              0xFFA00005  
    B1 02          (MAIN)   FEATURE            0x00000002 (45 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap 
    C0           (MAIN)   END_COLLECTION     Application
    */
    

    【讨论】:

    • 感谢您的回答。我对代码进行了建议的更改,但没有帮助。我解决了切换到 C++ 并使用“hidapi”的问题
    猜你喜欢
    • 2014-02-06
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 2017-07-06
    • 2014-12-20
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多