/* * FUNCTION: Read data from data port */ NTSTATUS i8042ReadDataWait( IN PPORT_DEVICE_EXTENSION DeviceExtension, OUT PUCHAR Data) { ULONG Counter; NTSTATUS Status; Counter = DeviceExtension->Settings.PollingIterations; while (Counter--) { Status = i8042ReadKeyboardData(DeviceExtension, Data); if (NT_SUCCESS(Status)) return Status; KeStallExecutionProcessor(50); } /* Timed out */ return STATUS_IO_TIMEOUT; }
/* Inspired from ReactOS's i8042 keyboard driver */ hvm_status KeyboardReadKeystroke(Bit8u* pc, hvm_bool unget, hvm_bool* pisMouse) { Bit32u counter; Bit8u port_status, scancode; hvm_status r; counter = POLL_STATUS_ITERATIONS; while (counter) { port_status = IoReadPortByte(KEYB_REGISTER_STATUS); r = i8042ReadKeyboardData(&scancode, pisMouse); if (r == HVM_STATUS_SUCCESS) { break; } CmSleep(1); counter--; } if (counter == 0) { return HVM_STATUS_UNSUCCESSFUL; } if (unget) { /* Echo back the scancode */ i8042WriteKeyboardData(KEYB_REGISTER_COMMAND, KEYB_COMMAND_DISABLE_KEYBOARD); i8042WriteKeyboardData(KEYB_REGISTER_COMMAND, KEYB_COMMAND_WRITE_OUTPUT); i8042WriteKeyboardData(KEYB_REGISTER_DATA, scancode); i8042WriteKeyboardData(KEYB_REGISTER_COMMAND, KEYB_COMMAND_ENABLE_KEYBOARD); } *pc = scancode; return HVM_STATUS_SUCCESS; }
BOOLEAN NTAPI i8042KbdInterruptService( IN PKINTERRUPT Interrupt, PVOID Context) { PI8042_KEYBOARD_EXTENSION DeviceExtension; PPORT_DEVICE_EXTENSION PortDeviceExtension; PKEYBOARD_INPUT_DATA InputData; ULONG Counter; UCHAR PortStatus = 0, Output = 0; BOOLEAN ToReturn = FALSE; NTSTATUS Status; UNREFERENCED_PARAMETER(Interrupt); DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context; PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; InputData = DeviceExtension->KeyboardBuffer + DeviceExtension->KeysInBuffer; Counter = PortDeviceExtension->Settings.PollStatusIterations; while (Counter) { Status = i8042ReadStatus(PortDeviceExtension, &PortStatus); if (!NT_SUCCESS(Status)) { WARN_(I8042PRT, "i8042ReadStatus() failed with status 0x%08lx\n", Status); return FALSE; } Status = i8042ReadKeyboardData(PortDeviceExtension, &Output); if (NT_SUCCESS(Status)) break; KeStallExecutionProcessor(1); Counter--; } if (Counter == 0) { WARN_(I8042PRT, "Spurious i8042 keyboard interrupt\n"); return FALSE; } INFO_(I8042PRT, "Got: 0x%02x\n", Output); if (PortDeviceExtension->Settings.CrashOnCtrlScroll) { /* Test for CTRL + SCROLL LOCK twice */ static const UCHAR ScanCodes[] = { 0x1d, 0x46, 0xc6, 0x46, 0 }; if (Output == ScanCodes[DeviceExtension->ComboPosition]) { DeviceExtension->ComboPosition++; if (ScanCodes[DeviceExtension->ComboPosition] == 0) KeBugCheck(MANUALLY_INITIATED_CRASH); } else if (Output == 0xfa) { /* Ignore ACK */ } else if (Output == ScanCodes[0]) DeviceExtension->ComboPosition = 1; else DeviceExtension->ComboPosition = 0; /* Test for TAB + key combination */ if (InputData->MakeCode == 0x0F) DeviceExtension->TabPressed = !(InputData->Flags & KEY_BREAK); else if (DeviceExtension->TabPressed) { DeviceExtension->TabPressed = FALSE; /* Check which action to do */ if (InputData->MakeCode == 0x25) { /* k - Breakpoint */ DbgBreakPoint(); } else if (InputData->MakeCode == 0x30) { /* b - Bugcheck */ KeBugCheck(MANUALLY_INITIATED_CRASH); } else { /* Send request to the kernel debugger. * Unknown requests will be ignored. */ KdSystemDebugControl(' soR', (PVOID)(ULONG_PTR)InputData->MakeCode, 0, NULL, 0, NULL, KernelMode); } } } if (i8042KbdCallIsrHook(DeviceExtension, PortStatus, Output, &ToReturn)) return ToReturn; if (i8042PacketIsr(PortDeviceExtension, Output)) { if (PortDeviceExtension->PacketComplete) { TRACE_(I8042PRT, "Packet complete\n"); KeInsertQueueDpc(&DeviceExtension->DpcKeyboard, NULL, NULL); } TRACE_(I8042PRT, "Irq eaten by packet\n"); return TRUE; } TRACE_(I8042PRT, "Irq is keyboard input\n"); if (DeviceExtension->KeyboardScanState == Normal) { switch (Output) { case 0xe0: DeviceExtension->KeyboardScanState = GotE0; return TRUE; case 0xe1: DeviceExtension->KeyboardScanState = GotE1; return TRUE; default: break; } } /* Update InputData */ InputData->Flags = 0; switch (DeviceExtension->KeyboardScanState) { case GotE0: InputData->Flags |= KEY_E0; break; case GotE1: InputData->Flags |= KEY_E1; break; default: break; } DeviceExtension->KeyboardScanState = Normal; if (Output & 0x80) InputData->Flags |= KEY_BREAK; else InputData->Flags |= KEY_MAKE; InputData->MakeCode = Output & 0x7f; InputData->Reserved = 0; DeviceExtension->KeyboardHook.QueueKeyboardPacket(DeviceExtension->KeyboardHook.CallContext); return TRUE; }