/* INCLUDES ****************************************************************/
-#include <ddk/ntddk.h>
-#include <ddk/ntddkbd.h>
-#include <ddk/ntdd8042.h>
-
#define NDEBUG
#include <debug.h>
#define I8042_MAX_COMMAND_LENGTH 16
#define I8042_MAX_UPWARDS_STACK 5
+UNICODE_STRING I8042RegistryPath;
+
/* FUNCTIONS *****************************************************************/
/*
* FUNCTION: Write data to a port, waiting first for it to become ready
*/
-BOOLEAN I8042Write(PDEVICE_EXTENSION DevExt, int addr, BYTE data)
+BOOLEAN I8042Write(PDEVICE_EXTENSION DevExt, PUCHAR addr, UCHAR data)
{
ULONG ResendIterations = DevExt->Settings.PollingIterations;
- while ((KBD_IBF & READ_PORT_UCHAR((PUCHAR)I8042_CTRL_PORT)) &&
+ while ((KBD_IBF & READ_PORT_UCHAR(I8042_CTRL_PORT)) &&
(ResendIterations--))
{
KeStallExecutionProcessor(50);
}
if (ResendIterations) {
- WRITE_PORT_UCHAR((PUCHAR)addr,data);
+ WRITE_PORT_UCHAR(addr,data);
DPRINT("Sent %x to %x\n", data, addr);
return TRUE;
}
/*
* FUNCTION: Write data to a port, without waiting first
*/
-static BOOLEAN I8042WriteNoWait(PDEVICE_EXTENSION DevExt, int addr, BYTE data)
+static BOOLEAN I8042WriteNoWait(PDEVICE_EXTENSION DevExt, int addr, UCHAR data)
{
WRITE_PORT_UCHAR((PUCHAR)addr,data);
DPRINT("Sent %x to %x\n", data, addr);
/*
* FUNCTION: Read data from port 0x60
*/
-NTSTATUS I8042ReadData(BYTE *Data)
+NTSTATUS I8042ReadData(UCHAR *Data)
{
- BYTE Status;
- Status=READ_PORT_UCHAR((PUCHAR)I8042_CTRL_PORT);
+ UCHAR Status;
+ Status=READ_PORT_UCHAR(I8042_CTRL_PORT);
// If data is available
if ((Status & KBD_OBF)) {
DPRINT("Read: %x (status: %x)\n", Data[0], Status);
// If the data is valid (not timeout, not parity error)
- if (0 == (Status & (KBD_GTO | KBD_PERR)))
+ if (0 == (Status & KBD_PERR))
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
-NTSTATUS I8042ReadStatus(BYTE *Status)
+NTSTATUS I8042ReadStatus(UCHAR *Status)
{
- Status[0]=READ_PORT_UCHAR((PUCHAR)I8042_CTRL_PORT);
+ Status[0]=READ_PORT_UCHAR(I8042_CTRL_PORT);
return STATUS_SUCCESS;
}
/*
* FUNCTION: Read data from port 0x60
*/
-NTSTATUS I8042ReadDataWait(PDEVICE_EXTENSION DevExt, BYTE *Data)
+NTSTATUS I8042ReadDataWait(PDEVICE_EXTENSION DevExt, UCHAR *Data)
{
ULONG Counter = DevExt->Settings.PollingIterations;
NTSTATUS Status;
VOID I8042Flush()
{
- BYTE Ignore;
+ UCHAR Ignore;
while (STATUS_SUCCESS == I8042ReadData(&Ignore)) {
- ; /* drop */
+ DPRINT("Data flushed\n"); /* drop */
}
}
{
NTSTATUS Status;
UCHAR Ack;
- UINT ResendIterations = DevExt->Settings.ResendIterations + 1;
+ ULONG ResendIterations = DevExt->Settings.ResendIterations + 1;
do {
if (Port)
if (!I8042Write(DevExt, I8042_DATA_PORT, Port))
- return STATUS_TIMEOUT;
+ {
+ DPRINT1("Failed to write Port\n");
+ return STATUS_IO_TIMEOUT;
+ }
if (!I8042Write(DevExt, I8042_DATA_PORT, Value))
- return STATUS_TIMEOUT;
+ {
+ DPRINT1("Failed to write Value\n");
+ return STATUS_IO_TIMEOUT;
+ }
if (WaitForAck) {
Status = I8042ReadDataWait(DevExt, &Ack);
if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to read Ack\n");
return Status;
+ }
if (Ack == KBD_ACK)
return STATUS_SUCCESS;
if (Ack != KBD_RESEND)
+ {
+ DPRINT1("Unexpected Ack 0x%x\n", Ack);
return STATUS_UNEXPECTED_IO_ERROR;
+ }
} else {
return STATUS_SUCCESS;
}
+ DPRINT("Reiterating\n");
ResendIterations--;
} while (ResendIterations);
- return STATUS_TIMEOUT;
+ return STATUS_IO_TIMEOUT;
}
/*
DevExt->PacketPort = 0;
if (!I8042PacketWrite(DevExt)) {
- Status = STATUS_TIMEOUT;
+ Status = STATUS_IO_TIMEOUT;
DevExt->Packet.State = Idle;
DevExt->PacketResult = STATUS_ABANDONED;
goto startpacketdone;
if (DevExt->PacketResends > DevExt->Settings.ResendIterations) {
DevExt->Packet.State = Idle;
DevExt->PacketComplete = TRUE;
- DevExt->PacketResult = STATUS_TIMEOUT;
+ DevExt->PacketResult = STATUS_IO_TIMEOUT;
DevExt->PacketResends = 0;
return TRUE;
}
if (!I8042PacketWrite(DevExt)) {
DevExt->Packet.State = Idle;
DevExt->PacketComplete = TRUE;
- DevExt->PacketResult = STATUS_TIMEOUT;
+ DevExt->PacketResult = STATUS_IO_TIMEOUT;
return TRUE;
}
DevExt->Packet.CurrentByte++;
VOID I8042PacketDpc(PDEVICE_EXTENSION DevExt)
{
- BOOL FinishIrp = FALSE;
+ BOOLEAN FinishIrp = FALSE;
NTSTATUS Result = STATUS_INTERNAL_ERROR; /* Shouldn't happen */
KIRQL Irql;
DPRINT("HookWorkItem done\n");
}
-VOID STDCALL I8042StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+static VOID STDCALL I8042StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (!I8042StartIoKbd(DeviceObject, Irp)) {
DPRINT1("Unhandled StartIo!\n");
}
}
-NTSTATUS STDCALL I8042InternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+static NTSTATUS STDCALL I8042InternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
PFDO_DEVICE_EXTENSION FdoDevExt = DeviceObject->DeviceExtension;
return Status;
}
-NTSTATUS STDCALL I8042CreateDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+static NTSTATUS STDCALL I8042CreateDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
{
NTSTATUS Status;
UCHAR Value = 0;
- UINT Counter;
+ ULONG Counter;
DevExt->MouseExists = FALSE;
DevExt->KeyboardExists = FALSE;
- if (!I8042Write(DevExt, I8042_DATA_PORT, 0x74))
- return STATUS_TIMEOUT;
-
I8042Flush();
- if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_SELF_TEST))
- return STATUS_TIMEOUT;
+ if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_SELF_TEST)) {
+ DPRINT1("Writing KBD_SELF_TEST command failed\n");
+ return STATUS_IO_TIMEOUT;
+ }
// Wait longer?
Counter = 3;
do {
Status = I8042ReadDataWait(DevExt, &Value);
- } while ((Counter--) && (STATUS_TIMEOUT == Status));
+ } while ((Counter--) && (STATUS_IO_TIMEOUT == Status));
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status)) {
+ DPRINT1("Failed to read KBD_SELF_TEST response, status 0x%x\n",
+ Status);
return Status;
+ }
if (Value != 0x55) {
DPRINT1("Got %x instead of 55\n", Value);
return STATUS_IO_DEVICE_ERROR;
}
- if (I8042Write(DevExt, I8042_CTRL_PORT, KBD_LINE_TEST))
- {
- Status = I8042ReadDataWait(DevExt, &Value);
- if (NT_SUCCESS(Status) && Value == 0)
- DevExt->KeyboardExists = TRUE;
+ if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_READ_MODE)) {
+ DPRINT1("Can't read i8042 mode\n");
+ return FALSE;
}
+ Status = I8042ReadDataWait(DevExt, &Value);
+ if (!NT_SUCCESS(Status)) {
+ DPRINT1("No response after read i8042 mode\n");
+ return FALSE;
+ }
+
+ Value |= CCB_KBD_DISAB | CCB_MOUSE_DISAB; /* disable keyboard/mouse */
+ Value &= ~(CCB_KBD_INT_ENAB | CCB_MOUSE_INT_ENAB);
+ /* don't enable keyboard and mouse interrupts */
+
+ if (!I8042Write(DevExt, I8042_CTRL_PORT, KBD_WRITE_MODE)) {
+ DPRINT1("Can't set i8042 mode\n");
+ return FALSE;
+ }
+
+ if (!I8042Write(DevExt, I8042_DATA_PORT, Value)) {
+ DPRINT1("Can't send i8042 mode\n");
+ return FALSE;
+ }
+
+ /*
+ * We used to send a KBD_LINE_TEST command here, but on at least HP
+ * Pavilion notebooks the response to that command was incorrect.
+ * So now we just assume that a keyboard is attached.
+ */
+ DevExt->KeyboardExists = TRUE;
+
if (I8042Write(DevExt, I8042_CTRL_PORT, MOUSE_LINE_TEST))
{
Status = I8042ReadDataWait(DevExt, &Value);
return Status;
}
+ if (DevExt->MouseExists) {
+ DPRINT("Aux port detected\n");
+ DevExt->MouseExists = I8042DetectMouse(DevExt);
+ }
+
if (!DevExt->KeyboardExists) {
DPRINT("Keyboard port not detected\n");
if (DevExt->Settings.Headless)
DevExt->KeyboardExists = I8042DetectKeyboard(DevExt);
}
- if (DevExt->MouseExists) {
- DPRINT("Mouse port detected\n");
- DevExt->MouseExists = I8042DetectMouse(DevExt);
- }
-
if (DevExt->KeyboardExists) {
DPRINT("Keyboard detected\n");
I8042KeyboardEnable(DevExt);
PDEVICE_EXTENSION DevExt;
PFDO_DEVICE_EXTENSION FdoDevExt;
PDEVICE_OBJECT Fdo;
+ static BOOLEAN AlreadyAdded = FALSE;
DPRINT("I8042AddDevice\n");
+ /* HACK! */
+ if (AlreadyAdded)
+ return STATUS_UNSUCCESSFUL;
+ AlreadyAdded = TRUE;
+
Status = IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
{
DPRINT("I8042 Driver 0.0.1\n");
+ I8042RegistryPath.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters");
+ I8042RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
+ I8042RegistryPath.MaximumLength,
+ TAG_I8042);
+ if (I8042RegistryPath.Buffer == NULL) {
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlCopyUnicodeString(&I8042RegistryPath, RegistryPath);
+ RtlAppendUnicodeToString(&I8042RegistryPath, L"\\Parameters");
+ I8042RegistryPath.Buffer[I8042RegistryPath.Length / sizeof(WCHAR)] = 0;
+
+
+
DriverObject->MajorFunction[IRP_MJ_CREATE] = I8042CreateDispatch;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
I8042InternalDeviceControl;
return(STATUS_SUCCESS);
}
-