задача: эмуляция нажатия клавиш через порты контроллера 8042 Как писать в порты разобрался, нашел описание http://heim.ifi.uio.no/~stanisls/helppc/8042.html Подскажите в какой последовательности в какой порт что писать чтобы эмулировать нажатие клавиш.
Код (Text): typedef struct { unsigned short IDTLimit; unsigned short LowIDTBase; unsigned short HiIDTBase; } IDTINFO; // Содержание регистра IDTR typedef struct { unsigned short LowOffset; unsigned short selector; unsigned char unused_lo; unsigned char unused_hi:4; unsigned char DPL:4; unsigned short HiOffset; } IDTENTRY; // Запись в таблице IDT unsigned long OldInt; IDTENTRY *idt_entry; IDTINFO idt_info; _asm { sidt idt_info; } idt_entry = (IDTENTRY*) ((long)(((unsigned short)idt_info.LowIDTBase) | ((unsigned long)((unsigned short)idt_info.HiIDTBase)) << 16)); OldInt = ((long)(((unsigned short)idt_entry[0x93].LowOffset) | ((unsigned long)((unsigned short)idt_entry[0x93].HiOffset)) << 16)); С помощью этого кода можно найти адрес прерывания от клавитуры (OldInt). Далее нужно записать в буфер клавиатуры сканкод и передать управление обработчику прерывания.
если не ошибаюсь, запись во внутренний буфер клавы осущ-ся командой D2h в порт 64h, а затем запись собстно сканкода в порт 60h.
Вот фрагмент драйвера пищущего в порт ps/2: Код (Text): const ULONG IBUFFER_FULL = 0x02; const PUCHAR KBD_PORT_60 = (PUCHAR)0x60; const PUCHAR KBD_PORT_64 = (PUCHAR)0x64; ULONG wait_kbd() { UCHAR chr; ULONG i; for (i = 0; i < 100; i ++) // do at most 1000 iterations { chr = READ_PORT_UCHAR(KBD_PORT_64); if (! (chr & 0x02)) break; KeStallExecutionProcessor(50); } return i != 100; } NTSTATUS device_io(PDEVICE_OBJECT device_object, PIRP irp) { __try { PUCHAR buf = irp->AssociatedIrp.SystemBuffer; ULONG i; for (i = 0; buf[i]; i ++) { WRITE_PORT_UCHAR(KBD_PORT_64, 0xD2); wait_kbd(); WRITE_PORT_UCHAR(KBD_PORT_60, buf[i]); wait_kbd(); } } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("memory access error"); } IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_SUCCESS; }
Все так, только надо вроде еще вычитать из буфера быйты подтверждения ACK(0xFA), если опять чего не забыл)))