diff --git a/drivers/hid/hidclass/hidclass.c b/drivers/hid/hidclass/hidclass.c index caf6052544c..9cffb5f725e 100644 --- a/drivers/hid/hidclass/hidclass.c +++ b/drivers/hid/hidclass/hidclass.c @@ -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 diff --git a/drivers/hid/hidclass/pdo.c b/drivers/hid/hidclass/pdo.c index aa72daac63a..a3678deaaf7 100644 --- a/drivers/hid/hidclass/pdo.c +++ b/drivers/hid/hidclass/pdo.c @@ -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)); diff --git a/drivers/hid/hidclass/precomp.h b/drivers/hid/hidclass/precomp.h index 20b8e927370..401cd303a1a 100644 --- a/drivers/hid/hidclass/precomp.h +++ b/drivers/hid/hidclass/precomp.h @@ -1,6 +1,7 @@ #pragma once #define _HIDPI_NO_FUNCTION_MACROS_ +#define NDEBUG #include #include #include @@ -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__ diff --git a/drivers/hid/hidusb/hidusb.c b/drivers/hid/hidusb/hidusb.c index abaac609f6c..8addb0e5ad1 100644 --- a/drivers/hid/hidusb/hidusb.c +++ b/drivers/hid/hidusb/hidusb.c @@ -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 diff --git a/drivers/hid/hidusb/hidusb.h b/drivers/hid/hidusb/hidusb.h index 5aed01cd95e..02eb640cbac 100644 --- a/drivers/hid/hidusb/hidusb.h +++ b/drivers/hid/hidusb/hidusb.h @@ -2,6 +2,7 @@ #define _HIDPI_ #define _HIDPI_NO_FUNCTION_MACROS_ +#define NDEBUG #include #include #include diff --git a/drivers/hid/mouhid/mouhid.c b/drivers/hid/mouhid/mouhid.c index 037ed37c1dc..b61af2feb3a 100644 --- a/drivers/hid/mouhid/mouhid.c +++ b/drivers/hid/mouhid/mouhid.c @@ -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)