Всем привет! Необходимо получать все данные с PS/2 порта, но без использования драйвер фильтра. Пробовал хукать IRP_MJ_* драйвера i8042prt, только никаких irp там не обнаружил. Сейчас разбираюсь с чтением данных из порта. Тут несколько ключевых вопросов. По возникновению какого прерывания считывать данные из портов и из каких именно? Может есть другие способы перехвата инфы порта. Спасибо.
Почему же без фильтра? Не i8042prt, а kbdclass. Не занимайся хернёй, драйвер-фильтр класса Keyboard - вот что тебе нужно.
SlyBit IOCTL_INTERNAL_I8042_HOOK_KEYBOARD Operation The IOCTL_INTERNAL_I8042_HOOK_KEYBOARD request adds the following callback routines to I8042prt's operation: An optional initialization callback that I8042prt calls when it initializes a keyboard An optional callback into the I8042prt keyboard ISR Пример как юзать - в моем отладчике: http://code.google.com/p/ngdbg/source/browse/trunk/8042/8042.cpp#719
Вероятно, автор не знает, что существуют другие способы подключения клавиатур. А что ты предлагаешь - не есть правильно. Модель WDM предусматривает классовые драйвера-фильтры, в данном случае это класс Keyboard, к которому следует прицепиться как upper filter. Пример см. в исходниках ctrl2cap от Sysinternals (смотрим внимательно, потому что сам исходник ещё времён NT4 и некоторые базовые вещи теперь делаются по-другому, но сам принцип фильтрации реализован правильно).
x64 Ну оно то конечно так. Но если автору нужно именно PS/2 то этот вариант подходит больше, если нужно именно на низком уровне подключаться. А классовые фильтры это, конечно, хорошо. Так что надо спрашивать автора - ему нужен именно PS/2 или вообще клавиатуры любые.
Спасибо за советы. Нужно перехватывать данные любого устройства, подключаемого к PS/2 порту (мышь, клавиатура и т.д.). Желательно без перезагрузки компьютера после инсталляции драйвера.
Хукаю прерывание клавиатуры IRQ 1. В моём обработчике прерывания читаю байт из порта PS/2, сохраняю его и затем записываю назад в порт. Проблема заключается в том, что после записи байта в порт опять срабатываем моё прерывание и происходит зацикливание. Есть идеи как можно решить эту проблему? Код (Text): VOID WINAPI KbdInterruptHook() { UCHAR btData = 0; btData = READ_PORT_UCHAR(KEYBOARD_PORT_60); // save btData WRITE_PORT_UCHAR(KEYBOARD_PORT_64, 0xD2); WaitForKeyboard(); WRITE_PORT_UCHAR(KEYBOARD_PORT_60, btData); }
Есть, не надо записывать его назад. Надо использовать другую команду PS/2 контроллера,там есть какая-то типа "записать выходной порт" которая не генерит прерывания.
нужно отключить генерацию прерывания от клавиатуры/мыши при готовности данных в буффере контроллера а после включить но на деле чет получается фигня какая-то Great можно код команды? что-то не вижу такой в спецификации вот например команды которые я определил у себя какая-то из них? Код (Text): typedef enum _I8042_COMMAND { I8042CMD_READ_CMDBYTE = 0x20, I8042CMD_WRITE_CMDBYTE = 0x60, // :: struct _I8042_COMMAND_60_REG I8042CMD_AUX_INTERFACE_DISABLE = 0xA7, I8042CMD_AUX_INTERFACE_ENABLE = 0xA8, I8042CMD_AUX_INTERFACE_TEST = 0xA9, I8042CMD_CONTROLLER_SELFTEST = 0xAA, I8042CMD_KBD_INTERFACE_TEST = 0xAB, I8042CMD_KBD_INTERFACE_DISABLE = 0xAD, I8042CMD_KBD_INTERFACE_ENABLE = 0xAE, I8042CMD_QUERY_VERSION = 0xAF, I8042CMD_READ_INPUT_PORT = 0xC0, I8042CMD_POLL_INPUT_PORT_LOW = 0xC1, I8042CMD_POLL_INPUT_PORT_HIGH = 0xC2, I8042CMD_READ_OUTPUT_PORT = 0xD0, I8042CMD_WRITE_OUTPUT_PORT = 0xD1, I8042CMD_WRITE_KBD_OUTPUT_BUFFER= 0xD2, I8042CMD_WRITE_AUX_OUTPUT_BUFFER= 0xD3, I8042CMD_WRITE_AUX = 0xD4, I8042CMD_READ_TEST_INPUTS = 0xE0, I8042CMD_SET_LEDS_STATE = 0xED, I8042CMD_ECHO_DIAGNOSTICS = 0xEE, I8042CMD_CHANGE_WORK_MODE = 0xF0, I8042CMD_QUERY_ID_CODES = 0xF2, I8042CMD_SET_AUTOREPEAT_PARAMS = 0xF3, I8042CMD_ENABLE_DATAFLOW = 0xF4, I8042CM_DEFAULTS_DISABLE_POLLING= 0xF5, I8042CMD_DEFAULTS = 0xF6, I8042CMD_ENABLE_AUTOREPEAT = 0xF7, I8042CMD_PRESS_RELEASE_ENABLE = 0xF8, I8042CMD_PRESS_ONLY_ENABLE = 0xF9, I8042CMD_ENABLE_ALL = 0xFA, I8042CMD_AUTOREPEAT_DIRECT = 0xFB, I8042CMD_PRESS_DIRECT = 0xFC, I8042CMD_PRESS_RELEASE_DIRECT = 0xFD, I8042CMD_REPEAT_TRANSMISSION = 0xFE, I8042CMD_RESET = 0xFF }I8042_COMMAND;
А вот, вспомнил, можно так: там есть команды disable/enable keyboard, disable/enable mouse. Код (Text): // // Write scan-code back to i8042 controller. // Controller will write it to output port // // Temporarily disable keyboard & mouse I8xPutBytePolled (CommandPort, ControllerDevice, FALSE, (UCHAR) I8042_DISABLE_KEYBOARD ); I8xPutBytePolled (CommandPort, ControllerDevice, FALSE, (UCHAR) I8042_DISABLE_MOUSE ); I8xPutBytePolled (CommandPort, ControllerDevice, FALSE, (UCHAR)I8042_WRITE_OUTPUT_REGISTER); I8xPutBytePolled (DataPort, ControllerDevice, FALSE, ScanCode); // Enable keyboard & mouse I8xPutBytePolled (CommandPort, ControllerDevice, FALSE, (UCHAR) I8042_ENABLE_KEYBOARD ); I8xPutBytePolled (CommandPort, ControllerDevice, FALSE, (UCHAR) I8042_ENABLE_MOUSE ); Вроде работало у меня (насколько я помню, писалось год назад...) Еще нашел команду клавиатуры (не контроллера, а клавиатуры) #define KBD_RESEND 0xFE Судя по всему, запрашивает повторную отсылку последнего скан-кода (я уже не помню пробовал ли я ее, или нет, но вроде работало...) А вообще, я остановился на IOCTL_INTERNAL_I8042_HOOK_KEYBOARD - для моих целей отладчика это подходило
странно вроде как команды отключения устройств используются для того чтобы можно было считать данные от контроллера, при передаче ему команды, возвращающей результат после передачи контроллеру команд 0xD2/0xD3 и данных, произойдет прерывание от соответствующего устройства если оно не маскировано
вобщем если вдруг кому это интересно было то рабочее решение для фильтрации до оригинальной ISR может иметь следующий вид