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;
}
{
PIO_STACK_LOCATION IoStack;
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
+ NTSTATUS Status;
//
// get device extension
{
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;
}
}
}
KeInitializeSpinLock(&Context->Lock);
InitializeListHead(&Context->ReadPendingIrpListHead);
InitializeListHead(&Context->IrpCompletedListHead);
+ KeInitializeEvent(&Context->IrpReadComplete, NotificationEvent, FALSE);
//
// store context
{
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
//
// 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
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
//
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+ //
+ // is list empty
+ //
+ IsEmpty = IsListEmpty(&IrpContext->FileOp->ReadPendingIrpListHead);
+
//
// insert into completed list
//
//
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
//
//
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
//
//
LIST_ENTRY IrpCompletedListHead;
+ //
+ // stop in progress indicator
+ //
+ BOOLEAN StopInProgress;
+
+ //
+ // read complete event
+ //
+ KEVENT IrpReadComplete;
+
}HIDCLASS_FILEOP_CONTEXT, *PHIDCLASS_FILEOP_CONTEXT;
typedef struct
//
// free resources
//
- if (HidDeviceExtension->HidDescriptor)
+ if (HidDeviceExtension->ConfigurationDescriptor)
{
- ExFreePool(HidDeviceExtension->HidDescriptor);
- HidDeviceExtension->HidDescriptor = NULL;
+ ExFreePool(HidDeviceExtension->ConfigurationDescriptor);
+ HidDeviceExtension->ConfigurationDescriptor = NULL;
}
//
// hid descriptor
//
PHID_DESCRIPTOR HidDescriptor;
+
}HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
typedef struct
// reset port feature
//
Status = m_Hardware->SetPortFeature(PortId, PORT_RESET);
- PC_ASSERT(Status == STATUS_SUCCESS);
break;
}
default:
// constructor / destructor
CUSBDevice(IUnknown *OuterUnknown){}
- virtual ~CUSBDevice(){}
+ virtual ~CUSBDevice();
protected:
LONG m_Ref;
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