IN PIRP Irp)
{
KEVENT Event;
- PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
+ PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension;
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
//
// get device extension
//
- FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
- ASSERT(FDODeviceExtension->Common.IsFDO);
+ CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
//
// set completion routine
// 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
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
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);
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
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
--- /dev/null
+/*
+ * 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