From a64411cfbf35f0a7e62bc88f11e25f5057b055cc Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sat, 31 Dec 2011 03:33:14 +0000 Subject: [PATCH] [USB-BRINGUP] - Implement HidClassFDO_DeviceRelations - Implement IOCTL_HID_GET_COLLECTION_INFORMATION, IOCTL_HID_GET_COLLECTION_DESCRIPTOR - Implement IRP_MN_QUERY_ID, IRP_MN_QUERY_CAPABILITIES, IRP_MN_QUERY_BUS_INFORMATION, IRP_MN_QUERY_PNP_STATE, IRP_MN_QUERY_DEVICE_RELATIONS, - HIDClass PDO is now created and starts initialization, needs IRP_MN_START_DEVICE request implementation - Tested in Vbox 4.1.4 + WinXP + ReactOS hidusb,hidmou,hidclass svn path=/branches/usb-bringup/; revision=54791 --- drivers/hid/hidclass/CMakeLists.txt | 1 + drivers/hid/hidclass/fdo.c | 132 ++++++- drivers/hid/hidclass/hidclass.c | 126 ++++++- drivers/hid/hidclass/pdo.c | 566 ++++++++++++++++++++++++++++ drivers/hid/hidclass/precomp.h | 73 +++- 5 files changed, 874 insertions(+), 24 deletions(-) create mode 100644 drivers/hid/hidclass/pdo.c diff --git a/drivers/hid/hidclass/CMakeLists.txt b/drivers/hid/hidclass/CMakeLists.txt index 45af00a812a..1f8691bc5a6 100644 --- a/drivers/hid/hidclass/CMakeLists.txt +++ b/drivers/hid/hidclass/CMakeLists.txt @@ -5,6 +5,7 @@ list(APPEND SOURCE fdo.c hidclass.c hidclass.rc + pdo.c ${CMAKE_CURRENT_BINARY_DIR}/hidclass.def) add_library(hidclass SHARED ${SOURCE}) diff --git a/drivers/hid/hidclass/fdo.c b/drivers/hid/hidclass/fdo.c index 294ac37eaf2..80157b71d79 100644 --- a/drivers/hid/hidclass/fdo.c +++ b/drivers/hid/hidclass/fdo.c @@ -145,7 +145,7 @@ HidClassFDO_DispatchRequestSynchronous( IN PIRP Irp) { KEVENT Event; - PHIDCLASS_FDO_EXTENSION FDODeviceExtension; + PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; NTSTATUS Status; PIO_STACK_LOCATION IoStack; @@ -157,8 +157,7 @@ HidClassFDO_DispatchRequestSynchronous( // // get device extension // - FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension; - ASSERT(FDODeviceExtension->Common.IsFDO); + CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // // set completion routine @@ -187,7 +186,7 @@ HidClassFDO_DispatchRequestSynchronous( // call driver // DPRINT1("IoStack MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction); - Status = FDODeviceExtension->DriverExtension->MajorFunction[IoStack->MajorFunction](DeviceObject, Irp); + Status = CommonDeviceExtension->DriverExtension->MajorFunction[IoStack->MajorFunction](DeviceObject, Irp); // // wait for the request to finish @@ -392,14 +391,133 @@ HidClassFDO_RemoveDevice( 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) { - UNIMPLEMENTED - ASSERT(FALSE); - return STATUS_NOT_IMPLEMENTED; + 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.Count == 0) + { + // + // time to create the pdos + // + Status = HidClassPDO_CreatePDO(DeviceObject); + 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 diff --git a/drivers/hid/hidclass/hidclass.c b/drivers/hid/hidclass/hidclass.c index 9ed5e52f080..107368f02e1 100644 --- a/drivers/hid/hidclass/hidclass.c +++ b/drivers/hid/hidclass/hidclass.c @@ -83,7 +83,7 @@ HidClassAddDevice( FDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension = (PVOID)((ULONG_PTR)FDODeviceExtension + sizeof(HIDCLASS_FDO_EXTENSION)); FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject = IoAttachDeviceToDeviceStack(NewDeviceObject, PhysicalDeviceObject); FDODeviceExtension->Common.IsFDO = TRUE; - FDODeviceExtension->DriverExtension = DriverExtension; + FDODeviceExtension->Common.DriverExtension = DriverExtension; /* sanity check */ ASSERT(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject); @@ -170,9 +170,105 @@ HidClass_DeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED - ASSERT(FALSE); - return STATUS_NOT_IMPLEMENTED; + PIO_STACK_LOCATION IoStack; + PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; + PHID_COLLECTION_INFORMATION CollectionInformation; + PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension; + + // + // get device extension + // + CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + ASSERT(CommonDeviceExtension->IsFDO == FALSE); + PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)CommonDeviceExtension; + + // + // get stack location + // + IoStack = IoGetCurrentIrpStackLocation(Irp); + + switch(IoStack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_HID_GET_COLLECTION_INFORMATION: + { + // + // check if output buffer is big enough + // + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_COLLECTION_INFORMATION)) + { + // + // invalid buffer size + // + Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INVALID_BUFFER_SIZE; + } + + // + // get output buffer + // + CollectionInformation = (PHID_COLLECTION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + ASSERT(CollectionInformation); + + // + // init result buffer + // + CollectionInformation->DescriptorSize = PDODeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedDataLength; //FIXME which collection is to be retrieved for composite devices / multi collection devices? + CollectionInformation->Polled = CommonDeviceExtension->DriverExtension->DevicesArePolled; + CollectionInformation->VendorID = PDODeviceExtension->Attributes.VendorID; + CollectionInformation->ProductID = PDODeviceExtension->Attributes.ProductID; + CollectionInformation->VersionNumber = PDODeviceExtension->Attributes.VersionNumber; + + // + // complete request + // + Irp->IoStatus.Information = sizeof(HID_COLLECTION_INFORMATION); + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + case IOCTL_HID_GET_COLLECTION_DESCRIPTOR: + { + // + // FIXME: which collection to use for composite / multi collection devices... + // + + // + // check if output buffer is big enough + // + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < PDODeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedDataLength) + { + // + // invalid buffer size + // + Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_INVALID_BUFFER_SIZE; + } + + // + // copy result + // + ASSERT(Irp->UserBuffer); + RtlCopyMemory(Irp->UserBuffer, PDODeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedData, PDODeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedDataLength); + + // + // complete request + // + Irp->IoStatus.Information = PDODeviceExtension->DeviceDescription.CollectionDesc[0].PreparsedDataLength; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + default: + { + DPRINT1("[HIDCLASS] DeviceControl IoControlCode 0x%x not implemented\n", IoStack->Parameters.DeviceIoControl.IoControlCode); + ASSERT(FALSE); + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_NOT_IMPLEMENTED; + } + } } NTSTATUS @@ -212,14 +308,22 @@ HidClass_PnP( CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; // - // FIXME: support PDO + // check type of device object // - ASSERT(CommonDeviceExtension->IsFDO == TRUE); - - // - // handle request - // - return HidClassFDO_PnP(DeviceObject, Irp); + if (CommonDeviceExtension->IsFDO) + { + // + // handle request + // + return HidClassFDO_PnP(DeviceObject, Irp); + } + else + { + // + // handle request + // + return HidClassPDO_PnP(DeviceObject, Irp); + } } NTSTATUS diff --git a/drivers/hid/hidclass/pdo.c b/drivers/hid/hidclass/pdo.c new file mode 100644 index 00000000000..c60d338e9ad --- /dev/null +++ b/drivers/hid/hidclass/pdo.c @@ -0,0 +1,566 @@ +/* + * 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 +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 + // + 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; + + // + // 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; + } + + // + // store hardware ids + // + Offset = swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Rev_%04x", PDODeviceExtension->Attributes.VendorID, PDODeviceExtension->Attributes.ProductID, PDODeviceExtension->Attributes.VersionNumber) + 1; + Offset += swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x", PDODeviceExtension->Attributes.VendorID, PDODeviceExtension->Attributes.ProductID) + 1; + + if (PDODeviceExtension->DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].UsagePage == HID_USAGE_PAGE_GENERIC) + { + switch(PDODeviceExtension->DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].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 (PDODeviceExtension->DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].UsagePage == HID_USAGE_PAGE_CONSUMER && PDODeviceExtension->DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].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 + // + 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); + // + //TODO implement instance id + // example: + // HID\VID_045E&PID_0047\8&1A0700BC&0&0000 + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +HidClassPDO_HandleQueryCompatibleId( + 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; + } + + // + // FIXME: implement me + // + return STATUS_NOT_IMPLEMENTED; +} + + +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: + { + DPRINT1("[HIDCLASS] PDO PnP not implemented %x\n", IoStack->MinorFunction); + ASSERT(FALSE); + + // + // do nothing + // + Status = Irp->IoStatus.Status; + break; + } + case IRP_MN_REMOVE_DEVICE: + { + DPRINT1("[HIDCLASS] PDO IRP_MN_REMOVE_DEVICE not implemented\n"); + ASSERT(FALSE); + + // + // do nothing + // + Status = 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) +{ + PHIDCLASS_FDO_EXTENSION FDODeviceExtension; + NTSTATUS Status; + PDEVICE_OBJECT PDODeviceObject; + PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension; + + // + // get device extension + // + FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension; + ASSERT(FDODeviceExtension->Common.IsFDO); + + // + // 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 device %x\n", Status); + return Status; + } + + // + // 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 = NULL; + PDODeviceExtension->Common.IsFDO = FALSE; + PDODeviceExtension->Common.DriverExtension = FDODeviceExtension->Common.DriverExtension; + RtlCopyMemory(&PDODeviceExtension->Attributes, &FDODeviceExtension->Attributes, sizeof(HID_DEVICE_ATTRIBUTES)); + RtlCopyMemory(&PDODeviceExtension->DeviceDescription, &FDODeviceExtension->DeviceDescription, sizeof(HIDP_DEVICE_DESC)); + RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES)); + + // + // FIXME: support composite devices + // + PDODeviceExtension->CollectionIndex = 0; + ASSERT(PDODeviceExtension->DeviceDescription.CollectionDescLength == 1); + + // + // store in device relations struct + // + FDODeviceExtension->DeviceRelations.Count = 1; + FDODeviceExtension->DeviceRelations.Objects[0] = PDODeviceObject; + + // + // set device flags + // + PDODeviceObject->Flags |= DO_MAP_IO_BUFFER; + + // + // device is initialized + // + PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + ObReferenceObject(PDODeviceObject); + + // + // done + // + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/drivers/hid/hidclass/precomp.h b/drivers/hid/hidclass/precomp.h index f099a4e0917..22c77fd529e 100644 --- a/drivers/hid/hidclass/precomp.h +++ b/drivers/hid/hidclass/precomp.h @@ -4,9 +4,13 @@ #include #include #include +#include +#include +#include #include + typedef struct { PDRIVER_OBJECT DriverObject; @@ -21,11 +25,22 @@ typedef struct typedef struct { + // + // hid device extension + // HID_DEVICE_EXTENSION HidDeviceExtension; + + // + // if it is a pdo + // BOOLEAN IsFDO; -}HIDCLASS_COMMON_DEVICE_EXTENSION, *PHIDCLASS_COMMON_DEVICE_EXTENSION; + // + // driver extension + // + PHIDCLASS_DRIVER_EXTENSION DriverExtension; +}HIDCLASS_COMMON_DEVICE_EXTENSION, *PHIDCLASS_COMMON_DEVICE_EXTENSION; typedef struct { @@ -34,11 +49,6 @@ typedef struct // HIDCLASS_COMMON_DEVICE_EXTENSION Common; - // - // driver extension - // - PHIDCLASS_DRIVER_EXTENSION DriverExtension; - // // device capabilities // @@ -64,8 +74,42 @@ typedef struct // HIDP_DEVICE_DESC DeviceDescription; + // + // device relations + // + DEVICE_RELATIONS DeviceRelations; + }HIDCLASS_FDO_EXTENSION, *PHIDCLASS_FDO_EXTENSION; +typedef struct +{ + // + // parts shared by fdo and pdo + // + HIDCLASS_COMMON_DEVICE_EXTENSION Common; + + // + // device descriptor + // + HID_DEVICE_ATTRIBUTES Attributes; + + // + // device capabilities + // + DEVICE_CAPABILITIES Capabilities; + + // + // device description + // + HIDP_DEVICE_DESC DeviceDescription; + + // + // collection index + // + ULONG CollectionIndex; + +}HIDCLASS_PDO_DEVICE_EXTENSION, *PHIDCLASS_PDO_DEVICE_EXTENSION; + /* fdo.c */ NTSTATUS @@ -73,3 +117,20 @@ 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); + +NTSTATUS +HidClassPDO_PnP( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + + +/* eof */ -- 2.17.1