Sync with trunk r63270.
[reactos.git] / drivers / hid / hidclass / pdo.c
index 6b8037b..876712e 100644 (file)
@@ -7,8 +7,14 @@
  *              Michael Martin (michael.martin@reactos.org)
  *              Johannes Anderwald (johannes.anderwald@reactos.org)
  */
+
 #include "precomp.h"
 
+#include <wdmguid.h>
+
+#define NDEBUG
+#include <debug.h>
+
 PHIDP_COLLECTION_DESC
 HidClassPDO_GetCollectionDescription(
     PHIDP_DEVICE_DESC DeviceDescription,
@@ -42,7 +48,7 @@ HidClassPDO_GetReportDescription(
 {
     ULONG Index;
 
-    for(Index = 0; Index < DeviceDescription->ReportIDsLength; Index++)
+    for (Index = 0; Index < DeviceDescription->ReportIDsLength; Index++)
     {
         if (DeviceDescription->ReportIDs[Index].CollectionNumber == CollectionNumber)
         {
@@ -97,7 +103,7 @@ HidClassPDO_HandleQueryDeviceId(
     //
     // allocate new buffer
     //
-    NewBuffer = (LPWSTR)ExAllocatePool(NonPagedPool, (Length + 1) * sizeof(WCHAR));
+    NewBuffer = ExAllocatePoolWithTag(NonPagedPool, (Length + 1) * sizeof(WCHAR), HIDCLASS_TAG);
     if (!NewBuffer)
     {
         //
@@ -126,11 +132,12 @@ HidClassPDO_HandleQueryDeviceId(
     //
     // free old buffer
     //
-    ExFreePool(Buffer);
+    ExFreePoolWithTag(Buffer, 0);
 
     //
     // store result
     //
+    DPRINT("NewBuffer %S\n", NewBuffer);
     Irp->IoStatus.Information = (ULONG_PTR)NewBuffer;
     return STATUS_SUCCESS;
 }
@@ -142,7 +149,7 @@ HidClassPDO_HandleQueryHardwareId(
 {
     NTSTATUS Status;
     PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
-    WCHAR Buffer[100];
+    WCHAR Buffer[200];
     ULONG Offset = 0;
     LPWSTR Ptr;
     PHIDP_COLLECTION_DESC CollectionDescription;
@@ -150,8 +157,8 @@ HidClassPDO_HandleQueryHardwareId(
     //
     // get device extension
     //
-   PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-   ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+    PDODeviceExtension = DeviceObject->DeviceExtension;
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
 
     //
     // copy current stack location
@@ -195,7 +202,7 @@ HidClassPDO_HandleQueryHardwareId(
 
     if (CollectionDescription->UsagePage == HID_USAGE_PAGE_GENERIC)
     {
-        switch(CollectionDescription->Usage)
+        switch (CollectionDescription->Usage)
         {
             case HID_USAGE_GENERIC_POINTER:
             case HID_USAGE_GENERIC_MOUSE:
@@ -235,8 +242,9 @@ HidClassPDO_HandleQueryHardwareId(
     }
 
     //
-    // FIXME: add 'HID_DEVICE_UP:0001_U:0002'
+    // add HID_DEVICE_UP:0001_U:0002'
     //
+    Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_UP:%04x_U:%04x", CollectionDescription->UsagePage, CollectionDescription->Usage) + 1;
 
     //
     // add HID
@@ -246,12 +254,12 @@ HidClassPDO_HandleQueryHardwareId(
     //
     // free old buffer
     //
-    ExFreePool((PVOID)Irp->IoStatus.Information);
+    ExFreePoolWithTag((PVOID)Irp->IoStatus.Information, 0);
 
     //
     // allocate buffer
     //
-    Ptr = (LPWSTR)ExAllocatePool(NonPagedPool, (Offset +1)* sizeof(WCHAR));
+    Ptr = ExAllocatePoolWithTag(NonPagedPool, (Offset + 1) * sizeof(WCHAR), HIDCLASS_TAG);
     if (!Ptr)
     {
         //
@@ -279,30 +287,37 @@ HidClassPDO_HandleQueryInstanceId(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp)
 {
-    NTSTATUS Status;
+    LPWSTR Buffer;
+    PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
 
     //
-    // copy current stack location
+    // get device extension
     //
-    IoCopyCurrentIrpStackLocationToNext(Irp);
+    PDODeviceExtension = DeviceObject->DeviceExtension;
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
 
     //
-    // call mini-driver
+    // allocate buffer
     //
-    Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
-    if (!NT_SUCCESS(Status))
+    Buffer = ExAllocatePoolWithTag(NonPagedPool, 5 * sizeof(WCHAR), HIDCLASS_TAG);
+    if (!Buffer)
     {
         //
         // failed
         //
-        return Status;
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
-    DPRINT1("HidClassPDO_HandleQueryInstanceId Buffer %S\n", Irp->IoStatus.Information);
+
+    //
+    // write device id
+    //
+    swprintf(Buffer, L"%04x", PDODeviceExtension->CollectionNumber);
+    Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+
+    //
+    // done
     //
-    //TODO implement instance id
-    // example:
-    // HID\VID_045E&PID_0047\8&1A0700BC&0&0000
-    return STATUS_NOT_IMPLEMENTED;
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
@@ -310,31 +325,29 @@ HidClassPDO_HandleQueryCompatibleId(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp)
 {
-    NTSTATUS Status;
-
-    //
-    // copy current stack location
-    //
-    IoCopyCurrentIrpStackLocationToNext(Irp);
+    LPWSTR Buffer;
 
-    //
-    // call mini-driver
-    //
-    Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
-    if (!NT_SUCCESS(Status))
+    Buffer = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), HIDCLASS_TAG);
+    if (!Buffer)
     {
         //
-        // failed
+        // no memory
         //
-        return Status;
+        return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     //
-    // FIXME: implement me
+    // zero buffer
     //
-    return STATUS_NOT_IMPLEMENTED;
-}
+    Buffer[0] = 0;
+    Buffer[1] = 0;
 
+    //
+    // store result
+    //
+    Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+    return STATUS_SUCCESS;
+}
 
 NTSTATUS
 HidClassPDO_PnP(
@@ -346,11 +359,12 @@ HidClassPDO_PnP(
     NTSTATUS Status;
     PPNP_BUS_INFORMATION BusInformation;
     PDEVICE_RELATIONS DeviceRelation;
+    ULONG Index, bFound;
 
     //
     // get device extension
     //
-    PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    PDODeviceExtension = DeviceObject->DeviceExtension;
     ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
 
     //
@@ -361,47 +375,47 @@ HidClassPDO_PnP(
     //
     // handle request
     //
-    switch(IoStack->MinorFunction)
+    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;
+            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:
         {
@@ -411,12 +425,15 @@ HidClassPDO_PnP(
                 // invalid request
                 //
                 Status = STATUS_DEVICE_CONFIGURATION_ERROR;
+                break;
             }
 
             //
             // copy capabilities
             //
-            RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &PDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
+            RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities,
+                          &PDODeviceExtension->Capabilities,
+                          sizeof(DEVICE_CAPABILITIES));
             Status = STATUS_SUCCESS;
             break;
         }
@@ -425,8 +442,8 @@ HidClassPDO_PnP(
             //
             //
             //
-            BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(NonPagedPool, sizeof(PNP_BUS_INFORMATION));
+            BusInformation = ExAllocatePoolWithTag(NonPagedPool, sizeof(PNP_BUS_INFORMATION), HIDCLASS_TAG);
+
             //
             // fill in result
             //
@@ -466,7 +483,7 @@ HidClassPDO_PnP(
             //
             // allocate device relations
             //
-            DeviceRelation = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS));
+            DeviceRelation = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_RELATIONS), HIDCLASS_TAG);
             if (!DeviceRelation)
             {
                 //
@@ -500,36 +517,64 @@ HidClassPDO_PnP(
             //
             // now register the device interface
             //
-            Status = IoRegisterDeviceInterface(PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject, &GUID_DEVINTERFACE_HID, NULL, &PDODeviceExtension->DeviceInterface);
+            Status = IoRegisterDeviceInterface(PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject,
+                                               &GUID_DEVINTERFACE_HID,
+                                               NULL,
+                                               &PDODeviceExtension->DeviceInterface);
+            DPRINT("[HIDCLASS] IoRegisterDeviceInterfaceState Status %x\n", Status);
             if (NT_SUCCESS(Status))
             {
                 //
                 // enable device interface
                 //
                 Status = IoSetDeviceInterfaceState(&PDODeviceExtension->DeviceInterface, TRUE);
+                DPRINT("[HIDCLASS] IoSetDeviceInterFaceState %x\n", Status);
             }
-            ASSERT(Status == STATUS_SUCCESS);
 
             //
-            // break
+            // done
             //
+            Status = STATUS_SUCCESS;
             break;
         }
         case IRP_MN_REMOVE_DEVICE:
         {
-            DPRINT1("[HIDCLASS] PDO IRP_MN_REMOVE_DEVICE not implemented\n");
-            ASSERT(FALSE);
+            /* Disable the device interface */
+            if (PDODeviceExtension->DeviceInterface.Length != 0)
+                IoSetDeviceInterfaceState(&PDODeviceExtension->DeviceInterface, FALSE);
 
             //
-            // do nothing
+            // remove us from the fdo's pdo list
             //
-            Status = STATUS_SUCCESS; //Irp->IoStatus.Status;
-            break;
+            bFound = FALSE;
+            for (Index = 0; Index < PDODeviceExtension->FDODeviceExtension->DeviceRelations->Count; Index++)
+            {
+                if (PDODeviceExtension->FDODeviceExtension->DeviceRelations->Objects[Index] == DeviceObject)
+                {
+                    //
+                    // remove us
+                    //
+                    bFound = TRUE;
+                    PDODeviceExtension->FDODeviceExtension->DeviceRelations->Objects[Index] = NULL;
+                    break;
+                }
+            }
+
+            /* Complete the IRP */
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+            if (bFound)
+            {
+                /* Delete our device object*/
+                IoDeleteDevice(DeviceObject);
+            }
+
+            return STATUS_SUCCESS;
         }
         case IRP_MN_QUERY_INTERFACE:
         {
             DPRINT1("[HIDCLASS] PDO IRP_MN_QUERY_INTERFACE not implemented\n");
-            ASSERT(FALSE);
 
             //
             // do nothing
@@ -537,6 +582,22 @@ HidClassPDO_PnP(
             Status = Irp->IoStatus.Status;
             break;
         }
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+        case IRP_MN_CANCEL_STOP_DEVICE:
+        case IRP_MN_QUERY_STOP_DEVICE:
+        case IRP_MN_CANCEL_REMOVE_DEVICE:
+        {
+            //
+            // no/op
+            //
+#if 0
+            Status = STATUS_SUCCESS;
+#else
+            DPRINT1("Denying removal of HID device due to IRP cancellation bugs\n");
+            Status = STATUS_UNSUCCESSFUL;
+#endif
+            break;
+        }
         default:
         {
             //
@@ -585,14 +646,14 @@ HidClassPDO_CreatePDO(
     //
     // get device extension
     //
-    FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
+    FDODeviceExtension = 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);
+    DeviceRelations = ExAllocatePoolWithTag(NonPagedPool, Length, HIDCLASS_TAG);
     if (!DeviceRelations)
     {
         //
@@ -607,15 +668,21 @@ HidClassPDO_CreatePDO(
     RtlZeroMemory(DeviceRelations, Length);
 
     //
-    // lets create a PDO for top level collection
+    // let's create a PDO for top level collection
     //
     Index = 0;
     do
     {
         //
-        // lets create the device object
+        // let's 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);
+        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))
         {
             //
@@ -633,7 +700,7 @@ HidClassPDO_CreatePDO(
         //
         // get device extension
         //
-        PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
+        PDODeviceExtension = PDODeviceObject->DeviceExtension;
 
         //
         // init device extension
@@ -642,6 +709,7 @@ HidClassPDO_CreatePDO(
         PDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject;
         PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject;
         PDODeviceExtension->Common.IsFDO = FALSE;
+        PDODeviceExtension->FDODeviceExtension = FDODeviceExtension;
         PDODeviceExtension->FDODeviceObject = DeviceObject;
         PDODeviceExtension->Common.DriverExtension = FDODeviceExtension->Common.DriverExtension;
         PDODeviceExtension->CollectionNumber = FDODeviceExtension->Common.DeviceDescription.CollectionDesc[Index].CollectionNumber;
@@ -671,10 +739,10 @@ HidClassPDO_CreatePDO(
 
         //
         // move to next
-        // 
+        //
         Index++;
 
-    }while(Index < FDODeviceExtension->Common.DeviceDescription.CollectionDescLength);
+    } while(Index < FDODeviceExtension->Common.DeviceDescription.CollectionDescLength);
 
 
     //
@@ -685,7 +753,7 @@ HidClassPDO_CreatePDO(
         //
         // failed
         //
-        for(Index = 0; Index < DeviceRelations->Count; Index++)
+        for (Index = 0; Index < DeviceRelations->Count; Index++)
         {
             //
             // delete device
@@ -696,7 +764,7 @@ HidClassPDO_CreatePDO(
         //
         // free device relations
         //
-        ExFreePool(DeviceRelations);
+        ExFreePoolWithTag(DeviceRelations, HIDCLASS_TAG);
         return Status;
     }
 
@@ -709,4 +777,4 @@ HidClassPDO_CreatePDO(
     // done
     //
     return STATUS_SUCCESS;
-}
\ No newline at end of file
+}