[USB-BRINGUP]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 31 Dec 2011 03:33:14 +0000 (03:33 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 31 Dec 2011 03:33:14 +0000 (03:33 +0000)
- 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
drivers/hid/hidclass/fdo.c
drivers/hid/hidclass/hidclass.c
drivers/hid/hidclass/pdo.c [new file with mode: 0644]
drivers/hid/hidclass/precomp.h

index 45af00a..1f8691b 100644 (file)
@@ -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})
index 294ac37..80157b7 100644 (file)
@@ -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
index 9ed5e52..107368f 100644 (file)
@@ -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 (file)
index 0000000..c60d338
--- /dev/null
@@ -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
index f099a4e..22c77fd 100644 (file)
@@ -4,9 +4,13 @@
 #include <ntddk.h>
 #include <hidport.h>
 #include <hidpddi.h>
+#include <stdio.h>
+#include <initguid.h>
+#include <wdmguid.h>
 #include <debug.h>
 
 
+
 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 */