Как правильно отправлять данные о нажатиях клавиш / вводе с клавиатуры из пользовательского драйвера устройства KMDF?

Я стажер и новичок в разработке драйверов. Моя компания хотела бы, чтобы я написал драйвер KMDF для пары устройств HID с поддержкой мультитач, которые они делают. Они наняли кого-то до меня, чтобы он работал над ним, кто пытался использовать сенсорное использование Windows, и столкнулся с некоторыми проблемами с этим и поэтому не смог завершить драйвер. Итак, мы решили, что мне следует написать драйвер, чтобы устройство работало как композитное устройство мыши и клавиатуры. Таким образом, мы можем отправлять данные системной мыши, когда используется одно касание, и отправлять данные клавиатуры (нажатия клавиш, которые активируют сочетания клавиш), когда распознаются определенные мультитач-жесты (поворот, масштабирование и т. Д.). У меня опущено распознавание жестов, и часть мыши работает отлично. Я начал с примера HidUsbFx2 в WDK, и в настоящее время я сталкиваюсь с двумя проблемами.

ПРОБЛЕМА № 1: Мышь будет работать только в том случае, если я закомментирую TLC клавиатуры в дескрипторе отчета, а функция отчета о клавиатуре будет работать (до того момента, пока я ее не завершу), если я закомментирую TLC мыши в дескрипторе отчета. Я понятия не имею, почему это происходит. Вот мой дескриптор отчета: `// Коллекция мышей

0x05, 0x01,  // USAGE_PAGE (Generic Desktop)     0
0x09, 0x02,                         // USAGE (Mouse)                    2
0xa1, 0x01,                         // COLLECTION (Application)         4
0x85, REPORTID_MOUSE,               //   REPORT_ID (Mouse)              6
0x09, 0x01,                         //   USAGE (Pointer)                8
0xa1, 0x00,                         //   COLLECTION (Physical)          10
0x05, 0x09,                         //     USAGE_PAGE (Button)          12
0x19, 0x01,                         //     USAGE_MINIMUM (Button 1)     14
0x29, 0x02,                         //     USAGE_MAXIMUM (Button 2)     16
0x15, 0x00,                         //     LOGICAL_MINIMUM (0)          18
0x25, 0x01,                         //     LOGICAL_MAXIMUM (1)          20
0x75, 0x01,                         //     REPORT_SIZE (1)              22
0x95, 0x02,                         //     REPORT_COUNT (2)             24
0x81, 0x02,                         //     INPUT (Data,Var,Abs)         26
0x95, 0x06,                         //     REPORT_COUNT (6)             28
0x81, 0x03,                         //     INPUT (Cnst,Var,Abs)         30
0x05, 0x01,                         //     USAGE_PAGE (Generic Desktop) 32
0x09, 0x30,                         //     USAGE (X)                    34
0x09, 0x31,                         //     USAGE (Y)                    36
0x75, 0x10,                         //     REPORT_SIZE (16)             38
0x95, 0x02,                         //     REPORT_COUNT (2)             40
0x16, 0x01, 0x80,                   //     LOGICAL_MINIMUM (-32767)     42
0x26, 0xff, 0x7f,                   //     LOGICAL_MAXIMUM (32767)      44
0x81, 0x06,                         //     INPUT (Data,Var,Rel)         47                              
0xc0,                               //   END_COLLECTION                 49
0xc0,                               // END_COLLECTION                   50/51 

// Коллекция клавиатуры

0x05, 0x01,                         // USAGE_PAGE (Generic Desktop)
0x09, 0x06,                         // USAGE (Keyboard)
0xa1, 0x01,                         // COLLECTION (Application) 
0x85, REPORTID_KEYBOARD,            //   REPORT_ID (2) 
0x05, 0x07,                         //   USAGE_PAGE (Keyboard)
0x09, 0xe0,                         //   USAGE (Keyboard LeftControl)
0x09, 0xe7,                         //   USAGE (Keyboard Right GUI)
0x15, 0x00,                         //   LOGICAL_MINIMUM (0)
0x25, 0x01,                         //   LOGICAL_MAXIMUM (1) 
0x95, 0x08,                         //   REPORT_COUNT (8)
0x75, 0x01,                         //   REPORT_SIZE (1) 
0x81, 0x02,                         //   INPUT (Data,Var,Abs)
0x95, 0x08,                         //   REPORT_COUNT (8)
0x75, 0x01,                         //   REPORT_SIZE (1)
0x81, 0x01,                         //   INPUT (Cnst,Ary,Abs)
0x05, 0x08,                         //   USAGE_PAGE (LEDs)
0x09, 0x01,                         //   USAGE (Num Lock)
0x09, 0x03,                         //   USAGE (Scroll Lock)
0x95, 0x03,                         //   REPORT_COUNT (3) 
0x75, 0x01,                         //   REPORT_SIZE (1) 
0x91, 0x02,                         //   OUTPUT (Data,Var,Abs) 
0x95, 0x01,                         //   REPORT_COUNT (1) 
0x75, 0x05,                         //   REPORT_SIZE (5) 
0x91, 0x01,                         //   OUTPUT (Cnst,Ary,Abs) 
0x05, 0x07,                         //   USAGE_PAGE (Keyboard)
0x09, 0x00,                         //   USAGE (Reserved (no event indicated))
0x09, 0xff,                         //   USAGE (Unkown)
0x15, 0x00,                         //   LOGICAL_MINIMUM (0) 
0x26, 0xff, 0x00,                   //   LOGICAL_MAXIMUM (255) 
0x95, 0x06,                         //   REPORT_COUNT (6) 
0x75, 0x08,                         //   REPORT_SIZE (8) 
0x81, 0x00,                         //   INPUT (Data,Ary,Abs) 
0xc0                                // END_COLLECTION

`

ПРОБЛЕМА № 2: Согласно моим отладочным инструкциям печати, функция, которую я использую для отправки отчета о вводе с клавиатуры, похоже, отправляет данные в систему, но нажатия клавиш никогда не отображаются. Драйвер успешно завершает функцию отчета с клавиатуры, и система продолжает отправлять запросы на чтение драйверу. Единственная проблема заключается в том, что символы, которые я пытаюсь отправить, никогда не отображаются в блокноте (я использую блокнот, чтобы проверить, успешно ли я отправляю нажатия клавиш). Вот функция, которую я использую для отправки отчетов о вводе с клавиатуры:

VOID Gh_HidKeyboardReport(PDEVICE_EXTENSION devContext, UCHAR eventID){
PHID_KEYBOARD_REPORT report;
NTSTATUS        status;
WDFREQUEST      request;
int i;
//size_t            bufferLength = 0;

DbgPrint("Gh_HidKeyboardReport\n");

status = WdfIoQueueRetrieveNextRequest(devContext->InterruptMsgQueue, &request);
//status = WdfIoQueueRetrieveNextRequest(devContext->ReadRequestQueue, &request);
if(!NT_SUCCESS(status)){
    DbgPrint("  WdfIoQueueRetrieveNextRequest failed with status: 0x%x\n",status);
}else if (NT_SUCCESS(status)){
    //DbgPrint("Check 1\n");
    //
    // IOCTL_HID_READ_REPORT is METHOD_NEITHER so WdfRequestRetrieveOutputBuffer
    // will correctly retrieve buffer from Irp->UserBuffer. Remember that
    // HIDCLASS provides the buffer in the Irp->UserBuffer field
    // irrespective of the ioctl buffer type. However, framework is very
    // strict about type checking. You cannot get Irp->UserBuffer by using
    // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER
    // internal ioctl.
    //

    status = WdfRequestRetrieveOutputBuffer(request,
                                            sizeof(HID_KEYBOARD_REPORT),
                                            &report,
                                            NULL); //bufferLength

    //DbgPrint("Check 2: 0x%x\n", status);

    //DbgPrint("Check 3: 0x%x\n", status);

    if (!NT_SUCCESS(status)) {   // should never happen
        DbgPrint("Went Wrong!\n");
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
           "WdfRequestRetrieveOutputBuffer failed with status: 0x%x\n", status);
        DbgPrint(("Retrieve error: 0x%x\n", status));
        WdfRequestComplete(request, status);
    }else{  
        //DbgPrint("Check 4\n");
        report->reportID = REPORTID_KEYBOARD;
        report->modifierKeys = NO_MODIFIERS;
        report->reserved = 0x00;
        for(i=0; i<6; i++){
            report->key[i] = 0x00;
        }
        if(eventID == NO_EVENT){
            goto leave;
        }else if(eventID == PUSH_BUTTON){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == RING_ENCODER_CLKWSE){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == RING_ENCODER_CNTRCLKWSE){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == ROTARY_CLKWSE){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == ROTARY_CNTRCLKWSE){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == ROTATE_CLKWSE){
            report->key[0] = KEY_A;
            //report->key[1] = KEY_B;
            //report->key[2] = KEY_C;
            //report->key[3] = KEY_D;
            //report->key[4] = KEY_E;
            //report->key[5] = KEY_F;
        }else if(eventID == ROTATE_CNTRCLKWSE){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == SWIPE_UP){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == SWIPE_DOWN){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == SWIPE_RIGHT){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == SWIPE_LEFT){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == ZOOM_IN){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }else if(eventID == ZOOM_OUT){
            report->key[0] = KEY_A;
            report->key[1] = KEY_B;
            report->key[2] = KEY_C;
            report->key[3] = KEY_D;
            report->key[4] = KEY_E;
            report->key[5] = KEY_F;
        }

оставьте: DbgPrint("0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, статус: %d\n", отчет -> идентификатор_отчета, отчет-> зарезервировано, отчет-> клавиши-модификаторы, отчет-> ключ [0], отчет-> ключ [1], отчет-> ключ [2], отчет-> ключ [3], отчет-> ключ [4], отчет-> клавиша [5], статус);

        WdfRequestCompleteWithInformation(request,status,sizeof(HID_KEYBOARD_REPORT));
    //  WdfRequestComplete(request, status);
    }
}

}

* ПРИМЕЧАНИЕ: я буду изменять нажатия клавиш, которые я отправляю для каждого события, как только я смогу заставить их успешно отправлять. Я использую эти коды клавиш: KEY_A = 4, KEY_B = 5...KEYPAD_PERIOD = 99.

Любая информация по любому из этих вопросов будет принята с благодарностью. Я застрял на некоторое время, и мне нужно закончить эту работу к концу августа.

0 ответов

Другие вопросы по тегам