#filter #driver #wdk #joystick
#Фильтр #драйвер #wdk #джойстик
Вопрос:
В качестве учебного упражнения я пытаюсь написать драйвер фильтра для проводного контроллера XBox 360 в 64-разрядной версии Windows 7. Этот контроллер отображается как скрытый джойстик, поэтому кажется, что это должно быть просто.
Я создал пример драйвера фильтра для своей мыши, который меняет местами левую и правую кнопки мыши. Это было основано на образцах moufiltr и firefly, которые поставляются с WDK. Однако у меня возникли проблемы с преобразованием этого примера для работы с контроллером XBox 360.
Когда я подключаю контроллер, в диспетчере устройств отображаются 3 разных устройства:
- Устройства с человеческим интерфейсом / игровой контроллер, совместимый с HID
- Устройства с человеческим интерфейсом /USB-устройство с человеческим интерфейсом
- Общий класс контроллера для Windows / Контроллер Xbox 360 для Windows
К какому из них мне следует подключить мой драйвер?
С драйвером фильтра мыши я смог следовать инструкциям по установке из примера firefly: щелкните правой кнопкой мыши в диспетчере устройств, выберите «обновить драйвер». Что касается контроллера XBox 360, я не уверен, для какого устройства мне следует установить драйвер. Или все они взаимодействуют с оборудованием независимо, и мне нужно будет установить фильтр для каждого из них?
Я должен отметить, что я пытался подключить драйвер фильтра к каждому из 3 устройств, чтобы распечатать IOCTLs, доступные для моего драйвера фильтра. Для «устройства USB Human Interface Device» мой фильтр не получил IOCTLS.
Для игрового контроллера, совместимого с HID, он получил:
- IOCTL_HID_GET_COLLECTION_INFORMATION (несколько раз)
- IOCTL_HID_GET_COLLECTION_DESCRIPTOR (несколько раз)
- IOCTL_GET_SYS_BUTTON_CAPS
Для контроллера Xbox 360 для Windows он получает кучу IOCTLs, для которых я не могу отследить символическое имя:
- 0x80006000 (несколько раз)
- 0x8000e00c (несколько раз)
- 0x8000e008
- 0x8000a010
- 0x8000e018
- 0x8000e014
К сожалению, я все еще не знаю, какое устройство мне следует пытаться фильтровать. (Я надеялся, что одно из них получит эквивалент IOCTL_INTERNAL_MOUSE_CONNECT для джойстика, но, похоже, это не так.)
Ответ №1:
Я думаю, вы хотите отфильтровать внутренние IOCTLS (в частности, IOCTL_HID_GET_INPUT_REPORT / IOCTL_HID_READ_REPORT)
Вероятно, вы фильтровали EvtIoDeviceControl, попробуйте EvtIoInternalDeviceControl и найдите отчет о чтении / получении ввода ioctl, он будет исходить от любой системной службы, которая захочет прочитать события джойстика.
Как только вам удастся отфильтровать правильный ioctl, вам нужно будет посмотреть на дескриптор отчета для этого джойстика, чтобы выяснить, как интерпретировать (а затем изменять) данные.
Ответ №2:
Из xusb22.sys XInputRequestDispatcher::Dispatch():
0x80006000 DispatchGetInformation((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer, (ULONG)ioctlCode);
0x8000A010 DispatchSetState((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer);
0x8000A01C DispatchPowerDownDevice((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer);
0x8000E004 DispatchGetCapabilities((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer);
0x8000E008 DispatchGetLedState((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer)
0x8000E00C DispatchGetState((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer);
0x8000E014 DispatchWaitForGuideButton((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer)
0x8000E018 DispatchGetBatteryInformation((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer);
0x8000E020 DispatchGetAudioDeviceInformation((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer);
0x8000E3AC DispatchWaitForInput((XInputRequestServicers *)this, (struct XenonBusInformation *)amp;v6, (RequestBuffers*)buffer);
0x8000E3FC DispatchGetInformationEx((XInputRequestServicers *)this, (WDFREQUEST)request, (RequestBuffers*)buffer);
Итак, в соответствии с этим мы можем перепроектировать коды:
#include <windows.h>
// https://learn.microsoft.com/windows-hardware/drivers/kernel/defining-i-o-control-codes
// {EC87F1E3-C13B-4100-B5F7-8B84D54260CB}
DEFINE_GUID(XUSB_INTERFACE_CLASS_GUID, 0xEC87F1E3, 0xC13B, 0x4100, 0xB5, 0xF7, 0x8B, 0x84, 0xD5, 0x42, 0x60, 0xCB);
// xusb22.sys IOCTLs
#define FILE_DEVICE_XUSB 0x8000
#define IOCTL_INDEX_XUSB 0x0800
#define IOCTL_XUSB_GET_INFORMATION /*0x80006000*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 0, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_XUSB_GET_CAPABILITIES /*0x8000E004*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_XUSB_GET_LED_STATE /*0x8000E008*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 2, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_XUSB_GET_STATE /*0x8000E00C*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 3, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_XUSB_SET_STATE /*0x8000A010*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 4, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_XUSB_WAIT_GUIDE_BUTTON /*0x8000E014*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 5, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_XUSB_GET_BATTERY_INFORMATION /*0x8000E018*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_XUSB_POWER_DOWN /*0x8000A01C*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 7, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_XUSB_GET_AUDIO_DEVICE_INFORMATION /*0x8000E020*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 8, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_XUSB_WAIT_FOR_INPUT /*0x8000E3AC*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 235, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_XUSB_GET_INFORMATION_EX /*0x8000E3FC*/ CTL_CODE(FILE_DEVICE_XUSB, IOCTL_INDEX_XUSB 255, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)