From 177a18b44b34cea8b082e77174524be1e1225815 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Tue, 21 Feb 2012 01:16:56 +0000 Subject: [PATCH] [HIDCLASS] - Call mini driver for pnp events - Wait for all pending irps to complete [HIDUSB] - Fix bug when removing device object found by Cameron Gutman [USBOHCI] - Remove assert - Delete configuration descriptors when device is deleted svn path=/trunk/; revision=55772 --- reactos/drivers/hid/hidclass/fdo.c | 62 ++++----- reactos/drivers/hid/hidclass/hidclass.c | 124 ++++++++++++++++-- reactos/drivers/hid/hidclass/precomp.h | 10 ++ reactos/drivers/hid/hidusb/hidusb.c | 6 +- reactos/drivers/hid/hidusb/hidusb.h | 1 + .../drivers/usb/usbohci/hub_controller.cpp | 1 - reactos/drivers/usb/usbohci/usb_device.cpp | 69 +++++++++- 7 files changed, 223 insertions(+), 50 deletions(-) diff --git a/reactos/drivers/hid/hidclass/fdo.c b/reactos/drivers/hid/hidclass/fdo.c index 27df9041161..898652692f7 100644 --- a/reactos/drivers/hid/hidclass/fdo.c +++ b/reactos/drivers/hid/hidclass/fdo.c @@ -384,17 +384,21 @@ HidClassFDO_RemoveDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - PHIDCLASS_FDO_EXTENSION FDODeviceExtension = DeviceObject->DeviceExtension; NTSTATUS Status; - /* Pass the IRP down */ - IoSkipCurrentIrpStackLocation(Irp); - Status = IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp); + /* FIXME cleanup */ - /* Now teardown our portion of the device stack */ - IoDetachDevice(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject); - IoDeleteDevice(DeviceObject); + // + // dispatch to minidriver + // + IoSkipCurrentIrpStackLocation(Irp); + Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp); + // + // complete request + // + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } @@ -533,6 +537,7 @@ HidClassFDO_PnP( { PIO_STACK_LOCATION IoStack; PHIDCLASS_FDO_EXTENSION FDODeviceExtension; + NTSTATUS Status; // // get device extension @@ -554,45 +559,34 @@ HidClassFDO_PnP( { return HidClassFDO_RemoveDevice(DeviceObject, Irp); } - case IRP_MN_QUERY_REMOVE_DEVICE: - case IRP_MN_QUERY_STOP_DEVICE: + case IRP_MN_QUERY_DEVICE_RELATIONS: { - // - // set status to succes - // - Irp->IoStatus.Status = STATUS_SUCCESS; - - // - // forward to lower device - // - IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp); + return HidClassFDO_DeviceRelations(DeviceObject, Irp); } + case IRP_MN_QUERY_REMOVE_DEVICE: + case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE: { // - // set status to succes + // set status to success and fall through // Irp->IoStatus.Status = STATUS_SUCCESS; - - // - // forward to lower device - // - IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp); - } - case IRP_MN_QUERY_DEVICE_RELATIONS: - { - return HidClassFDO_DeviceRelations(DeviceObject, Irp); - } + } default: { // - // dispatch to lower device + // dispatch to mini driver // - IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp); + IoSkipCurrentIrpStackLocation(Irp); + Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp); + + // + // complete request + // + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; } } } diff --git a/reactos/drivers/hid/hidclass/hidclass.c b/reactos/drivers/hid/hidclass/hidclass.c index deb67f496e0..6f9b7691b40 100644 --- a/reactos/drivers/hid/hidclass/hidclass.c +++ b/reactos/drivers/hid/hidclass/hidclass.c @@ -203,6 +203,7 @@ HidClass_Create( KeInitializeSpinLock(&Context->Lock); InitializeListHead(&Context->ReadPendingIrpListHead); InitializeListHead(&Context->IrpCompletedListHead); + KeInitializeEvent(&Context->IrpReadComplete, NotificationEvent, FALSE); // // store context @@ -226,7 +227,11 @@ HidClass_Close( { PIO_STACK_LOCATION IoStack; PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; - PHIDCLASS_IRP_CONTEXT IrpContext; + PHIDCLASS_FILEOP_CONTEXT IrpContext; + BOOLEAN IsRequestPending = FALSE; + KIRQL OldLevel; + PLIST_ENTRY Entry; + PIRP ListIrp; // // get device extension @@ -260,12 +265,79 @@ HidClass_Close( // // get irp context // - IrpContext = (PHIDCLASS_IRP_CONTEXT)IoStack->FileObject->FsContext; + IrpContext = (PHIDCLASS_FILEOP_CONTEXT)IoStack->FileObject->FsContext; + ASSERT(IrpContext); // - // cancel pending irps + // acquire lock // - UNIMPLEMENTED + KeAcquireSpinLock(&IrpContext->Lock, &OldLevel); + + if (!IsListEmpty(&IrpContext->ReadPendingIrpListHead)) + { + // + // FIXME cancel irp + // + IsRequestPending = TRUE; + } + + // + // signal stop + // + IrpContext->StopInProgress = TRUE; + + // + // release lock + // + KeReleaseSpinLock(&IrpContext->Lock, OldLevel); + + if (IsRequestPending) + { + // + // wait for request to complete + // + DPRINT1("[HIDCLASS] Waiting for read irp completion...\n"); + KeWaitForSingleObject(&IrpContext->IrpReadComplete, Executive, KernelMode, FALSE, NULL); + } + + // + // acquire lock + // + KeAcquireSpinLock(&IrpContext->Lock, &OldLevel); + + // + // sanity check + // + ASSERT(IsListEmpty(&IrpContext->ReadPendingIrpListHead)); + + // + // now free all irps + // + while(!IsListEmpty(&IrpContext->IrpCompletedListHead)) + { + // + // remove head irp + // + Entry = RemoveHeadList(&IrpContext->IrpCompletedListHead); + + // + // get irp + // + ListIrp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); + + // + // free the irp + // + IoFreeIrp(ListIrp); + } + + // + // release lock + // + KeReleaseSpinLock(&IrpContext->Lock, OldLevel); + + + // // remove context @@ -323,19 +395,20 @@ HidClass_ReadCompleteIrp( ULONG Offset; PHIDP_COLLECTION_DESC CollectionDescription; PHIDP_REPORT_IDS ReportDescription; + BOOLEAN IsEmpty; // // get irp context // IrpContext = (PHIDCLASS_IRP_CONTEXT)Ctx; - 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); + 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); // // copy result @@ -402,6 +475,11 @@ HidClass_ReadCompleteIrp( // RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + // + // is list empty + // + IsEmpty = IsListEmpty(&IrpContext->FileOp->ReadPendingIrpListHead); + // // insert into completed list // @@ -417,6 +495,17 @@ HidClass_ReadCompleteIrp( // IoCompleteRequest(IrpContext->OriginalIrp, IO_NO_INCREMENT); + + DPRINT1("StopInProgress %x IsEmpty %x\n", IrpContext->FileOp->StopInProgress, IsEmpty); + if (IrpContext->FileOp->StopInProgress && IsEmpty) + { + // + // last pending irp + // + DPRINT1("[HIDCLASS] LastPendingTransfer Signalling\n"); + KeSetEvent(&IrpContext->FileOp->IrpReadComplete, 0, FALSE); + } + // // free irp context // @@ -644,6 +733,19 @@ HidClass_Read( // ASSERT(Context->DeviceExtension->Common.DriverExtension->DevicesArePolled == FALSE); + if (Context->StopInProgress) + { + // + // stop in progress + // + DPRINT1("[HIDCLASS] Stop In Progress\n"); + Irp->IoStatus.Status = STATUS_CANCELLED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_CANCELLED; + + } + + // // build irp request // diff --git a/reactos/drivers/hid/hidclass/precomp.h b/reactos/drivers/hid/hidclass/precomp.h index 23820e6938a..7dca545f47d 100644 --- a/reactos/drivers/hid/hidclass/precomp.h +++ b/reactos/drivers/hid/hidclass/precomp.h @@ -136,6 +136,16 @@ typedef struct __HIDCLASS_FILEOP_CONTEXT__ // LIST_ENTRY IrpCompletedListHead; + // + // stop in progress indicator + // + BOOLEAN StopInProgress; + + // + // read complete event + // + KEVENT IrpReadComplete; + }HIDCLASS_FILEOP_CONTEXT, *PHIDCLASS_FILEOP_CONTEXT; typedef struct diff --git a/reactos/drivers/hid/hidusb/hidusb.c b/reactos/drivers/hid/hidusb/hidusb.c index 79720ac44a2..a227d0911ad 100644 --- a/reactos/drivers/hid/hidusb/hidusb.c +++ b/reactos/drivers/hid/hidusb/hidusb.c @@ -1576,10 +1576,10 @@ HidPnp( // // free resources // - if (HidDeviceExtension->HidDescriptor) + if (HidDeviceExtension->ConfigurationDescriptor) { - ExFreePool(HidDeviceExtension->HidDescriptor); - HidDeviceExtension->HidDescriptor = NULL; + ExFreePool(HidDeviceExtension->ConfigurationDescriptor); + HidDeviceExtension->ConfigurationDescriptor = NULL; } // diff --git a/reactos/drivers/hid/hidusb/hidusb.h b/reactos/drivers/hid/hidusb/hidusb.h index 816afb8ed33..ae8a1a41347 100644 --- a/reactos/drivers/hid/hidusb/hidusb.h +++ b/reactos/drivers/hid/hidusb/hidusb.h @@ -45,6 +45,7 @@ typedef struct // hid descriptor // PHID_DESCRIPTOR HidDescriptor; + }HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION; typedef struct diff --git a/reactos/drivers/usb/usbohci/hub_controller.cpp b/reactos/drivers/usb/usbohci/hub_controller.cpp index 35a96e2aaa6..16fe16e4874 100644 --- a/reactos/drivers/usb/usbohci/hub_controller.cpp +++ b/reactos/drivers/usb/usbohci/hub_controller.cpp @@ -1012,7 +1012,6 @@ CHubController::HandleClassOther( // reset port feature // Status = m_Hardware->SetPortFeature(PortId, PORT_RESET); - PC_ASSERT(Status == STATUS_SUCCESS); break; } default: diff --git a/reactos/drivers/usb/usbohci/usb_device.cpp b/reactos/drivers/usb/usbohci/usb_device.cpp index 838f4e68b61..af1e988e3fd 100644 --- a/reactos/drivers/usb/usbohci/usb_device.cpp +++ b/reactos/drivers/usb/usbohci/usb_device.cpp @@ -65,7 +65,7 @@ public: // constructor / destructor CUSBDevice(IUnknown *OuterUnknown){} - virtual ~CUSBDevice(){} + virtual ~CUSBDevice(); protected: LONG m_Ref; @@ -85,6 +85,73 @@ protected: PUSB_CONFIGURATION m_ConfigurationDescriptors; }; +CUSBDevice::~CUSBDevice() +{ + ULONG Index, InterfaceIndex, EndpointIndex; + //NTSTATUS Status; + + if (!m_ConfigurationDescriptors) + { + // + // nothing to do + // + return; + } + + + // + // clean up resources + // + for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++) + { + for(InterfaceIndex = 0; InterfaceIndex < m_ConfigurationDescriptors[Index].ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++) + { + // + // are there any endpoint descriptors + // + for(EndpointIndex = 0; EndpointIndex < m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints; EndpointIndex++) + { + // + // abort pipe + // + //Status = AbortPipe((PUSB_ENDPOINT_DESCRIPTOR)&m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints[EndpointIndex]); + //DPRINT1("[USBOHCI] Deleting Device Abort Pipe Status %x\n", Status); + } + + if (m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].InterfaceDescriptor.bNumEndpoints) + { + // + // free endpoints + // + ExFreePool(m_ConfigurationDescriptors[Index].Interfaces[InterfaceIndex].EndPoints); + } + } + + if (m_ConfigurationDescriptors[Index].ConfigurationDescriptor->bNumInterfaces) + { + // + // free interface descriptors + // + ExFreePool(m_ConfigurationDescriptors[Index].Interfaces); + } + + if (m_ConfigurationDescriptors[Index].ConfigurationDescriptor) + { + // + // free configuration descriptor + // + ExFreePool(m_ConfigurationDescriptors[Index].ConfigurationDescriptor); + } + } + + // + // free configuration descriptor + // + ExFreePool(m_ConfigurationDescriptors); +} + + + //---------------------------------------------------------------------------------------- NTSTATUS STDMETHODCALLTYPE -- 2.17.1