mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:56:00 +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 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue