[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 PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
PHIDCLASS_FDO_EXTENSION FDODeviceExtension = DeviceObject->DeviceExtension;
NTSTATUS Status; NTSTATUS Status;
/* Pass the IRP down */ /* FIXME cleanup */
//
// dispatch to minidriver
//
IoSkipCurrentIrpStackLocation(Irp); IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp); Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
/* Now teardown our portion of the device stack */
IoDetachDevice(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject);
IoDeleteDevice(DeviceObject);
//
// complete request
//
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status; return Status;
} }
@ -533,6 +537,7 @@ HidClassFDO_PnP(
{ {
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
PHIDCLASS_FDO_EXTENSION FDODeviceExtension; PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
NTSTATUS Status;
// //
// get device extension // get device extension
@ -554,45 +559,34 @@ HidClassFDO_PnP(
{ {
return HidClassFDO_RemoveDevice(DeviceObject, Irp); 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: case IRP_MN_QUERY_DEVICE_RELATIONS:
{ {
return HidClassFDO_DeviceRelations(DeviceObject, 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 success and fall through
//
Irp->IoStatus.Status = STATUS_SUCCESS;
}
default: default:
{ {
// //
// dispatch to lower device // dispatch to mini driver
// //
IoSkipCurrentIrpStackLocation(Irp); 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); KeInitializeSpinLock(&Context->Lock);
InitializeListHead(&Context->ReadPendingIrpListHead); InitializeListHead(&Context->ReadPendingIrpListHead);
InitializeListHead(&Context->IrpCompletedListHead); InitializeListHead(&Context->IrpCompletedListHead);
KeInitializeEvent(&Context->IrpReadComplete, NotificationEvent, FALSE);
// //
// store context // store context
@ -226,7 +227,11 @@ HidClass_Close(
{ {
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension; 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 // get device extension
@ -260,12 +265,79 @@ HidClass_Close(
// //
// get irp context // 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 // remove context
@ -323,19 +395,20 @@ HidClass_ReadCompleteIrp(
ULONG Offset; ULONG Offset;
PHIDP_COLLECTION_DESC CollectionDescription; PHIDP_COLLECTION_DESC CollectionDescription;
PHIDP_REPORT_IDS ReportDescription; PHIDP_REPORT_IDS ReportDescription;
BOOLEAN IsEmpty;
// //
// get irp context // get irp context
// //
IrpContext = (PHIDCLASS_IRP_CONTEXT)Ctx; IrpContext = (PHIDCLASS_IRP_CONTEXT)Ctx;
DPRINT("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql()); DPRINT1("HidClass_ReadCompleteIrp Irql %lu\n", KeGetCurrentIrql());
DPRINT("HidClass_ReadCompleteIrp Status %lx\n", Irp->IoStatus.Status); DPRINT1("HidClass_ReadCompleteIrp Status %lx\n", Irp->IoStatus.Status);
DPRINT("HidClass_ReadCompleteIrp Length %lu\n", Irp->IoStatus.Information); DPRINT1("HidClass_ReadCompleteIrp Length %lu\n", Irp->IoStatus.Information);
DPRINT("HidClass_ReadCompleteIrp Irp %p\n", Irp); DPRINT1("HidClass_ReadCompleteIrp Irp %p\n", Irp);
DPRINT("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext->InputReportBuffer); DPRINT1("HidClass_ReadCompleteIrp InputReportBuffer %p\n", IrpContext->InputReportBuffer);
DPRINT("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext->InputReportBufferLength); DPRINT1("HidClass_ReadCompleteIrp InputReportBufferLength %li\n", IrpContext->InputReportBufferLength);
DPRINT("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext->OriginalIrp); DPRINT1("HidClass_ReadCompleteIrp OriginalIrp %p\n", IrpContext->OriginalIrp);
// //
// copy result // copy result
@ -402,6 +475,11 @@ HidClass_ReadCompleteIrp(
// //
RemoveEntryList(&Irp->Tail.Overlay.ListEntry); RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
//
// is list empty
//
IsEmpty = IsListEmpty(&IrpContext->FileOp->ReadPendingIrpListHead);
// //
// insert into completed list // insert into completed list
// //
@ -417,6 +495,17 @@ HidClass_ReadCompleteIrp(
// //
IoCompleteRequest(IrpContext->OriginalIrp, IO_NO_INCREMENT); 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 // free irp context
// //
@ -644,6 +733,19 @@ HidClass_Read(
// //
ASSERT(Context->DeviceExtension->Common.DriverExtension->DevicesArePolled == FALSE); 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 // build irp request
// //

View file

@ -136,6 +136,16 @@ typedef struct __HIDCLASS_FILEOP_CONTEXT__
// //
LIST_ENTRY IrpCompletedListHead; LIST_ENTRY IrpCompletedListHead;
//
// stop in progress indicator
//
BOOLEAN StopInProgress;
//
// read complete event
//
KEVENT IrpReadComplete;
}HIDCLASS_FILEOP_CONTEXT, *PHIDCLASS_FILEOP_CONTEXT; }HIDCLASS_FILEOP_CONTEXT, *PHIDCLASS_FILEOP_CONTEXT;
typedef struct typedef struct

View file

@ -1576,10 +1576,10 @@ HidPnp(
// //
// free resources // free resources
// //
if (HidDeviceExtension->HidDescriptor) if (HidDeviceExtension->ConfigurationDescriptor)
{ {
ExFreePool(HidDeviceExtension->HidDescriptor); ExFreePool(HidDeviceExtension->ConfigurationDescriptor);
HidDeviceExtension->HidDescriptor = NULL; HidDeviceExtension->ConfigurationDescriptor = NULL;
} }
// //

View file

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

View file

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

View file

@ -65,7 +65,7 @@ public:
// constructor / destructor // constructor / destructor
CUSBDevice(IUnknown *OuterUnknown){} CUSBDevice(IUnknown *OuterUnknown){}
virtual ~CUSBDevice(){} virtual ~CUSBDevice();
protected: protected:
LONG m_Ref; LONG m_Ref;
@ -85,6 +85,73 @@ protected:
PUSB_CONFIGURATION m_ConfigurationDescriptors; 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 NTSTATUS
STDMETHODCALLTYPE STDMETHODCALLTYPE