mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 05:32:55 +00:00
[USB-BRINGUP-TRUNK]
- Merge 54115-54859 svn path=/branches/usb-bringup-trunk/; revision=55020
This commit is contained in:
parent
6e24a0c6a8
b03bdfff2a
c9d5364c98
8632f8d0f0
c671800d55
a64411cfbf
d8200951b5
3c59337294
065fd7dbd5
3477d17d4b
d1e00dac5c
ee21e811d0
commit
753f07c723
51 changed files with 11501 additions and 391 deletions
|
@ -4,6 +4,7 @@ add_subdirectory(battery)
|
||||||
add_subdirectory(bus)
|
add_subdirectory(bus)
|
||||||
add_subdirectory(directx)
|
add_subdirectory(directx)
|
||||||
add_subdirectory(filesystems)
|
add_subdirectory(filesystems)
|
||||||
|
add_subdirectory(hid)
|
||||||
add_subdirectory(input)
|
add_subdirectory(input)
|
||||||
add_subdirectory(ksfilter)
|
add_subdirectory(ksfilter)
|
||||||
add_subdirectory(network)
|
add_subdirectory(network)
|
||||||
|
|
5
drivers/hid/CMakeLists.txt
Normal file
5
drivers/hid/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
add_subdirectory(hidclass)
|
||||||
|
add_subdirectory(hidparse)
|
||||||
|
add_subdirectory(hidusb)
|
||||||
|
add_subdirectory(kbdhid)
|
||||||
|
add_subdirectory(mouhid)
|
21
drivers/hid/hidclass/CMakeLists.txt
Normal file
21
drivers/hid/hidclass/CMakeLists.txt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
spec2def(hidclass.sys hidclass.spec)
|
||||||
|
|
||||||
|
list(APPEND SOURCE
|
||||||
|
fdo.c
|
||||||
|
hidclass.c
|
||||||
|
hidclass.rc
|
||||||
|
pdo.c
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/hidclass.def)
|
||||||
|
|
||||||
|
add_library(hidclass SHARED ${SOURCE})
|
||||||
|
|
||||||
|
set_entrypoint(hidclass 0)
|
||||||
|
set_image_base(hidclass 0x00010000)
|
||||||
|
set_subsystem(hidclass native)
|
||||||
|
set_target_properties(hidclass PROPERTIES SUFFIX ".sys")
|
||||||
|
|
||||||
|
|
||||||
|
add_importlibs(hidclass ntoskrnl hidparse hal)
|
||||||
|
add_cab_target(hidclass 2)
|
||||||
|
add_importlib_target(hidclass.spec)
|
587
drivers/hid/hidclass/fdo.c
Normal file
587
drivers/hid/hidclass/fdo.c
Normal file
|
@ -0,0 +1,587 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/hid/hidclass/fdo.c
|
||||||
|
* PURPOSE: HID Class Driver
|
||||||
|
* PROGRAMMERS:
|
||||||
|
* Michael Martin (michael.martin@reactos.org)
|
||||||
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||||
|
*/
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidClassFDO_QueryCapabilitiesCompletionRoutine(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set event
|
||||||
|
//
|
||||||
|
KeSetEvent((PRKEVENT)Context, 0, FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// completion is done in the HidClassFDO_QueryCapabilities routine
|
||||||
|
//
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_QueryCapabilities(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN OUT PDEVICE_CAPABILITIES Capabilities)
|
||||||
|
{
|
||||||
|
PIRP Irp;
|
||||||
|
KEVENT Event;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init event
|
||||||
|
//
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// now allocte the irp
|
||||||
|
//
|
||||||
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
if (!Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get next stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init stack location
|
||||||
|
//
|
||||||
|
IoStack->MajorFunction = IRP_MJ_PNP;
|
||||||
|
IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
|
||||||
|
IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
|
||||||
|
|
||||||
|
//
|
||||||
|
// set completion routine
|
||||||
|
//
|
||||||
|
IoSetCompletionRoutine(Irp, HidClassFDO_QueryCapabilitiesCompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init capabilities
|
||||||
|
//
|
||||||
|
RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||||
|
Capabilities->Size = sizeof(DEVICE_CAPABILITIES);
|
||||||
|
Capabilities->Version = 1; // FIXME hardcoded constant
|
||||||
|
Capabilities->Address = MAXULONG;
|
||||||
|
Capabilities->UINumber = MAXULONG;
|
||||||
|
|
||||||
|
//
|
||||||
|
// pnp irps have default completion code
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
//
|
||||||
|
// call lower device
|
||||||
|
//
|
||||||
|
Status = IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// wait for completion
|
||||||
|
//
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get status
|
||||||
|
//
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
IoFreeIrp(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidClassFDO_DispatchRequestSynchronousCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// signal event
|
||||||
|
//
|
||||||
|
KeSetEvent((PRKEVENT)Context, 0, FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_DispatchRequestSynchronous(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
KEVENT Event;
|
||||||
|
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
|
||||||
|
//
|
||||||
|
// init event
|
||||||
|
//
|
||||||
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// set completion routine
|
||||||
|
//
|
||||||
|
IoSetCompletionRoutine(Irp, HidClassFDO_DispatchRequestSynchronousCompletion, &Event, TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
ASSERT(Irp->CurrentLocation > 0);
|
||||||
|
//
|
||||||
|
// create stack location
|
||||||
|
//
|
||||||
|
IoSetNextIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get next stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// store device object
|
||||||
|
//
|
||||||
|
IoStack->DeviceObject = DeviceObject;
|
||||||
|
|
||||||
|
//
|
||||||
|
// call driver
|
||||||
|
//
|
||||||
|
DPRINT1("IoStack MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction);
|
||||||
|
Status = CommonDeviceExtension->DriverExtension->MajorFunction[IoStack->MajorFunction](DeviceObject, Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// wait for the request to finish
|
||||||
|
//
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// update status
|
||||||
|
//
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_GetDescriptors(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||||
|
|
||||||
|
//
|
||||||
|
// lets allocate irp
|
||||||
|
//
|
||||||
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
if (!Irp)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init stack location
|
||||||
|
//
|
||||||
|
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||||||
|
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_DEVICE_DESCRIPTOR;
|
||||||
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(HID_DESCRIPTOR);
|
||||||
|
IoStack->Parameters.DeviceIoControl.InputBufferLength = 0;
|
||||||
|
IoStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
|
||||||
|
Irp->UserBuffer = &FDODeviceExtension->HidDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// send request
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to get device descriptor
|
||||||
|
//
|
||||||
|
DPRINT1("[HIDCLASS] IOCTL_HID_GET_DEVICE_DESCRIPTOR failed with %x\n", Status);
|
||||||
|
IoFreeIrp(Irp);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// lets get device attributes
|
||||||
|
//
|
||||||
|
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_DEVICE_ATTRIBUTES;
|
||||||
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(HID_DEVICE_ATTRIBUTES);
|
||||||
|
Irp->UserBuffer = &FDODeviceExtension->Common.Attributes;
|
||||||
|
|
||||||
|
//
|
||||||
|
// send request
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to get device descriptor
|
||||||
|
//
|
||||||
|
DPRINT1("[HIDCLASS] IOCTL_HID_GET_DEVICE_ATTRIBUTES failed with %x\n", Status);
|
||||||
|
IoFreeIrp(Irp);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
ASSERT(FDODeviceExtension->HidDescriptor.bLength == sizeof(HID_DESCRIPTOR));
|
||||||
|
ASSERT(FDODeviceExtension->HidDescriptor.bNumDescriptors > 0);
|
||||||
|
ASSERT(FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength > 0);
|
||||||
|
ASSERT(FDODeviceExtension->HidDescriptor.DescriptorList[0].bReportType == HID_REPORT_DESCRIPTOR_TYPE);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// now allocate space for the report descriptor
|
||||||
|
//
|
||||||
|
FDODeviceExtension->ReportDescriptor = (PUCHAR)ExAllocatePool(NonPagedPool, FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength);
|
||||||
|
if (!FDODeviceExtension->ReportDescriptor)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// not enough memory
|
||||||
|
//
|
||||||
|
IoFreeIrp(Irp);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// init stack location
|
||||||
|
//
|
||||||
|
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_REPORT_DESCRIPTOR;
|
||||||
|
IoStack->Parameters.DeviceIoControl.OutputBufferLength = FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength;
|
||||||
|
Irp->UserBuffer = FDODeviceExtension->ReportDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// send request
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to get device descriptor
|
||||||
|
//
|
||||||
|
DPRINT1("[HIDCLASS] IOCTL_HID_GET_REPORT_DESCRIPTOR failed with %x\n", Status);
|
||||||
|
IoFreeIrp(Irp);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// completed successfully
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_StartDevice(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||||
|
|
||||||
|
//
|
||||||
|
// query capabilities
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_QueryCapabilities(DeviceObject, &FDODeviceExtension->Capabilities);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// lets start the lower device too
|
||||||
|
//
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// lets get the descriptors
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_GetDescriptors(DeviceObject);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// now get the the collection description
|
||||||
|
//
|
||||||
|
Status = HidP_GetCollectionDescription(FDODeviceExtension->ReportDescriptor, FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength, NonPagedPool, &FDODeviceExtension->Common.DeviceDescription);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_RemoveDevice(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_CopyDeviceRelations(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
OUT PDEVICE_RELATIONS *OutRelations)
|
||||||
|
{
|
||||||
|
PDEVICE_RELATIONS DeviceRelations;
|
||||||
|
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate result
|
||||||
|
//
|
||||||
|
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS) + (FDODeviceExtension->DeviceRelations->Count-1) * sizeof(PDEVICE_OBJECT));
|
||||||
|
if (!DeviceRelations)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
*OutRelations = NULL;
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy device objects
|
||||||
|
//
|
||||||
|
for(Index = 0; Index < FDODeviceExtension->DeviceRelations->Count; Index++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// reference pdo
|
||||||
|
//
|
||||||
|
ObReferenceObject(FDODeviceExtension->DeviceRelations->Objects[Index]);
|
||||||
|
|
||||||
|
//
|
||||||
|
// store object
|
||||||
|
//
|
||||||
|
DeviceRelations->Objects[Index] = FDODeviceExtension->DeviceRelations->Objects[Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// set object count
|
||||||
|
//
|
||||||
|
DeviceRelations->Count = FDODeviceExtension->DeviceRelations->Count;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
*OutRelations = DeviceRelations;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_DeviceRelations(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PDEVICE_RELATIONS DeviceRelations;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check relations type
|
||||||
|
//
|
||||||
|
if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// only bus relations are handled
|
||||||
|
//
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FDODeviceExtension->DeviceRelations == NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// time to create the pdos
|
||||||
|
//
|
||||||
|
Status = HidClassPDO_CreatePDO(DeviceObject, &FDODeviceExtension->DeviceRelations);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed
|
||||||
|
//
|
||||||
|
DPRINT1("[HIDCLASS] HidClassPDO_CreatePDO failed with %x\n", Status);
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(FDODeviceExtension->DeviceRelations->Count > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// now copy device relations
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_CopyDeviceRelations(DeviceObject, &DeviceRelations);
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_PnP(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
switch(IoStack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_START_DEVICE:
|
||||||
|
{
|
||||||
|
return HidClassFDO_StartDevice(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
|
{
|
||||||
|
return HidClassFDO_RemoveDevice(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_STOP_DEVICE:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set status to succes
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// forward to lower device
|
||||||
|
//
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||||
|
}
|
||||||
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// set status to succes
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// forward to lower device
|
||||||
|
//
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||||
|
{
|
||||||
|
return HidClassFDO_DeviceRelations(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// dispatch to lower device
|
||||||
|
//
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1012
drivers/hid/hidclass/hidclass.c
Normal file
1012
drivers/hid/hidclass/hidclass.c
Normal file
File diff suppressed because it is too large
Load diff
5
drivers/hid/hidclass/hidclass.rc
Normal file
5
drivers/hid/hidclass/hidclass.rc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#define REACTOS_VERSION_DLL
|
||||||
|
#define REACTOS_STR_FILE_DESCRIPTION "USB HID Bus Driver\0"
|
||||||
|
#define REACTOS_STR_INTERNAL_NAME "hidclass\0"
|
||||||
|
#define REACTOS_STR_ORIGINAL_FILENAME "hidclass.sys\0"
|
||||||
|
#include <reactos/version.rc>
|
4
drivers/hid/hidclass/hidclass.spec
Normal file
4
drivers/hid/hidclass/hidclass.spec
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
@ stdcall -private DllInitialize(long)
|
||||||
|
@ stdcall -private DllUnload()
|
||||||
|
@ stdcall HidRegisterMinidriver(ptr)
|
||||||
|
|
711
drivers/hid/hidclass/pdo.c
Normal file
711
drivers/hid/hidclass/pdo.c
Normal file
|
@ -0,0 +1,711 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/hid/hidclass/fdo.c
|
||||||
|
* PURPOSE: HID Class Driver
|
||||||
|
* PROGRAMMERS:
|
||||||
|
* Michael Martin (michael.martin@reactos.org)
|
||||||
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||||
|
*/
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
PHIDP_COLLECTION_DESC
|
||||||
|
HidClassPDO_GetCollectionDescription(
|
||||||
|
PHIDP_DEVICE_DESC DeviceDescription,
|
||||||
|
ULONG CollectionNumber)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
|
for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++)
|
||||||
|
{
|
||||||
|
if (DeviceDescription->CollectionDesc[Index].CollectionNumber == CollectionNumber)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// found collection
|
||||||
|
//
|
||||||
|
return &DeviceDescription->CollectionDesc[Index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// failed to find collection
|
||||||
|
//
|
||||||
|
DPRINT1("[HIDCLASS] GetCollectionDescription CollectionNumber %x not found\n", CollectionNumber);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHIDP_REPORT_IDS
|
||||||
|
HidClassPDO_GetReportDescription(
|
||||||
|
PHIDP_DEVICE_DESC DeviceDescription,
|
||||||
|
ULONG CollectionNumber)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
|
for(Index = 0; Index < DeviceDescription->ReportIDsLength; Index++)
|
||||||
|
{
|
||||||
|
if (DeviceDescription->ReportIDs[Index].CollectionNumber == CollectionNumber)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// found collection
|
||||||
|
//
|
||||||
|
return &DeviceDescription->ReportIDs[Index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// failed to find collection
|
||||||
|
//
|
||||||
|
DPRINT1("[HIDCLASS] GetReportDescription CollectionNumber %x not found\n", CollectionNumber);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassPDO_HandleQueryDeviceId(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
LPWSTR Buffer;
|
||||||
|
LPWSTR NewBuffer, Ptr;
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy current stack location
|
||||||
|
//
|
||||||
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// call mini-driver
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get buffer
|
||||||
|
//
|
||||||
|
Buffer = (LPWSTR)Irp->IoStatus.Information;
|
||||||
|
Length = wcslen(Buffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate new buffer
|
||||||
|
//
|
||||||
|
NewBuffer = (LPWSTR)ExAllocatePool(NonPagedPool, (Length + 1) * sizeof(WCHAR));
|
||||||
|
if (!NewBuffer)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to allocate buffer
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// replace bus
|
||||||
|
//
|
||||||
|
wcscpy(NewBuffer, L"HID\\");
|
||||||
|
|
||||||
|
//
|
||||||
|
// get offset to first '\\'
|
||||||
|
//
|
||||||
|
Ptr = wcschr(Buffer, L'\\');
|
||||||
|
if (Ptr)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// append result
|
||||||
|
//
|
||||||
|
wcscat(NewBuffer, Ptr + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// free old buffer
|
||||||
|
//
|
||||||
|
ExFreePool(Buffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
DPRINT1("NewBuffer %S\n", NewBuffer);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)NewBuffer;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassPDO_HandleQueryHardwareId(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
WCHAR Buffer[100];
|
||||||
|
ULONG Offset = 0;
|
||||||
|
LPWSTR Ptr;
|
||||||
|
PHIDP_COLLECTION_DESC CollectionDescription;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy current stack location
|
||||||
|
//
|
||||||
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// call mini-driver
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PDODeviceExtension->Common.DeviceDescription.CollectionDescLength > 1)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// multi-tlc device
|
||||||
|
//
|
||||||
|
Offset = swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Rev_%04x&Col%02x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->Common.Attributes.VersionNumber, PDODeviceExtension->CollectionNumber) + 1;
|
||||||
|
Offset += swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Col%02x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->CollectionNumber) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// single tlc device
|
||||||
|
//
|
||||||
|
Offset = swprintf(&Buffer[Offset], L"HID\\Vix_%04x&Pid_%04x&Rev_%04x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->Common.Attributes.VersionNumber) + 1;
|
||||||
|
Offset += swprintf(&Buffer[Offset], L"HID\\Vix_%04x&Pid_%04x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get collection description
|
||||||
|
//
|
||||||
|
CollectionDescription = HidClassPDO_GetCollectionDescription(&PDODeviceExtension->Common.DeviceDescription, PDODeviceExtension->CollectionNumber);
|
||||||
|
ASSERT(CollectionDescription);
|
||||||
|
|
||||||
|
if (CollectionDescription->UsagePage == HID_USAGE_PAGE_GENERIC)
|
||||||
|
{
|
||||||
|
switch(CollectionDescription->Usage)
|
||||||
|
{
|
||||||
|
case HID_USAGE_GENERIC_POINTER:
|
||||||
|
case HID_USAGE_GENERIC_MOUSE:
|
||||||
|
//
|
||||||
|
// Pointer / Mouse
|
||||||
|
//
|
||||||
|
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_MOUSE") + 1;
|
||||||
|
break;
|
||||||
|
case HID_USAGE_GENERIC_GAMEPAD:
|
||||||
|
case HID_USAGE_GENERIC_JOYSTICK:
|
||||||
|
//
|
||||||
|
// Joystick / Gamepad
|
||||||
|
//
|
||||||
|
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_GAME") + 1;
|
||||||
|
break;
|
||||||
|
case HID_USAGE_GENERIC_KEYBOARD:
|
||||||
|
case HID_USAGE_GENERIC_KEYPAD:
|
||||||
|
//
|
||||||
|
// Keyboard / Keypad
|
||||||
|
//
|
||||||
|
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_KEYBOARD") + 1;
|
||||||
|
break;
|
||||||
|
case HID_USAGE_GENERIC_SYSTEM_CTL:
|
||||||
|
//
|
||||||
|
// System Control
|
||||||
|
//
|
||||||
|
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_CONTROL") + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CollectionDescription->UsagePage == HID_USAGE_PAGE_CONSUMER && CollectionDescription->Usage == HID_USAGE_CONSUMERCTRL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Consumer Audio Control
|
||||||
|
//
|
||||||
|
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_CONSUMER") + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME: add 'HID_DEVICE_UP:0001_U:0002'
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// add HID
|
||||||
|
//
|
||||||
|
Offset +=swprintf(&Buffer[Offset], L"HID_DEVICE") + 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// free old buffer
|
||||||
|
//
|
||||||
|
ExFreePool((PVOID)Irp->IoStatus.Information);
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate buffer
|
||||||
|
//
|
||||||
|
Ptr = (LPWSTR)ExAllocatePool(NonPagedPool, (Offset +1)* sizeof(WCHAR));
|
||||||
|
if (!Ptr)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy buffer
|
||||||
|
//
|
||||||
|
RtlCopyMemory(Ptr, Buffer, Offset * sizeof(WCHAR));
|
||||||
|
Ptr[Offset] = UNICODE_NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)Ptr;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassPDO_HandleQueryInstanceId(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy current stack location
|
||||||
|
//
|
||||||
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// call mini-driver
|
||||||
|
//
|
||||||
|
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
DPRINT1("HidClassPDO_HandleQueryInstanceId Buffer %S\n", Irp->IoStatus.Information);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassPDO_HandleQueryCompatibleId(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
LPWSTR Buffer;
|
||||||
|
|
||||||
|
Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// zero buffer
|
||||||
|
//
|
||||||
|
Buffer[0] = 0;
|
||||||
|
Buffer[1] = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassPDO_PnP(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PPNP_BUS_INFORMATION BusInformation;
|
||||||
|
PDEVICE_RELATIONS DeviceRelation;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get current irp stack location
|
||||||
|
//
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// handle request
|
||||||
|
//
|
||||||
|
switch(IoStack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_QUERY_ID:
|
||||||
|
{
|
||||||
|
if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// handle query device id
|
||||||
|
//
|
||||||
|
Status = HidClassPDO_HandleQueryDeviceId(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// handle instance id
|
||||||
|
//
|
||||||
|
Status = HidClassPDO_HandleQueryHardwareId(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// handle instance id
|
||||||
|
//
|
||||||
|
Status = HidClassPDO_HandleQueryInstanceId(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// handle instance id
|
||||||
|
//
|
||||||
|
Status = HidClassPDO_HandleQueryCompatibleId(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("[HIDCLASS]: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType);
|
||||||
|
Status = STATUS_NOT_SUPPORTED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_CAPABILITIES:
|
||||||
|
{
|
||||||
|
if (IoStack->Parameters.DeviceCapabilities.Capabilities == NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// invalid request
|
||||||
|
//
|
||||||
|
Status = STATUS_DEVICE_CONFIGURATION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy capabilities
|
||||||
|
//
|
||||||
|
RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &PDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_BUS_INFORMATION:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(NonPagedPool, sizeof(PNP_BUS_INFORMATION));
|
||||||
|
|
||||||
|
//
|
||||||
|
// fill in result
|
||||||
|
//
|
||||||
|
RtlCopyMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_HID, sizeof(GUID));
|
||||||
|
BusInformation->LegacyBusType = PNPBus;
|
||||||
|
BusInformation->BusNumber = 0; //FIXME
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_PNP_DEVICE_STATE:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME set flags when driver fails / disabled
|
||||||
|
//
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// only target relations are supported
|
||||||
|
//
|
||||||
|
if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// not supported
|
||||||
|
//
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocate device relations
|
||||||
|
//
|
||||||
|
DeviceRelation = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS));
|
||||||
|
if (!DeviceRelation)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// init device relation
|
||||||
|
//
|
||||||
|
DeviceRelation->Count = 1;
|
||||||
|
DeviceRelation->Objects[0] = DeviceObject;
|
||||||
|
ObReferenceObject(DeviceRelation->Objects[0]);
|
||||||
|
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_START_DEVICE:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME: support polled devices
|
||||||
|
//
|
||||||
|
ASSERT(PDODeviceExtension->Common.DriverExtension->DevicesArePolled == FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// now register the device interface
|
||||||
|
//
|
||||||
|
Status = IoRegisterDeviceInterface(PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject, &GUID_DEVINTERFACE_HID, NULL, &PDODeviceExtension->DeviceInterface);
|
||||||
|
DPRINT1("[HIDCLASS] IoRegisterDeviceInterfaceState Status %x\n", Status);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// enable device interface
|
||||||
|
//
|
||||||
|
Status = IoSetDeviceInterfaceState(&PDODeviceExtension->DeviceInterface, TRUE);
|
||||||
|
DPRINT1("[HIDCLASS] IoSetDeviceInterFaceState %x\n", Status);
|
||||||
|
}
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
//
|
||||||
|
// break
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
|
{
|
||||||
|
DPRINT1("[HIDCLASS] PDO IRP_MN_REMOVE_DEVICE not implemented\n");
|
||||||
|
ASSERT(FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// do nothing
|
||||||
|
//
|
||||||
|
Status = STATUS_SUCCESS; //Irp->IoStatus.Status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRP_MN_QUERY_INTERFACE:
|
||||||
|
{
|
||||||
|
DPRINT1("[HIDCLASS] PDO IRP_MN_QUERY_INTERFACE not implemented\n");
|
||||||
|
ASSERT(FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// do nothing
|
||||||
|
//
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// do nothing
|
||||||
|
//
|
||||||
|
Status = Irp->IoStatus.Status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
if (Status != STATUS_PENDING)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// store result
|
||||||
|
//
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// complete request
|
||||||
|
//
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done processing
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassPDO_CreatePDO(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
OUT PDEVICE_RELATIONS *OutDeviceRelations)
|
||||||
|
{
|
||||||
|
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PDEVICE_OBJECT PDODeviceObject;
|
||||||
|
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||||
|
ULONG Index;
|
||||||
|
PDEVICE_RELATIONS DeviceRelations;
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||||
|
|
||||||
|
//
|
||||||
|
// first allocate device relations
|
||||||
|
//
|
||||||
|
Length = sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * FDODeviceExtension->Common.DeviceDescription.CollectionDescLength;
|
||||||
|
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, Length);
|
||||||
|
if (!DeviceRelations)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// no memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// zero device relations
|
||||||
|
//
|
||||||
|
RtlZeroMemory(DeviceRelations, Length);
|
||||||
|
|
||||||
|
//
|
||||||
|
// lets create a PDO for top level collection
|
||||||
|
//
|
||||||
|
Index = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// lets create the device object
|
||||||
|
//
|
||||||
|
Status = IoCreateDevice(FDODeviceExtension->Common.DriverExtension->DriverObject, sizeof(HIDCLASS_PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &PDODeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed to create device
|
||||||
|
//
|
||||||
|
DPRINT1("[HIDCLASS] Failed to create PDO %x\n", Status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// patch stack size
|
||||||
|
//
|
||||||
|
PDODeviceObject->StackSize = DeviceObject->StackSize + 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// init device extension
|
||||||
|
//
|
||||||
|
PDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension = FDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension;
|
||||||
|
PDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject;
|
||||||
|
PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject;
|
||||||
|
PDODeviceExtension->Common.IsFDO = FALSE;
|
||||||
|
PDODeviceExtension->FDODeviceObject = DeviceObject;
|
||||||
|
PDODeviceExtension->Common.DriverExtension = FDODeviceExtension->Common.DriverExtension;
|
||||||
|
PDODeviceExtension->CollectionNumber = FDODeviceExtension->Common.DeviceDescription.CollectionDesc[Index].CollectionNumber;
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy device data
|
||||||
|
//
|
||||||
|
RtlCopyMemory(&PDODeviceExtension->Common.Attributes, &FDODeviceExtension->Common.Attributes, sizeof(HID_DEVICE_ATTRIBUTES));
|
||||||
|
RtlCopyMemory(&PDODeviceExtension->Common.DeviceDescription, &FDODeviceExtension->Common.DeviceDescription, sizeof(HIDP_DEVICE_DESC));
|
||||||
|
RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||||
|
|
||||||
|
//
|
||||||
|
// set device flags
|
||||||
|
//
|
||||||
|
PDODeviceObject->Flags |= DO_MAP_IO_BUFFER;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device is initialized
|
||||||
|
//
|
||||||
|
PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
//
|
||||||
|
// store device object in device relations
|
||||||
|
//
|
||||||
|
DeviceRelations->Objects[Index] = PDODeviceObject;
|
||||||
|
DeviceRelations->Count++;
|
||||||
|
|
||||||
|
//
|
||||||
|
// move to next
|
||||||
|
//
|
||||||
|
Index++;
|
||||||
|
|
||||||
|
}while(Index < FDODeviceExtension->Common.DeviceDescription.CollectionDescLength);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if creating succeeded
|
||||||
|
//
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// failed
|
||||||
|
//
|
||||||
|
for(Index = 0; Index < DeviceRelations->Count; Index++)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// delete device
|
||||||
|
//
|
||||||
|
IoDeleteDevice(DeviceRelations->Objects[Index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// free device relations
|
||||||
|
//
|
||||||
|
ExFreePool(DeviceRelations);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// store device relations
|
||||||
|
//
|
||||||
|
*OutDeviceRelations = DeviceRelations;
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
197
drivers/hid/hidclass/precomp.h
Normal file
197
drivers/hid/hidclass/precomp.h
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||||
|
#define NDEBUG
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <initguid.h>
|
||||||
|
#include <hidport.h>
|
||||||
|
#include <hidpddi.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <wdmguid.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PDRIVER_OBJECT DriverObject;
|
||||||
|
ULONG DeviceExtensionSize;
|
||||||
|
BOOLEAN DevicesArePolled;
|
||||||
|
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
|
||||||
|
PDRIVER_ADD_DEVICE AddDevice;
|
||||||
|
PDRIVER_UNLOAD DriverUnload;
|
||||||
|
KSPIN_LOCK Lock;
|
||||||
|
|
||||||
|
}HIDCLASS_DRIVER_EXTENSION, *PHIDCLASS_DRIVER_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// hid device extension
|
||||||
|
//
|
||||||
|
HID_DEVICE_EXTENSION HidDeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// if it is a pdo
|
||||||
|
//
|
||||||
|
BOOLEAN IsFDO;
|
||||||
|
|
||||||
|
//
|
||||||
|
// driver extension
|
||||||
|
//
|
||||||
|
PHIDCLASS_DRIVER_EXTENSION DriverExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device description
|
||||||
|
//
|
||||||
|
HIDP_DEVICE_DESC DeviceDescription;
|
||||||
|
|
||||||
|
//
|
||||||
|
// hid attributes
|
||||||
|
//
|
||||||
|
HID_DEVICE_ATTRIBUTES Attributes;
|
||||||
|
|
||||||
|
}HIDCLASS_COMMON_DEVICE_EXTENSION, *PHIDCLASS_COMMON_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// parts shared by fdo and pdo
|
||||||
|
//
|
||||||
|
HIDCLASS_COMMON_DEVICE_EXTENSION Common;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device capabilities
|
||||||
|
//
|
||||||
|
DEVICE_CAPABILITIES Capabilities;
|
||||||
|
|
||||||
|
//
|
||||||
|
// hid descriptor
|
||||||
|
//
|
||||||
|
HID_DESCRIPTOR HidDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// report descriptor
|
||||||
|
//
|
||||||
|
PUCHAR ReportDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device relations
|
||||||
|
//
|
||||||
|
PDEVICE_RELATIONS DeviceRelations;
|
||||||
|
|
||||||
|
}HIDCLASS_FDO_EXTENSION, *PHIDCLASS_FDO_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// parts shared by fdo and pdo
|
||||||
|
//
|
||||||
|
HIDCLASS_COMMON_DEVICE_EXTENSION Common;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device capabilities
|
||||||
|
//
|
||||||
|
DEVICE_CAPABILITIES Capabilities;
|
||||||
|
|
||||||
|
//
|
||||||
|
// collection index
|
||||||
|
//
|
||||||
|
ULONG CollectionNumber;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device interface
|
||||||
|
//
|
||||||
|
UNICODE_STRING DeviceInterface;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FDO device object
|
||||||
|
//
|
||||||
|
PDEVICE_OBJECT FDODeviceObject;
|
||||||
|
|
||||||
|
}HIDCLASS_PDO_DEVICE_EXTENSION, *PHIDCLASS_PDO_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct __HIDCLASS_FILEOP_CONTEXT__
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// device extension
|
||||||
|
//
|
||||||
|
PHIDCLASS_PDO_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
//
|
||||||
|
// spin lock
|
||||||
|
//
|
||||||
|
KSPIN_LOCK Lock;
|
||||||
|
|
||||||
|
//
|
||||||
|
// read irp pending list
|
||||||
|
//
|
||||||
|
LIST_ENTRY ReadPendingIrpListHead;
|
||||||
|
|
||||||
|
//
|
||||||
|
// completed irp list
|
||||||
|
//
|
||||||
|
LIST_ENTRY IrpCompletedListHead;
|
||||||
|
|
||||||
|
}HIDCLASS_FILEOP_CONTEXT, *PHIDCLASS_FILEOP_CONTEXT;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// original request
|
||||||
|
//
|
||||||
|
PIRP OriginalIrp;
|
||||||
|
|
||||||
|
//
|
||||||
|
// file op
|
||||||
|
//
|
||||||
|
PHIDCLASS_FILEOP_CONTEXT FileOp;
|
||||||
|
|
||||||
|
//
|
||||||
|
// buffer for reading report
|
||||||
|
//
|
||||||
|
PVOID InputReportBuffer;
|
||||||
|
|
||||||
|
//
|
||||||
|
// buffer length
|
||||||
|
//
|
||||||
|
ULONG InputReportBufferLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// work item
|
||||||
|
//
|
||||||
|
PIO_WORKITEM CompletionWorkItem;
|
||||||
|
|
||||||
|
}HIDCLASS_IRP_CONTEXT, *PHIDCLASS_IRP_CONTEXT;
|
||||||
|
|
||||||
|
/* fdo.c */
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_PnP(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassFDO_DispatchRequestSynchronous(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp);
|
||||||
|
|
||||||
|
/* pdo.c */
|
||||||
|
NTSTATUS
|
||||||
|
HidClassPDO_CreatePDO(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
OUT PDEVICE_RELATIONS *OutDeviceRelations);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
HidClassPDO_PnP(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp);
|
||||||
|
|
||||||
|
PHIDP_COLLECTION_DESC
|
||||||
|
HidClassPDO_GetCollectionDescription(
|
||||||
|
PHIDP_DEVICE_DESC DeviceDescription,
|
||||||
|
ULONG CollectionNumber);
|
||||||
|
|
||||||
|
PHIDP_REPORT_IDS
|
||||||
|
HidClassPDO_GetReportDescription(
|
||||||
|
PHIDP_DEVICE_DESC DeviceDescription,
|
||||||
|
ULONG CollectionNumber);
|
||||||
|
|
||||||
|
/* eof */
|
|
@ -2,7 +2,10 @@
|
||||||
spec2def(hidparse.sys hidparse.spec)
|
spec2def(hidparse.sys hidparse.spec)
|
||||||
add_definitions(-DDEBUG_MODE)
|
add_definitions(-DDEBUG_MODE)
|
||||||
|
|
||||||
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
include_directories(
|
||||||
|
${REACTOS_SOURCE_DIR}/ntoskrnl/include
|
||||||
|
${REACTOS_SOURCE_DIR}/lib/drivers/hidparser)
|
||||||
|
|
||||||
|
|
||||||
add_library(hidparse SHARED hidparse.c hidparse.rc ${CMAKE_CURRENT_BINARY_DIR}/hidparse.def)
|
add_library(hidparse SHARED hidparse.c hidparse.rc ${CMAKE_CURRENT_BINARY_DIR}/hidparse.def)
|
||||||
|
|
||||||
|
@ -12,3 +15,5 @@ add_cab_target(hidparse 2)
|
||||||
|
|
||||||
add_cab_target(hidparse 2)
|
add_cab_target(hidparse 2)
|
||||||
add_importlib_target(hidparse.spec)
|
add_importlib_target(hidparse.spec)
|
||||||
|
|
||||||
|
target_link_libraries(hidparse hidparser)
|
|
@ -10,30 +10,346 @@
|
||||||
|
|
||||||
#include "hidparse.h"
|
#include "hidparse.h"
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
NTAPI
|
||||||
|
AllocFunction(
|
||||||
|
IN ULONG ItemSize)
|
||||||
|
{
|
||||||
|
PVOID Item = ExAllocatePool(NonPagedPool, ItemSize);
|
||||||
|
if (Item)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// zero item
|
||||||
|
//
|
||||||
|
RtlZeroMemory(Item, ItemSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Item;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
NTAPI
|
||||||
|
FreeFunction(
|
||||||
|
IN PVOID Item)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// free item
|
||||||
|
//
|
||||||
|
ExFreePool(Item);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
ZeroFunction(
|
||||||
|
IN PVOID Item,
|
||||||
|
IN ULONG ItemSize)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// zero item
|
||||||
|
//
|
||||||
|
RtlZeroMemory(Item, ItemSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CopyFunction(
|
||||||
|
IN PVOID Target,
|
||||||
|
IN PVOID Source,
|
||||||
|
IN ULONG Length)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// copy item
|
||||||
|
//
|
||||||
|
RtlCopyMemory(Target, Source, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
DebugFunction(
|
||||||
|
IN LPCSTR FormatStr, ...)
|
||||||
|
{
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
unsigned int i;
|
||||||
|
char printbuffer[1024];
|
||||||
|
|
||||||
|
va_start(args, FormatStr);
|
||||||
|
i = vsprintf(printbuffer, FormatStr, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
DbgPrint(printbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
HidP_FreeCollectionDescription (
|
HidP_FreeCollectionDescription (
|
||||||
IN PHIDP_DEVICE_DESC DeviceDescription)
|
IN PHIDP_DEVICE_DESC DeviceDescription)
|
||||||
{
|
{
|
||||||
DPRINT1("HidP_FreeCollectionDescription DeviceDescription %p\n", DeviceDescription);
|
HID_PARSER Parser;
|
||||||
|
|
||||||
|
//
|
||||||
|
// init parser
|
||||||
|
//
|
||||||
|
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, NULL, &Parser);
|
||||||
|
|
||||||
//
|
//
|
||||||
// free collection
|
// free collection
|
||||||
//
|
//
|
||||||
ExFreePool(DeviceDescription->CollectionDesc);
|
HidParser_FreeCollectionDescription(&Parser, DeviceDescription);
|
||||||
|
|
||||||
//
|
|
||||||
// free report ids
|
|
||||||
//
|
|
||||||
ExFreePool(DeviceDescription->ReportIDs);
|
|
||||||
|
|
||||||
//
|
|
||||||
// free description itself
|
|
||||||
//
|
|
||||||
ExFreePool(DeviceDescription);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_GetCaps(
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
OUT PHIDP_CAPS Capabilities)
|
||||||
|
{
|
||||||
|
HID_PARSER Parser;
|
||||||
|
|
||||||
|
//
|
||||||
|
// init parser
|
||||||
|
//
|
||||||
|
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get caps
|
||||||
|
//
|
||||||
|
return HidParser_GetCaps(&Parser, Capabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_GetCollectionDescription(
|
||||||
|
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
|
||||||
|
IN ULONG DescLength,
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
OUT PHIDP_DEVICE_DESC DeviceDescription)
|
||||||
|
{
|
||||||
|
PHID_PARSER Parser;
|
||||||
|
HIDPARSER_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// first allocate the parser
|
||||||
|
//
|
||||||
|
Status = HidParser_AllocateParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||||
|
if (Status != HIDPARSER_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// not enough memory
|
||||||
|
//
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// get description;
|
||||||
|
//
|
||||||
|
Status = HidParser_GetCollectionDescription(Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIXME parser memory leak
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
HidP_MaxUsageListLength(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage OPTIONAL,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData)
|
||||||
|
{
|
||||||
|
HID_PARSER Parser;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init parser
|
||||||
|
//
|
||||||
|
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// get usage length
|
||||||
|
//
|
||||||
|
return HidParser_MaxUsageListLength(&Parser, ReportType, UsagePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_GetSpecificValueCaps(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
IN USAGE Usage,
|
||||||
|
OUT PHIDP_VALUE_CAPS ValueCaps,
|
||||||
|
IN OUT PULONG ValueCapsLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData)
|
||||||
|
{
|
||||||
|
HID_PARSER Parser;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init parser
|
||||||
|
//
|
||||||
|
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get value caps
|
||||||
|
//
|
||||||
|
return HidParser_GetSpecificValueCaps(&Parser, ReportType, UsagePage, LinkCollection, Usage, ValueCaps, ValueCapsLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_GetUsages(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection OPTIONAL,
|
||||||
|
OUT USAGE *UsageList,
|
||||||
|
IN OUT ULONG *UsageLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength)
|
||||||
|
{
|
||||||
|
HID_PARSER Parser;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init parser
|
||||||
|
//
|
||||||
|
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get usages
|
||||||
|
//
|
||||||
|
return HidParser_GetUsages(&Parser, ReportType, UsagePage, LinkCollection, UsageList, UsageLength, Report, ReportLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef HidP_GetButtonCaps
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_UsageListDifference(
|
||||||
|
IN PUSAGE PreviousUsageList,
|
||||||
|
IN PUSAGE CurrentUsageList,
|
||||||
|
OUT PUSAGE BreakUsageList,
|
||||||
|
OUT PUSAGE MakeUsageList,
|
||||||
|
IN ULONG UsageListLength)
|
||||||
|
{
|
||||||
|
return HidParser_UsageListDifference(PreviousUsageList, CurrentUsageList, BreakUsageList, MakeUsageList, UsageListLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_GetUsagesEx(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
OUT PUSAGE_AND_PAGE ButtonList,
|
||||||
|
IN OUT ULONG *UsageLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength)
|
||||||
|
{
|
||||||
|
return HidP_GetUsages(ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, PreparsedData, Report, ReportLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_UsageAndPageListDifference(
|
||||||
|
IN PUSAGE_AND_PAGE PreviousUsageList,
|
||||||
|
IN PUSAGE_AND_PAGE CurrentUsageList,
|
||||||
|
OUT PUSAGE_AND_PAGE BreakUsageList,
|
||||||
|
OUT PUSAGE_AND_PAGE MakeUsageList,
|
||||||
|
IN ULONG UsageListLength)
|
||||||
|
{
|
||||||
|
return HidParser_UsageAndPageListDifference(PreviousUsageList, CurrentUsageList, BreakUsageList, MakeUsageList, UsageListLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_GetScaledUsageValue(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection OPTIONAL,
|
||||||
|
IN USAGE Usage,
|
||||||
|
OUT PLONG UsageValue,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength)
|
||||||
|
{
|
||||||
|
HID_PARSER Parser;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init parser
|
||||||
|
//
|
||||||
|
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, PreparsedData, &Parser);
|
||||||
|
|
||||||
|
//
|
||||||
|
// get scaled usage value
|
||||||
|
//
|
||||||
|
return HidParser_GetScaledUsageValue(&Parser, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidP_TranslateUsageAndPagesToI8042ScanCodes(
|
||||||
|
IN PUSAGE_AND_PAGE ChangedUsageList,
|
||||||
|
IN ULONG UsageListLength,
|
||||||
|
IN HIDP_KEYBOARD_DIRECTION KeyAction,
|
||||||
|
IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
|
||||||
|
IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
|
||||||
|
IN PVOID InsertCodesContext)
|
||||||
|
{
|
||||||
|
HID_PARSER Parser;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||||
|
|
||||||
|
//
|
||||||
|
// init parser
|
||||||
|
//
|
||||||
|
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, NULL, &Parser);
|
||||||
|
|
||||||
|
//
|
||||||
|
// translate usage pages
|
||||||
|
//
|
||||||
|
return HidParser_TranslateUsageAndPagesToI8042ScanCodes(Parser, UsageListLength, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HIDAPI
|
HIDAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -43,7 +359,7 @@ HidP_GetButtonCaps(
|
||||||
PUSHORT ButtonCapsLength,
|
PUSHORT ButtonCapsLength,
|
||||||
PHIDP_PREPARSED_DATA PreparsedData)
|
PHIDP_PREPARSED_DATA PreparsedData)
|
||||||
{
|
{
|
||||||
return HidP_GetSpecificButtonCaps(ReportType, 0, 0, 0, ButtonCaps, (PULONG)ButtonCapsLength, PreparsedData);
|
return HidP_GetSpecificButtonCaps(ReportType, HID_USAGE_PAGE_UNDEFINED, 0, 0, ButtonCaps, (PULONG)ButtonCapsLength, PreparsedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
HIDAPI
|
HIDAPI
|
||||||
|
@ -63,31 +379,6 @@ HidP_GetSpecificButtonCaps(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidP_GetCaps(
|
|
||||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
|
||||||
OUT PHIDP_CAPS Capabilities)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
HidP_GetCollectionDescription(
|
|
||||||
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
|
|
||||||
IN ULONG DescLength,
|
|
||||||
IN POOL_TYPE PoolType,
|
|
||||||
OUT PHIDP_DEVICE_DESC DeviceDescription)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HIDAPI
|
HIDAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -109,7 +400,7 @@ NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
HidP_GetExtendedAttributes(
|
HidP_GetExtendedAttributes(
|
||||||
IN HIDP_REPORT_TYPE ReportType,
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
IN USHORT DataIndex,
|
IN USAGE UsagePage,
|
||||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
|
OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
|
||||||
IN OUT PULONG LengthAttributes)
|
IN OUT PULONG LengthAttributes)
|
||||||
|
@ -132,24 +423,6 @@ HidP_GetLinkCollectionNodes(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidP_GetScaledUsageValue(
|
|
||||||
IN HIDP_REPORT_TYPE ReportType,
|
|
||||||
IN USAGE UsagePage,
|
|
||||||
IN USHORT LinkCollection OPTIONAL,
|
|
||||||
IN USAGE Usage,
|
|
||||||
OUT PLONG UsageValue,
|
|
||||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
|
||||||
IN PCHAR Report,
|
|
||||||
IN ULONG ReportLength)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HIDAPI
|
HIDAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -168,72 +441,8 @@ HidP_GetUsageValue(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
HidP_UsageListDifference(
|
|
||||||
IN PUSAGE PreviousUsageList,
|
|
||||||
IN PUSAGE CurrentUsageList,
|
|
||||||
OUT PUSAGE BreakUsageList,
|
|
||||||
OUT PUSAGE MakeUsageList,
|
|
||||||
IN ULONG UsageListLength)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidP_GetSpecificValueCaps(
|
|
||||||
IN HIDP_REPORT_TYPE ReportType,
|
|
||||||
IN USAGE UsagePage,
|
|
||||||
IN USHORT LinkCollection,
|
|
||||||
IN USAGE Usage,
|
|
||||||
OUT PHIDP_VALUE_CAPS ValueCaps,
|
|
||||||
IN OUT PULONG ValueCapsLength,
|
|
||||||
IN PHIDP_PREPARSED_DATA PreparsedData)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
HidP_MaxUsageListLength(
|
|
||||||
IN HIDP_REPORT_TYPE ReportType,
|
|
||||||
IN USAGE UsagePage OPTIONAL,
|
|
||||||
IN PHIDP_PREPARSED_DATA PreparsedData)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidP_GetUsages(
|
|
||||||
IN HIDP_REPORT_TYPE ReportType,
|
|
||||||
IN USAGE UsagePage,
|
|
||||||
IN USHORT LinkCollection OPTIONAL,
|
|
||||||
OUT USAGE *UsageList,
|
|
||||||
IN OUT ULONG *UsageLength,
|
|
||||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
|
||||||
IN PCHAR Report,
|
|
||||||
IN ULONG ReportLength)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
HidP_SysPowerEvent (
|
HidP_SysPowerEvent (
|
||||||
IN PCHAR HidPacket,
|
IN PCHAR HidPacket,
|
||||||
IN USHORT HidPacketLength,
|
IN USHORT HidPacketLength,
|
||||||
|
@ -246,6 +455,7 @@ HidP_SysPowerEvent (
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
HidP_SysPowerCaps (
|
HidP_SysPowerCaps (
|
||||||
IN PHIDP_PREPARSED_DATA Ppd,
|
IN PHIDP_PREPARSED_DATA Ppd,
|
||||||
OUT PULONG OutputBuffer)
|
OUT PULONG OutputBuffer)
|
||||||
|
@ -274,38 +484,6 @@ HidP_GetUsageValueArray(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidP_GetUsagesEx(
|
|
||||||
IN HIDP_REPORT_TYPE ReportType,
|
|
||||||
IN USHORT LinkCollection,
|
|
||||||
OUT PUSAGE_AND_PAGE ButtonList,
|
|
||||||
IN OUT ULONG *UsageLength,
|
|
||||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
|
||||||
IN PCHAR Report,
|
|
||||||
IN ULONG ReportLength)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidP_UsageAndPageListDifference(
|
|
||||||
IN PUSAGE_AND_PAGE PreviousUsageList,
|
|
||||||
IN PUSAGE_AND_PAGE CurrentUsageList,
|
|
||||||
OUT PUSAGE_AND_PAGE BreakUsageList,
|
|
||||||
OUT PUSAGE_AND_PAGE MakeUsageList,
|
|
||||||
IN ULONG UsageListLength)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HIDAPI
|
HIDAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -341,22 +519,6 @@ HidP_TranslateUsagesToI8042ScanCodes(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
HIDAPI
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidP_TranslateUsageAndPagesToI8042ScanCodes(
|
|
||||||
IN PUSAGE_AND_PAGE ChangedUsageList,
|
|
||||||
IN ULONG UsageListLength,
|
|
||||||
IN HIDP_KEYBOARD_DIRECTION KeyAction,
|
|
||||||
IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
|
|
||||||
IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
|
|
||||||
IN PVOID InsertCodesContext)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
HIDAPI
|
HIDAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -473,6 +635,8 @@ HidP_InitializeReportForID(
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef HidP_GetValueCaps
|
||||||
|
|
||||||
HIDAPI
|
HIDAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
|
@ -5,4 +5,6 @@
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
#include <hidpddi.h>
|
#include <hidpddi.h>
|
||||||
#include <hidpi.h>
|
#include <hidpi.h>
|
||||||
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include "hidparser.h"
|
|
@ -10,7 +10,7 @@
|
||||||
@ stdcall HidP_GetSpecificValueCaps(long long long long ptr ptr ptr)
|
@ stdcall HidP_GetSpecificValueCaps(long long long long ptr ptr ptr)
|
||||||
@ stdcall HidP_GetUsageValue(long long long long ptr ptr ptr long)
|
@ stdcall HidP_GetUsageValue(long long long long ptr ptr ptr long)
|
||||||
@ stdcall HidP_GetUsageValueArray(long long long long ptr long ptr ptr long)
|
@ stdcall HidP_GetUsageValueArray(long long long long ptr long ptr ptr long)
|
||||||
@ stdcall HidP_GetUsages(long long ptr ptr ptr ptr long)
|
@ stdcall HidP_GetUsages(long long long ptr ptr ptr ptr long)
|
||||||
@ stdcall HidP_GetUsagesEx(long long ptr ptr ptr ptr long)
|
@ stdcall HidP_GetUsagesEx(long long ptr ptr ptr ptr long)
|
||||||
@ stdcall HidP_GetValueCaps(long ptr ptr ptr)
|
@ stdcall HidP_GetValueCaps(long ptr ptr ptr)
|
||||||
@ stdcall HidP_InitializeReportForID(long long ptr ptr long)
|
@ stdcall HidP_InitializeReportForID(long long ptr ptr long)
|
|
@ -1,11 +1,11 @@
|
||||||
|
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
hidusb.c
|
hidusb.c
|
||||||
usbhub.rc)
|
hidusb.rc)
|
||||||
|
|
||||||
add_library(hidusb SHARED ${SOURCE})
|
add_library(hidusb SHARED ${SOURCE})
|
||||||
|
|
||||||
set_module_type(hidusb kernelmodedriver)
|
set_module_type(hidusb kernelmodedriver)
|
||||||
add_importlibs(hidusb hidclass ntoskrnl usbd)
|
add_importlibs(hidusb hidclass ntoskrnl usbd hal)
|
||||||
|
|
||||||
add_cab_target(usbhub 2)
|
add_cab_target(hidusb 2)
|
1643
drivers/hid/hidusb/hidusb.c
Normal file
1643
drivers/hid/hidusb/hidusb.c
Normal file
File diff suppressed because it is too large
Load diff
82
drivers/hid/hidusb/hidusb.h
Normal file
82
drivers/hid/hidusb/hidusb.h
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define _HIDPI_
|
||||||
|
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||||
|
#define NDEBUG
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <hidport.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <hubbusif.h>
|
||||||
|
#include <usbbusif.h>
|
||||||
|
#include <usbioctl.h>
|
||||||
|
#include <usb.h>
|
||||||
|
#include <usbdlib.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// event for completion
|
||||||
|
//
|
||||||
|
KEVENT Event;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device descriptor
|
||||||
|
//
|
||||||
|
PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// configuration descriptor
|
||||||
|
//
|
||||||
|
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// interface information
|
||||||
|
//
|
||||||
|
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
|
||||||
|
|
||||||
|
//
|
||||||
|
// configuration handle
|
||||||
|
//
|
||||||
|
USBD_CONFIGURATION_HANDLE ConfigurationHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// hid descriptor
|
||||||
|
//
|
||||||
|
PHID_DESCRIPTOR HidDescriptor;
|
||||||
|
}HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// request irp
|
||||||
|
//
|
||||||
|
PIRP Irp;
|
||||||
|
|
||||||
|
//
|
||||||
|
// work item
|
||||||
|
//
|
||||||
|
PIO_WORKITEM WorkItem;
|
||||||
|
|
||||||
|
//
|
||||||
|
// device object
|
||||||
|
//
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
|
||||||
|
}HID_USB_RESET_CONTEXT, *PHID_USB_RESET_CONTEXT;
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Hid_GetDescriptor(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN USHORT UrbFunction,
|
||||||
|
IN USHORT UrbLength,
|
||||||
|
IN OUT PVOID *UrbBuffer,
|
||||||
|
IN OUT PULONG UrbBufferLength,
|
||||||
|
IN UCHAR DescriptorType,
|
||||||
|
IN UCHAR Index,
|
||||||
|
IN USHORT LanguageIndex);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Hid_DispatchUrb(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PURB Urb);
|
5
drivers/hid/hidusb/hidusb.rc
Normal file
5
drivers/hid/hidusb/hidusb.rc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#define REACTOS_VERSION_DLL
|
||||||
|
#define REACTOS_STR_FILE_DESCRIPTION "USB HID Interface Driver\0"
|
||||||
|
#define REACTOS_STR_INTERNAL_NAME "hidusb\0"
|
||||||
|
#define REACTOS_STR_ORIGINAL_FILENAME "hidusb.sys\0"
|
||||||
|
#include <reactos/version.rc>
|
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)
|
||||||
|
|
855
drivers/hid/kbdhid/kbdhid.c
Normal file
855
drivers/hid/kbdhid/kbdhid.c
Normal file
|
@ -0,0 +1,855 @@
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
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 + 1, &InputDataConsumed);
|
||||||
|
|
||||||
|
/* lower irql to previous level */
|
||||||
|
KeLowerIrql(OldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
KbdHid_InsertScanCodes(
|
||||||
|
IN PVOID Context,
|
||||||
|
IN PCHAR NewScanCodes,
|
||||||
|
IN ULONG Length)
|
||||||
|
{
|
||||||
|
KEYBOARD_INPUT_DATA InputData;
|
||||||
|
ULONG Index;
|
||||||
|
|
||||||
|
for(Index = 0; Index < Length; Index++)
|
||||||
|
{
|
||||||
|
DPRINT1("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index, NewScanCodes[Index] & 0xFF);
|
||||||
|
//
|
||||||
|
// TODO: set up input data
|
||||||
|
//
|
||||||
|
//KbdHid_DispatchInputData((PKBDHID_DEVICE_EXTENSION)Context, &InputData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
KbdHid_ReadCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG ButtonLength;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get current usages */
|
||||||
|
ButtonLength = DeviceExtension->UsageListLength;
|
||||||
|
Status = HidP_GetUsagesEx(HidP_Input, HIDP_LINK_COLLECTION_UNSPECIFIED, DeviceExtension->CurrentUsageList, &ButtonLength, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||||
|
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/* FIXME check if needs mapping */
|
||||||
|
|
||||||
|
/* get usage difference */
|
||||||
|
Status = HidP_UsageAndPageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength);
|
||||||
|
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/* replace previous usage list with current list */
|
||||||
|
RtlMoveMemory(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, sizeof(USAGE_AND_PAGE) * DeviceExtension->UsageListLength);
|
||||||
|
|
||||||
|
/* translate break usage list */
|
||||||
|
HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->BreakUsageList, DeviceExtension->UsageListLength, HidP_Keyboard_Break, &DeviceExtension->ModifierState, KbdHid_InsertScanCodes, DeviceExtension);
|
||||||
|
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/* translate new usage list */
|
||||||
|
HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength, HidP_Keyboard_Make, &DeviceExtension->ModifierState, KbdHid_InsertScanCodes, DeviceExtension);
|
||||||
|
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
PCONNECT_DATA Data;
|
||||||
|
PKEYBOARD_ATTRIBUTES Attributes;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
/* verify output buffer length */
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
|
||||||
|
{
|
||||||
|
/* invalid request */
|
||||||
|
DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
|
||||||
|
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get output buffer */
|
||||||
|
Attributes = (PKEYBOARD_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
/* copy attributes */
|
||||||
|
RtlCopyMemory(Attributes, &DeviceExtension->Attributes, sizeof(KEYBOARD_ATTRIBUTES));
|
||||||
|
|
||||||
|
/* complete request */
|
||||||
|
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_CONNECT)
|
||||||
|
{
|
||||||
|
/* verify input buffer length */
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
|
||||||
|
{
|
||||||
|
/* invalid request */
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is it already connected */
|
||||||
|
if (DeviceExtension->ClassService)
|
||||||
|
{
|
||||||
|
/* already connected */
|
||||||
|
Irp->IoStatus.Status = STATUS_SHARING_VIOLATION;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SHARING_VIOLATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get connect data */
|
||||||
|
Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||||
|
|
||||||
|
/* store connect details */
|
||||||
|
DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
|
||||||
|
DeviceExtension->ClassService = Data->ClassService;
|
||||||
|
|
||||||
|
/* completed successfully */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISCONNECT)
|
||||||
|
{
|
||||||
|
/* not implemented */
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_ENABLE)
|
||||||
|
{
|
||||||
|
/* not supported */
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISABLE)
|
||||||
|
{
|
||||||
|
/* not supported */
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATORS)
|
||||||
|
{
|
||||||
|
/* not implemented */
|
||||||
|
DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATORS not implemented\n");
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_TYPEMATIC)
|
||||||
|
{
|
||||||
|
/* not implemented */
|
||||||
|
DPRINT1("IOCTL_KEYBOARD_QUERY_TYPEMATIC not implemented\n");
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_INDICATORS)
|
||||||
|
{
|
||||||
|
/* not implemented */
|
||||||
|
DPRINT1("IOCTL_KEYBOARD_SET_INDICATORS not implemented\n");
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_TYPEMATIC)
|
||||||
|
{
|
||||||
|
/* not implemented */
|
||||||
|
DPRINT1("IOCTL_KEYBOARD_SET_TYPEMATIC not implemented\n");
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION)
|
||||||
|
{
|
||||||
|
/* not implemented */
|
||||||
|
DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n");
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unknown control code */
|
||||||
|
DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* init keyboard attributes */
|
||||||
|
DeviceExtension->Attributes.KeyboardIdentifier.Type = KEYBOARD_TYPE_UNKNOWN;
|
||||||
|
DeviceExtension->Attributes.KeyboardIdentifier.Subtype = MICROSOFT_KBD_101_TYPE;
|
||||||
|
DeviceExtension->Attributes.NumberOfFunctionKeys = MICROSOFT_KBD_FUNC;
|
||||||
|
DeviceExtension->Attributes.NumberOfIndicators = 3; // caps, num lock, scroll lock
|
||||||
|
DeviceExtension->Attributes.NumberOfKeysTotal = 101;
|
||||||
|
DeviceExtension->Attributes.InputDataQueueLength = 1;
|
||||||
|
DeviceExtension->Attributes.KeyRepeatMinimum.Rate = KEYBOARD_TYPEMATIC_RATE_MINIMUM;
|
||||||
|
DeviceExtension->Attributes.KeyRepeatMinimum.Delay = KEYBOARD_TYPEMATIC_DELAY_MINIMUM;
|
||||||
|
DeviceExtension->Attributes.KeyRepeatMaximum.Rate = KEYBOARD_TYPEMATIC_RATE_DEFAULT;
|
||||||
|
DeviceExtension->Attributes.KeyRepeatMaximum.Delay = KEYBOARD_TYPEMATIC_DELAY_MAXIMUM;
|
||||||
|
|
||||||
|
/* allocate irp */
|
||||||
|
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;
|
||||||
|
}
|
133
drivers/hid/kbdhid/kbdhid.h
Normal file
133
drivers/hid/kbdhid/kbdhid.h
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <hidclass.h>
|
||||||
|
#include <hidpddi.h>
|
||||||
|
#include <hidpi.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <kbdmou.h>
|
||||||
|
//#include <kbd.h>
|
||||||
|
#include <ntddkbd.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
|
||||||
|
//
|
||||||
|
PHIDP_PREPARSED_DATA PreparsedData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// mdl for reading input report
|
||||||
|
//
|
||||||
|
PMDL ReportMDL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// input report buffer
|
||||||
|
//
|
||||||
|
PCHAR 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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// keyboard attributes
|
||||||
|
//
|
||||||
|
KEYBOARD_ATTRIBUTES Attributes;
|
||||||
|
|
||||||
|
//
|
||||||
|
// keyboard modifier state
|
||||||
|
//
|
||||||
|
HIDP_KEYBOARD_MODIFIER_STATE ModifierState;
|
||||||
|
|
||||||
|
}KBDHID_DEVICE_EXTENSION, *PKBDHID_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
/* defaults from kbfiltr.h */
|
||||||
|
#define KEYBOARD_TYPEMATIC_RATE_MINIMUM 2
|
||||||
|
#define KEYBOARD_TYPEMATIC_RATE_MAXIMUM 30
|
||||||
|
#define KEYBOARD_TYPEMATIC_RATE_DEFAULT 30
|
||||||
|
#define KEYBOARD_TYPEMATIC_DELAY_MINIMUM 250
|
||||||
|
#define KEYBOARD_TYPEMATIC_DELAY_MAXIMUM 1000
|
||||||
|
#define KEYBOARD_TYPEMATIC_DELAY_DEFAULT 250
|
||||||
|
|
||||||
|
/* FIXME: write kbd.h */
|
||||||
|
#define MICROSOFT_KBD_FUNC 12
|
||||||
|
#define KEYBOARD_TYPE_UNKNOWN (0x51)
|
||||||
|
#define MICROSOFT_KBD_101_TYPE 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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>
|
13
drivers/hid/mouhid/CMakeLists.txt
Normal file
13
drivers/hid/mouhid/CMakeLists.txt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
add_definitions(-DDEBUG_MODE)
|
||||||
|
|
||||||
|
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
||||||
|
|
||||||
|
add_library(mouhid SHARED mouhid.c mouhid.rc)
|
||||||
|
|
||||||
|
set_module_type(mouhid kernelmodedriver)
|
||||||
|
add_importlibs(mouhid ntoskrnl hal hidparse)
|
||||||
|
add_cab_target(mouhid 2)
|
||||||
|
|
||||||
|
add_cab_target(mouhid 2)
|
||||||
|
|
962
drivers/hid/mouhid/mouhid.c
Normal file
962
drivers/hid/mouhid/mouhid.c
Normal file
|
@ -0,0 +1,962 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS HID Stack
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: drivers/hid/mouhid/mouhid.c
|
||||||
|
* PURPOSE: Mouse HID Driver
|
||||||
|
* PROGRAMMERS:
|
||||||
|
* Michael Martin (michael.martin@reactos.org)
|
||||||
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mouhid.h"
|
||||||
|
|
||||||
|
static USHORT MouHid_ButtonUpFlags[] =
|
||||||
|
{
|
||||||
|
0xFF, /* unused */
|
||||||
|
MOUSE_LEFT_BUTTON_DOWN,
|
||||||
|
MOUSE_RIGHT_BUTTON_DOWN,
|
||||||
|
MOUSE_MIDDLE_BUTTON_DOWN,
|
||||||
|
MOUSE_BUTTON_4_DOWN,
|
||||||
|
MOUSE_BUTTON_5_DOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
static USHORT MouHid_ButtonDownFlags[] =
|
||||||
|
{
|
||||||
|
0xFF, /* unused */
|
||||||
|
MOUSE_LEFT_BUTTON_UP,
|
||||||
|
MOUSE_RIGHT_BUTTON_UP,
|
||||||
|
MOUSE_MIDDLE_BUTTON_UP,
|
||||||
|
MOUSE_BUTTON_4_UP,
|
||||||
|
MOUSE_BUTTON_5_UP
|
||||||
|
};
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MouHid_GetButtonMove(
|
||||||
|
IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
OUT PLONG LastX,
|
||||||
|
OUT PLONG LastY)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* init result */
|
||||||
|
*LastX = 0;
|
||||||
|
*LastY = 0;
|
||||||
|
|
||||||
|
/* get scaled usage value x */
|
||||||
|
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PLONG)LastX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||||
|
/* FIXME handle error */
|
||||||
|
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/* get scaled usage value y */
|
||||||
|
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PLONG)LastY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||||
|
/* FIXME handle error */
|
||||||
|
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MouHid_GetButtonFlags(
|
||||||
|
IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
OUT PUSHORT ButtonFlags)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
USAGE Usage;
|
||||||
|
ULONG Index;
|
||||||
|
PUSAGE TempList;
|
||||||
|
ULONG CurrentUsageListLength;
|
||||||
|
|
||||||
|
/* init flags */
|
||||||
|
*ButtonFlags = 0;
|
||||||
|
|
||||||
|
/* get usages */
|
||||||
|
CurrentUsageListLength = DeviceExtension->UsageListLength;
|
||||||
|
Status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, HIDP_LINK_COLLECTION_UNSPECIFIED, DeviceExtension->CurrentUsageList, &CurrentUsageListLength, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||||
|
if (Status != HIDP_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract usage list difference */
|
||||||
|
Status = HidP_UsageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength);
|
||||||
|
if (Status != HIDP_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceExtension->UsageListLength)
|
||||||
|
{
|
||||||
|
Index = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* get usage */
|
||||||
|
Usage = DeviceExtension->BreakUsageList[Index];
|
||||||
|
if (!Usage)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (Usage <= 5)
|
||||||
|
{
|
||||||
|
/* max 5 buttons supported */
|
||||||
|
*ButtonFlags |= MouHid_ButtonDownFlags[Usage];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move to next index*/
|
||||||
|
Index++;
|
||||||
|
}while(Index < DeviceExtension->UsageListLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeviceExtension->UsageListLength)
|
||||||
|
{
|
||||||
|
Index = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* get usage */
|
||||||
|
Usage = DeviceExtension->MakeUsageList[Index];
|
||||||
|
if (!Usage)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (Usage <= 5)
|
||||||
|
{
|
||||||
|
/* max 5 buttons supported */
|
||||||
|
*ButtonFlags |= MouHid_ButtonUpFlags[Usage];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move to next index*/
|
||||||
|
Index++;
|
||||||
|
}while(Index < DeviceExtension->UsageListLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now switch the previous list with current list */
|
||||||
|
TempList = DeviceExtension->CurrentUsageList;
|
||||||
|
DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
|
||||||
|
DeviceExtension->PreviousUsageList = TempList;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MouHid_DispatchInputData(
|
||||||
|
IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN PMOUSE_INPUT_DATA InputData)
|
||||||
|
{
|
||||||
|
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 + 1, &InputDataConsumed);
|
||||||
|
|
||||||
|
/* lower irql to previous level */
|
||||||
|
KeLowerIrql(OldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MouHid_ReadCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
USHORT ButtonFlags;
|
||||||
|
LONG UsageValue;
|
||||||
|
NTSTATUS Status;
|
||||||
|
LONG LastX, LastY;
|
||||||
|
MOUSE_INPUT_DATA MouseInputData;
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_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("[MOUHID] 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get mouse change flags */
|
||||||
|
MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
|
||||||
|
|
||||||
|
/* get mouse change */
|
||||||
|
MouHid_GetButtonMove(DeviceExtension, &LastX, &LastY);
|
||||||
|
|
||||||
|
/* init input data */
|
||||||
|
RtlZeroMemory(&MouseInputData, sizeof(MOUSE_INPUT_DATA));
|
||||||
|
|
||||||
|
/* init input data */
|
||||||
|
MouseInputData.ButtonFlags = ButtonFlags;
|
||||||
|
MouseInputData.LastX = LastX;
|
||||||
|
MouseInputData.LastY = LastY;
|
||||||
|
|
||||||
|
/* detect mouse wheel change */
|
||||||
|
if (DeviceExtension->MouseIdentifier == WHEELMOUSE_HID_HARDWARE)
|
||||||
|
{
|
||||||
|
/* get usage */
|
||||||
|
UsageValue = 0;
|
||||||
|
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_WHEEL, &UsageValue, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||||
|
if (Status == HIDP_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* store wheel status */
|
||||||
|
MouseInputData.ButtonFlags |= MOUSE_WHEEL;
|
||||||
|
MouseInputData.ButtonData = (USHORT)UsageValue; /* FIXME */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("[MOUHID] failed to get wheel status with %x\n", Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("[MOUHID] LastX %ld LastY %ld Flags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
|
||||||
|
|
||||||
|
/* dispatch mouse action */
|
||||||
|
MouHid_DispatchInputData(DeviceExtension, &MouseInputData);
|
||||||
|
|
||||||
|
/* re-init read */
|
||||||
|
MouHid_InitiateRead(DeviceExtension);
|
||||||
|
|
||||||
|
/* stop completion */
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MouHid_InitiateRead(
|
||||||
|
IN PMOUHID_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, MouHid_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
|
||||||
|
MouHid_CreateCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
KeSetEvent((PKEVENT)Context, 0, FALSE);
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MouHid_Create(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KEVENT Event;
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
DPRINT1("MOUHID: IRP_MJ_CREATE\n");
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_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, MouHid_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 = MouHid_InitiateRead(DeviceExtension);
|
||||||
|
DPRINT1("[MOUHID] MouHid_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
|
||||||
|
MouHid_Close(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
DPRINT("[MOUHID] 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("[MOUHID] 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
|
||||||
|
MouHid_InternalDeviceControl(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PMOUSE_ATTRIBUTES Attributes;
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
PCONNECT_DATA Data;
|
||||||
|
|
||||||
|
/* get current stack location */
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
DPRINT1("[MOUHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
/* handle requests */
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUSE_QUERY_ATTRIBUTES)
|
||||||
|
{
|
||||||
|
/* verify output buffer length */
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
|
||||||
|
{
|
||||||
|
/* invalid request */
|
||||||
|
DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
|
||||||
|
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get output buffer */
|
||||||
|
Attributes = (PMOUSE_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
/* type of mouse */
|
||||||
|
Attributes->MouseIdentifier = DeviceExtension->MouseIdentifier;
|
||||||
|
|
||||||
|
/* number of buttons */
|
||||||
|
Attributes->NumberOfButtons = DeviceExtension->UsageListLength;
|
||||||
|
|
||||||
|
/* sample rate not used for usb */
|
||||||
|
Attributes->SampleRate = 0;
|
||||||
|
|
||||||
|
/* queue length */
|
||||||
|
Attributes->InputDataQueueLength = 2;
|
||||||
|
|
||||||
|
DPRINT1("[MOUHID] MouseIdentifier %x\n", Attributes->MouseIdentifier);
|
||||||
|
DPRINT1("[MOUHID] NumberOfButtons %x\n", Attributes->NumberOfButtons);
|
||||||
|
DPRINT1("[MOUHID] SampleRate %x\n", Attributes->SampleRate);
|
||||||
|
DPRINT1("[MOUHID] InputDataQueueLength %x\n", Attributes->InputDataQueueLength);
|
||||||
|
|
||||||
|
/* complete request */
|
||||||
|
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_CONNECT)
|
||||||
|
{
|
||||||
|
/* verify input buffer length */
|
||||||
|
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
|
||||||
|
{
|
||||||
|
/* invalid request */
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is it already connected */
|
||||||
|
if (DeviceExtension->ClassService)
|
||||||
|
{
|
||||||
|
/* already connected */
|
||||||
|
Irp->IoStatus.Status = STATUS_SHARING_VIOLATION;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SHARING_VIOLATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get connect data */
|
||||||
|
Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||||
|
|
||||||
|
/* store connect details */
|
||||||
|
DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
|
||||||
|
DeviceExtension->ClassService = Data->ClassService;
|
||||||
|
|
||||||
|
/* completed successfully */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_DISCONNECT)
|
||||||
|
{
|
||||||
|
/* not supported */
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_ENABLE)
|
||||||
|
{
|
||||||
|
/* not supported */
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_DISABLE)
|
||||||
|
{
|
||||||
|
/* not supported */
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("[MOUHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||||
|
/* unknown request not supported */
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MouHid_DeviceControl(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
/* skip stack location */
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/* pass and forget */
|
||||||
|
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MouHid_Power(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MouHid_SubmitRequest(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
ULONG IoControlCode,
|
||||||
|
ULONG InputBufferSize,
|
||||||
|
PVOID InputBuffer,
|
||||||
|
ULONG OutputBufferSize,
|
||||||
|
PVOID OutputBuffer)
|
||||||
|
{
|
||||||
|
KEVENT Event;
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
PIRP Irp;
|
||||||
|
NTSTATUS Status;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_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
|
||||||
|
MouHid_StartDevice(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG Buttons;
|
||||||
|
HID_COLLECTION_INFORMATION Information;
|
||||||
|
PVOID PreparsedData;
|
||||||
|
HIDP_CAPS Capabilities;
|
||||||
|
ULONG ValueCapsLength;
|
||||||
|
HIDP_VALUE_CAPS ValueCaps;
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
PUSHORT Buffer;
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
/* query collection information */
|
||||||
|
Status = MouHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* failed to query collection information */
|
||||||
|
DPRINT1("[MOUHID] failed to obtain collection information with %x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* lets allocate space for preparsed data */
|
||||||
|
PreparsedData = ExAllocatePool(NonPagedPool, Information.DescriptorSize);
|
||||||
|
if (!PreparsedData)
|
||||||
|
{
|
||||||
|
/* no memory */
|
||||||
|
DPRINT1("[MOUHID] no memory size %u\n", Information.DescriptorSize);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now obtain the preparsed data */
|
||||||
|
Status = MouHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR, 0, NULL, Information.DescriptorSize, PreparsedData);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* failed to get preparsed data */
|
||||||
|
DPRINT1("[MOUHID] 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("[MOUHID] failed to obtain caps with %x\n", Status);
|
||||||
|
ExFreePool(PreparsedData);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT1("[MOUHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
|
||||||
|
|
||||||
|
/* verify capabilities */
|
||||||
|
if (Capabilities.Usage != HID_USAGE_GENERIC_POINTER && Capabilities.Usage != HID_USAGE_GENERIC_MOUSE || Capabilities.UsagePage != HID_USAGE_PAGE_GENERIC)
|
||||||
|
{
|
||||||
|
/* not supported */
|
||||||
|
ExFreePool(PreparsedData);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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("[MOUHID] Buttons %lu\n", Buttons);
|
||||||
|
ASSERT(Buttons > 0);
|
||||||
|
|
||||||
|
/* now allocate an array for those buttons */
|
||||||
|
Buffer = ExAllocatePool(NonPagedPool, sizeof(USAGE) * 4 * Buttons);
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
/* no memory */
|
||||||
|
ExFreePool(PreparsedData);
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init usage lists */
|
||||||
|
RtlZeroMemory(Buffer, sizeof(USAGE) * 4 * Buttons);
|
||||||
|
DeviceExtension->CurrentUsageList = Buffer;
|
||||||
|
Buffer += Buttons;
|
||||||
|
DeviceExtension->PreviousUsageList = Buffer;
|
||||||
|
Buffer += Buttons;
|
||||||
|
DeviceExtension->MakeUsageList = Buffer;
|
||||||
|
Buffer += Buttons;
|
||||||
|
DeviceExtension->BreakUsageList = Buffer;
|
||||||
|
|
||||||
|
/* store number of buttons */
|
||||||
|
DeviceExtension->UsageListLength = (USHORT)Buttons;
|
||||||
|
|
||||||
|
/* store preparsed data */
|
||||||
|
DeviceExtension->PreparsedData = PreparsedData;
|
||||||
|
|
||||||
|
ValueCapsLength = 1;
|
||||||
|
HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &ValueCaps, &ValueCapsLength, PreparsedData);
|
||||||
|
|
||||||
|
ValueCapsLength = 1;
|
||||||
|
HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &ValueCaps, &ValueCapsLength, PreparsedData);
|
||||||
|
|
||||||
|
/* now check for wheel mouse support */
|
||||||
|
ValueCapsLength = 1;
|
||||||
|
Status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_WHEEL, &ValueCaps, &ValueCapsLength, PreparsedData);
|
||||||
|
if (Status == HIDP_STATUS_SUCCESS )
|
||||||
|
{
|
||||||
|
/* mouse has wheel support */
|
||||||
|
DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
|
||||||
|
DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
|
||||||
|
DPRINT1("[MOUHID] mouse wheel support detected\n", Status);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* check if the mouse has z-axis */
|
||||||
|
ValueCapsLength = 1;
|
||||||
|
Status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Z, &ValueCaps, &ValueCapsLength, PreparsedData);
|
||||||
|
if (Status == HIDP_STATUS_SUCCESS && ValueCapsLength == 1)
|
||||||
|
{
|
||||||
|
/* wheel support */
|
||||||
|
DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
|
||||||
|
DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
|
||||||
|
DPRINT1("[MOUHID] mouse wheel support detected with z-axis\n", Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* completed successfully */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MouHid_StartDeviceCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
KeSetEvent((PKEVENT)Context, 0, FALSE);
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
MouHid_Flush(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_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
|
||||||
|
MouHid_Pnp(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
KEVENT Event;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
|
||||||
|
/* get device extension */
|
||||||
|
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
/* get current irp stack */
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
DPRINT1("[MOUHID] 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, MouHid_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 = MouHid_StartDevice(DeviceObject);
|
||||||
|
DPRINT1("MouHid_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
|
||||||
|
MouHid_AddDevice(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PDEVICE_OBJECT DeviceObject, NextDeviceObject;
|
||||||
|
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||||
|
POWER_STATE State;
|
||||||
|
|
||||||
|
/* create device object */
|
||||||
|
Status = IoCreateDevice(DriverObject, sizeof(MOUHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_MOUSE, 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 = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
/* zero extension */
|
||||||
|
RtlZeroMemory(DeviceExtension, sizeof(MOUHID_DEVICE_EXTENSION));
|
||||||
|
|
||||||
|
/* init device extension */
|
||||||
|
DeviceExtension->MouseIdentifier = MOUSE_HID_HARDWARE;
|
||||||
|
DeviceExtension->WheelUsagePage = 0;
|
||||||
|
DeviceExtension->NextDeviceObject = NextDeviceObject;
|
||||||
|
KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
|
||||||
|
DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
|
||||||
|
|
||||||
|
/* FIXME handle allocation error */
|
||||||
|
ASSERT(DeviceExtension->Irp);
|
||||||
|
|
||||||
|
/* FIXME query parameter 'FlipFlopWheel', 'WheelScalingFactor' */
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
MouHid_Unload(
|
||||||
|
IN PDRIVER_OBJECT DriverObject)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
DriverEntry(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegPath)
|
||||||
|
{
|
||||||
|
/* FIXME check for parameters 'UseOnlyMice', 'TreatAbsoluteAsRelative', 'TreatAbsolutePointerAsAbsolute' */
|
||||||
|
|
||||||
|
/* initialize driver object */
|
||||||
|
DriverObject->DriverUnload = MouHid_Unload;
|
||||||
|
DriverObject->DriverExtension->AddDevice = MouHid_AddDevice;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = MouHid_Create;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouHid_Close;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = MouHid_Flush;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MouHid_DeviceControl;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = MouHid_InternalDeviceControl;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_POWER] = MouHid_Power;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_PNP] = MouHid_Pnp;
|
||||||
|
DriverObject->DriverUnload = MouHid_Unload;
|
||||||
|
DriverObject->DriverExtension->AddDevice = MouHid_AddDevice;
|
||||||
|
|
||||||
|
/* done */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
116
drivers/hid/mouhid/mouhid.h
Normal file
116
drivers/hid/mouhid/mouhid.h
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// mouse type
|
||||||
|
//
|
||||||
|
USHORT MouseIdentifier;
|
||||||
|
|
||||||
|
//
|
||||||
|
// wheel usage page
|
||||||
|
//
|
||||||
|
USHORT WheelUsagePage;
|
||||||
|
|
||||||
|
//
|
||||||
|
// usage list length
|
||||||
|
//
|
||||||
|
USHORT UsageListLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// current usage list length
|
||||||
|
//
|
||||||
|
PUSAGE CurrentUsageList;
|
||||||
|
|
||||||
|
//
|
||||||
|
// previous usage list
|
||||||
|
//
|
||||||
|
PUSAGE PreviousUsageList;
|
||||||
|
|
||||||
|
//
|
||||||
|
// removed usage item list
|
||||||
|
//
|
||||||
|
PUSAGE BreakUsageList;
|
||||||
|
|
||||||
|
//
|
||||||
|
// new item usage list
|
||||||
|
//
|
||||||
|
PUSAGE 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;
|
||||||
|
|
||||||
|
}MOUHID_DEVICE_EXTENSION, *PMOUHID_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
MouHid_InitiateRead(
|
||||||
|
IN PMOUHID_DEVICE_EXTENSION DeviceExtension);
|
5
drivers/hid/mouhid/mouhid.rc
Normal file
5
drivers/hid/mouhid/mouhid.rc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#define REACTOS_VERSION_DLL
|
||||||
|
#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>
|
|
@ -1,4 +1,3 @@
|
||||||
add_subdirectory(hidparse)
|
|
||||||
add_subdirectory(nt4compat)
|
add_subdirectory(nt4compat)
|
||||||
add_subdirectory(usbd)
|
add_subdirectory(usbd)
|
||||||
add_subdirectory(usbehci_new)
|
add_subdirectory(usbehci_new)
|
||||||
|
|
|
@ -1,151 +0,0 @@
|
||||||
/*
|
|
||||||
* PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver
|
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
|
||||||
* FILE: drivers/usb/hidusb/hidusb.c
|
|
||||||
* PURPOSE: HID USB Interface Driver
|
|
||||||
* PROGRAMMERS:
|
|
||||||
* Michael Martin (michael.martin@reactos.org)
|
|
||||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "hidusb.h"
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidCreate(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
|
||||||
PIO_STACK_LOCATION IoStack;
|
|
||||||
|
|
||||||
//
|
|
||||||
// get current irp stack location
|
|
||||||
//
|
|
||||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
||||||
|
|
||||||
//
|
|
||||||
// sanity check for hidclass driver
|
|
||||||
//
|
|
||||||
ASSERT(IoStack->MajorFunction == IRP_MJ_CREATE || IoStack->MajorFunction == IRP_MJ_CLOSE);
|
|
||||||
|
|
||||||
//
|
|
||||||
// complete request
|
|
||||||
//
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
//
|
|
||||||
// informal debug print
|
|
||||||
//
|
|
||||||
DPRINT1("HIDUSB Request: %x\n", IoStack->MajorFunction);
|
|
||||||
|
|
||||||
//
|
|
||||||
// done
|
|
||||||
//
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidInternalDeviceControl(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidPower(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidSystemControl(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
|
||||||
PHID_DEVICE_EXTENSION DeviceExtension;
|
|
||||||
|
|
||||||
//
|
|
||||||
// get hid device extension
|
|
||||||
//
|
|
||||||
DeviceExtension = (PHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
||||||
|
|
||||||
//
|
|
||||||
// copy stack location
|
|
||||||
//
|
|
||||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
||||||
|
|
||||||
//
|
|
||||||
// submit request
|
|
||||||
//
|
|
||||||
return IoCallDriver(DeviceExtension->NextDeviceObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
HidPnp(
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT(FALSE);
|
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
DriverEntry(
|
|
||||||
IN PDRIVER_OBJECT DriverObject,
|
|
||||||
IN PUNICODE_STRING RegPath)
|
|
||||||
{
|
|
||||||
HID_MINIDRIVER_REGISTRATION Registration;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
//
|
|
||||||
// initialize driver object
|
|
||||||
//
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = HidCreate;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = HidCreate;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidInternalDeviceControl;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_POWER] = HidPower;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HidSystemControl;
|
|
||||||
DriverObject->MajorFunction[IRP_MJ_PNP] = HidPnp;
|
|
||||||
|
|
||||||
//
|
|
||||||
// prepare registration info
|
|
||||||
//
|
|
||||||
RtlZeroMemory(&Registration, sizeof(HID_MINIDRIVER_REGISTRATION));
|
|
||||||
|
|
||||||
//
|
|
||||||
// fill in registration info
|
|
||||||
//
|
|
||||||
Registration.Revision = HID_REVISION;
|
|
||||||
Registration.DriverObject = DriverObject;
|
|
||||||
Registration.RegistryPath = RegPath;
|
|
||||||
Registration.DeviceExtensionSize = sizeof(HID_USB_DEVICE_EXTENSION);
|
|
||||||
Registration.DevicesArePolled = FALSE;
|
|
||||||
|
|
||||||
//
|
|
||||||
// register driver
|
|
||||||
//
|
|
||||||
Status = HidRegisterMinidriver(&Registration);
|
|
||||||
|
|
||||||
//
|
|
||||||
// informal debug
|
|
||||||
//
|
|
||||||
DPRINT1("********* HIDUSB *********\n");
|
|
||||||
DPRINT1("HIDUSB Registration Status %x\n", Status);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define _HIDPI_
|
|
||||||
#define _HIDPI_NO_FUNCTION_MACROS_
|
|
||||||
#include <ntddk.h>
|
|
||||||
#include <hidport.h>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// event for completion
|
|
||||||
//
|
|
||||||
KEVENT Event;
|
|
||||||
|
|
||||||
//
|
|
||||||
// list for pending requests
|
|
||||||
//
|
|
||||||
LIST_ENTRY PendingRequests;
|
|
||||||
|
|
||||||
}HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
|
|
||||||
|
|
|
@ -60,13 +60,16 @@ public:
|
||||||
VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
|
VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
|
||||||
// internal ioctl routines
|
// internal ioctl routines
|
||||||
NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb);
|
||||||
|
NTSTATUS HandleGetDescriptorFromInterface(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleClassInterface(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleClassInterface(IN OUT PIRP Irp, PURB Urb);
|
||||||
|
NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb);
|
||||||
NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
|
NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb);
|
||||||
|
NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb);
|
||||||
|
|
||||||
friend VOID StatusChangeEndpointCallBack(PVOID Context);
|
friend VOID StatusChangeEndpointCallBack(PVOID Context);
|
||||||
|
|
||||||
|
@ -756,6 +759,47 @@ CHubController::HandlePower(
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CHubController::HandleIsochronousTransfer(
|
||||||
|
IN OUT PIRP Irp,
|
||||||
|
PURB Urb)
|
||||||
|
{
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request
|
||||||
|
//
|
||||||
|
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle;
|
||||||
|
|
||||||
|
if (!EndPointDesc)
|
||||||
|
{
|
||||||
|
DPRINT1("No EndpointDesc\n");
|
||||||
|
Urb->UrbIsochronousTransfer.Hdr.Status = USBD_STATUS_INVALID_PIPE_HANDLE;
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity checks
|
||||||
|
//
|
||||||
|
ASSERT(EndPointDesc);
|
||||||
|
ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if this is a valid usb device handle
|
||||||
|
//
|
||||||
|
PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device
|
||||||
|
//
|
||||||
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
return UsbDevice->SubmitIrp(Irp);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CHubController::HandleBulkOrInterruptTransfer(
|
CHubController::HandleBulkOrInterruptTransfer(
|
||||||
|
@ -794,22 +838,11 @@ CHubController::HandleBulkOrInterruptTransfer(
|
||||||
//
|
//
|
||||||
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
|
||||||
|
|
||||||
switch(EndPointDesc->bmAttributes & 0x0F)
|
//
|
||||||
{
|
// sanity checks
|
||||||
case USB_ENDPOINT_TYPE_CONTROL:
|
//
|
||||||
DPRINT1("Control Transfer is not expected!!!\n");
|
ASSERT(EndPointDesc);
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK || (EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT);
|
||||||
case USB_ENDPOINT_TYPE_BULK:
|
|
||||||
DPRINT("Initiating Bulk Transfer\n");
|
|
||||||
break;
|
|
||||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
|
||||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
|
||||||
DPRINT1("Not Supported\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DPRINT1("Unknown EndPoint Type!\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// check if this is a valid usb device handle
|
// check if this is a valid usb device handle
|
||||||
|
@ -1086,7 +1119,10 @@ CHubController::HandleGetStatusFromDevice(
|
||||||
IN OUT PIRP Irp,
|
IN OUT PIRP Irp,
|
||||||
PURB Urb)
|
PURB Urb)
|
||||||
{
|
{
|
||||||
PUSHORT Status;
|
PUSHORT DeviceStatus;
|
||||||
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
|
||||||
//
|
//
|
||||||
// sanity checks
|
// sanity checks
|
||||||
|
@ -1094,22 +1130,54 @@ CHubController::HandleGetStatusFromDevice(
|
||||||
PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
|
PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
|
||||||
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
|
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
|
||||||
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
|
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
|
||||||
PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// get status buffer
|
// get status buffer
|
||||||
//
|
//
|
||||||
Status = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
|
DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
if (Urb->UrbHeader.UsbdDeviceHandle == NULL)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// FIXME need more flags ?
|
||||||
|
//
|
||||||
|
*DeviceStatus = USB_PORT_STATUS_CONNECT;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIXME need more flags ?
|
// check if this is a valid usb device handle
|
||||||
//
|
//
|
||||||
*Status = USB_PORT_STATUS_CONNECT;
|
ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device
|
||||||
|
//
|
||||||
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// generate setup packet
|
||||||
|
//
|
||||||
|
CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
|
||||||
|
CtrlSetup.wValue.LowByte = 0;
|
||||||
|
CtrlSetup.wValue.HiByte = 0;
|
||||||
|
CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index;
|
||||||
|
CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
|
||||||
|
CtrlSetup.bmRequestType.B = 0x80;
|
||||||
|
|
||||||
|
//
|
||||||
|
// submit setup packet
|
||||||
|
//
|
||||||
|
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
DPRINT1("CHubController::HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus);
|
||||||
|
|
||||||
//
|
//
|
||||||
// done
|
// done
|
||||||
//
|
//
|
||||||
return STATUS_SUCCESS;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
|
@ -1122,6 +1190,8 @@ CHubController::HandleClassDevice(
|
||||||
PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
|
PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
|
||||||
ULONG PortCount, Dummy2;
|
ULONG PortCount, Dummy2;
|
||||||
USHORT Dummy1;
|
USHORT Dummy1;
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
|
|
||||||
DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
|
DPRINT("CHubController::HandleClassDevice Request %x Class %x\n", Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8);
|
||||||
|
|
||||||
|
@ -1130,6 +1200,36 @@ CHubController::HandleClassDevice(
|
||||||
//
|
//
|
||||||
switch(Urb->UrbControlVendorClassRequest.Request)
|
switch(Urb->UrbControlVendorClassRequest.Request)
|
||||||
{
|
{
|
||||||
|
case USB_REQUEST_GET_STATUS:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// check if this is a valid usb device handle
|
||||||
|
//
|
||||||
|
ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device
|
||||||
|
//
|
||||||
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// generate setup packet
|
||||||
|
//
|
||||||
|
CtrlSetup.bRequest = USB_REQUEST_GET_STATUS;
|
||||||
|
CtrlSetup.wValue.LowByte = Urb->UrbControlVendorClassRequest.Index;
|
||||||
|
CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
|
||||||
|
CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
|
||||||
|
CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength;
|
||||||
|
CtrlSetup.bmRequestType.B = 0xA0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// submit setup packet
|
||||||
|
//
|
||||||
|
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case USB_REQUEST_GET_DESCRIPTOR:
|
case USB_REQUEST_GET_DESCRIPTOR:
|
||||||
{
|
{
|
||||||
switch (Urb->UrbControlVendorClassRequest.Value >> 8)
|
switch (Urb->UrbControlVendorClassRequest.Value >> 8)
|
||||||
|
@ -1191,6 +1291,55 @@ CHubController::HandleClassDevice(
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CHubController::HandleGetDescriptorFromInterface(
|
||||||
|
IN OUT PIRP Irp,
|
||||||
|
IN OUT PURB Urb)
|
||||||
|
{
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength);
|
||||||
|
ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if this is a valid usb device handle
|
||||||
|
//
|
||||||
|
ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device
|
||||||
|
//
|
||||||
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
//
|
||||||
|
// generate setup packet
|
||||||
|
//
|
||||||
|
CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
||||||
|
CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index;
|
||||||
|
CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType;
|
||||||
|
CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId;
|
||||||
|
CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength;
|
||||||
|
CtrlSetup.bmRequestType.B = 0x81;
|
||||||
|
|
||||||
|
//
|
||||||
|
// submit setup packet
|
||||||
|
//
|
||||||
|
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CHubController::HandleGetDescriptor(
|
CHubController::HandleGetDescriptor(
|
||||||
|
@ -1300,8 +1449,6 @@ CHubController::HandleGetDescriptor(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINT1("Length %u\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// check if this is a valid usb device handle
|
// check if this is a valid usb device handle
|
||||||
//
|
//
|
||||||
|
@ -1392,7 +1539,7 @@ CHubController::HandleGetDescriptor(
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
CHubController::HandleClassInterface(
|
CHubController::HandleClassEndpoint(
|
||||||
IN OUT PIRP Irp,
|
IN OUT PIRP Irp,
|
||||||
IN OUT PURB Urb)
|
IN OUT PURB Urb)
|
||||||
{
|
{
|
||||||
|
@ -1418,6 +1565,70 @@ CHubController::HandleClassInterface(
|
||||||
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
|
||||||
|
DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n");
|
||||||
|
DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
|
||||||
|
DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
|
||||||
|
DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer);
|
||||||
|
DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL);
|
||||||
|
DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits);
|
||||||
|
DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request);
|
||||||
|
DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
|
||||||
|
DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
|
||||||
|
|
||||||
|
//
|
||||||
|
// initialize setup packet
|
||||||
|
//
|
||||||
|
CtrlSetup.bmRequestType.B = 0xa2; //FIXME: Const.
|
||||||
|
CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request;
|
||||||
|
CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value;
|
||||||
|
CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index;
|
||||||
|
CtrlSetup.wLength = Urb->UrbControlVendorClassRequest.TransferBufferLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// issue request
|
||||||
|
//
|
||||||
|
Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// assert on failure
|
||||||
|
//
|
||||||
|
PC_ASSERT(NT_SUCCESS(Status));
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// done
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------------
|
||||||
|
NTSTATUS
|
||||||
|
CHubController::HandleClassInterface(
|
||||||
|
IN OUT PIRP Irp,
|
||||||
|
IN OUT PURB Urb)
|
||||||
|
{
|
||||||
|
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PUSBDEVICE UsbDevice;
|
||||||
|
|
||||||
|
//
|
||||||
|
// sanity check
|
||||||
|
//
|
||||||
|
//ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL);
|
||||||
|
//ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength);
|
||||||
|
PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
//
|
||||||
|
// check if this is a valid usb device handle
|
||||||
|
//
|
||||||
|
PC_ASSERT(ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// get device
|
||||||
|
//
|
||||||
|
UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle);
|
||||||
|
|
||||||
|
|
||||||
DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
|
DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
|
||||||
DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
|
DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
|
||||||
DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
|
DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
|
||||||
|
@ -1490,6 +1701,9 @@ CHubController::HandleDeviceControl(
|
||||||
|
|
||||||
switch (Urb->UrbHeader.Function)
|
switch (Urb->UrbHeader.Function)
|
||||||
{
|
{
|
||||||
|
case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
|
||||||
|
Status = HandleGetDescriptorFromInterface(Irp, Urb);
|
||||||
|
break;
|
||||||
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
|
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
|
||||||
Status = HandleGetDescriptor(Irp, Urb);
|
Status = HandleGetDescriptor(Irp, Urb);
|
||||||
break;
|
break;
|
||||||
|
@ -1511,9 +1725,15 @@ CHubController::HandleDeviceControl(
|
||||||
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
|
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
|
||||||
Status = HandleBulkOrInterruptTransfer(Irp, Urb);
|
Status = HandleBulkOrInterruptTransfer(Irp, Urb);
|
||||||
break;
|
break;
|
||||||
|
case URB_FUNCTION_ISOCH_TRANSFER:
|
||||||
|
Status = HandleIsochronousTransfer(Irp, Urb);
|
||||||
|
break;
|
||||||
case URB_FUNCTION_CLASS_INTERFACE:
|
case URB_FUNCTION_CLASS_INTERFACE:
|
||||||
Status = HandleClassInterface(Irp, Urb);
|
Status = HandleClassInterface(Irp, Urb);
|
||||||
break;
|
break;
|
||||||
|
case URB_FUNCTION_CLASS_ENDPOINT:
|
||||||
|
Status = HandleClassEndpoint(Irp, Urb);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
|
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
|
||||||
break;
|
break;
|
||||||
|
@ -2301,12 +2521,8 @@ USBHI_RestoreUsbDevice(
|
||||||
PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
|
PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
|
||||||
|
|
||||||
DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
|
DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
|
||||||
|
|
||||||
|
|
||||||
DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
|
DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
|
||||||
|
|
||||||
PC_ASSERT(FALSE);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// remove old device handle
|
// remove old device handle
|
||||||
//
|
//
|
||||||
|
|
|
@ -803,6 +803,7 @@ CreateDeviceIds(
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
ULONG Index;
|
ULONG Index;
|
||||||
PWCHAR BufferPtr;
|
PWCHAR BufferPtr;
|
||||||
|
WCHAR Buffer[100];
|
||||||
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
|
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
|
||||||
|
|
||||||
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
|
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
|
||||||
|
@ -954,6 +955,28 @@ CreateDeviceIds(
|
||||||
UsbChildExtension->usInstanceId.MaximumLength = UsbChildExtension->usInstanceId.Length;
|
UsbChildExtension->usInstanceId.MaximumLength = UsbChildExtension->usInstanceId.Length;
|
||||||
DPRINT1("Usb InstanceId %wZ\n", &UsbChildExtension->usInstanceId);
|
DPRINT1("Usb InstanceId %wZ\n", &UsbChildExtension->usInstanceId);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// the device did not provide a serial number, lets create a pseudo instance id
|
||||||
|
//
|
||||||
|
Index = swprintf(Buffer, L"0&%04d", UsbChildExtension->PortNumber) + 1;
|
||||||
|
UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR));
|
||||||
|
if (UsbChildExtension->usInstanceId.Buffer == NULL)
|
||||||
|
{
|
||||||
|
DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR));
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy instance id
|
||||||
|
//
|
||||||
|
RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR));
|
||||||
|
UsbChildExtension->usInstanceId.Length = UsbChildExtension->usDeviceId.MaximumLength = Index * sizeof(WCHAR);
|
||||||
|
|
||||||
|
DPRINT1("usDeviceId %wZ\n", &UsbChildExtension->usInstanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
|
||||||
|
|
|
@ -1364,7 +1364,7 @@ InterruptServiceRoutine(
|
||||||
//
|
//
|
||||||
// defer processing
|
// defer processing
|
||||||
//
|
//
|
||||||
DPRINT1("Status %x Acknowledge %x FrameNumber %x\n", Status, Acknowledge, This->m_HCCA->CurrentFrameNumber);
|
DPRINT("Status %x Acknowledge %x FrameNumber %x\n", Status, Acknowledge, This->m_HCCA->CurrentFrameNumber);
|
||||||
KeInsertQueueDpc(&This->m_IntDpcObject, (PVOID)Status, (PVOID)(DoneHead & ~1));
|
KeInsertQueueDpc(&This->m_IntDpcObject, (PVOID)Status, (PVOID)(DoneHead & ~1));
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -1634,6 +1634,12 @@ CHubController::HandleClassInterface(
|
||||||
DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
|
DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
|
||||||
DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
|
DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
|
||||||
|
|
||||||
|
if (Urb->UrbControlVendorClassRequest.TransferBufferLength == 0)
|
||||||
|
{
|
||||||
|
DPRINT1("Invalid request length\n");
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// initialize setup packet
|
// initialize setup packet
|
||||||
//
|
//
|
||||||
|
|
|
@ -620,7 +620,7 @@ CUSBQueue::TransferDescriptorCompletionCallback(
|
||||||
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
|
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
DPRINT1("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
|
DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
|
||||||
|
|
||||||
//
|
//
|
||||||
// find transfer descriptor in control list
|
// find transfer descriptor in control list
|
||||||
|
|
|
@ -941,7 +941,7 @@ CUSBRequest::AllocateEndpointDescriptor(
|
||||||
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
|
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
|
||||||
Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
|
Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize());
|
||||||
|
|
||||||
DPRINT1("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %x\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
|
DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %x\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize());
|
||||||
|
|
||||||
//
|
//
|
||||||
// is there an endpoint descriptor
|
// is there an endpoint descriptor
|
||||||
|
|
|
@ -73,16 +73,9 @@ DEFINE_GUID (GUID_HID_INTERFACE_HIDPARSE, \
|
||||||
|
|
||||||
#define IOCTL_HID_GET_DRIVER_CONFIG HID_BUFFER_CTL_CODE(100)
|
#define IOCTL_HID_GET_DRIVER_CONFIG HID_BUFFER_CTL_CODE(100)
|
||||||
#define IOCTL_HID_SET_DRIVER_CONFIG HID_BUFFER_CTL_CODE(101)
|
#define IOCTL_HID_SET_DRIVER_CONFIG HID_BUFFER_CTL_CODE(101)
|
||||||
|
#define IOCTL_HID_GET_INDEXED_STRING HID_OUT_CTL_CODE(120)
|
||||||
#define IOCTL_HID_GET_MS_GENRE_DESCRIPTOR HID_OUT_CTL_CODE(121)
|
#define IOCTL_HID_GET_MS_GENRE_DESCRIPTOR HID_OUT_CTL_CODE(121)
|
||||||
|
|
||||||
/* FIXME: these values are wrong! */
|
|
||||||
#define IOCTL_HID_GET_STRING 0
|
|
||||||
#define IOCTL_HID_GET_DEVICE_ATTRIBUTES 1
|
|
||||||
#define IOCTL_HID_GET_DEVICE_DESCRIPTOR 2
|
|
||||||
#define IOCTL_HID_READ_REPORT 3
|
|
||||||
#define IOCTL_HID_WRITE_REPORT 4
|
|
||||||
#define IOCTL_HID_GET_REPORT_DESCRIPTOR 5
|
|
||||||
|
|
||||||
typedef enum _HID_STRING_TYPE
|
typedef enum _HID_STRING_TYPE
|
||||||
{
|
{
|
||||||
HID_STRING_INDEXED = 0,
|
HID_STRING_INDEXED = 0,
|
||||||
|
|
|
@ -43,6 +43,7 @@ typedef struct _HIDP_DEVICE_DESC
|
||||||
}HIDP_DEVICE_DESC, *PHIDP_DEVICE_DESC;
|
}HIDP_DEVICE_DESC, *PHIDP_DEVICE_DESC;
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
HidP_GetCollectionDescription(
|
HidP_GetCollectionDescription(
|
||||||
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
|
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
|
||||||
IN ULONG DescLength,
|
IN ULONG DescLength,
|
||||||
|
@ -51,11 +52,13 @@ HidP_GetCollectionDescription(
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
NTAPI
|
||||||
HidP_FreeCollectionDescription (
|
HidP_FreeCollectionDescription (
|
||||||
IN PHIDP_DEVICE_DESC DeviceDescription
|
IN PHIDP_DEVICE_DESC DeviceDescription
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
HidP_SysPowerEvent (
|
HidP_SysPowerEvent (
|
||||||
IN PCHAR HidPacket,
|
IN PCHAR HidPacket,
|
||||||
IN USHORT HidPacketLength,
|
IN USHORT HidPacketLength,
|
||||||
|
@ -64,6 +67,7 @@ HidP_SysPowerEvent (
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
HidP_SysPowerCaps (
|
HidP_SysPowerCaps (
|
||||||
IN PHIDP_PREPARSED_DATA Ppd,
|
IN PHIDP_PREPARSED_DATA Ppd,
|
||||||
OUT PULONG OutputBuffer
|
OUT PULONG OutputBuffer
|
||||||
|
|
|
@ -50,8 +50,8 @@ typedef struct _HID_DESCRIPTOR
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
VOID
|
VOID
|
||||||
(*HID_SEND_IDLE_CALLBACK)(
|
(NTAPI *HID_SEND_IDLE_CALLBACK)(
|
||||||
__in PVOID Context
|
IN PVOID Context
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef struct _HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO
|
typedef struct _HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO
|
||||||
|
|
|
@ -199,6 +199,14 @@ typedef USHORT USAGE, *PUSAGE;
|
||||||
#define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA)
|
#define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA)
|
||||||
#define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB)
|
#define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB)
|
||||||
|
|
||||||
|
|
||||||
|
#define HID_USAGE_CONSUMERCTRL ((USAGE)0x01)
|
||||||
|
#define HID_USAGE_DIGITIZER_PEN ((USAGE)0x02)
|
||||||
|
#define HID_USAGE_DIGITIZER_IN_RANGE ((USAGE)0x32)
|
||||||
|
#define HID_USAGE_DIGITIZER_TIP_SWITCH ((USAGE)0x42)
|
||||||
|
#define HID_USAGE_DIGITIZER_BARREL_SWITCH ((USAGE)0x44)
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
add_subdirectory(chew)
|
add_subdirectory(chew)
|
||||||
add_subdirectory(csq)
|
add_subdirectory(csq)
|
||||||
|
add_subdirectory(hidparser)
|
||||||
add_subdirectory(ip)
|
add_subdirectory(ip)
|
||||||
add_subdirectory(lwip)
|
add_subdirectory(lwip)
|
||||||
add_subdirectory(sound)
|
add_subdirectory(sound)
|
||||||
|
|
13
lib/drivers/hidparser/CMakeLists.txt
Normal file
13
lib/drivers/hidparser/CMakeLists.txt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
add_definitions(
|
||||||
|
-DUNICODE -D_UNICODE
|
||||||
|
-DNDEBUG=1)
|
||||||
|
|
||||||
|
list(APPEND SOURCE
|
||||||
|
hidparser.c
|
||||||
|
parser.c
|
||||||
|
api.c)
|
||||||
|
|
||||||
|
add_library(hidparser ${SOURCE})
|
||||||
|
add_dependencies(hidparser bugcodes)
|
||||||
|
|
1077
lib/drivers/hidparser/api.c
Normal file
1077
lib/drivers/hidparser/api.c
Normal file
File diff suppressed because it is too large
Load diff
1159
lib/drivers/hidparser/hidparser.c
Normal file
1159
lib/drivers/hidparser/hidparser.c
Normal file
File diff suppressed because it is too large
Load diff
428
lib/drivers/hidparser/hidparser.h
Normal file
428
lib/drivers/hidparser/hidparser.h
Normal file
|
@ -0,0 +1,428 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: lib/drivers/hidparser/hidparser.c
|
||||||
|
* PURPOSE: HID Parser
|
||||||
|
* PROGRAMMERS:
|
||||||
|
* Michael Martin (michael.martin@reactos.org)
|
||||||
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define _HIDPI_
|
||||||
|
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <hidpddi.h>
|
||||||
|
#include <hidpi.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// function prototypes
|
||||||
|
//
|
||||||
|
typedef PVOID (NTAPI *PHIDPARSER_ALLOC_FUNCTION)(ULONG Size);
|
||||||
|
typedef VOID (NTAPI *PHIDPARSER_FREE_FUNCTION)(PVOID Item);
|
||||||
|
typedef VOID (NTAPI *PHIDPARSER_ZERO_FUNCTION)(PVOID Item, ULONG Size);
|
||||||
|
typedef VOID (NTAPI *PHIDPARSER_COPY_FUNCTION)(PVOID Target, PVOID Source, ULONG Size);
|
||||||
|
typedef VOID (NTAPI *PHIDPARSER_DEBUG_FUNCTION)(LPCSTR Src, ...);
|
||||||
|
|
||||||
|
//
|
||||||
|
// status code
|
||||||
|
//
|
||||||
|
typedef long HIDPARSER_STATUS;
|
||||||
|
|
||||||
|
//
|
||||||
|
// result codes
|
||||||
|
//
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
HIDPARSER_STATUS_SUCCESS = 0,
|
||||||
|
HIDPARSER_STATUS_INSUFFICIENT_RESOURCES = -1,
|
||||||
|
HIDPARSER_STATUS_NOT_IMPLEMENTED = -2,
|
||||||
|
HIDPARSER_STATUS_REPORT_NOT_FOUND = -3,
|
||||||
|
HIDPARSER_STATUS_COLLECTION_NOT_FOUND = -4,
|
||||||
|
HIDPARSER_STATUS_INVALID_REPORT_LENGTH = -5,
|
||||||
|
HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6,
|
||||||
|
HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7,
|
||||||
|
HIDPARSER_STATUS_USAGE_NOT_FOUND = -8,
|
||||||
|
HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9
|
||||||
|
}HIDPARSER_STATUS_CODES;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// size of struct
|
||||||
|
//
|
||||||
|
unsigned long Size;
|
||||||
|
|
||||||
|
//
|
||||||
|
// allocation function
|
||||||
|
//
|
||||||
|
PHIDPARSER_ALLOC_FUNCTION Alloc;
|
||||||
|
|
||||||
|
//
|
||||||
|
// free function
|
||||||
|
//
|
||||||
|
PFREE_FUNCTION Free;
|
||||||
|
|
||||||
|
//
|
||||||
|
// zero function
|
||||||
|
//
|
||||||
|
PHIDPARSER_ZERO_FUNCTION Zero;
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy function
|
||||||
|
//
|
||||||
|
PHIDPARSER_COPY_FUNCTION Copy;
|
||||||
|
|
||||||
|
//
|
||||||
|
// debug function
|
||||||
|
//
|
||||||
|
PHIDPARSER_DEBUG_FUNCTION Debug;
|
||||||
|
|
||||||
|
//
|
||||||
|
// parser context
|
||||||
|
//
|
||||||
|
void * ParserContext;
|
||||||
|
|
||||||
|
}HID_PARSER, *PHID_PARSER;
|
||||||
|
|
||||||
|
HIDPARSER_STATUS
|
||||||
|
HidParser_AllocateParser(
|
||||||
|
IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
|
||||||
|
IN PHIDPARSER_FREE_FUNCTION FreeFunction,
|
||||||
|
IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
|
||||||
|
IN PHIDPARSER_COPY_FUNCTION CopyFunction,
|
||||||
|
IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
|
||||||
|
OUT PHID_PARSER *OutParser);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HidParser_InitParser(
|
||||||
|
IN PHIDPARSER_ALLOC_FUNCTION AllocFunction,
|
||||||
|
IN PHIDPARSER_FREE_FUNCTION FreeFunction,
|
||||||
|
IN PHIDPARSER_ZERO_FUNCTION ZeroFunction,
|
||||||
|
IN PHIDPARSER_COPY_FUNCTION CopyFunction,
|
||||||
|
IN PHIDPARSER_DEBUG_FUNCTION DebugFunction,
|
||||||
|
IN PVOID ParserContext,
|
||||||
|
OUT PHID_PARSER Parser);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetCollectionDescription(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
|
||||||
|
IN ULONG DescLength,
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
OUT PHIDP_DEVICE_DESC DeviceDescription);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
HidParser_FreeCollectionDescription(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN PHIDP_DEVICE_DESC DeviceDescription);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetCaps(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
OUT PHIDP_CAPS Capabilities);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetSpecificValueCaps(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
IN USAGE Usage,
|
||||||
|
OUT PHIDP_VALUE_CAPS ValueCaps,
|
||||||
|
IN OUT PULONG ValueCapsLength);
|
||||||
|
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetButtonCaps(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
HIDP_REPORT_TYPE ReportType,
|
||||||
|
PHIDP_BUTTON_CAPS ButtonCaps,
|
||||||
|
PUSHORT ButtonCapsLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetSpecificButtonCaps(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
IN USAGE Usage,
|
||||||
|
OUT PHIDP_BUTTON_CAPS ButtonCaps,
|
||||||
|
IN OUT PULONG ButtonCapsLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetScaledUsageValue(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection OPTIONAL,
|
||||||
|
IN USAGE Usage,
|
||||||
|
OUT PLONG UsageValue,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetData(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
OUT PHIDP_DATA DataList,
|
||||||
|
IN OUT PULONG DataLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetExtendedAttributes(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USHORT DataIndex,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
|
||||||
|
IN OUT PULONG LengthAttributes);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetLinkCollectionNodes(
|
||||||
|
OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes,
|
||||||
|
IN OUT PULONG LinkCollectionNodesLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetUsageValue(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
IN USAGE Usage,
|
||||||
|
OUT PULONG UsageValue,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_UsageListDifference(
|
||||||
|
IN PUSAGE PreviousUsageList,
|
||||||
|
IN PUSAGE CurrentUsageList,
|
||||||
|
OUT PUSAGE BreakUsageList,
|
||||||
|
OUT PUSAGE MakeUsageList,
|
||||||
|
IN ULONG UsageListLength);
|
||||||
|
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
HidParser_MaxUsageListLength(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage OPTIONAL);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetUsages(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection OPTIONAL,
|
||||||
|
OUT USAGE *UsageList,
|
||||||
|
IN OUT ULONG *UsageLength,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetUsagesEx(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
OUT PUSAGE_AND_PAGE ButtonList,
|
||||||
|
IN OUT ULONG *UsageLength,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_SysPowerEvent (
|
||||||
|
IN PCHAR HidPacket,
|
||||||
|
IN USHORT HidPacketLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA Ppd,
|
||||||
|
OUT PULONG OutputBuffer);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_SysPowerCaps (
|
||||||
|
IN PHIDP_PREPARSED_DATA Ppd,
|
||||||
|
OUT PULONG OutputBuffer);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetUsageValueArray(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection OPTIONAL,
|
||||||
|
IN USAGE Usage,
|
||||||
|
OUT PCHAR UsageValue,
|
||||||
|
IN USHORT UsageValueByteLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_UsageAndPageListDifference(
|
||||||
|
IN PUSAGE_AND_PAGE PreviousUsageList,
|
||||||
|
IN PUSAGE_AND_PAGE CurrentUsageList,
|
||||||
|
OUT PUSAGE_AND_PAGE BreakUsageList,
|
||||||
|
OUT PUSAGE_AND_PAGE MakeUsageList,
|
||||||
|
IN ULONG UsageListLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_UnsetUsages(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
IN PUSAGE UsageList,
|
||||||
|
IN OUT PULONG UsageLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN OUT PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_TranslateUsagesToI8042ScanCodes(
|
||||||
|
IN PUSAGE ChangedUsageList,
|
||||||
|
IN ULONG UsageListLength,
|
||||||
|
IN HIDP_KEYBOARD_DIRECTION KeyAction,
|
||||||
|
IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
|
||||||
|
IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
|
||||||
|
IN PVOID InsertCodesContext);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_TranslateUsageAndPagesToI8042ScanCodes(
|
||||||
|
IN PUSAGE_AND_PAGE ChangedUsageList,
|
||||||
|
IN ULONG UsageListLength,
|
||||||
|
IN HIDP_KEYBOARD_DIRECTION KeyAction,
|
||||||
|
IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
|
||||||
|
IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
|
||||||
|
IN PVOID InsertCodesContext);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_SetUsages(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
IN PUSAGE UsageList,
|
||||||
|
IN OUT PULONG UsageLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN OUT PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_SetUsageValueArray(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection OPTIONAL,
|
||||||
|
IN USAGE Usage,
|
||||||
|
IN PCHAR UsageValue,
|
||||||
|
IN USHORT UsageValueByteLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
OUT PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_SetUsageValue(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection,
|
||||||
|
IN USAGE Usage,
|
||||||
|
IN ULONG UsageValue,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN OUT PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_SetScaledUsageValue(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USHORT LinkCollection OPTIONAL,
|
||||||
|
IN USAGE Usage,
|
||||||
|
IN LONG UsageValue,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN OUT PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_SetData(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN PHIDP_DATA DataList,
|
||||||
|
IN OUT PULONG DataLength,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN OUT PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
HidParser_MaxDataListLength(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_InitializeReportForID(
|
||||||
|
IN HIDP_REPORT_TYPE ReportType,
|
||||||
|
IN UCHAR ReportID,
|
||||||
|
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
|
IN OUT PCHAR Report,
|
||||||
|
IN ULONG ReportLength);
|
||||||
|
|
||||||
|
HIDAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
HidParser_GetValueCaps(
|
||||||
|
HIDP_REPORT_TYPE ReportType,
|
||||||
|
PHIDP_VALUE_CAPS ValueCaps,
|
||||||
|
PULONG ValueCapsLength,
|
||||||
|
PHIDP_PREPARSED_DATA PreparsedData);
|
1347
lib/drivers/hidparser/parser.c
Normal file
1347
lib/drivers/hidparser/parser.c
Normal file
File diff suppressed because it is too large
Load diff
362
lib/drivers/hidparser/parser.h
Normal file
362
lib/drivers/hidparser/parser.h
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <pshpack1.h>
|
||||||
|
#include "hidparser.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2007, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HID_REPORT_TYPE_ANY 0x07
|
||||||
|
|
||||||
|
|
||||||
|
#define ITEM_TYPE_MAIN 0x0
|
||||||
|
#define ITEM_TYPE_GLOBAL 0x1
|
||||||
|
#define ITEM_TYPE_LOCAL 0x2
|
||||||
|
#define ITEM_TYPE_LONG 0x3
|
||||||
|
|
||||||
|
#define ITEM_TAG_MAIN_INPUT 0x8
|
||||||
|
#define ITEM_TAG_MAIN_OUTPUT 0x9
|
||||||
|
#define ITEM_TAG_MAIN_FEATURE 0xb
|
||||||
|
#define ITEM_TAG_MAIN_COLLECTION 0xa
|
||||||
|
#define ITEM_TAG_MAIN_END_COLLECTION 0xc
|
||||||
|
|
||||||
|
#define ITEM_TAG_GLOBAL_USAGE_PAGE 0x0
|
||||||
|
#define ITEM_TAG_GLOBAL_LOGICAL_MINIMUM 0x1
|
||||||
|
#define ITEM_TAG_GLOBAL_LOGICAL_MAXIMUM 0x2
|
||||||
|
#define ITEM_TAG_GLOBAL_PHYSICAL_MINIMUM 0x3
|
||||||
|
#define ITEM_TAG_GLOBAL_PHYSICAL_MAXIMUM 0x4
|
||||||
|
#define ITEM_TAG_GLOBAL_UNIT_EXPONENT 0x5
|
||||||
|
#define ITEM_TAG_GLOBAL_UNIT 0x6
|
||||||
|
#define ITEM_TAG_GLOBAL_REPORT_SIZE 0x7
|
||||||
|
#define ITEM_TAG_GLOBAL_REPORT_ID 0x8
|
||||||
|
#define ITEM_TAG_GLOBAL_REPORT_COUNT 0x9
|
||||||
|
#define ITEM_TAG_GLOBAL_PUSH 0xa
|
||||||
|
#define ITEM_TAG_GLOBAL_POP 0xb
|
||||||
|
|
||||||
|
#define ITEM_TAG_LOCAL_USAGE 0x0
|
||||||
|
#define ITEM_TAG_LOCAL_USAGE_MINIMUM 0x1
|
||||||
|
#define ITEM_TAG_LOCAL_USAGE_MAXIMUM 0x2
|
||||||
|
#define ITEM_TAG_LOCAL_DESIGNATOR_INDEX 0x3
|
||||||
|
#define ITEM_TAG_LOCAL_DESIGNATOR_MINIMUM 0x4
|
||||||
|
#define ITEM_TAG_LOCAL_DESIGNATOR_MAXIMUM 0x5
|
||||||
|
#define ITEM_TAG_LOCAL_STRING_INDEX 0x7
|
||||||
|
#define ITEM_TAG_LOCAL_STRING_MINIMUM 0x8
|
||||||
|
#define ITEM_TAG_LOCAL_STRING_MAXIMUM 0x9
|
||||||
|
#define ITEM_TAG_LOCAL_DELIMITER 0xa
|
||||||
|
|
||||||
|
#define ITEM_TAG_LONG 0xf
|
||||||
|
|
||||||
|
#define COLLECTION_PHYSICAL 0x00
|
||||||
|
#define COLLECTION_APPLICATION 0x01
|
||||||
|
#define COLLECTION_LOGICAL 0x02
|
||||||
|
#define COLLECTION_REPORT 0x03
|
||||||
|
#define COLLECTION_NAMED_ARRAY 0x04
|
||||||
|
#define COLLECTION_USAGE_SWITCH 0x05
|
||||||
|
#define COLLECTION_USAGE_MODIFIER 0x06
|
||||||
|
#define COLLECTION_ALL 0xff
|
||||||
|
|
||||||
|
#define UNIT_SYSTEM 0x0
|
||||||
|
#define UNIT_LENGTH 0x1
|
||||||
|
#define UNIT_MASS 0x2
|
||||||
|
#define UNIT_TIME 0x3
|
||||||
|
#define UNIT_TEMPERATURE 0x4
|
||||||
|
#define UNIT_CURRENT 0x5
|
||||||
|
#define UNIT_LUMINOUS_INTENSITY 0x6
|
||||||
|
|
||||||
|
#define USAGE_PAGE_SHIFT 16
|
||||||
|
#define USAGE_PAGE_MASK 0xffff
|
||||||
|
#define USAGE_ID_SHIFT 0
|
||||||
|
#define USAGE_ID_MASK 0xffff
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UCHAR Size:2;
|
||||||
|
UCHAR Type:2;
|
||||||
|
UCHAR Tag:4;
|
||||||
|
}ITEM_PREFIX, *PITEM_PREFIX;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ITEM_PREFIX Prefix;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UCHAR UData8[4];
|
||||||
|
CHAR SData8[4];
|
||||||
|
USHORT UData16[2];
|
||||||
|
SHORT SData16[2];
|
||||||
|
ULONG UData32;
|
||||||
|
LONG SData32;
|
||||||
|
}Data;
|
||||||
|
|
||||||
|
}SHORT_ITEM, *PSHORT_ITEM;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ITEM_PREFIX Prefix;
|
||||||
|
UCHAR DataSize;
|
||||||
|
UCHAR LongItemTag;
|
||||||
|
UCHAR Data[0];
|
||||||
|
|
||||||
|
}LONG_ITEM,*PLONG_ITEM;
|
||||||
|
|
||||||
|
|
||||||
|
#define LBITFIELD9(b1,b2,b3,b4,b5,b6,b7,b8,b9) USHORT b9,b8,b7,b6,b5,b4,b3,b2,b1
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
USHORT DataConstant:1;
|
||||||
|
USHORT ArrayVariable:1;
|
||||||
|
USHORT Relative:1;
|
||||||
|
USHORT Wrap:1;
|
||||||
|
USHORT NonLinear:1;
|
||||||
|
USHORT NoPreferred:1;
|
||||||
|
USHORT NullState:1;
|
||||||
|
USHORT IsVolatile:1;
|
||||||
|
USHORT BitsBytes:1;
|
||||||
|
UCHAR reserved[2];
|
||||||
|
|
||||||
|
}MAIN_ITEM_DATA, *PMAIN_ITEM_DATA;
|
||||||
|
|
||||||
|
typedef struct __GLOBAL_ITEM_STATE_
|
||||||
|
{
|
||||||
|
USHORT UsagePage;
|
||||||
|
ULONG LogicalMinimum;
|
||||||
|
ULONG LogicialMaximum;
|
||||||
|
ULONG PhysicalMinimum;
|
||||||
|
ULONG PhysicalMaximum;
|
||||||
|
UCHAR UnitExponent;
|
||||||
|
UCHAR Unit;
|
||||||
|
ULONG ReportSize;
|
||||||
|
ULONG ReportCount;
|
||||||
|
UCHAR ReportId;
|
||||||
|
struct __GLOBAL_ITEM_STATE__ * Next;
|
||||||
|
}GLOBAL_ITEM_STATE, *PGLOBAL_ITEM_STATE;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct usage_value
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
USHORT UsageId;
|
||||||
|
USHORT UsagePage;
|
||||||
|
}s;
|
||||||
|
ULONG Extended;
|
||||||
|
}u;
|
||||||
|
|
||||||
|
UCHAR IsExtended;
|
||||||
|
}USAGE_VALUE, *PUSAGE_VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PUSAGE_VALUE UsageStack;
|
||||||
|
ULONG UsageStackUsed;
|
||||||
|
ULONG UsageStackAllocated;
|
||||||
|
|
||||||
|
USAGE_VALUE UsageMinimum;
|
||||||
|
USAGE_VALUE UsageMaximum;
|
||||||
|
|
||||||
|
UCHAR UsageMinimumSet;
|
||||||
|
UCHAR UsageMaximumSet;
|
||||||
|
|
||||||
|
ULONG DesignatorIndex;
|
||||||
|
UCHAR DesignatorIndexSet;
|
||||||
|
|
||||||
|
ULONG DesignatorMinimum;
|
||||||
|
ULONG DesignatorMaximum;
|
||||||
|
|
||||||
|
UCHAR StringIndex;
|
||||||
|
UCHAR StringIndexSet;
|
||||||
|
UCHAR StringMinimum;
|
||||||
|
UCHAR StringMaximum;
|
||||||
|
|
||||||
|
}LOCAL_ITEM_STATE, *PLOCAL_ITEM_STATE;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ULONG ByteOffset;
|
||||||
|
UCHAR Shift;
|
||||||
|
ULONG Mask;
|
||||||
|
UCHAR BitCount;
|
||||||
|
UCHAR HasData;
|
||||||
|
UCHAR Array;
|
||||||
|
UCHAR Relative;
|
||||||
|
ULONG Minimum;
|
||||||
|
ULONG Maximum;
|
||||||
|
ULONG UsageMinimum;
|
||||||
|
ULONG UsageMaximum;
|
||||||
|
ULONG Data;
|
||||||
|
UCHAR Valid;
|
||||||
|
}HID_REPORT_ITEM, *PHID_REPORT_ITEM;
|
||||||
|
|
||||||
|
struct HID_REPORT;
|
||||||
|
|
||||||
|
typedef struct __HID_COLLECTION__
|
||||||
|
{
|
||||||
|
struct __HID_COLLECTION__ * Root;
|
||||||
|
|
||||||
|
UCHAR Type;
|
||||||
|
ULONG Usage;
|
||||||
|
UCHAR StringID;
|
||||||
|
UCHAR PhysicalID;
|
||||||
|
ULONG NodeCount;
|
||||||
|
struct __HID_COLLECTION__ ** Nodes;
|
||||||
|
|
||||||
|
ULONG ItemCount;
|
||||||
|
ULONG ItemCountAllocated;
|
||||||
|
PHID_REPORT_ITEM * Items;
|
||||||
|
|
||||||
|
//ULONG ReportCount;
|
||||||
|
//struct HID_REPORT ** Reports;
|
||||||
|
|
||||||
|
}HID_COLLECTION, *PHID_COLLECTION;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UCHAR Type;
|
||||||
|
UCHAR ReportID;
|
||||||
|
ULONG ReportSize;
|
||||||
|
|
||||||
|
ULONG ItemCount;
|
||||||
|
ULONG ItemAllocated;
|
||||||
|
PHID_REPORT_ITEM *Items;
|
||||||
|
|
||||||
|
ULONG ReportStatus;
|
||||||
|
UCHAR * CurrentReport;
|
||||||
|
ULONG BusyCount;
|
||||||
|
}HID_REPORT, *PHID_REPORT;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// global item state
|
||||||
|
//
|
||||||
|
GLOBAL_ITEM_STATE GlobalItemState;
|
||||||
|
|
||||||
|
//
|
||||||
|
// local item state
|
||||||
|
//
|
||||||
|
LOCAL_ITEM_STATE LocalItemState;
|
||||||
|
|
||||||
|
//
|
||||||
|
// root collection
|
||||||
|
//
|
||||||
|
PHID_COLLECTION RootCollection;
|
||||||
|
|
||||||
|
//
|
||||||
|
// report count
|
||||||
|
//
|
||||||
|
ULONG ReportCount;
|
||||||
|
|
||||||
|
//
|
||||||
|
// reports
|
||||||
|
//
|
||||||
|
PHID_REPORT * Reports;
|
||||||
|
|
||||||
|
//
|
||||||
|
// uses report ids
|
||||||
|
//
|
||||||
|
UCHAR UseReportIDs;
|
||||||
|
|
||||||
|
}HID_PARSER_CONTEXT, *PHID_PARSER_CONTEXT;
|
||||||
|
|
||||||
|
HIDPARSER_STATUS
|
||||||
|
HidParser_ParseReportDescriptor(
|
||||||
|
PHID_PARSER Parser,
|
||||||
|
PUCHAR Report,
|
||||||
|
ULONG ReportSize);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
HidParser_NumberOfTopCollections(
|
||||||
|
IN PHID_PARSER Parser);
|
||||||
|
|
||||||
|
#define HID_REPORT_TYPE_INPUT 0x01
|
||||||
|
#define HID_REPORT_TYPE_OUTPUT 0x02
|
||||||
|
#define HID_REPORT_TYPE_FEATURE 0x04
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
HidParser_NumberOfReports(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG ReportType);
|
||||||
|
|
||||||
|
HIDPARSER_STATUS
|
||||||
|
HidParser_GetCollectionUsagePage(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG CollectionNumber,
|
||||||
|
OUT PUSHORT Usage,
|
||||||
|
OUT PUSHORT UsagePage);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
HidParser_GetReportLength(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG ReportType);
|
||||||
|
|
||||||
|
UCHAR
|
||||||
|
HidParser_IsReportIDUsed(
|
||||||
|
IN PHID_PARSER Parser);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
HidParser_GetReportItemCountFromReportType(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG ReportType);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
HidParser_GetReportItemTypeCountFromReportType(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG ReportType,
|
||||||
|
IN ULONG bData);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
HidParser_GetContextSize(
|
||||||
|
IN PHID_PARSER Parser);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HidParser_FreeContext(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN PUCHAR Context,
|
||||||
|
IN ULONG ContextLength);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
HidParser_GetTotalCollectionCount(
|
||||||
|
IN PHID_PARSER Parser);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
HidParser_GetMaxUsageListLengthWithReportAndPage(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG ReportType,
|
||||||
|
IN USAGE UsagePage OPTIONAL);
|
||||||
|
|
||||||
|
HIDPARSER_STATUS
|
||||||
|
HidParser_GetSpecificValueCapsWithReport(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG ReportType,
|
||||||
|
IN USHORT UsagePage,
|
||||||
|
IN USHORT Usage,
|
||||||
|
OUT PHIDP_VALUE_CAPS ValueCaps,
|
||||||
|
IN OUT PULONG ValueCapsLength);
|
||||||
|
|
||||||
|
|
||||||
|
HIDPARSER_STATUS
|
||||||
|
HidParser_GetUsagesWithReport(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
OUT USAGE *UsageList,
|
||||||
|
IN OUT PULONG UsageLength,
|
||||||
|
IN PCHAR ReportDescriptor,
|
||||||
|
IN ULONG ReportDescriptorLength);
|
||||||
|
|
||||||
|
HIDPARSER_STATUS
|
||||||
|
HidParser_GetScaledUsageValueWithReport(
|
||||||
|
IN PHID_PARSER Parser,
|
||||||
|
IN ULONG ReportType,
|
||||||
|
IN USAGE UsagePage,
|
||||||
|
IN USAGE Usage,
|
||||||
|
OUT PLONG UsageValue,
|
||||||
|
IN PCHAR ReportDescriptor,
|
||||||
|
IN ULONG ReportDescriptorLength);
|
|
@ -11,6 +11,7 @@ list(APPEND INF_FILES
|
||||||
font.inf
|
font.inf
|
||||||
hal.inf
|
hal.inf
|
||||||
hdc.inf
|
hdc.inf
|
||||||
|
input.inf
|
||||||
intl.inf
|
intl.inf
|
||||||
keyboard.inf
|
keyboard.inf
|
||||||
ks.inf
|
ks.inf
|
||||||
|
|
73
media/inf/input.inf
Normal file
73
media/inf/input.inf
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
[Version]
|
||||||
|
Signature="$WINDOWS NT$"
|
||||||
|
Class=HIDClass
|
||||||
|
ClassGuid={745a17a0-74d3-11d0-b6fe-00a0c90f57da}
|
||||||
|
Provider=%MSFT%
|
||||||
|
LayoutFile=layout.inf
|
||||||
|
DriverVer=07/01/2001,5.1.2600.5512
|
||||||
|
|
||||||
|
[DestinationDirs]
|
||||||
|
DefaultDestDir = 12
|
||||||
|
HID_Inst.CopyFilesDLL.NT = 11
|
||||||
|
SPI_Files_DLL = 11
|
||||||
|
|
||||||
|
[ClassInstall]
|
||||||
|
Addreg=HIDClassReg
|
||||||
|
|
||||||
|
[HIDClassReg]
|
||||||
|
HKR,,,,%HID.ClassName%
|
||||||
|
HKR,,Icon,,-24
|
||||||
|
HKR,,NoInstallClass,,1
|
||||||
|
|
||||||
|
[ClassInstall32]
|
||||||
|
Addreg=HIDClassReg
|
||||||
|
|
||||||
|
[MSMice]
|
||||||
|
%USB\VID_045E&PID_0009.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_0009
|
||||||
|
%USB\VID_045E&PID_001E.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_001E
|
||||||
|
%USB\VID_045E&PID_0023.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_0023
|
||||||
|
%USB\VID_045E&PID_0024.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_0024
|
||||||
|
%USB\VID_045E&PID_0025.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_0025
|
||||||
|
%USB\VID_045E&PID_0029.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_0029
|
||||||
|
%USB\VID_045E&PID_0039.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_0039
|
||||||
|
%USB\VID_045E&PID_0040.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_0040
|
||||||
|
%USB\VID_045E&PID_0047.DeviceDesc%=HID_Inst,, USB\VID_045E&PID_0047
|
||||||
|
|
||||||
|
|
||||||
|
[Standard]
|
||||||
|
%HID_DEVICE_SYSTEM_GAME%=HID_Raw_Inst,, HID_DEVICE_SYSTEM_GAME
|
||||||
|
%HID_DEVICE%=HID_Raw_Inst,, HID_DEVICE
|
||||||
|
%HID.DeviceDesc% = HID_Inst,,GENERIC_HID_DEVICE,USB\Class_03&SubClass_01,USB\Class_03
|
||||||
|
|
||||||
|
|
||||||
|
[HID_Inst.NT]
|
||||||
|
Copyfiles = HID_Inst.CopyFiles.NT, HID_Inst.CopyFilesDLL.NT
|
||||||
|
|
||||||
|
[HID_Inst.CopyFiles.NT]
|
||||||
|
hidusb.sys
|
||||||
|
hidclass.sys
|
||||||
|
hidparse.sys
|
||||||
|
|
||||||
|
[HID_INST.CopyFilesDLL.NT]
|
||||||
|
hid.dll
|
||||||
|
|
||||||
|
[HID_Inst.NT.Services]
|
||||||
|
AddService = hidusb, 0x00000002, HID_Service_Inst
|
||||||
|
|
||||||
|
[HID_Service_Inst]
|
||||||
|
ServiceType = 1
|
||||||
|
StartType = 3
|
||||||
|
ErrorControl = 1
|
||||||
|
ServiceBinary = %12%\hidusb.sys
|
||||||
|
LoadOrderGroup = extended base
|
||||||
|
|
||||||
|
[strings]
|
||||||
|
MSFT = "ReactOS"
|
||||||
|
HID.DeviceDesc = "USB-HID (Human Interface Device)"
|
||||||
|
HID.DefaultDevice = "HID-Standardgerät"
|
||||||
|
HID.ClassName = "Eingabegeräte (Human Interface Devices)"
|
||||||
|
HID.SvcDesc = "ReactOS HID Class-Treiber"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -22,6 +22,7 @@ display.inf
|
||||||
fdc.inf
|
fdc.inf
|
||||||
hal.inf
|
hal.inf
|
||||||
hdc.inf
|
hdc.inf
|
||||||
|
input.inf
|
||||||
keyboard.inf
|
keyboard.inf
|
||||||
machine.inf
|
machine.inf
|
||||||
msmouse.inf
|
msmouse.inf
|
||||||
|
|
|
@ -1208,4 +1208,30 @@ ObQueryDeviceMapInformation(IN PEPROCESS Process,
|
||||||
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ObIsDosDeviceLocallyMapped(
|
||||||
|
IN ULONG Index,
|
||||||
|
OUT PUCHAR DosDeviceState)
|
||||||
|
{
|
||||||
|
/* check parameters */
|
||||||
|
if (Index < 1 || Index > 26)
|
||||||
|
{
|
||||||
|
/* invalid index */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acquire lock */
|
||||||
|
KeAcquireGuardedMutex(&ObpDeviceMapLock);
|
||||||
|
|
||||||
|
/* get drive mapping status */
|
||||||
|
*DosDeviceState = (ObSystemDeviceMap->DriveMap & (1 << Index)) != 0;
|
||||||
|
|
||||||
|
/* release lock */
|
||||||
|
KeReleaseGuardedMutex(&ObpDeviceMapLock);
|
||||||
|
|
||||||
|
/* done */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue