Beispiel #1
0
/*
 * 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;
}
Beispiel #2
0
/* 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;
}
Beispiel #3
0
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;
}