[USB-BRINGUP]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 6 Jan 2012 16:35:55 +0000 (16:35 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 6 Jan 2012 16:35:55 +0000 (16:35 +0000)
- Add keyboard hid driver template ripped off from mouhid driver
- Implement keyboard driver initialization

svn path=/branches/usb-bringup/; revision=54850

drivers/hid/CMakeLists.txt
drivers/hid/kbdhid/CMakeLists.txt [new file with mode: 0644]
drivers/hid/kbdhid/kbdhid.c [new file with mode: 0644]
drivers/hid/kbdhid/kbdhid.h [new file with mode: 0644]
drivers/hid/kbdhid/kbdhid.rc [new file with mode: 0644]
drivers/hid/mouhid/mouhid.rc

index 166cf18..6051356 100644 (file)
@@ -1,4 +1,5 @@
 add_subdirectory(hidclass)
 add_subdirectory(hidparse)
 add_subdirectory(hidusb)
+add_subdirectory(kbdhid)
 add_subdirectory(mouhid)
diff --git a/drivers/hid/kbdhid/CMakeLists.txt b/drivers/hid/kbdhid/CMakeLists.txt
new file mode 100644 (file)
index 0000000..57d918b
--- /dev/null
@@ -0,0 +1,13 @@
+
+add_definitions(-DDEBUG_MODE)
+
+include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
+
+add_library(kbdhid SHARED kbdhid.c kbdhid.rc)
+
+set_module_type(kbdhid kernelmodedriver)
+add_importlibs(kbdhid ntoskrnl hal hidparse)
+add_cab_target(kbdhid 2)
+
+add_cab_target(kbdhid 2)
+
diff --git a/drivers/hid/kbdhid/kbdhid.c b/drivers/hid/kbdhid/kbdhid.c
new file mode 100644 (file)
index 0000000..d0ad1e5
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * PROJECT:     ReactOS HID Stack
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        drivers/hid/kbdhid/kbdhid.c
+ * PURPOSE:     Keyboard HID Driver
+ * PROGRAMMERS:
+ *              Michael Martin (michael.martin@reactos.org)
+ *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ */
+
+#include "kbdhid.h"
+
+VOID
+KbdHid_DispatchInputData(
+    IN PKBDHID_DEVICE_EXTENSION DeviceExtension,
+    IN PKEYBOARD_INPUT_DATA InputData,
+    IN ULONG InputDataLength)
+{
+    KIRQL OldIrql;
+    ULONG InputDataConsumed;
+
+    if (!DeviceExtension->ClassService)
+        return;
+
+    /* sanity check */
+    ASSERT(DeviceExtension->ClassService);
+    ASSERT(DeviceExtension->ClassDeviceObject);
+
+    /* raise irql */
+    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+
+    /* dispatch input data */
+    (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(DeviceExtension->ClassDeviceObject, InputData, InputData + InputDataLength + 1, &InputDataConsumed);
+
+    /* lower irql to previous level */
+    KeLowerIrql(OldIrql);
+}
+
+NTSTATUS
+NTAPI
+KbdHid_ReadCompletion(
+    IN PDEVICE_OBJECT  DeviceObject,
+    IN PIRP  Irp,
+    IN PVOID  Context)
+{
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)Context;
+
+    if (Irp->IoStatus.Status == STATUS_PRIVILEGE_NOT_HELD ||
+        Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED ||
+        Irp->IoStatus.Status == STATUS_CANCELLED ||
+        DeviceExtension->StopReadReport)
+    {
+        /* failed to read or should be stopped*/
+        DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp->IoStatus.Status);
+
+        /* report no longer active */
+        DeviceExtension->ReadReportActive = FALSE;
+
+        /* request stopping of the report cycle */
+        DeviceExtension->StopReadReport = FALSE;
+
+        /* signal completion event */
+        KeSetEvent(&DeviceExtension->ReadCompletionEvent, 0, 0);
+        return STATUS_MORE_PROCESSING_REQUIRED;
+    }
+
+    UNIMPLEMENTED
+    ASSERT(FALSE);
+
+    /* dispatch mouse action */
+    //KbdHid_DispatchInputData(DeviceExtension, &InputData);
+
+    /* re-init read */
+    KbdHid_InitiateRead(DeviceExtension);
+
+    /* stop completion */
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+KbdHid_InitiateRead(
+    IN PKBDHID_DEVICE_EXTENSION DeviceExtension)
+{
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+
+    /* re-use irp */
+    IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS);
+
+    /* init irp */
+    DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL;
+
+    /* get next stack location */
+    IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp);
+
+    /* init stack location */
+    IoStack->Parameters.Read.Length = DeviceExtension->ReportLength;
+    IoStack->Parameters.Read.Key = 0;
+    IoStack->Parameters.Read.ByteOffset.QuadPart = 0LL;
+    IoStack->MajorFunction = IRP_MJ_READ;
+    IoStack->FileObject = DeviceExtension->FileObject;
+
+    /* set completion routine */
+    IoSetCompletionRoutine(DeviceExtension->Irp, KbdHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE);
+
+    /* read is active */
+    DeviceExtension->ReadReportActive = TRUE;
+
+    /* start the read */
+    Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp);
+
+    /* done */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+KbdHid_CreateCompletion(
+    IN PDEVICE_OBJECT  DeviceObject,
+    IN PIRP  Irp,
+    IN PVOID  Context)
+{
+    KeSetEvent((PKEVENT)Context, 0, FALSE);
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+
+NTSTATUS
+NTAPI
+KbdHid_Create(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+    KEVENT Event;
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+
+    DPRINT1("[KBDHID]: IRP_MJ_CREATE\n");
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* get stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* copy stack location to next */
+    IoCopyCurrentIrpStackLocationToNext(Irp);
+
+    /* init event */
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    /* prepare irp */
+    IoSetCompletionRoutine(Irp, KbdHid_CreateCompletion, &Event, TRUE, TRUE, TRUE);
+
+    /* call lower driver */
+    Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        /* request pending */
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+    }
+
+    /* check for success */
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed */
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return Status;
+    }
+
+    /* is the driver already in use */
+    if (DeviceExtension->FileObject == NULL)
+    {
+         /* did the caller specify correct attributes */
+         ASSERT(IoStack->Parameters.Create.SecurityContext);
+         if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
+         {
+             /* store file object */
+             DeviceExtension->FileObject = IoStack->FileObject;
+
+             /* reset event */
+             KeResetEvent(&DeviceExtension->ReadCompletionEvent);
+
+             /* initiating read */
+             Status = KbdHid_InitiateRead(DeviceExtension);
+             DPRINT1("[KBDHID] KbdHid_InitiateRead: status %x\n", Status);
+             if (Status == STATUS_PENDING)
+             {
+                 /* report irp is pending */
+                 Status = STATUS_SUCCESS;
+             }
+         }
+    }
+
+    /* complete request */
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return Status;
+}
+
+
+NTSTATUS
+NTAPI
+KbdHid_Close(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
+
+    if (DeviceExtension->ReadReportActive)
+    {
+        /* request stopping of the report cycle */
+        DeviceExtension->StopReadReport = TRUE;
+
+        /* wait until the reports have been read */
+        KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
+
+        /* cancel irp */
+        IoCancelIrp(DeviceExtension->Irp);
+    }
+
+    DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
+
+    /* remove file object */
+    DeviceExtension->FileObject = NULL;
+
+    /* skip location */
+    IoSkipCurrentIrpStackLocation(Irp);
+
+    /* pass irp to down the stack */
+    return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+}
+
+NTSTATUS
+NTAPI
+KbdHid_InternalDeviceControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+
+    /* get current stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    DPRINT1("[KBDHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+
+    ASSERT(FALSE);
+    /* unknown request not supported */
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+KbdHid_DeviceControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* skip stack location */
+    IoSkipCurrentIrpStackLocation(Irp);
+
+    /* pass and forget */
+    return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+}
+
+NTSTATUS
+NTAPI
+KbdHid_Power(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+KbdHid_SubmitRequest(
+    PDEVICE_OBJECT DeviceObject,
+    ULONG IoControlCode,
+    ULONG InputBufferSize,
+    PVOID InputBuffer,
+    ULONG OutputBufferSize,
+    PVOID OutputBuffer)
+{
+    KEVENT Event;
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+    PIRP Irp;
+    NTSTATUS Status;
+    IO_STATUS_BLOCK IoStatus;
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* init event */
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+    /* build request */
+    Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus);
+    if (!Irp)
+    {
+        /* no memory */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* send request */
+    Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+    if (Status == STATUS_PENDING)
+    {
+        /* wait for request to complete */
+        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+        Status = IoStatus.Status;
+    }
+
+    /* done */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+KbdHid_StartDevice(
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    NTSTATUS Status;
+    ULONG Buttons;
+    HID_COLLECTION_INFORMATION Information;
+    PHIDP_PREPARSED_DATA PreparsedData;
+    HIDP_CAPS Capabilities;
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+    PUSAGE_AND_PAGE Buffer;
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* query collection information */
+    Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information);
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to query collection information */
+        DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
+        return Status;
+    }
+
+    /* lets allocate space for preparsed data */
+    PreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool(NonPagedPool, Information.DescriptorSize);
+    if (!PreparsedData)
+    {
+        /* no memory */
+        DPRINT1("[KBDHID] no memory size %u\n", Information.DescriptorSize);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* now obtain the preparsed data */
+    Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR, 0, NULL, Information.DescriptorSize, PreparsedData);
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to get preparsed data */
+        DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
+        ExFreePool(PreparsedData);
+        return Status;
+    }
+
+    /* lets get the caps */
+    Status = HidP_GetCaps(PreparsedData, &Capabilities);
+    if (Status != HIDP_STATUS_SUCCESS)
+    {
+        /* failed to get capabilities */
+        DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status);
+        ExFreePool(PreparsedData);
+        return Status;
+    }
+
+    DPRINT1("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
+
+    /* init input report*/
+    DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
+    ASSERT(DeviceExtension->ReportLength);
+    DeviceExtension->Report = (PUCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
+    ASSERT(DeviceExtension->Report);
+    RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
+
+    /* build mdl */
+    DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL);
+    ASSERT(DeviceExtension->ReportMDL);
+
+    /* init mdl */
+    MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL);
+
+    /* get max number of buttons */
+    Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, PreparsedData);
+    DPRINT1("[KBDHID] Buttons %lu\n", Buttons);
+    ASSERT(Buttons > 0);
+
+    /* now allocate an array for those buttons */
+    Buffer = (PUSAGE_AND_PAGE)ExAllocatePool(NonPagedPool, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
+    if (!Buffer)
+    {
+        /* no memory */
+        ExFreePool(PreparsedData);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* init usage lists */
+    RtlZeroMemory(Buffer, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
+    DeviceExtension->CurrentUsageList = Buffer;
+    Buffer += Buttons;
+    DeviceExtension->PreviousUsageList = Buffer;
+    Buffer += Buttons;
+    DeviceExtension->MakeUsageList = Buffer;
+    Buffer += Buttons;
+    DeviceExtension->BreakUsageList = Buffer;
+
+    //
+    // FIMXE: implement device hacks
+    //
+    // UsageMappings
+    // KeyboardTypeOverride
+    // KeyboardSubTypeOverride
+    // KeyboardNumberTotalKeysOverride
+    // KeyboardNumberFunctionKeysOverride
+    // KeyboardNumberIndicatorsOverride
+
+    /* store number of buttons */
+    DeviceExtension->UsageListLength = (USHORT)Buttons;
+
+    /* store preparsed data */
+    DeviceExtension->PreparsedData = PreparsedData;
+
+    /* completed successfully */
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+KbdHid_StartDeviceCompletion(
+    IN PDEVICE_OBJECT  DeviceObject,
+    IN PIRP  Irp,
+    IN PVOID  Context)
+{
+    KeSetEvent((PKEVENT)Context, 0, FALSE);
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+NTAPI
+KbdHid_Flush(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* skip current stack location */
+    IoSkipCurrentIrpStackLocation(Irp);
+
+    /* get next stack location */
+    IoStack = IoGetNextIrpStackLocation(Irp);
+
+    /* change request to hid flush queue request */
+    IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
+    IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE;
+
+    /* call device */
+    return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+}
+
+NTSTATUS
+NTAPI
+KbdHid_Pnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    KEVENT Event;
+    NTSTATUS Status;
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    DPRINT1("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
+
+    if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE)
+    {
+        /* indicate success */
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+
+        /* skip irp stack location */
+        IoSkipCurrentIrpStackLocation(Irp);
+
+        /* dispatch to lower device */
+        return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+    }
+    else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
+    {
+        /* FIXME synchronization */
+
+        /* cancel irp */
+        IoCancelIrp(DeviceExtension->Irp);
+
+        /* indicate success */
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+
+        /* skip irp stack location */
+        IoSkipCurrentIrpStackLocation(Irp);
+
+        /* dispatch to lower device */
+        Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+
+        IoFreeIrp(DeviceExtension->Irp);
+        IoDetachDevice(DeviceExtension->NextDeviceObject);
+        IoDeleteDevice(DeviceObject);
+        return Status;
+    }
+    else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
+    {
+        /* init event */
+        KeInitializeEvent(&Event, NotificationEvent, FALSE);
+
+        /* copy stack location */
+        IoCopyCurrentIrpStackLocationToNext (Irp);
+
+        /* set completion routine */
+        IoSetCompletionRoutine(Irp, KbdHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE);
+        Irp->IoStatus.Status = 0;
+
+        /* pass request */
+        Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+        if (Status == STATUS_PENDING)
+        {
+            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            Status = Irp->IoStatus.Status;
+        }
+
+        if (!NT_SUCCESS(Status))
+        {
+            /* failed */
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
+        }
+
+        /* lets start the device */
+        Status = KbdHid_StartDevice(DeviceObject);
+        DPRINT1("KbdHid_StartDevice %x\n", Status);
+
+        /* complete request */
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        /* done */
+        return Status;
+    }
+    else
+    {
+        /* skip irp stack location */
+        IoSkipCurrentIrpStackLocation(Irp);
+
+        /* dispatch to lower device */
+        return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+    }
+}
+
+NTSTATUS
+NTAPI
+KbdHid_AddDevice(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+    NTSTATUS Status;
+    PDEVICE_OBJECT DeviceObject, NextDeviceObject;
+    PKBDHID_DEVICE_EXTENSION DeviceExtension;
+    POWER_STATE State;
+
+    /* create device object */
+    Status = IoCreateDevice(DriverObject, sizeof(KBDHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &DeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to create device object */
+        return Status;
+    }
+
+    /* now attach it */
+    NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
+    if (!NextDeviceObject)
+    {
+        /* failed to attach */
+        IoDeleteDevice(DeviceObject);
+        return STATUS_DEVICE_NOT_CONNECTED;
+    }
+
+    /* get device extension */
+    DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    /* zero extension */
+    RtlZeroMemory(DeviceExtension, sizeof(KBDHID_DEVICE_EXTENSION));
+
+    /* init device extension */
+    DeviceExtension->NextDeviceObject = NextDeviceObject;
+    KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
+    DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
+
+    /* FIXME handle allocation error */
+    ASSERT(DeviceExtension->Irp);
+
+    /* set power state to D0 */
+    State.DeviceState =  PowerDeviceD0;
+    PoSetPowerState(DeviceObject, DevicePowerState, State);
+
+    /* init device object */
+    DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
+    DeviceObject->Flags  &= ~DO_DEVICE_INITIALIZING;
+
+    /* completed successfully */
+    return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+KbdHid_Unload(
+    IN PDRIVER_OBJECT DriverObject)
+{
+    UNIMPLEMENTED
+}
+
+
+NTSTATUS
+NTAPI
+DriverEntry(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PUNICODE_STRING RegPath)
+{
+    /* initialize driver object */
+    DriverObject->DriverUnload = KbdHid_Unload;
+    DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdHid_Create;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdHid_Close;
+    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = KbdHid_Flush;
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdHid_DeviceControl;
+    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = KbdHid_InternalDeviceControl;
+    DriverObject->MajorFunction[IRP_MJ_POWER] = KbdHid_Power;
+    DriverObject->MajorFunction[IRP_MJ_PNP] = KbdHid_Pnp;
+    DriverObject->DriverUnload = KbdHid_Unload;
+    DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
+
+    /* done */
+    return STATUS_SUCCESS;
+}
diff --git a/drivers/hid/kbdhid/kbdhid.h b/drivers/hid/kbdhid/kbdhid.h
new file mode 100644 (file)
index 0000000..8add178
--- /dev/null
@@ -0,0 +1,106 @@
+#pragma once
+
+#define _HIDPI_NO_FUNCTION_MACROS_
+#include <ntddk.h>
+#include <hidclass.h>
+#include <hidpddi.h>
+#include <hidpi.h>
+#include <debug.h>
+#include <ntddmou.h>
+#include <kbdmou.h>
+#include <debug.h>
+
+
+typedef struct
+{
+    //
+    // lower device object
+    //
+    PDEVICE_OBJECT NextDeviceObject;
+
+    //
+    // irp which is used for reading input reports
+    //
+    PIRP Irp;
+
+    //
+    // event 
+    //
+    KEVENT ReadCompletionEvent;
+
+    //
+    // device object for class callback
+    //
+    PDEVICE_OBJECT ClassDeviceObject;
+
+    //
+    // class callback
+    //
+    PVOID ClassService;
+
+    //
+    // usage list length
+    //
+    USHORT UsageListLength;
+
+    //
+    // current usage list length
+    //
+    PUSAGE_AND_PAGE CurrentUsageList;
+
+    //
+    // previous usage list
+    //
+    PUSAGE_AND_PAGE PreviousUsageList;
+
+    //
+    // removed usage item list
+    //
+    PUSAGE_AND_PAGE BreakUsageList;
+
+    //
+    // new item usage list
+    //
+    PUSAGE_AND_PAGE MakeUsageList;
+
+    //
+    // preparsed data
+    //
+    PVOID PreparsedData;
+
+    //
+    // mdl for reading input report
+    //
+    PMDL ReportMDL;
+
+    //
+    // input report buffer
+    //
+    PUCHAR Report;
+
+    //
+    // input report length
+    //
+    ULONG ReportLength;
+
+    //
+    // file object the device is reading reports from
+    //
+    PFILE_OBJECT FileObject;
+
+    //
+    // report read is active
+    //
+    UCHAR ReadReportActive;
+
+    //
+    // stop reading flag
+    //
+    UCHAR StopReadReport;
+
+}KBDHID_DEVICE_EXTENSION, *PKBDHID_DEVICE_EXTENSION;
+
+
+NTSTATUS
+KbdHid_InitiateRead(
+    IN PKBDHID_DEVICE_EXTENSION DeviceExtension);
diff --git a/drivers/hid/kbdhid/kbdhid.rc b/drivers/hid/kbdhid/kbdhid.rc
new file mode 100644 (file)
index 0000000..317d71e
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "Keyboard HID Class Driver\0"
+#define REACTOS_STR_INTERNAL_NAME      "kbdhid\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "kbdhid.sys\0"
+#include <reactos/version.rc>
index 3da21c3..ae82d18 100644 (file)
@@ -1,5 +1,5 @@
 #define REACTOS_VERSION_DLL
-#define REACTOS_STR_FILE_DESCRIPTION   "USB HID Parser\0"
-#define REACTOS_STR_INTERNAL_NAME      "hidparse\0"
-#define REACTOS_STR_ORIGINAL_FILENAME  "hidparse.sys\0"
+#define REACTOS_STR_FILE_DESCRIPTION   "Mouse HID Class Driver\0"
+#define REACTOS_STR_INTERNAL_NAME      "mouhid\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "mouhid.sys\0"
 #include <reactos/version.rc>