[USB-BRINGUP]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Sun, 1 Jan 2012 22:48:08 +0000 (22:48 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Sun, 1 Jan 2012 22:48:08 +0000 (22:48 +0000)
- Fake status success for unimplemented IRP_MN_REMOVE_DEVICE
- Fix tons of bugs in the read report completion routine
- Implement function to re-use a complete report irp
- Use correct device object when invoking the mini driver's dispatch routine in the read function
- silence a few traces
- Mouse now works with with ReactOS USB stack + ReactOS HID stack (TBD: implement hidparse.sys)

svn path=/branches/usb-bringup/; revision=54806

drivers/hid/hidclass/hidclass.c
drivers/hid/hidclass/pdo.c
drivers/hid/hidclass/precomp.h
drivers/hid/hidusb/hidusb.c
drivers/hid/hidusb/hidusb.h
drivers/hid/mouhid/mouhid.c

index caf6052..9cffb5f 100644 (file)
@@ -140,7 +140,6 @@ HidClass_Create(
          //
          // only supported for PDO
          //
-         DPRINT1("[HIDCLASS] IRP_MJ_CREATE for FDO\n");
          Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
          IoCompleteRequest(Irp, IO_NO_INCREMENT);
          return STATUS_UNSUCCESSFUL;
@@ -269,6 +268,31 @@ HidClass_Close(
     return STATUS_SUCCESS;
 }
 
+PVOID
+HidClass_GetSystemAddress(
+    IN PMDL ReportMDL)
+{
+    //
+    // sanity check
+    //
+    ASSERT(ReportMDL);
+
+    if (ReportMDL->MdlFlags & (MDL_SOURCE_IS_NONPAGED_POOL | MDL_MAPPED_TO_SYSTEM_VA))
+    {
+       //
+       // buffer is non paged pool
+       //
+       return ReportMDL->MappedSystemVa;
+    }
+    else
+    {
+       //
+       // map mdl
+       //
+       return MmMapLockedPages(ReportMDL, KernelMode);
+    }
+}
+
 NTSTATUS
 NTAPI
 HidClass_ReadCompleteIrp(
@@ -278,19 +302,23 @@ HidClass_ReadCompleteIrp(
 {
     PHIDCLASS_IRP_CONTEXT IrpContext;
     KIRQL OldLevel;
+    PUCHAR Address;
+    ULONG Offset;
+    PHIDP_DEVICE_DESC DeviceDescription;
+    ULONG CollectionIndex;
 
     //
     // get irp context
     //
     IrpContext = (PHIDCLASS_IRP_CONTEXT)Ctx;
 
-    DPRINT1("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
-    DPRINT1("HidClass_ReadCompleteIrp Status %lx\n", Irp->IoStatus.Status);
-    DPRINT1("HidClass_ReadCompleteIrp Length %lu\n", Irp->IoStatus.Information);
-    DPRINT1("HidClass_ReadCompleteIrp Irp %p\n", Irp);
-    DPRINT1("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext->InputReportBuffer);
-    DPRINT1("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext->InputReportBufferLength);
-    DPRINT1("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext->OriginalIrp);
+    DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
+    DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp->IoStatus.Status);
+    DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp->IoStatus.Information);
+    DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp);
+    DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext->InputReportBuffer);
+    DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext->InputReportBufferLength);
+    DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext->OriginalIrp);
 
     //
     // copy result
@@ -298,9 +326,28 @@ HidClass_ReadCompleteIrp(
     if (Irp->IoStatus.Information)
     {
         //
-        // copy result
+        // get address
         //
-        RtlCopyMemory(IrpContext->OriginalIrp->UserBuffer, IrpContext->InputReportBuffer, IrpContext->InputReportBufferLength);
+        Address = HidClass_GetSystemAddress(IrpContext->OriginalIrp->MdlAddress);
+        if (Address)
+        {
+            //
+            // reports may have a report id prepended
+            //
+            CollectionIndex = IrpContext->FileOp->DeviceExtension->CollectionIndex;
+            DeviceDescription = &IrpContext->FileOp->DeviceExtension->Common.DeviceDescription;
+
+            //
+            // calculate offset
+            //
+            ASSERT(DeviceDescription->CollectionDesc[CollectionIndex].InputLength >= DeviceDescription->ReportIDs[CollectionIndex].InputLength);
+            Offset = DeviceDescription->CollectionDesc[CollectionIndex].InputLength - DeviceDescription->ReportIDs[CollectionIndex].InputLength;
+
+            //
+            // copy result
+            //
+            RtlCopyMemory(&Address[Offset], IrpContext->InputReportBuffer, IrpContext->InputReportBufferLength);
+        }
     }
 
     //
@@ -314,11 +361,6 @@ HidClass_ReadCompleteIrp(
     //
     ExFreePool(IrpContext->InputReportBuffer);
 
-    //
-    // complete original request
-    //
-    IoCompleteRequest(IrpContext->OriginalIrp, IO_NO_INCREMENT);
-
     //
     // remove us from pending list
     //
@@ -329,11 +371,21 @@ HidClass_ReadCompleteIrp(
     //
     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
 
+    //
+    // insert into completed list
+    //
+    InsertTailList(&IrpContext->FileOp->IrpCompletedListHead, &Irp->Tail.Overlay.ListEntry);
+
     //
     // release lock
     //
     KeReleaseSpinLock(&IrpContext->FileOp->Lock, OldLevel);
 
+    //
+    // complete original request
+    //
+    IoCompleteRequest(IrpContext->OriginalIrp, IO_NO_INCREMENT);
+
     //
     // free irp context
     //
@@ -342,7 +394,47 @@ HidClass_ReadCompleteIrp(
     //
     // done
     //
-    return STATUS_SUCCESS;
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+PIRP
+HidClass_GetIrp(
+    IN PHIDCLASS_FILEOP_CONTEXT Context)
+{
+   KIRQL OldLevel;
+   PIRP Irp = NULL;
+   PLIST_ENTRY ListEntry;
+
+    //
+    // acquire lock
+    //
+    KeAcquireSpinLock(&Context->Lock, &OldLevel);
+
+    //
+    // is list empty?
+    //
+    if (!IsListEmpty(&Context->IrpCompletedListHead))
+    {
+        //
+        // grab first entry
+        //
+        ListEntry = RemoveHeadList(&Context->IrpCompletedListHead);
+
+        //
+        // get irp
+        //
+        Irp = (PIRP)CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry);
+    }
+
+    //
+    // release lock
+    //
+    KeReleaseSpinLock(&Context->Lock, OldLevel);
+
+    //
+    // done
+    //
+    return Irp;
 }
 
 NTSTATUS
@@ -358,17 +450,32 @@ HidClass_BuildIrp(
     PIRP Irp;
     PIO_STACK_LOCATION IoStack;
     PHIDCLASS_IRP_CONTEXT IrpContext;
+    PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
 
     //
-    // build new irp
+    // get an irp from fresh list
     //
-    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+    Irp = HidClass_GetIrp(Context);
     if (!Irp)
     {
         //
-        // no memory
+        // build new irp
         //
-        return STATUS_INSUFFICIENT_RESOURCES;
+        Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+        if (!Irp)
+        {
+            //
+            // no memory
+            //
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+    }
+    else
+    {
+        //
+        // re-use irp
+        //
+        IoReuseIrp(Irp, STATUS_SUCCESS);
     }
 
     //
@@ -384,18 +491,32 @@ HidClass_BuildIrp(
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
+    //
+    // get device extension
+    //
+    PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
+
+    //
+    // sanity checks
+    //
+    ASSERT(PDODeviceExtension->CollectionIndex < PDODeviceExtension->Common.DeviceDescription.CollectionDescLength);
+    ASSERT(PDODeviceExtension->CollectionIndex < PDODeviceExtension->Common.DeviceDescription.ReportIDsLength);
+    ASSERT(PDODeviceExtension->Common.DeviceDescription.ReportIDs[PDODeviceExtension->CollectionIndex].InputLength > 0);
+    ASSERT(PDODeviceExtension->Common.DeviceDescription.CollectionDesc[PDODeviceExtension->CollectionIndex].InputLength == BufferLength);
+
     //
     // init irp context
     //
     RtlZeroMemory(IrpContext, sizeof(HIDCLASS_IRP_CONTEXT));
-    IrpContext->InputReportBufferLength = BufferLength;
+    IrpContext->InputReportBufferLength = PDODeviceExtension->Common.DeviceDescription.ReportIDs[PDODeviceExtension->CollectionIndex].InputLength;
     IrpContext->OriginalIrp = RequestIrp;
     IrpContext->FileOp = Context;
 
     //
     // allocate buffer
     //
-    IrpContext->InputReportBuffer = ExAllocatePool(NonPagedPool, BufferLength);
+    IrpContext->InputReportBuffer = ExAllocatePool(NonPagedPool, IrpContext->InputReportBufferLength);
     if (!IrpContext->InputReportBuffer)
     {
         //
@@ -428,8 +549,6 @@ HidClass_BuildIrp(
     *OutIrp = Irp;
     *OutIrpContext = IrpContext;
 
-    DPRINT1("IRP %p Buffer %p\n", Irp, Irp->UserBuffer);
-
     //
     // done
     //
@@ -449,12 +568,19 @@ HidClass_Read(
     NTSTATUS Status;
     PIRP NewIrp;
     PHIDCLASS_IRP_CONTEXT NewIrpContext;
+    PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension;
 
     //
     // get current stack location
     //
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
+    //
+    // get device extension
+    //
+    CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    ASSERT(CommonDeviceExtension->IsFDO == FALSE);
+
     //
     // sanity check
     //
@@ -472,12 +598,10 @@ HidClass_Read(
     //
     ASSERT(Context->DeviceExtension->Common.DriverExtension->DevicesArePolled == FALSE);
 
-    DPRINT1("[HIDCLASS] IRP_MJ_READ\n");
-
     //
     // build irp request
     //
-    Status = HidClass_BuildIrp(DeviceObject, Irp, Context, IOCTL_HID_READ_REPORT, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &NewIrp, &NewIrpContext);
+    Status = HidClass_BuildIrp(DeviceObject, Irp, Context, IOCTL_HID_READ_REPORT, IoStack->Parameters.Read.Length, &NewIrp, &NewIrpContext);
     if (!NT_SUCCESS(Status))
     {
         //
@@ -523,12 +647,12 @@ HidClass_Read(
     // lets dispatch the request
     //
     ASSERT(Context->DeviceExtension);
-    Status = Context->DeviceExtension->Common.DriverExtension->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL](DeviceObject, NewIrp);
+    Status = Context->DeviceExtension->Common.DriverExtension->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL](Context->DeviceExtension->FDODeviceObject, NewIrp);
 
     //
     // complete
     //
-    return Status;
+    return STATUS_PENDING;
 }
 
 NTSTATUS
@@ -655,6 +779,8 @@ HidClass_InternalDeviceControl(
 {
     UNIMPLEMENTED
     ASSERT(FALSE);
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
     return STATUS_NOT_IMPLEMENTED;
 }
 
@@ -728,7 +854,7 @@ HidClass_DispatchDefault(
     //
     // dispatch to lower device object
     //
-       return IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, Irp);
+    return IoCallDriver(CommonDeviceExtension->HidDeviceExtension.NextDeviceObject, Irp);
 }
 
 
@@ -744,7 +870,7 @@ HidClassDispatch(
     // get current stack location
     //
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    DPRINT1("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack->MajorFunction, IoStack->MinorFunction);
+    DPRINT("[HIDCLASS] Dispatch Major %x Minor %x\n", IoStack->MajorFunction, IoStack->MinorFunction);
 
     //
     // dispatch request based on major function
index aa72daa..a3678de 100644 (file)
@@ -453,7 +453,7 @@ HidClassPDO_PnP(
             //
             // do nothing
             //
-            Status = Irp->IoStatus.Status;
+            Status = STATUS_SUCCESS; //Irp->IoStatus.Status;
             break;
         }
         case IRP_MN_QUERY_INTERFACE:
@@ -544,6 +544,7 @@ HidClassPDO_CreatePDO(
     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;
     RtlCopyMemory(&PDODeviceExtension->Common.Attributes, &FDODeviceExtension->Common.Attributes, sizeof(HID_DEVICE_ATTRIBUTES));
     RtlCopyMemory(&PDODeviceExtension->Common.DeviceDescription, &FDODeviceExtension->Common.DeviceDescription, sizeof(HIDP_DEVICE_DESC));
index 20b8e92..401cd30 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once
 
 #define _HIDPI_NO_FUNCTION_MACROS_
+#define NDEBUG
 #include <ntddk.h>
 #include <initguid.h>
 #include <hidport.h>
@@ -48,7 +49,6 @@ typedef struct
     //
     HID_DEVICE_ATTRIBUTES Attributes;
 
-
 }HIDCLASS_COMMON_DEVICE_EXTENSION, *PHIDCLASS_COMMON_DEVICE_EXTENSION;
 
 typedef struct
@@ -101,6 +101,12 @@ typedef struct
     // device interface 
     //
     UNICODE_STRING DeviceInterface;
+
+    //
+    // FDO device object
+    //
+    PDEVICE_OBJECT FDODeviceObject;
+
 }HIDCLASS_PDO_DEVICE_EXTENSION, *PHIDCLASS_PDO_DEVICE_EXTENSION;
 
 typedef struct __HIDCLASS_FILEOP_CONTEXT__
index abaac60..8addb0e 100644 (file)
@@ -340,7 +340,7 @@ HidUsb_ResetWorkerRoutine(
     // get port status
     //
     Status = HidUsb_GetPortStatus(ResetContext->DeviceObject, &PortStatus);
-    DPRINT1("[HIDUSB] ResetWorkerRoutine GetPortStatus %x\n", Status);
+    DPRINT1("[HIDUSB] ResetWorkerRoutine GetPortStatus %x PortStatus %x\n", Status, PortStatus);
     if (NT_SUCCESS(Status))
     {
         if (!(PortStatus & USB_PORT_STATUS_ENABLE))
@@ -393,7 +393,6 @@ HidUsb_ResetWorkerRoutine(
     //
     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
     IoFreeWorkItem(ResetContext->WorkItem);
-    ResetContext->Irp->IoStatus.Status = STATUS_SUCCESS;
     IoCompleteRequest(ResetContext->Irp, IO_NO_INCREMENT);
     ExFreePool(ResetContext);
 }
@@ -409,7 +408,6 @@ HidUsb_ReadReportCompletion(
     PHID_USB_DEVICE_EXTENSION HidDeviceExtension;
     PHID_DEVICE_EXTENSION DeviceExtension;
     PURB Urb;
-    PUCHAR Buffer;
     PHID_USB_RESET_CONTEXT ResetContext;
 
     //
@@ -418,6 +416,16 @@ HidUsb_ReadReportCompletion(
     Urb = (PURB)Context;
     ASSERT(Urb);
 
+    DPRINT("[HIDUSB] HidUsb_ReadReportCompletion %p Status %x Urb Status %x\n", Irp, Irp->IoStatus, Urb->UrbHeader.Status);
+
+    if (Irp->PendingReturned)
+    {
+        //
+        // mark irp pending
+        //
+        IoMarkIrpPending(Irp);
+    }
+
     //
     // did the reading report succeed / cancelled
     //
@@ -433,11 +441,6 @@ HidUsb_ReadReportCompletion(
         //
         ASSERT(Urb->UrbHeader.Status == USBD_STATUS_SUCCESS);
 
-
-        Buffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer;
-        ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBufferLength == 4);
-        DPRINT("[HIDUSB] ReadCompletion Information %lu Buffer %x %x %x %x\n", Buffer[0] & 0xFF, Buffer[1] & 0xFF, Buffer[2] & 0xFF, Buffer[3] & 0xFF);
-
         //
         // free the urb
         //
@@ -446,7 +449,7 @@ HidUsb_ReadReportCompletion(
         //
         // finish completion
         //
-        return STATUS_SUCCESS;
+        return STATUS_CONTINUE_COMPLETION;
     }
 
     //
@@ -502,7 +505,7 @@ HidUsb_ReadReportCompletion(
     //
     // complete request
     //
-    return STATUS_SUCCESS;
+    return STATUS_CONTINUE_COMPLETION;
 }
 
 
@@ -559,6 +562,13 @@ HidUsb_ReadReport(
     //
     RtlZeroMemory(Urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
 
+    //
+    // sanity check
+    //
+    ASSERT(Irp->UserBuffer);
+    ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+    ASSERT(PipeInformation->PipeHandle);
+
     //
     // build the urb
     //
@@ -571,6 +581,11 @@ HidUsb_ReadReport(
                                            USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
                                            NULL);
 
+    //
+    // store configuration handle
+    //
+    Urb->UrbHeader.UsbdDeviceHandle = HidDeviceExtension->ConfigurationHandle;
+
     //
     // get next location to setup irp
     //
@@ -580,8 +595,12 @@ HidUsb_ReadReport(
     // init irp for lower driver
     //
     IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
-    IoStack->Parameters.Others.Argument1 = (PVOID)Urb;
     IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+    IoStack->Parameters.DeviceIoControl.InputBufferLength = 0;
+    IoStack->Parameters.DeviceIoControl.OutputBufferLength = 0;
+    IoStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
+    IoStack->Parameters.Others.Argument1 = (PVOID)Urb;
+
 
     //
     // set completion routine
@@ -762,7 +781,7 @@ HidInternalDeviceControl(
         }
         case IOCTL_HID_READ_REPORT:
         {
-            DPRINT1("[HIDUSB] IOCTL_HID_READ_REPORT\n");
+            DPRINT("[HIDUSB] IOCTL_HID_READ_REPORT\n");
             Status = HidUsb_ReadReport(DeviceObject, Irp);
             return Status;
         }
@@ -950,6 +969,11 @@ Hid_DispatchUrb(
     //
     IoStack->Parameters.Others.Argument1 = (PVOID)Urb;
 
+    //
+    // set completion routine
+    //
+    IoSetCompletionRoutine(Irp, Hid_PnpCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
+
     //
     // call driver
     //
@@ -1329,6 +1353,7 @@ Hid_PnpStart(
         // select configuration
         //
         Status = Hid_SelectConfiguration(DeviceObject);
+        ASSERT(Status == STATUS_SUCCESS);
 
         //
         // done
index 5aed01c..02eb640 100644 (file)
@@ -2,6 +2,7 @@
 
 #define _HIDPI_
 #define _HIDPI_NO_FUNCTION_MACROS_
+#define NDEBUG
 #include <ntddk.h>
 #include <hidport.h>
 #include <debug.h>
index 037ed37..b61af2f 100644 (file)
@@ -637,7 +637,7 @@ MouHid_StartDevice(
 
     /* lets get the caps */
     Status = HidP_GetCaps(PreparsedData, &Capabilities);
-    if (!NT_SUCCESS(Status))
+    if (Status != HIDP_STATUS_SUCCESS)
     {
         /* failed to get capabilities */
         DPRINT1("[MOUHID] failed to obtain caps with %x\n", Status);
@@ -645,7 +645,7 @@ MouHid_StartDevice(
         return Status;
     }
 
-    DPRINT1("[MOUHID] Usage %x UsagePage %x\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
+    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)