【问题标题】:Mac OS X: custom HID driverMac OS X:自定义 HID 驱动程序
【发布时间】:2012-11-29 05:18:54
【问题描述】:

我参与为 Mac OS 开发自定义 HID 设备支持。 但是它不是 HID 投诉,即它被 IOUSBCompositeDriver 抓取。

该设备应该用作输入设备(键盘、鼠标),因此我正在尝试将驱动程序实现为 kext。我尝试从 newReportDescriptor() 方法返回以下报告描述符(取自 Windows 团队)的子类 IOUSBHIDDriver 和 IOHIDDevice:

const unsigned char g_ReportDescriptor[] = {
// Keyboard report   
0x05, 0x01,                         // USAGE_PAGE (Generic Desktop)
0x09, 0x06,                         // USAGE (Keyboard)
0xa1, 0x01,                         // COLLECTION (Application)
0x85, REPORTID_KEYBOARD,            //   REPORT_ID (Keyboard)    
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, 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

// Relative Mouse report
0x05, 0x01,                         // USAGE_PAGE (Generic Desktop)
0x09, 0x02,                         // USAGE (Mouse)
0xa1, 0x01,                         // COLLECTION (Application)
0x85, REPORTID_RELATIVE_MOUSE,      //   REPORT_ID (Mouse)
0x09, 0x01,                         //   USAGE (Pointer)
0xa1, 0x00,                         //   COLLECTION (Physical)
0x05, 0x09,                         //     USAGE_PAGE (Button)
0x19, 0x01,                         //     USAGE_MINIMUM (Button 1)
0x29, 0x05,                         //     USAGE_MAXIMUM (Button 5)
0x15, 0x00,                         //     LOGICAL_MINIMUM (0)
0x25, 0x01,                         //     LOGICAL_MAXIMUM (1)
0x75, 0x01,                         //     REPORT_SIZE (1)
0x95, 0x05,                         //     REPORT_COUNT (5)
0x81, 0x02,                         //     INPUT (Data,Var,Abs)
0x95, 0x03,                         //     REPORT_COUNT (3)
0x81, 0x03,                         //     INPUT (Cnst,Var,Abs)
0x05, 0x01,                         //     USAGE_PAGE (Generic Desktop)
0x09, 0x30,                         //     USAGE (X)
0x09, 0x31,                         //     USAGE (Y)
0x15, 0x81,                         //     Logical Minimum (-127)
0x25, 0x7F,                         //     Logical Maximum (127)
0x75, 0x08,                         //     REPORT_SIZE (8)
0x95, 0x02,                         //     REPORT_COUNT (2)
0x81, 0x06,                         //     INPUT (Data,Var,Rel)
0x05, 0x01,                         //     Usage Page (Generic Desktop)
0x09, 0x38,                         //     Usage (Wheel)
0x15, 0x81,                         //     Logical Minimum (-127)
0x25, 0x7F,                         //     Logical Maximum (127)
0x75, 0x08,                         //     Report Size (8)
0x95, 0x01,                         //     Report Count (1)
0x81, 0x06,                         //     Input (Data, Variable, Relative)
0xc0,                               //   END_COLLECTION
0xc0,                               // END_COLLECTION


// Control report
0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)
0x09, 0x01,                    // USAGE (Vendor Usage 1)
0xa1, 0x01,                    // COLLECTION (Application)
0x85, REPORTID_VXYCONTROL,     //   REPORT_ID ()
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x7f,              //   LOGICAL_MAXIMUM (32767)
0x75, 0x10,                    //   REPORT_SIZE (16)
0x95, 0x02,                    //   REPORT_COUNT (2)
0x09, 0x01,                    //   USAGE (Vendor Usage 1)
0x91, 0x00,                    //   OUTPUT (Data,Ary,Abs)
0xc0,                          // END_COLLECTION

// Trigger Macro report
0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)
0x09, 0x02,                    // USAGE (Vendor Usage 2)
0xa1, 0x01,                    // COLLECTION (Application)
0x85, REPORTID_MACROTRIG,      //   REPORT_ID (5)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0x09, 0x02,                    //   USAGE (Vendor Usage 2)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)
0xc0                           // END_COLLECTION

};

然后将以下结构提供给 handleReport() 方法

#define KBD_KEY_CODES        6

#pragma pack(1)
typedef struct _VHID_KEYBOARD_REPORT
{
    UInt8      ReportID;
    // Left Control, Left Shift, Left Alt, Left GUI
    // Right Control, Right Shift, Right Alt, Right GUI
    UInt8      ShiftKeyFlags;
    UInt8      Reserved;
    UInt8      KeyCodes[KBD_KEY_CODES];
} VHID_KEYBOARD_REPORT;

VHID_KEYBOARD_REPORT keyboardReport;

bzero(&keyboardReport, sizeof(keyboardReport));
keyboardReport.ReportID = REPORTID_KEYBOARD;
keyboardReport.ShiftKeyFlags = 0;
keyboardReport.KeyCodes[0] = kHIDUsage_KeyboardA;

IOBufferMemoryDescriptor *report = IOBufferMemoryDescriptor::withBytes(&keyboardReport, sizeof(keyboardReport), kIODirectionInOut);

handleReport(report);

但是我没有看到任何效果。我预计会生成按键事件。

我错过了什么?这种驱动程序的一般工作流程是什么?

【问题讨论】:

    标签: macos kernel hid


    【解决方案1】:

    这里有很多问题…从你的 info.plist 的 IOKitPersonalities…和 OSBundleLibraries 开始(你的所有版本都匹配吗?)你知道你的 kext 是匹配的吗? (您可以 kextload/kextstat 您的驱动程序吗?)假设这很好,您将如何替换报告描述符?假设您正确覆盖 ::newReportDescriptor(您是否调用了 super::newReportDescriptor?)您将如何返回新描述符?

    IOBufferMemoryDescriptor* memDesc = IOBufferMemoryDescriptor::withBytes(& g_ReportDescriptor, sizeof(g_ReportDescriptor), kIODirectionOutIn, false);
    

    在您的代码中添加一些 IOLog 可能会有所帮助,以确保一切按您的预期进行。

    【讨论】:

    • 是的!我的 kext 与操作系统匹配并已加载。我正在使用以下代码覆盖 newReportDescriptor:{ IOLog("New Report Descriptor\n"); *descriptor = IOBufferMemoryDescriptor::withBytes(&g_ReportDescriptor, sizeof(g_ReportDescriptor), kIODirectionInOut); return kIOReturnSuccess; } 目前我只是想生成事件,因此我正在从 start() 方法调用 handleReport()。我仍然希望该事件会生成。
    • 我不认为从 start 方法调用 handleReport 会起作用(因为它实际上没有要处理的报告)。
    • 我最好的建议是联系 dts@apple.com(无空格)以获得“官方”答案。如果可能,请发送您的项目。
    • 我的印象是,制作 report(OP 的第二部分)并将其提供给 handleReport(report) 方法将使 HID 系统根据报告描述符处理该报告。
    猜你喜欢
    • 1970-01-01
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 1970-01-01
    相关资源
    最近更新 更多