[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
This commit is contained in:
Johannes Anderwald 2012-02-21 01:16:56 +00:00
parent 5429a4441e
commit 177a18b44b
7 changed files with 227 additions and 54 deletions

View file

@ -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 */
/* FIXME cleanup */
//
// dispatch to minidriver
//
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
/* Now teardown our portion of the device stack */
IoDetachDevice(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject);
IoDeleteDevice(DeviceObject);
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:
{
//
// set status to succes
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// forward to lower device
//
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
}
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
{
//
// set status to succes
//
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);
}
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 success and fall through
//
Irp->IoStatus.Status = STATUS_SUCCESS;
}
default:
{
//
// dispatch to lower device
// dispatch to mini driver
//
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
//
// complete request
//
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
}
}

View file

@ -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
//

View file

@ -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

View file

@ -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;
}
//

View file

@ -45,6 +45,7 @@ typedef struct
// hid descriptor
//
PHID_DESCRIPTOR HidDescriptor;
}HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
typedef struct

View file

@ -1012,7 +1012,6 @@ CHubController::HandleClassOther(
// reset port feature
//
Status = m_Hardware->SetPortFeature(PortId, PORT_RESET);
PC_ASSERT(Status == STATUS_SUCCESS);
break;
}
default:

View file

@ -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