Big move of driver input stack to a Plug-and-Play model:
- mouclass:
Do non buffered IO. The pointer move should be smoother.
Search non Plug-and-Play drivers in registry, instead of using their
device name.
- kbdclass:
Full rewrite to support more than one keyboard.
Use registry settings as specified in MSDN.
(Info: kbdclass is now very similar to mouclass)
- i8042prt:
Keep it as a non Plug-and-Play driver, but register it in DEVICEMAP
registry key.
- USB controller:
Enable USB keyboard/mouse
I may have broken support for serial mice, i'll add it back in a few
days...
Modified: trunk/reactos/bootdata/hivesys.inf
Modified: trunk/reactos/drivers/input/i8042prt/i8042prt.c
Modified: trunk/reactos/drivers/input/kbdclass/kbdclass.c
Modified: trunk/reactos/drivers/input/kbdclass/kbdclass.h
Modified: trunk/reactos/drivers/input/kbdclass/kbdclass.xml
Added: trunk/reactos/drivers/input/kbdclass/misc.c
Modified: trunk/reactos/drivers/input/mouclass/mouclass.c
Modified: trunk/reactos/drivers/input/mouclass/mouclass.h
Modified: trunk/reactos/drivers/usb/miniport/common/main.c
Modified: trunk/reactos/media/inf/syssetup.inf
Modified: trunk/reactos/subsys/win32k/ntuser/input.c
_____
Modified: trunk/reactos/bootdata/hivesys.inf
--- trunk/reactos/bootdata/hivesys.inf 2005-10-31 11:59:29 UTC (rev
18910)
+++ trunk/reactos/bootdata/hivesys.inf 2005-10-31 16:46:46 UTC (rev
18911)
@@ -532,7 +532,6 @@
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Type",0x00010001,0x00
000001
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","ConnectMul
tiplePorts",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","MouseDataQ
ueueSize",0x00010001,0x00000064
-HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","PointerDe
viceBaseName",0x00000000,"PointerClassPnp"
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96F-E325-11CE-BFC1-08
002BE10318}","UpperFilters",0x00010000,"mouclass"
; Mailslot filesystem driver
_____
Modified: trunk/reactos/drivers/input/i8042prt/i8042prt.c
--- trunk/reactos/drivers/input/i8042prt/i8042prt.c 2005-10-31
11:59:29 UTC (rev 18910)
+++ trunk/reactos/drivers/input/i8042prt/i8042prt.c 2005-10-31
16:46:46 UTC (rev 18911)
@@ -417,6 +417,7 @@
goto hookworkitemdone;
}
+#if 0
Status = IoCallDriver(
WorkItemData->Target,
NewIrp);
@@ -427,6 +428,7 @@
KernelMode,
FALSE,
NULL);
+#endif
if (IsKbd) {
/* Call the hooked initialization if it exists */
@@ -633,11 +635,58 @@
return STATUS_SUCCESS;
}
+static NTSTATUS
+AddRegistryEntry(
+ IN PCWSTR PortTypeName,
+ IN PUNICODE_STRING DeviceName,
+ IN PCWSTR RegistryPath)
+{
+ UNICODE_STRING PathU =
RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE hDeviceMapKey = (HANDLE)-1;
+ HANDLE hPortKey = (HANDLE)-1;
+ UNICODE_STRING PortTypeNameU;
+ NTSTATUS Status;
+
+ InitializeObjectAttributes(&ObjectAttributes, &PathU,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
+ Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwOpenKey() failed with status 0x%08lx\n",
Status);
+ goto cleanup;
+ }
+
+ RtlInitUnicodeString(&PortTypeNameU, PortTypeName);
+ InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU,
OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL);
+ Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE,
&ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwCreateKey() failed with status 0x%08lx\n",
Status);
+ goto cleanup;
+ }
+
+ Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ,
(PVOID)RegistryPath, wcslen(RegistryPath) * sizeof(WCHAR) +
sizeof(UNICODE_NULL));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwSetValueKey() failed with status 0x%08lx\n",
Status);
+ goto cleanup;
+ }
+
+ Status = STATUS_SUCCESS;
+
+cleanup:
+ if (hDeviceMapKey != (HANDLE)-1)
+ ZwClose(hDeviceMapKey);
+ if (hPortKey != (HANDLE)-1)
+ ZwClose(hPortKey);
+ return Status;
+}
+
static NTSTATUS STDCALL I8042AddDevice(PDRIVER_OBJECT DriverObject,
PDEVICE_OBJECT Pdo)
{
- UNICODE_STRING DeviceName =
RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
- UNICODE_STRING MouseName =
RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
+ UNICODE_STRING DeviceName =
RTL_CONSTANT_STRING(L"\\Device\\KeyboardPort8042");
+ UNICODE_STRING MouseName =
RTL_CONSTANT_STRING(L"\\Device\\PointerPort8042");
ULONG MappedIrqKeyboard = 0, MappedIrqMouse = 0;
KIRQL DirqlKeyboard = 0;
KIRQL DirqlMouse = 0;
@@ -716,6 +765,7 @@
if (NT_SUCCESS(Status))
{
+ AddRegistryEntry(L"KeyboardPort", &DeviceName,
L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\i8042prt");
FdoDevExt = Fdo->DeviceExtension;
RtlZeroMemory(FdoDevExt,
sizeof(FDO_DEVICE_EXTENSION));
@@ -764,6 +814,7 @@
if (NT_SUCCESS(Status))
{
+ AddRegistryEntry(L"PointerPort", &MouseName,
L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\i8042prt");
FdoDevExt = Fdo->DeviceExtension;
RtlZeroMemory(FdoDevExt,
sizeof(FDO_DEVICE_EXTENSION));
_____
Modified: trunk/reactos/drivers/input/kbdclass/kbdclass.c
--- trunk/reactos/drivers/input/kbdclass/kbdclass.c 2005-10-31
11:59:29 UTC (rev 18910)
+++ trunk/reactos/drivers/input/kbdclass/kbdclass.c 2005-10-31
16:46:46 UTC (rev 18911)
@@ -1,302 +1,718 @@
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: drivers/input/kbdclass/kbdclass.c
- * PURPOSE: Keyboard class driver
- * PROGRAMMER: Victor Kirhenshtein (sauros(a)iname.com)
- * Jason Filby (jasonfilby(a)yahoo.com)
- * Tinus_
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Keyboard class driver
+ * FILE: drivers/kbdclass/kbdclass.c
+ * PURPOSE: Keyboard class driver
+ *
+ * PROGRAMMERS: HervÚ Poussineau (hpoussin(a)reactos.org)
*/
-/* INCLUDES
****************************************************************/
-
-#include <ddk/ntddk.h>
-
#define NDEBUG
#include <debug.h>
+#define INITGUID
#include "kbdclass.h"
-/* GLOBALS
*******************************************************************/
+static VOID NTAPI
+DriverUnload(IN PDRIVER_OBJECT DriverObject)
+{
+ // nothing to do here yet
+}
-NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
- PUNICODE_STRING RegistryPath);
+static NTSTATUS NTAPI
+KbdclassCreate(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ DPRINT("IRP_MJ_CREATE\n");
-/*
- * Driver data
- */
+ if
(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+ return ForwardIrpAndForget(DeviceObject, Irp);
-static BOOLEAN AlreadyOpened = FALSE;
+ /* FIXME: open all associated Port devices */
+ return STATUS_SUCCESS;
+}
-static VOID STDCALL KbdCopyKeys(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+static NTSTATUS NTAPI
+KbdclassClose(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- PDEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension;
- PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
- ULONG NrToRead = stk->Parameters.Read.Length /
-
sizeof(KEYBOARD_INPUT_DATA);
- ULONG NrRead =
Irp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA);
- KEYBOARD_INPUT_DATA *Rec =
- (KEYBOARD_INPUT_DATA
*)Irp->AssociatedIrp.SystemBuffer;
+ DPRINT("IRP_MJ_CLOSE\n");
- while (DevExt->KeysInBuffer &&
- NrRead < NrToRead) {
- memcpy(&Rec[NrRead],
- &DevExt->KbdBuffer[DevExt->BufHead],
- sizeof(KEYBOARD_INPUT_DATA));
+ if
(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+ return ForwardIrpAndForget(DeviceObject, Irp);
- if (++DevExt->BufHead >= KBD_BUFFER_SIZE)
- DevExt->BufHead = 0;
+ /* FIXME: close all associated Port devices */
+ return STATUS_SUCCESS;
+}
- DevExt->KeysInBuffer--;
- NrRead++;
- }
- Irp->IoStatus.Information = NrRead *
sizeof(KEYBOARD_INPUT_DATA);
+static NTSTATUS NTAPI
+KbdclassRead(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ DPRINT("IRP_MJ_READ\n");
- if (NrRead < NrToRead) {
- Irp->IoStatus.Status = STATUS_PENDING;
- DPRINT("Pending... (NrRead %d, NrToRead %d\n", NrRead,
NrToRead);
- } else {
- DPRINT("Send scancode: %x\n",
((KEYBOARD_INPUT_DATA*)Irp->AssociatedIrp.SystemBuffer)->MakeCode);
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ if
(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+ return ForwardIrpAndForget(DeviceObject, Irp);
+
+ if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length <
sizeof(KEYBOARD_INPUT_DATA))
+ {
+ Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
- IoStartNextPacket (DeviceObject, FALSE);
- DPRINT("Success!\n");
+
+ return STATUS_BUFFER_TOO_SMALL;
}
+
+ IoMarkIrpPending(Irp);
+ IoStartPacket(DeviceObject, Irp, NULL, NULL);
+ return STATUS_PENDING;
}
-static VOID STDCALL KbdClassServiceCallback (
- PDEVICE_OBJECT DeviceObject,
- PKEYBOARD_INPUT_DATA
InputDataStart,
- PKEYBOARD_INPUT_DATA
InputDataEnd,
- PULONG InputDataConsumed)
+static NTSTATUS NTAPI
+KbdclassDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- PDEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension;
- PKEYBOARD_INPUT_DATA CurrentInput = InputDataStart;
+ NTSTATUS Status;
- DPRINT("ServiceCallback called\n");
+ DPRINT("IRP_MJ_DEVICE_CONTROL\n");
+
+ if
(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+ return ForwardIrpAndForget(DeviceObject, Irp);
- while (DevExt->KeysInBuffer < KBD_BUFFER_SIZE &&
- CurrentInput < InputDataEnd) {
- memcpy(&DevExt->KbdBuffer[DevExt->BufTail],
- CurrentInput,
- sizeof(KEYBOARD_INPUT_DATA));
+ switch
(IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControl
Code)
+ {
+ case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
+ case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
+ case IOCTL_KEYBOARD_QUERY_INDICATORS:
+ case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
+ case IOCTL_KEYBOARD_SET_INDICATORS:
+ case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would
seem logical */
+ /* FIXME: send it to all associated Port devices
*/
+ Status = STATUS_NOT_SUPPORTED;
+ break;
+ default:
+ DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O
control code 0x%lx\n",
+
IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlC
ode);
+ Status = STATUS_NOT_SUPPORTED;
+ }
- if (++DevExt->BufTail >= KBD_BUFFER_SIZE)
- DevExt->BufTail = 0;
- DevExt->KeysInBuffer++;
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
- CurrentInput++;
- InputDataConsumed[0]++;
- }
+ return Status;
+}
- if (CurrentInput < InputDataStart)
- /* Copy the rest to the beginning, perhaps the keyboard
- * can buffer it for us */
- memmove(InputDataStart,
- CurrentInput,
- ((char *)InputDataEnd - (char *)CurrentInput));
+static NTSTATUS NTAPI
+IrpStub(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status = STATUS_NOT_SUPPORTED;
- if (DeviceObject->CurrentIrp) {
- PIRP Irp = DeviceObject->CurrentIrp;
- PIO_STACK_LOCATION stk =
IoGetCurrentIrpStackLocation(Irp);
- if (stk->MajorFunction == IRP_MJ_READ)
- KbdCopyKeys(DeviceObject, Irp);
+ if
(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
+ {
+ /* Forward some IRPs to lower device */
+ switch
(IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
+ {
+ case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+ return ForwardIrpAndForget(DeviceObject,
Irp);
+ default:
+ {
+ DPRINT1("Port DO stub for major function
0x%lx\n",
+
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
+ ASSERT(FALSE);
+ Status = Irp->IoStatus.Status;
+ }
+ }
}
+ else
+ {
+ DPRINT1("Class DO stub for major function 0x%lx\n",
+
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
+ ASSERT(FALSE);
+ Status = Irp->IoStatus.Status;
+ }
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
}
-static VOID STDCALL KbdStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+static NTSTATUS
+ReadRegistryEntries(
+ IN PUNICODE_STRING RegistryPath,
+ IN PKBDCLASS_DRIVER_EXTENSION DriverExtension)
{
- /* We only do this for read irps */
- DPRINT("KeyboardStartIo(DeviceObject %x Irp
%x)\n",DeviceObject,Irp);
- KbdCopyKeys(DeviceObject, Irp);
-}
+ RTL_QUERY_REGISTRY_TABLE Parameters[4];
+ NTSTATUS Status;
+ ULONG DefaultConnectMultiplePorts = 1;
+ ULONG DefaultKeyboardDataQueueSize = 0x64;
+ UNICODE_STRING DefaultKeyboardDeviceBaseName =
RTL_CONSTANT_STRING(L"KeyboardClass");
-/*
- * These are just passed down the stack but we must change the IOCTL to
be
- * INTERNAL. MSDN says there might be more...
- */
-static NTSTATUS STDCALL KbdDeviceControl(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
-{
- PDEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension;
- PIO_STACK_LOCATION Stk = IoGetCurrentIrpStackLocation(Irp);
- PIO_STACK_LOCATION NextStk = IoGetNextIrpStackLocation(Irp);
+ RtlZeroMemory(Parameters, sizeof(Parameters));
- DPRINT ("KbdDeviceControl %x\n",
Stk->Parameters.DeviceIoControl.IoControlCode);
+ Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT |
RTL_REGISTRY_OPTIONAL;
+ Parameters[0].Name = L"ConnectMultiplePorts";
+ Parameters[0].EntryContext =
&DriverExtension->ConnectMultiplePorts;
+ Parameters[0].DefaultType = REG_DWORD;
+ Parameters[0].DefaultData = &DefaultConnectMultiplePorts;
+ Parameters[0].DefaultLength = sizeof(ULONG);
+
+ Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT |
RTL_REGISTRY_OPTIONAL;
+ Parameters[1].Name = L"KeyboardDataQueueSize";
+ Parameters[1].EntryContext =
&DriverExtension->KeyboardDataQueueSize;
+ Parameters[1].DefaultType = REG_DWORD;
+ Parameters[1].DefaultData = &DefaultKeyboardDataQueueSize;
+ Parameters[1].DefaultLength = sizeof(ULONG);
+
+ Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT |
RTL_REGISTRY_OPTIONAL;
+ Parameters[2].Name = L"KeyboardDeviceBaseName";
+ Parameters[2].EntryContext =
&DriverExtension->KeyboardDeviceBaseName;
+ Parameters[2].DefaultType = REG_SZ;
+ Parameters[2].DefaultData = &DefaultKeyboardDeviceBaseName;
+ Parameters[2].DefaultLength = sizeof(ULONG);
- switch (Stk->Parameters.DeviceIoControl.IoControlCode) {
- case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
- case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
- case IOCTL_KEYBOARD_QUERY_INDICATORS:
- case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
- case IOCTL_KEYBOARD_SET_INDICATORS:
- case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem
logical */
- IoCopyCurrentIrpStackLocationToNext(Irp);
- NextStk->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ Status = RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE,
+ RegistryPath->Buffer,
+ Parameters,
+ NULL,
+ NULL);
- return IoCallDriver(DevExt->I8042Device, Irp);
- default:
- return STATUS_INVALID_DEVICE_REQUEST;
+ if (NT_SUCCESS(Status))
+ {
+ /* Check values */
+ if (DriverExtension->ConnectMultiplePorts != 0
+ && DriverExtension->ConnectMultiplePorts != 1)
+ {
+ DriverExtension->ConnectMultiplePorts =
DefaultConnectMultiplePorts;
+ }
+ if (DriverExtension->KeyboardDataQueueSize == 0)
+ {
+ DriverExtension->KeyboardDataQueueSize =
DefaultKeyboardDataQueueSize;
+ }
}
+
+ return Status;
}
-static NTSTATUS STDCALL KbdInternalDeviceControl(PDEVICE_OBJECT
DeviceObject,
- PIRP Irp)
+static NTSTATUS
+CreateKeyboardClassDeviceObject(
+ IN PDRIVER_OBJECT DriverObject,
+ OUT PDEVICE_OBJECT *ClassDO OPTIONAL)
{
- PDEVICE_EXTENSION DevExt = DeviceObject->DeviceExtension;
+ PKBDCLASS_DRIVER_EXTENSION DriverExtension;
+ ULONG DeviceId = 0;
+ ULONG PrefixLength;
+ UNICODE_STRING DeviceNameU;
+ PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */
+ PDEVICE_OBJECT Fdo;
+ PKBDCLASS_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
- DPRINT ("KbdInternalDeviceControl\n");
+ DPRINT("CreateKeyboardClassDeviceObject(0x%p)\n", DriverObject);
- IoSkipCurrentIrpStackLocation(Irp);
- return IoCallDriver(DevExt->I8042Device, Irp);
+ /* Create new device object */
+ DriverExtension = IoGetDriverObjectExtension(DriverObject,
DriverObject);
+ DeviceNameU.Length = 0;
+ DeviceNameU.MaximumLength =
+ wcslen(L"\\Device\\") * sizeof(WCHAR) /*
"\Device\" */
+ + DriverExtension->KeyboardDeviceBaseName.Length/*
"KeyboardClass" */
+ + 4 * sizeof(WCHAR) /* Id
between 0 and 9999 */
+ + sizeof(UNICODE_NULL); /* Final
NULL char */
+ DeviceNameU.Buffer = ExAllocatePool(PagedPool,
DeviceNameU.MaximumLength);
+ if (!DeviceNameU.Buffer)
+ {
+ DPRINT("ExAllocatePool() failed\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ Status = RtlAppendUnicodeToString(&DeviceNameU, L"\\Device\\");
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("RtlAppendUnicodeToString() failed with status
0x%08lx\n", Status);
+ goto cleanup;
+ }
+ Status = RtlAppendUnicodeStringToString(&DeviceNameU,
&DriverExtension->KeyboardDeviceBaseName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("RtlAppendUnicodeStringToString() failed with
status 0x%08lx\n", Status);
+ goto cleanup;
+ }
+ PrefixLength = DeviceNameU.MaximumLength - 4 * sizeof(WCHAR) -
sizeof(UNICODE_NULL);
+ DeviceIdW = &DeviceNameU.Buffer[PrefixLength / sizeof(WCHAR)];
+ while (DeviceId < 9999)
+ {
+ DeviceNameU.Length = PrefixLength + swprintf(DeviceIdW,
L"%lu", DeviceId) * sizeof(WCHAR);
+ Status = IoCreateDevice(
+ DriverObject,
+ sizeof(KBDCLASS_DEVICE_EXTENSION),
+ &DeviceNameU,
+ FILE_DEVICE_KEYBOARD,
+ FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &Fdo);
+ if (NT_SUCCESS(Status))
+ goto cleanup;
+ else if (Status != STATUS_OBJECT_NAME_COLLISION)
+ {
+ DPRINT("IoCreateDevice() failed with status
0x%08lx\n", Status);
+ goto cleanup;
+ }
+ DeviceId++;
+ }
+ DPRINT("Too much devices starting with '\\Device\\%wZ'\n",
&DriverExtension->KeyboardDeviceBaseName);
+ Status = STATUS_UNSUCCESSFUL;
+cleanup:
+ ExFreePool(DeviceNameU.Buffer);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ DeviceExtension =
(PKBDCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
+ RtlZeroMemory(DeviceExtension,
sizeof(KBDCLASS_DEVICE_EXTENSION));
+ DeviceExtension->Common.IsClassDO = TRUE;
+ DeviceExtension->DriverExtension = DriverExtension;
+ DeviceExtension->PnpState = dsStopped;
+ KeInitializeSpinLock(&(DeviceExtension->SpinLock));
+ DeviceExtension->ReadIsPending = FALSE;
+ DeviceExtension->InputCount = 0;
+ DeviceExtension->PortData = ExAllocatePool(NonPagedPool,
DeviceExtension->DriverExtension->KeyboardDataQueueSize *
sizeof(KEYBOARD_INPUT_DATA));
+ Fdo->Flags |= DO_POWER_PAGABLE;
+ Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ /* FIXME: create registry entry in
HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
+
+ if (ClassDO)
+ *ClassDO = Fdo;
+
+ return STATUS_SUCCESS;
}
-static NTSTATUS STDCALL KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP
Irp)
+static BOOLEAN
+KbdclassCallback(
+ IN PDEVICE_OBJECT ClassDeviceObject,
+ IN OUT PKEYBOARD_INPUT_DATA KeyboardDataStart,
+ IN PKEYBOARD_INPUT_DATA KeyboardDataEnd,
+ IN OUT PULONG ConsumedCount)
{
- PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
- NTSTATUS Status;
+ PKBDCLASS_DEVICE_EXTENSION ClassDeviceExtension =
ClassDeviceObject->DeviceExtension;
+ PIRP Irp = NULL;
+ KIRQL OldIrql;
+ PIO_STACK_LOCATION Stack;
+ ULONG InputCount = KeyboardDataEnd - KeyboardDataStart;
+ ULONG ReadSize;
- DPRINT("DeviceObject %x\n",DeviceObject);
- DPRINT("Irp %x\n",Irp);
+ ASSERT(ClassDeviceExtension->Common.IsClassDO);
- DPRINT("Dispatch: stk->MajorFunction %d\n", stk->MajorFunction);
- DPRINT("AlreadyOpened %d\n",AlreadyOpened);
+ DPRINT("KbdclassCallback()\n");
+ /* A filter driver might have consumed all the data already; I'm
+ * not sure if they are supposed to move the packets when they
+ * consume them though.
+ */
+ if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
+ {
+ Irp = ClassDeviceObject->CurrentIrp;
+ ClassDeviceObject->CurrentIrp = NULL;
+ Stack = IoGetCurrentIrpStackLocation(Irp);
- switch (stk->MajorFunction) {
- case IRP_MJ_CREATE:
- if (AlreadyOpened == TRUE) {
- CHECKPOINT;
- Status = STATUS_UNSUCCESSFUL;
- DPRINT1("Keyboard is already open\n");
- } else {
- CHECKPOINT;
- Status = STATUS_SUCCESS;
- AlreadyOpened = TRUE;
- }
- break;
+ /* A read request is waiting for input, so go straight
to it */
+ /* FIXME: use SEH */
+ RtlCopyMemory(
+ Irp->MdlAddress ?
MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) :
Irp->UserBuffer,
+ KeyboardDataStart,
+ sizeof(KEYBOARD_INPUT_DATA));
- case IRP_MJ_CLOSE:
- Status = STATUS_SUCCESS;
- AlreadyOpened = FALSE;
- break;
+ /* Go to next packet and complete this request with
STATUS_SUCCESS */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = sizeof(KEYBOARD_INPUT_DATA);
+ Stack->Parameters.Read.Length =
sizeof(KEYBOARD_INPUT_DATA);
- case IRP_MJ_READ:
- DPRINT("Queueing packet\n");
- IoMarkIrpPending(Irp);
- IoStartPacket(DeviceObject,Irp,NULL,NULL);
- return(STATUS_PENDING);
+ ClassDeviceExtension->ReadIsPending = FALSE;
- default:
- Status = STATUS_NOT_IMPLEMENTED;
- break;
+ /* Skip the packet we just sent away */
+ KeyboardDataStart++;
+ (*ConsumedCount)++;
+ InputCount--;
}
- Irp->IoStatus.Status = Status;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp,IO_NO_INCREMENT);
- DPRINT("Status %d\n",Status);
- return(Status);
+ /* If we have data from the port driver and a higher service to
send the data to */
+ if (InputCount != 0)
+ {
+ KeAcquireSpinLock(&ClassDeviceExtension->SpinLock,
&OldIrql);
+
+ if (ClassDeviceExtension->InputCount + InputCount >
ClassDeviceExtension->DriverExtension->KeyboardDataQueueSize)
+ ReadSize =
ClassDeviceExtension->DriverExtension->KeyboardDataQueueSize -
ClassDeviceExtension->InputCount;
+ else
+ ReadSize = InputCount;
+
+ /*
+ * FIXME: If we exceed the buffer, keyboard data gets
thrown away.. better
+ * solution?
+ */
+
+ /*
+ * Move the keyboard input data from the port data queue
to our class data
+ * queue.
+ */
+ RtlMoveMemory(
+ ClassDeviceExtension->PortData,
+ (PCHAR)KeyboardDataStart,
+ sizeof(KEYBOARD_INPUT_DATA) * ReadSize);
+
+ /* Move the pointer and counter up */
+ ClassDeviceExtension->PortData += ReadSize;
+ ClassDeviceExtension->InputCount += ReadSize;
+
+ KeReleaseSpinLock(&ClassDeviceExtension->SpinLock,
OldIrql);
+ (*ConsumedCount) += ReadSize;
+ }
+ else
+ {
+ DPRINT("KbdclassCallBack() entered, InputCount = %lu -
DOING NOTHING\n", InputCount);
+ }
+
+ if (Irp != NULL)
+ {
+ IoStartNextPacket(ClassDeviceObject, FALSE);
+ IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
+ }
+
+ DPRINT("Leaving KbdclassCallback()\n");
+ return TRUE;
}
-static VOID STDCALL KbdClassSendConnect(PDEVICE_EXTENSION DevExt)
+/* Send IOCTL_INTERNAL_KEYBOARD_CONNECT to keyboard port */
+static NTSTATUS
+ConnectKeyboardPortDriver(
+ IN PDEVICE_OBJECT KeyboardPortDO,
+ IN PDEVICE_OBJECT KeyboardClassDO)
{
- CONNECT_DATA ConnectData;
KEVENT Event;
+ PIRP Irp;
IO_STATUS_BLOCK IoStatus;
+ CONNECT_DATA ConnectData;
NTSTATUS Status;
- PIRP Irp;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
- ConnectData.ClassDeviceObject = DevExt->DeviceObject;
- ConnectData.ClassService = KbdClassServiceCallback;
+ ConnectData.ClassDeviceObject = KeyboardClassDO;
+ ConnectData.ClassService = KbdclassCallback;
- Irp = IoBuildDeviceIoControlRequest(
- IOCTL_INTERNAL_KEYBOARD_CONNECT,
- DevExt->I8042Device,
- &ConnectData,
- sizeof(CONNECT_DATA),
- NULL,
- 0,
- TRUE,
- &Event,
- &IoStatus);
+ Irp =
IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_KEYBOARD_CONNECT,
+ KeyboardPortDO,
+ &ConnectData, sizeof(CONNECT_DATA),
+ NULL, 0,
+ TRUE, &Event, &IoStatus);
- if (!Irp)
- return;
+ Status = IoCallDriver(KeyboardPortDO, Irp);
- Status = IoCallDriver(
- DevExt->I8042Device,
- Irp);
- DPRINT("SendConnect status: %x\n", Status);
+ if (Status == STATUS_PENDING)
+ KeWaitForSingleObject(&Event, Suspended, KernelMode,
FALSE, NULL);
+ else
+ IoStatus.Status = Status;
- if (STATUS_PENDING ==Status)
- KeWaitForSingleObject(&Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- DPRINT("SendConnect done\n");
+ return IoStatus.Status;
}
-NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
- PUNICODE_STRING RegistryPath)
-/*
- * FUNCTION: Module entry point
- */
+static NTSTATUS NTAPI
+KbdclassAddDevice(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT Pdo)
{
- PDEVICE_OBJECT DeviceObject;
- PDEVICE_EXTENSION DevExt;
- PFILE_OBJECT I8042File;
+ PKBDCLASS_DRIVER_EXTENSION DriverExtension;
+ PDEVICE_OBJECT Fdo;
+ PKBDCLASS_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
- UNICODE_STRING DeviceName =
RTL_CONSTANT_STRING(L"\\Device\\Keyboard");
- UNICODE_STRING SymlinkName =
RTL_CONSTANT_STRING(L"\\??\\Keyboard");
- UNICODE_STRING I8042Name =
RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
- DPRINT("Keyboard Class Driver 0.0.1\n");
+ DPRINT("KbdclassAddDevice called. Pdo = 0x%p\n", Pdo);
- DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdDispatch;
- DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdDispatch;
- DriverObject->MajorFunction[IRP_MJ_READ] = KbdDispatch;
- DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
-
KbdInternalDeviceControl;
- DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
KbdDeviceControl;
+ DriverExtension = IoGetDriverObjectExtension(DriverObject,
DriverObject);
- DriverObject->DriverStartIo = KbdStartIo;
+ /* Create new device object */
+ Status = IoCreateDevice(
+ DriverObject,
+ sizeof(KBDCLASS_DEVICE_EXTENSION),
+ NULL,
+ Pdo->DeviceType,
+ FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &Fdo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("IoCreateDevice() failed with status 0x%08lx\n",
Status);
+ return Status;
+ }
- IoCreateDevice(DriverObject,
- sizeof(DEVICE_EXTENSION),
- &DeviceName,
- FILE_DEVICE_KEYBOARD,
- 0,
- TRUE,
- &DeviceObject);
+ DeviceExtension =
(PKBDCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
+ RtlZeroMemory(DeviceExtension,
sizeof(KBDCLASS_DEVICE_EXTENSION));
+ DeviceExtension->Common.IsClassDO = FALSE;
+ DeviceExtension->PnpState = dsStopped;
+ Fdo->Flags |= DO_POWER_PAGABLE;
+ Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo,
&DeviceExtension->LowerDevice);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("IoAttachDeviceToDeviceStackSafe() failed with
status 0x%08lx\n", Status);
+ IoDeleteDevice(Fdo);
+ return Status;
+ }
+ Fdo->Flags |= DO_BUFFERED_IO;
+ Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
- RtlZeroMemory(DeviceObject->DeviceExtension,
sizeof(DEVICE_EXTENSION));
- DevExt = DeviceObject->DeviceExtension;
- DevExt->DeviceObject = DeviceObject;
+ if (DriverExtension->ConnectMultiplePorts)
+ Status = ConnectKeyboardPortDriver(Fdo,
DriverExtension->MainKbdclassDeviceObject);
+ else
+ Status = ConnectKeyboardPortDriver(Fdo, Fdo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ConnectKeyboardPortDriver() failed with status
0x%08lx\n", Status);
+ /* FIXME: why can't I cleanup without error? */
+ //IoDetachDevice(Fdo);
+ //IoDeleteDevice(Fdo);
+ return Status;
+ }
- Status = IoGetDeviceObjectPointer(&I8042Name,
- FILE_READ_DATA,
- &I8042File,
- &DevExt->I8042Device);
+ /* Register GUID_DEVINTERFACE_KEYBOARD interface */
+ Status = IoRegisterDeviceInterface(
+ Pdo,
+ &GUID_DEVINTERFACE_KEYBOARD,
+ NULL,
+ &DeviceExtension->KeyboardInterfaceName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("IoRegisterDeviceInterface() failed with status
0x%08lx\n", Status);
+ return Status;
+ }
- if (STATUS_SUCCESS != Status) {
- DPRINT("Failed to open device: %x\n", Status);
+ return STATUS_SUCCESS;
+}
+
+static VOID NTAPI
+KbdclassStartIo(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PKBDCLASS_DEVICE_EXTENSION DeviceExtension =
DeviceObject->DeviceExtension;
+ PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+
+ ASSERT(DeviceExtension->Common.IsClassDO);
+
+ if (DeviceExtension->InputCount > 0)
+ {
+ KIRQL oldIrql;
+
+ KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
+
+ /* FIXME: use SEH */
+ RtlCopyMemory(
+ Irp->MdlAddress ?
MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority) :
Irp->UserBuffer,
+ DeviceExtension->PortData -
DeviceExtension->InputCount,
+ sizeof(KEYBOARD_INPUT_DATA));
+
+ if (DeviceExtension->InputCount > 1)
+ {
+ RtlMoveMemory(
+ DeviceExtension->PortData -
DeviceExtension->InputCount,
+ DeviceExtension->PortData -
DeviceExtension->InputCount + 1,
+ (DeviceExtension->InputCount - 1) *
sizeof(KEYBOARD_INPUT_DATA));
+ }
+ DeviceExtension->PortData--;
+ DeviceExtension->InputCount--;
+ DeviceExtension->ReadIsPending = FALSE;
+
+ /* Go to next packet and complete this request with
STATUS_SUCCESS */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = sizeof(KEYBOARD_INPUT_DATA);
+ Stack->Parameters.Read.Length =
sizeof(KEYBOARD_INPUT_DATA);
+ IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
+
+ IoStartNextPacket(DeviceObject, FALSE);
+ KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql);
+ }
+ else
+ {
+ DeviceExtension->ReadIsPending = TRUE;
+ }
+}
+
+static NTSTATUS
+SearchForLegacyDrivers(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PKBDCLASS_DRIVER_EXTENSION DriverExtension)
+{
+ UNICODE_STRING DeviceMapKeyU =
RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
+ UNICODE_STRING PortBaseName = {0, };
+ PKEY_VALUE_BASIC_INFORMATION KeyValueInformation = NULL;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE hDeviceMapKey = (HANDLE)-1;
+ HANDLE hPortKey = (HANDLE)-1;
+ ULONG Index = 0;
+ ULONG Size, ResultLength;
+ NTSTATUS Status;
+
+ /* Create port base name, by replacing Class by Port at the end
of the class base name */
+ Status = RtlDuplicateUnicodeString(
+ RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+ &DriverExtension->KeyboardDeviceBaseName,
+ &PortBaseName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("RtlDuplicateUnicodeString() failed with status
0x%08lx\n", Status);
+ goto cleanup;
+ }
+ PortBaseName.Length -= (sizeof(L"Class") -
sizeof(UNICODE_NULL));
+ RtlAppendUnicodeToString(&PortBaseName, L"Port");
+
+ /* Allocate memory */
+ Size = sizeof(KEY_VALUE_BASIC_INFORMATION) + MAX_PATH;
+ KeyValueInformation = ExAllocatePool(PagedPool, Size);
+ if (!KeyValueInformation)
+ {
+ DPRINT("ExAllocatePool() failed\n");
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto cleanup;
+ }
+
+ /* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
+ InitializeObjectAttributes(&ObjectAttributes, &DeviceMapKeyU,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
+ Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwOpenKey() failed with status 0x%08lx\n",
Status);
+ goto cleanup;
+ }
+
+ /* Open sub key */
+ InitializeObjectAttributes(&ObjectAttributes, &PortBaseName,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceMapKey, NULL);
+ Status = ZwOpenKey(&hPortKey, KEY_QUERY_VALUE,
&ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ZwOpenKey() failed with status 0x%08lx\n",
Status);
+ DPRINT1("ZwOpenKey() failed with status 0x%08lx\n",
Status);
+ goto cleanup;
+ }
+
+ /* Read each value name */
+ while (ZwEnumerateValueKey(hPortKey, Index++,
KeyValueBasicInformation, KeyValueInformation, Size, &ResultLength) ==
STATUS_SUCCESS)
+ {
+ UNICODE_STRING PortName;
+ PDEVICE_OBJECT PortDeviceObject = NULL;
+ PFILE_OBJECT FileObject = NULL;
+
+ PortName.Length = PortName.MaximumLength =
KeyValueInformation->NameLength;
+ PortName.Buffer = KeyValueInformation->Name;
+
+ /* Open the device object pointer */
+ Status = IoGetDeviceObjectPointer(&PortName,
FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("IoGetDeviceObjectPointer(%wZ) failed
with status 0x%08lx\n", Status);
+ }
+
+ /* Connect the port device object */
+ if (DriverExtension->ConnectMultiplePorts)
+ {
+ Status =
ConnectKeyboardPortDriver(PortDeviceObject,
DriverExtension->MainKbdclassDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: Log the error */
+ DPRINT("ConnectKeyboardPortDriver()
failed with status 0x%08lx\n", Status);
+ /* FIXME: cleanup */
+ }
+ }
+ else
+ {
+ PDEVICE_OBJECT ClassDO;
+ Status =
CreateKeyboardClassDeviceObject(DriverObject, &ClassDO);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: Log the error */
+ DPRINT("CreatePointerClassDeviceObject()
failed with status 0x%08lx\n", Status);
+ /* FIXME: cleanup */
+ continue;
+ }
+ Status =
ConnectKeyboardPortDriver(PortDeviceObject, ClassDO);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: Log the error */
+ DPRINT("ConnectKeyboardPortDriver()
failed with status 0x%08lx\n", Status);
+ /* FIXME: cleanup */
+ }
+ }
+ }
+ if (Status == STATUS_NO_MORE_ENTRIES)
+ Status = STATUS_SUCCESS;
+
+cleanup:
+ if (KeyValueInformation != NULL)
+ ExFreePool(KeyValueInformation);
+ if (hDeviceMapKey != (HANDLE)-1)
+ ZwClose(hDeviceMapKey);
+ if (hPortKey != (HANDLE)-1)
+ ZwClose(hPortKey);
+ return Status;
+}
+
+/*
+ * Standard DriverEntry method.
+ */
+NTSTATUS NTAPI
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath)
+{
+ PKBDCLASS_DRIVER_EXTENSION DriverExtension;
+ ULONG i;
+ NTSTATUS Status;
+
+ Status = IoAllocateDriverObjectExtension(
+ DriverObject,
+ DriverObject,
+ sizeof(KBDCLASS_DRIVER_EXTENSION),
+ (PVOID*)&DriverExtension);
+ if (!NT_SUCCESS(Status))
[truncated at 1000 lines; 662 more skipped]