HID 提交 HID_XFER_PACKET 以模拟击键

问题描述

我正在尝试编写一个 KMDF 驱动程序来模拟击键。

当驱动程序收到 IOCTL_HID_READ_REPORT 时,它会将请求重定向到队列:

switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
    KdPrint(("GET DEVICE DESCRIPTOR\n"));
    _Analysis_assume_(deviceContext->HidDescriptor.bLength != 0);
    status = RequestCopyFromBuffer(Request,&deviceContext->HidDescriptor,deviceContext->HidDescriptor.bLength);
    break;

case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
    KdPrint(("GET DEVICE ATTRIBUTES\n"));
    status = RequestCopyFromBuffer(Request,&queueContext->DeviceContext->HidDeviceAttributes,sizeof(HID_DEVICE_ATTRIBUTES));
    break;

case IOCTL_HID_GET_REPORT_DESCRIPTOR:
    KdPrint(("GET REPORT DESCRIPTOR\n"));
    status = RequestCopyFromBuffer(Request,deviceContext->ReportDescriptor,deviceContext->HidDescriptor.DescriptorList[0].wReportLength);
    break;

case IOCTL_HID_READ_REPORT:
   WdfRequestForwardToIoQueue(Request,QueueContext->DeviceContext->ManualQueue); // <= HERE
    break;}

使用计时器,项目会定期出队,并在请求中复制键盘输入报告

void EvtTimerFunc(_In_  WDFTIMER Timer)
{
    NTSTATUS                status;
    WDFQUEUE                queue;
    PMANUAL_QUEUE_CONTEXT   queueContext;
    WDFREQUEST              request;


    KdPrint(("EvtTimerFunc\n"));

    queue = (WDFQUEUE)WdfTimerGetParentObject(Timer);
    queueContext = GetManualQueueContext(queue);

    //
    // see if we have a request in manual queue
    //
    status = WdfIoQueueRetrieveNextRequest(queueContext->Queue,&request);

    if (NT_SUCCESS(status))
    {
        KdPrint(("Handling"));

        HID_XFER_PACKET hidXferPacket;

        BYTE keycodes[6] = {0};
        keycodes[0] = 0x04;

        HID_KEYBOARD_INPUT_REPORT report;
        report.ReportId = REPORT_ID_KEYBOARD_INPUT;
        report.Modifiers = 0;
        report._reserved = 0;
        memcpy(&report.KeyCodes,&keycodes,6);

        hidXferPacket.reportBuffer = (UCHAR*)&report;
        hidXferPacket.reportBufferLen = sizeof(HID_KEYBOARD_INPUT_REPORT);
        hidXferPacket.reportId = REPORT_ID_KEYBOARD_INPUT;

        RequestCopyFromBuffer(request,hidXferPacket.reportBuffer,sizeof(HID_KEYBOARD_INPUT_REPORT));
        
        WdfRequestComplete(request,status);
    }
}
   

尽管一切正常,但不会发出任何击键。我错过了什么?!

描述符:

HID_REPORT_DESCRIPTOR g_reportDescriptor[] = {
    0x05,0x01,// USAGE_PAGE (Generic Desktop)
    0x09,0x02,// USAGE (Mouse)
    0xA1,// COLLECTION (Application)
    0x85,REPORT_ID_MOUSE_INPUT,0x09,// USAGE_PAGE (Pointer)
    0xA1,0x00,// COLLECTION (Physical)
    0x05,// USAGE_PAGE (Buttons)
    0x19,// USAGE_MINIMUM (1)
    0x29,0x03,// USAGE_MAXIMUM (3)
    0x15,// LOGICAL_MINIMUM (0)
    0x25,// LOGICAL_MAXIMUM (1)
    0x95,// REPORT_COUNT (3)
    0x75,// REPORT_SIZE (1)
    0x81,// INPUT (Data,Variable,Absolute)
    0x95,// REPORT_COUNT (1)
    0x75,0x05,// REPORT_SIZE (5)
    0x81,// INPUT (Constant)
    0x05,0x30,// USAGE (X)
    0x09,0x31,// USAGE (Y)
    0x15,0x81,// LOGICAL_MINIMUM (-127)
    0x25,0x7F,// LOGICAL_MAXIMUM (127)
    0x75,0x08,// REPORT_SIZE (8)
    0x95,// REPORT_COUNT (2)
    0x81,0x06,// Input (Data,Relative)
    0xC0,// END_COLLECTION
    0xC0,// END_COLLECTION

    0x05,// USAGE (Undefined)
    0xa1,REPORT_ID_MOUSE_OUTPUT,// USAGE (Undefined)
    0x15,// LOGICAL_MINIMUM (0)
    0x26,0xff,// LOGICAL_MAXIMUM (255)
    0x95,// REPORT_SIZE (8)
    0x91,// OUTPUT (Data,Absolute)
    0xc0,// USAGE (Keyboard)
    0xA1,REPORT_ID_KEYBOARD_INPUT,0x07,// USAGE_PAGE (Keyboard Key Codes)
    0x19,0xE0,// USAGE_MINIMUM (224)
    0x29,0xE7,// USAGE_MAXIMUM (231)
    0x15,// LOGICAL_MAXIMUM (1)
    0x75,// REPORT_SIZE (1)
    0x95,// REPORT_COUNT (8)
    0x81,// REPORT_SIZE (8)
    0x81,// INPUT (Constant)
    0x19,// USAGE_MINIMUM (0)
    0x29,0x65,// USAGE_MAXIMUM (101)
    0x15,// LOGICAL_MAXIMUM (101)
    0x95,// REPORT_COUNT (6)
    0x75,Array,Absolute)
    0x05,// USAGE_PAGE (LEDs)
    0x19,// USAGE_MINIMUM (Num Lock)
    0x29,// USAGE_MAXIMUM (Kana)
    0x95,// REPORT_COUNT (5)
    0x75,// REPORT_SIZE (1)
    0x91,// REPORT_SIZE (3)
    0x91,// OUTPUT (Constant)
    0xC0,REPORT_ID_KEYBOARD_OUTPUT,// REPORT_COUNT (8)
    0x75,Absolute)
    0xc0               // END_COLLECTION
};

HID_DESCRIPTOR g_hidDescriptor = {
    0x09,// length of HID descriptor
    0x21,// descriptor type == HID 0x21
    0x0100,// hid spec release
    0x00,// country code == Not Specified
    0x01,// number of HID class descriptors
    {            // DescriptorList[0]
        0x22,// report descriptor type 0x22
        sizeof(g_reportDescriptor)        // total length of report descriptor
    }
};

解决方法

我使用 Hyper V 虚拟机作为调试机器,这就是它不起作用的原因。 我一使用另一台计算机,就发送了按键。

如果您想模拟击键或鼠标移动,这就是我的建议:

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...