2012-01-26 03:42:56 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
* FILE: drivers/usb/usbccgp/fdo.c
|
|
|
|
* PURPOSE: USB device driver.
|
|
|
|
* PROGRAMMERS:
|
|
|
|
* Michael Martin (michael.martin@reactos.org)
|
|
|
|
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
|
|
* Cameron Gutman
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "usbccgp.h"
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
FDO_QueryCapabilitiesCompletionRoutine(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp,
|
|
|
|
IN PVOID Context)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// set event
|
|
|
|
//
|
|
|
|
KeSetEvent((PRKEVENT)Context, 0, FALSE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// completion is done in the HidClassFDO_QueryCapabilities routine
|
|
|
|
//
|
|
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FDO_QueryCapabilities(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN OUT PDEVICE_CAPABILITIES Capabilities)
|
|
|
|
{
|
|
|
|
PIRP Irp;
|
|
|
|
KEVENT Event;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get device extension
|
|
|
|
//
|
|
|
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
|
|
|
|
|
|
|
//
|
|
|
|
// init event
|
|
|
|
//
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// now allocte the irp
|
|
|
|
//
|
|
|
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
|
|
|
if (!Irp)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// no memory
|
|
|
|
//
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// get next stack location
|
|
|
|
//
|
|
|
|
IoStack = IoGetNextIrpStackLocation(Irp);
|
|
|
|
|
|
|
|
//
|
|
|
|
// init stack location
|
|
|
|
//
|
|
|
|
IoStack->MajorFunction = IRP_MJ_PNP;
|
|
|
|
IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
|
|
|
|
IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
|
|
|
|
|
|
|
|
//
|
|
|
|
// set completion routine
|
|
|
|
//
|
|
|
|
IoSetCompletionRoutine(Irp, FDO_QueryCapabilitiesCompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// init capabilities
|
|
|
|
//
|
|
|
|
RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
|
|
|
|
Capabilities->Size = sizeof(DEVICE_CAPABILITIES);
|
|
|
|
Capabilities->Version = 1; // FIXME hardcoded constant
|
|
|
|
Capabilities->Address = MAXULONG;
|
|
|
|
Capabilities->UINumber = MAXULONG;
|
|
|
|
|
|
|
|
//
|
|
|
|
// pnp irps have default completion code
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
|
|
|
//
|
|
|
|
// call lower device
|
|
|
|
//
|
|
|
|
Status = IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
|
|
|
if (Status == STATUS_PENDING)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// wait for completion
|
|
|
|
//
|
|
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// get status
|
|
|
|
//
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
|
|
|
|
//
|
|
|
|
// complete request
|
|
|
|
//
|
|
|
|
IoFreeIrp(Irp);
|
|
|
|
|
|
|
|
//
|
|
|
|
// done
|
|
|
|
//
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FDO_DeviceRelations(
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
2012-01-26 19:11:44 +00:00
|
|
|
ULONG DeviceCount = 0;
|
|
|
|
ULONG Index;
|
|
|
|
PDEVICE_RELATIONS DeviceRelations;
|
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get device extension
|
|
|
|
//
|
|
|
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get current irp stack location
|
|
|
|
//
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
|
|
//
|
|
|
|
// check if relation type is BusRelations
|
|
|
|
//
|
|
|
|
if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FDO always only handles bus relations
|
|
|
|
//
|
|
|
|
return USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// go through array and count device objects
|
|
|
|
//
|
|
|
|
for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
|
|
|
|
{
|
|
|
|
if (FDODeviceExtension->ChildPDO[Index])
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// child pdo
|
|
|
|
//
|
|
|
|
DeviceCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// allocate device relations
|
|
|
|
//
|
|
|
|
DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
|
|
|
|
if (!DeviceRelations)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// no memory
|
|
|
|
//
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// add device objects
|
|
|
|
//
|
|
|
|
for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
|
|
|
|
{
|
|
|
|
if (FDODeviceExtension->ChildPDO[Index])
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// store child pdo
|
|
|
|
//
|
|
|
|
DeviceRelations->Objects[DeviceRelations->Count] = FDODeviceExtension->ChildPDO[Index];
|
|
|
|
|
|
|
|
//
|
|
|
|
// add reference
|
|
|
|
//
|
|
|
|
ObReferenceObject(FDODeviceExtension->ChildPDO[Index]);
|
|
|
|
|
|
|
|
//
|
|
|
|
// increment count
|
|
|
|
//
|
|
|
|
DeviceRelations->Count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// store result
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
|
|
|
|
|
|
|
//
|
|
|
|
// request completed successfully
|
|
|
|
//
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FDO_CreateChildPdo(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PDEVICE_OBJECT PDODeviceObject;
|
|
|
|
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
|
|
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
|
|
|
ULONG Index;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get device extension
|
|
|
|
//
|
|
|
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
|
|
|
|
|
|
|
//
|
|
|
|
// lets create array for the child PDO
|
|
|
|
//
|
|
|
|
FDODeviceExtension->ChildPDO = AllocateItem(NonPagedPool, sizeof(PDEVICE_OBJECT) * FDODeviceExtension->FunctionDescriptorCount);
|
|
|
|
if (!FDODeviceExtension->ChildPDO)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// no memory
|
|
|
|
//
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// create pdo for each function
|
|
|
|
//
|
|
|
|
for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// create the PDO
|
|
|
|
//
|
|
|
|
Status = IoCreateDevice(FDODeviceExtension->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_USB, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &PDODeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// failed to create device object
|
|
|
|
//
|
|
|
|
DPRINT1("IoCreateDevice failed with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// store in array
|
|
|
|
//
|
|
|
|
FDODeviceExtension->ChildPDO[Index] = PDODeviceObject;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get device extension
|
|
|
|
//
|
|
|
|
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
|
|
|
|
RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
|
|
|
|
|
|
|
|
//
|
|
|
|
// init device extension
|
|
|
|
//
|
|
|
|
PDODeviceExtension->Common.IsFDO = FALSE;
|
|
|
|
PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
|
2012-02-03 16:03:42 +00:00
|
|
|
PDODeviceExtension->NextDeviceObject = DeviceObject;
|
2012-01-26 19:11:44 +00:00
|
|
|
PDODeviceExtension->FunctionIndex = Index;
|
2012-02-02 10:17:14 +00:00
|
|
|
PDODeviceExtension->FDODeviceExtension = FDODeviceExtension;
|
2012-01-30 10:41:52 +00:00
|
|
|
PDODeviceExtension->InterfaceList = FDODeviceExtension->InterfaceList;
|
|
|
|
PDODeviceExtension->InterfaceListCount = FDODeviceExtension->InterfaceListCount;
|
2012-01-28 19:49:53 +00:00
|
|
|
PDODeviceExtension->ConfigurationHandle = FDODeviceExtension->ConfigurationHandle;
|
2012-01-27 20:58:58 +00:00
|
|
|
PDODeviceExtension->ConfigurationDescriptor = FDODeviceExtension->ConfigurationDescriptor;
|
2012-01-26 19:11:44 +00:00
|
|
|
RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
2012-01-27 20:58:58 +00:00
|
|
|
RtlCopyMemory(&PDODeviceExtension->DeviceDescriptor, &FDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
2012-01-26 19:11:44 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// patch the stack size
|
|
|
|
//
|
|
|
|
PDODeviceObject->StackSize = DeviceObject->StackSize + 1;
|
|
|
|
|
|
|
|
//
|
|
|
|
// set device flags
|
|
|
|
//
|
|
|
|
PDODeviceObject->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
|
|
|
|
|
|
|
|
//
|
|
|
|
// device is initialized
|
|
|
|
//
|
|
|
|
PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// done
|
|
|
|
//
|
|
|
|
return STATUS_SUCCESS;
|
2012-01-26 03:42:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FDO_StartDevice(
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get device extension
|
|
|
|
//
|
|
|
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
|
|
|
|
|
|
|
//
|
|
|
|
// first start lower device
|
|
|
|
//
|
|
|
|
Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// failed to start lower device
|
|
|
|
//
|
|
|
|
DPRINT1("FDO_StartDevice lower device failed to start with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get descriptors
|
|
|
|
Status = USBCCGP_GetDescriptors(DeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
// failed to start lower device
|
|
|
|
DPRINT1("FDO_StartDevice failed to get descriptors with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// get capabilities
|
|
|
|
Status = FDO_QueryCapabilities(DeviceObject, &FDODeviceExtension->Capabilities);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
// failed to start lower device
|
|
|
|
DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// now select the configuration
|
|
|
|
Status = USBCCGP_SelectConfiguration(DeviceObject, FDODeviceExtension);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
// failed to select interface
|
|
|
|
DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2012-01-26 13:45:59 +00:00
|
|
|
// query bus interface
|
|
|
|
USBCCGP_QueryInterface(FDODeviceExtension->NextDeviceObject, &FDODeviceExtension->BusInterface);
|
|
|
|
|
|
|
|
// now enumerate the functions
|
|
|
|
Status = USBCCGP_EnumerateFunctions(DeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
// failed to enumerate functions
|
|
|
|
DPRINT1("Failed to enumerate functions with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// sanity checks
|
|
|
|
//
|
|
|
|
ASSERT(FDODeviceExtension->FunctionDescriptorCount);
|
|
|
|
ASSERT(FDODeviceExtension->FunctionDescriptor);
|
2012-01-27 18:04:39 +00:00
|
|
|
DumpFunctionDescriptor(FDODeviceExtension->FunctionDescriptor, FDODeviceExtension->FunctionDescriptorCount);
|
2012-01-26 13:45:59 +00:00
|
|
|
|
2012-01-26 03:42:56 +00:00
|
|
|
//
|
2012-01-26 19:11:44 +00:00
|
|
|
// now create the pdo
|
2012-01-26 03:42:56 +00:00
|
|
|
//
|
2012-01-26 19:11:44 +00:00
|
|
|
Status = FDO_CreateChildPdo(DeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// failed
|
|
|
|
//
|
|
|
|
DPRINT1("FDO_CreateChildPdo failed with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// inform pnp manager of new device objects
|
|
|
|
//
|
|
|
|
IoInvalidateDeviceRelations(FDODeviceExtension->PhysicalDeviceObject, BusRelations);
|
|
|
|
|
|
|
|
//
|
|
|
|
// done
|
|
|
|
//
|
|
|
|
DPRINT1("[USBCCGP] FDO initialized successfully\n");
|
2012-01-26 03:42:56 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FDO_HandlePnp(
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
|
|
|
|
|
|
|
// get device extension
|
|
|
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
|
|
|
|
|
|
|
|
|
|
|
// get stack location
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
2012-02-02 10:17:14 +00:00
|
|
|
DPRINT1("[USBCCGP] PnP Minor %x\n", IoStack->MinorFunction);
|
2012-01-26 03:42:56 +00:00
|
|
|
switch(IoStack->MinorFunction)
|
|
|
|
{
|
2012-02-02 10:17:14 +00:00
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
|
|
{
|
|
|
|
/* Send the IRP down the stack */
|
|
|
|
Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Detach from the device stack
|
|
|
|
//
|
|
|
|
IoDetachDevice(FDODeviceExtension->NextDeviceObject);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Delete the device object
|
|
|
|
//
|
|
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// request completed
|
|
|
|
//
|
|
|
|
break;
|
|
|
|
}
|
2012-01-26 03:42:56 +00:00
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
{
|
2012-01-26 19:11:44 +00:00
|
|
|
//
|
|
|
|
// start the device
|
|
|
|
//
|
2012-01-26 03:42:56 +00:00
|
|
|
Status = FDO_StartDevice(DeviceObject, Irp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
|
|
{
|
2012-01-26 19:11:44 +00:00
|
|
|
//
|
|
|
|
// handle device relations
|
|
|
|
//
|
2012-01-26 03:42:56 +00:00
|
|
|
Status = FDO_DeviceRelations(DeviceObject, Irp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// copy capabilities
|
|
|
|
//
|
|
|
|
RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
|
|
|
Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// surprise removal ok
|
|
|
|
//
|
|
|
|
IoStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-02-03 22:59:53 +00:00
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// sure
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
//
|
|
|
|
// forward irp to next device object
|
|
|
|
//
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
|
|
|
}
|
2012-01-26 03:42:56 +00:00
|
|
|
default:
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// forward irp to next device object
|
|
|
|
//
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// complete request
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
2012-02-03 16:03:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FDO_HandleResetCyclePort(
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
|
|
|
PLIST_ENTRY ListHead, Entry;
|
|
|
|
LIST_ENTRY TempList;
|
|
|
|
PUCHAR ResetActive;
|
|
|
|
PIRP ListIrp;
|
|
|
|
KIRQL OldLevel;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get device extension
|
|
|
|
//
|
|
|
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
|
|
|
|
|
|
|
// get stack location
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
DPRINT1("FDO_HandleResetCyclePort IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
|
|
|
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// use reset port list
|
|
|
|
//
|
|
|
|
ListHead = &FDODeviceExtension->ResetPortListHead;
|
|
|
|
ResetActive = &FDODeviceExtension->ResetPortActive;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// use cycle port list
|
|
|
|
//
|
|
|
|
ListHead = &FDODeviceExtension->CyclePortListHead;
|
|
|
|
ResetActive = &FDODeviceExtension->CyclePortActive;
|
|
|
|
}
|
2012-01-26 03:42:56 +00:00
|
|
|
|
2012-02-03 16:03:42 +00:00
|
|
|
//
|
|
|
|
// acquire lock
|
|
|
|
//
|
|
|
|
KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel);
|
2012-01-26 03:42:56 +00:00
|
|
|
|
2012-02-03 16:03:42 +00:00
|
|
|
if (*ResetActive)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// insert into pending list
|
|
|
|
//
|
|
|
|
InsertTailList(ListHead, &Irp->Tail.Overlay.ListEntry);
|
|
|
|
|
|
|
|
//
|
|
|
|
// mark irp pending
|
|
|
|
//
|
|
|
|
IoMarkIrpPending(Irp);
|
|
|
|
Status = STATUS_PENDING;
|
|
|
|
|
|
|
|
//
|
|
|
|
// release lock
|
|
|
|
//
|
|
|
|
KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// mark reset active
|
|
|
|
//
|
|
|
|
*ResetActive = TRUE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// release lock
|
|
|
|
//
|
|
|
|
KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
|
|
|
|
|
|
|
|
//
|
|
|
|
// forward request synchronized
|
|
|
|
//
|
|
|
|
USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
|
|
|
|
|
|
|
//
|
|
|
|
// reacquire lock
|
|
|
|
//
|
|
|
|
KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel);
|
|
|
|
|
|
|
|
//
|
|
|
|
// mark reset as completed
|
|
|
|
//
|
|
|
|
*ResetActive = FALSE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// move all requests into temporary list
|
|
|
|
//
|
|
|
|
InitializeListHead(&TempList);
|
|
|
|
while(!IsListEmpty(ListHead))
|
|
|
|
{
|
|
|
|
Entry = RemoveHeadList(ListHead);
|
|
|
|
InsertTailList(&TempList, Entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// release lock
|
|
|
|
//
|
|
|
|
KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
|
|
|
|
|
|
|
|
//
|
|
|
|
// complete pending irps
|
|
|
|
//
|
|
|
|
while(!IsListEmpty(&TempList))
|
|
|
|
{
|
|
|
|
Entry = RemoveHeadList(&TempList);
|
|
|
|
ListIrp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
|
|
|
|
|
|
|
|
//
|
|
|
|
// complete request with status success
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// status success
|
|
|
|
//
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FDO_HandleInternalDeviceControl(
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
|
|
|
|
|
|
|
//
|
|
|
|
// get device extension
|
|
|
|
//
|
|
|
|
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
|
|
ASSERT(FDODeviceExtension->Common.IsFDO);
|
|
|
|
|
|
|
|
// get stack location
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
|
|
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT ||
|
|
|
|
IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// handle reset / cycle ports
|
|
|
|
//
|
|
|
|
Status = FDO_HandleResetCyclePort(DeviceObject, Irp);
|
|
|
|
DPRINT1("FDO_HandleResetCyclePort Status %x\n", Status);
|
|
|
|
if (Status != STATUS_PENDING)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// complete request
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// forward and forget request
|
|
|
|
//
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
2012-01-26 03:42:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FDO_Dispatch(
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PIRP Irp)
|
|
|
|
{
|
|
|
|
PIO_STACK_LOCATION IoStack;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* get stack location */
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
|
|
switch(IoStack->MajorFunction)
|
|
|
|
{
|
|
|
|
case IRP_MJ_PNP:
|
|
|
|
return FDO_HandlePnp(DeviceObject, Irp);
|
2012-02-03 16:03:42 +00:00
|
|
|
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
|
|
|
return FDO_HandleInternalDeviceControl(DeviceObject, Irp);
|
2012-01-26 03:42:56 +00:00
|
|
|
default:
|
|
|
|
DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
|
|
|
|
ASSERT(FALSE);
|
|
|
|
Status = Irp->IoStatus.Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
|
|
}
|
2012-01-26 19:11:44 +00:00
|
|
|
|
2012-01-26 03:42:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|