mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
[USB-BRINGUP]
- Add keyboard hid driver template ripped off from mouhid driver - Implement keyboard driver initialization svn path=/branches/usb-bringup/; revision=54850
This commit is contained in:
parent
f53c2c4f14
commit
065fd7dbd5
6 changed files with 802 additions and 3 deletions
|
@ -1,4 +1,5 @@
|
|||
add_subdirectory(hidclass)
|
||||
add_subdirectory(hidparse)
|
||||
add_subdirectory(hidusb)
|
||||
add_subdirectory(kbdhid)
|
||||
add_subdirectory(mouhid)
|
||||
|
|
13
drivers/hid/kbdhid/CMakeLists.txt
Normal file
13
drivers/hid/kbdhid/CMakeLists.txt
Normal file
|
@ -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)
|
||||
|
674
drivers/hid/kbdhid/kbdhid.c
Normal file
674
drivers/hid/kbdhid/kbdhid.c
Normal file
|
@ -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;
|
||||
}
|
106
drivers/hid/kbdhid/kbdhid.h
Normal file
106
drivers/hid/kbdhid/kbdhid.h
Normal file
|
@ -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);
|
5
drivers/hid/kbdhid/kbdhid.rc
Normal file
5
drivers/hid/kbdhid/kbdhid.rc
Normal file
|
@ -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>
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue