[USB-BRINGUP-TRUNK]

- Merge 54115-54859

svn path=/branches/usb-bringup-trunk/; revision=55020
This commit is contained in:
Cameron Gutman 2012-01-20 21:19:37 +00:00
51 changed files with 11501 additions and 391 deletions

View file

@ -4,6 +4,7 @@ add_subdirectory(battery)
add_subdirectory(bus)
add_subdirectory(directx)
add_subdirectory(filesystems)
add_subdirectory(hid)
add_subdirectory(input)
add_subdirectory(ksfilter)
add_subdirectory(network)

View file

@ -0,0 +1,5 @@
add_subdirectory(hidclass)
add_subdirectory(hidparse)
add_subdirectory(hidusb)
add_subdirectory(kbdhid)
add_subdirectory(mouhid)

View 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
View 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);
}
}
}

File diff suppressed because it is too large Load diff

View 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>

View file

@ -0,0 +1,4 @@
@ stdcall -private DllInitialize(long)
@ stdcall -private DllUnload()
@ stdcall HidRegisterMinidriver(ptr)

711
drivers/hid/hidclass/pdo.c Normal file
View 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;
}

View 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 */

View file

@ -2,7 +2,10 @@
spec2def(hidparse.sys hidparse.spec)
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)
@ -12,3 +15,5 @@ add_cab_target(hidparse 2)
add_cab_target(hidparse 2)
add_importlib_target(hidparse.spec)
target_link_libraries(hidparse hidparser)

View file

@ -10,30 +10,346 @@
#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
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 (
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
//
ExFreePool(DeviceDescription->CollectionDesc);
//
// free report ids
//
ExFreePool(DeviceDescription->ReportIDs);
//
// free description itself
//
ExFreePool(DeviceDescription);
HidParser_FreeCollectionDescription(&Parser, 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
NTSTATUS
NTAPI
@ -43,7 +359,7 @@ HidP_GetButtonCaps(
PUSHORT ButtonCapsLength,
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
@ -63,31 +379,6 @@ HidP_GetSpecificButtonCaps(
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
NTSTATUS
NTAPI
@ -109,7 +400,7 @@ NTSTATUS
NTAPI
HidP_GetExtendedAttributes(
IN HIDP_REPORT_TYPE ReportType,
IN USHORT DataIndex,
IN USAGE UsagePage,
IN PHIDP_PREPARSED_DATA PreparsedData,
OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
IN OUT PULONG LengthAttributes)
@ -132,24 +423,6 @@ HidP_GetLinkCollectionNodes(
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
NTSTATUS
NTAPI
@ -168,72 +441,8 @@ HidP_GetUsageValue(
return STATUS_NOT_IMPLEMENTED;
}
HIDAPI
NTSTATUS
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 (
IN PCHAR HidPacket,
IN USHORT HidPacketLength,
@ -246,6 +455,7 @@ HidP_SysPowerEvent (
}
NTSTATUS
NTAPI
HidP_SysPowerCaps (
IN PHIDP_PREPARSED_DATA Ppd,
OUT PULONG OutputBuffer)
@ -274,38 +484,6 @@ HidP_GetUsageValueArray(
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
NTSTATUS
@ -341,22 +519,6 @@ HidP_TranslateUsagesToI8042ScanCodes(
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
NTSTATUS
NTAPI
@ -473,6 +635,8 @@ HidP_InitializeReportForID(
return STATUS_NOT_IMPLEMENTED;
}
#undef HidP_GetValueCaps
HIDAPI
NTSTATUS
NTAPI

View file

@ -5,4 +5,6 @@
#include <ntddk.h>
#include <hidpddi.h>
#include <hidpi.h>
#define NDEBUG
#include <debug.h>
#include "hidparser.h"

View file

@ -10,7 +10,7 @@
@ stdcall HidP_GetSpecificValueCaps(long long long long ptr ptr ptr)
@ 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_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_GetValueCaps(long ptr ptr ptr)
@ stdcall HidP_InitializeReportForID(long long ptr ptr long)

View file

@ -1,11 +1,11 @@
list(APPEND SOURCE
hidusb.c
usbhub.rc)
hidusb.rc)
add_library(hidusb SHARED ${SOURCE})
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

File diff suppressed because it is too large Load diff

View 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);

View 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>

View 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
View 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
View 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);

View 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>

View 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
View 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
View 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);

View 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>

View file

@ -1,4 +1,3 @@
add_subdirectory(hidparse)
add_subdirectory(nt4compat)
add_subdirectory(usbd)
add_subdirectory(usbehci_new)

View file

@ -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;
}

View file

@ -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;

View file

@ -60,13 +60,16 @@ public:
VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine);
// internal ioctl routines
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 HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb);
NTSTATUS HandleClassOther(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 HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb);
friend VOID StatusChangeEndpointCallBack(PVOID Context);
@ -756,6 +759,47 @@ CHubController::HandlePower(
IoCompleteRequest(Irp, IO_NO_INCREMENT);
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
CHubController::HandleBulkOrInterruptTransfer(
@ -794,22 +838,11 @@ CHubController::HandleBulkOrInterruptTransfer(
//
EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbBulkOrInterruptTransfer.PipeHandle;
switch(EndPointDesc->bmAttributes & 0x0F)
{
case USB_ENDPOINT_TYPE_CONTROL:
DPRINT1("Control Transfer is not expected!!!\n");
return STATUS_INVALID_DEVICE_REQUEST;
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;
}
//
// sanity checks
//
ASSERT(EndPointDesc);
ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK || (EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT);
//
// check if this is a valid usb device handle
@ -1086,7 +1119,10 @@ CHubController::HandleGetStatusFromDevice(
IN OUT PIRP Irp,
PURB Urb)
{
PUSHORT Status;
PUSHORT DeviceStatus;
USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup;
NTSTATUS Status;
PUSBDEVICE UsbDevice;
//
// sanity checks
@ -1094,22 +1130,54 @@ CHubController::HandleGetStatusFromDevice(
PC_ASSERT(Urb->UrbControlGetStatusRequest.Index == 0);
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT));
PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer);
PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle == NULL);
//
// 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
//
return STATUS_SUCCESS;
return Status;
}
//-----------------------------------------------------------------------------------------
@ -1122,6 +1190,8 @@ CHubController::HandleClassDevice(
PUSB_HUB_DESCRIPTOR UsbHubDescriptor;
ULONG PortCount, Dummy2;
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);
@ -1130,6 +1200,36 @@ CHubController::HandleClassDevice(
//
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:
{
switch (Urb->UrbControlVendorClassRequest.Value >> 8)
@ -1191,6 +1291,55 @@ CHubController::HandleClassDevice(
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
CHubController::HandleGetDescriptor(
@ -1300,8 +1449,6 @@ CHubController::HandleGetDescriptor(
}
else
{
DPRINT1("Length %u\n", Urb->UrbControlDescriptorRequest.TransferBufferLength);
//
// check if this is a valid usb device handle
//
@ -1392,7 +1539,7 @@ CHubController::HandleGetDescriptor(
//-----------------------------------------------------------------------------------------
NTSTATUS
CHubController::HandleClassInterface(
CHubController::HandleClassEndpoint(
IN OUT PIRP Irp,
IN OUT PURB Urb)
{
@ -1418,6 +1565,70 @@ CHubController::HandleClassInterface(
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("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength);
@ -1490,6 +1701,9 @@ CHubController::HandleDeviceControl(
switch (Urb->UrbHeader.Function)
{
case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE:
Status = HandleGetDescriptorFromInterface(Irp, Urb);
break;
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
Status = HandleGetDescriptor(Irp, Urb);
break;
@ -1511,9 +1725,15 @@ CHubController::HandleDeviceControl(
case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
Status = HandleBulkOrInterruptTransfer(Irp, Urb);
break;
case URB_FUNCTION_ISOCH_TRANSFER:
Status = HandleIsochronousTransfer(Irp, Urb);
break;
case URB_FUNCTION_CLASS_INTERFACE:
Status = HandleClassInterface(Irp, Urb);
break;
case URB_FUNCTION_CLASS_ENDPOINT:
Status = HandleClassEndpoint(Irp, Urb);
break;
default:
DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
break;
@ -2301,12 +2521,8 @@ USBHI_RestoreUsbDevice(
PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice));
DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress());
DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress());
PC_ASSERT(FALSE);
//
// remove old device handle
//

View file

@ -803,6 +803,7 @@ CreateDeviceIds(
NTSTATUS Status;
ULONG Index;
PWCHAR BufferPtr;
WCHAR Buffer[100];
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension;
@ -954,6 +955,28 @@ CreateDeviceIds(
UsbChildExtension->usInstanceId.MaximumLength = UsbChildExtension->usInstanceId.Length;
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;

View file

@ -1364,7 +1364,7 @@ InterruptServiceRoutine(
//
// 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));
//

View file

@ -1634,6 +1634,12 @@ CHubController::HandleClassInterface(
DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value);
DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index);
if (Urb->UrbControlVendorClassRequest.TransferBufferLength == 0)
{
DPRINT1("Invalid request length\n");
return STATUS_SUCCESS;
}
//
// initialize setup packet
//

View file

@ -620,7 +620,7 @@ CUSBQueue::TransferDescriptorCompletionCallback(
POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor;
NTSTATUS Status;
DPRINT1("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress);
//
// find transfer descriptor in control list

View file

@ -941,7 +941,7 @@ CUSBRequest::AllocateEndpointDescriptor(
Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress());
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

View file

@ -73,16 +73,9 @@ DEFINE_GUID (GUID_HID_INTERFACE_HIDPARSE, \
#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_GET_INDEXED_STRING HID_OUT_CTL_CODE(120)
#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
{
HID_STRING_INDEXED = 0,

View file

@ -43,6 +43,7 @@ typedef struct _HIDP_DEVICE_DESC
}HIDP_DEVICE_DESC, *PHIDP_DEVICE_DESC;
NTSTATUS
NTAPI
HidP_GetCollectionDescription(
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
IN ULONG DescLength,
@ -51,11 +52,13 @@ HidP_GetCollectionDescription(
);
VOID
NTAPI
HidP_FreeCollectionDescription (
IN PHIDP_DEVICE_DESC DeviceDescription
);
NTSTATUS
NTAPI
HidP_SysPowerEvent (
IN PCHAR HidPacket,
IN USHORT HidPacketLength,
@ -64,6 +67,7 @@ HidP_SysPowerEvent (
);
NTSTATUS
NTAPI
HidP_SysPowerCaps (
IN PHIDP_PREPARSED_DATA Ppd,
OUT PULONG OutputBuffer

View file

@ -50,8 +50,8 @@ typedef struct _HID_DESCRIPTOR
typedef
VOID
(*HID_SEND_IDLE_CALLBACK)(
__in PVOID Context
(NTAPI *HID_SEND_IDLE_CALLBACK)(
IN PVOID Context
);
typedef struct _HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO

View file

@ -199,6 +199,14 @@ typedef USHORT USAGE, *PUSAGE;
#define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA)
#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
}
#endif

View file

@ -1,6 +1,7 @@
add_subdirectory(chew)
add_subdirectory(csq)
add_subdirectory(hidparser)
add_subdirectory(ip)
add_subdirectory(lwip)
add_subdirectory(sound)

View 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View 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);

File diff suppressed because it is too large Load diff

View 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);

View file

@ -11,6 +11,7 @@ list(APPEND INF_FILES
font.inf
hal.inf
hdc.inf
input.inf
intl.inf
keyboard.inf
ks.inf

73
media/inf/input.inf Normal file
View 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.

View file

@ -22,6 +22,7 @@ display.inf
fdc.inf
hal.inf
hdc.inf
input.inf
keyboard.inf
machine.inf
msmouse.inf

View file

@ -1208,4 +1208,30 @@ ObQueryDeviceMapInformation(IN PEPROCESS Process,
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 */