mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[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:
parent
5429a4441e
commit
177a18b44b
7 changed files with 227 additions and 54 deletions
|
@ -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);
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef struct
|
|||
// hid descriptor
|
||||
//
|
||||
PHID_DESCRIPTOR HidDescriptor;
|
||||
|
||||
}HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -1012,7 +1012,6 @@ CHubController::HandleClassOther(
|
|||
// reset port feature
|
||||
//
|
||||
Status = m_Hardware->SetPortFeature(PortId, PORT_RESET);
|
||||
PC_ASSERT(Status == STATUS_SUCCESS);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue