[HIDPARSE][HIDPARSER][LIBUSB][USBHUB] Merge USB stack improvements by Vardan Mikayelyan in GSoC.

svn path=/trunk/; revision=73605
This commit is contained in:
Amine Khaldi 2017-01-27 11:09:36 +00:00
parent 92d1110c00
commit 9bbe22afa8
11 changed files with 619 additions and 263 deletions

View file

@ -125,6 +125,29 @@ HidP_GetCaps(
return HidParser_GetCaps(&Parser, PreparsedData, Capabilities);
}
NTSTATUS
TranslateStatusForUpperLayer(
IN HIDPARSER_STATUS Status)
{
//
// now we are handling only this values, for others just return
// status as it is.
//
switch (Status)
{
case HIDPARSER_STATUS_INSUFFICIENT_RESOURCES:
return STATUS_INSUFFICIENT_RESOURCES;
case HIDPARSER_STATUS_INVALID_REPORT_TYPE:
return HIDP_STATUS_INVALID_REPORT_TYPE;
case HIDPARSER_STATUS_BUFFER_TOO_SMALL:
return STATUS_BUFFER_TOO_SMALL;
case HIDPARSER_STATUS_COLLECTION_NOT_FOUND:
return STATUS_NO_DATA_DETECTED;
default:
return Status;
}
}
NTSTATUS
NTAPI
HidP_GetCollectionDescription(
@ -134,6 +157,7 @@ HidP_GetCollectionDescription(
OUT PHIDP_DEVICE_DESC DeviceDescription)
{
HID_PARSER Parser;
NTSTATUS Status;
//
// init parser
@ -143,7 +167,8 @@ HidP_GetCollectionDescription(
//
// get description;
//
return HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
Status = HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
return TranslateStatusForUpperLayer(Status);
}
HIDAPI

View file

@ -1,5 +1,6 @@
add_definitions(-DDEBUG_MODE)
add_definitions(-DNTDDI_VERSION=0x05020400)
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
list(APPEND SOURCE

View file

@ -569,6 +569,11 @@ QueryInterface(
Stack->Parameters.QueryInterface.Interface = Interface;
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
//
// Initialize the status block before sending the IRP
//
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
@ -1089,8 +1094,7 @@ DestroyUsbChildDeviceObject(
PDEVICE_OBJECT ChildDeviceObject = NULL;
ULONG Index = 0;
DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index);
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
for (Index = 0; Index < USB_MAXCHILDREN; Index++)
{
if (HubDeviceExtension->ChildDeviceObject[Index])
@ -1111,12 +1115,17 @@ DestroyUsbChildDeviceObject(
if (!ChildDeviceObject)
{
DPRINT1("Removal request for non-existant device!\n");
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
return STATUS_UNSUCCESSFUL;
}
DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index);
/* Remove the device from the table */
HubDeviceExtension->ChildDeviceObject[Index] = NULL;
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
/* Invalidate device relations for the root hub */
IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations);
@ -1147,26 +1156,6 @@ CreateUsbChildDeviceObject(
HubInterface = &HubDeviceExtension->HubInterface;
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
HubInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext;
//
// Find an empty slot in the child device array
//
for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++)
{
if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL)
{
DPRINT("Found unused entry at %d\n", ChildDeviceCount);
break;
}
}
//
// Check if the limit has been reached for maximum usb devices
//
if (ChildDeviceCount == USB_MAXCHILDREN)
{
DPRINT1("USBHUB: Too many child devices!\n");
return STATUS_UNSUCCESSFUL;
}
while (TRUE)
{
@ -1226,10 +1215,6 @@ CreateUsbChildDeviceObject(
UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject;
UsbChildExtension->PortNumber = PortId;
// copy device interface
RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
//
// Create the UsbDeviceObject
//
@ -1244,12 +1229,6 @@ CreateUsbChildDeviceObject(
goto Cleanup;
}
// copy device interface
RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
// FIXME replace buscontext
UsbChildExtension->DeviceInterface.BusContext = UsbChildExtension->UsbDeviceHandle;
//
// Initialize UsbDevice
//
@ -1339,8 +1318,43 @@ CreateUsbChildDeviceObject(
goto Cleanup;
}
// copy device interface
RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->UsbDInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext);
INITIALIZE_PNP_STATE(UsbChildExtension->Common);
IoInitializeRemoveLock(&UsbChildExtension->Common.RemoveLock, 'pbuH', 0, 0);
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
//
// Find an empty slot in the child device array
//
for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++)
{
if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL)
{
DPRINT("Found unused entry at %d\n", ChildDeviceCount);
break;
}
}
//
// Check if the limit has been reached for maximum usb devices
//
if (ChildDeviceCount == USB_MAXCHILDREN)
{
DPRINT1("USBHUB: Too many child devices!\n");
Status = STATUS_UNSUCCESSFUL;
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext);
goto Cleanup;
}
HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject;
HubDeviceExtension->InstanceCount++;
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations);
return STATUS_SUCCESS;
@ -1384,16 +1398,20 @@ Cleanup:
NTSTATUS
USBHUB_FdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_RELATIONS RelationsFromTop,
OUT PDEVICE_RELATIONS* pDeviceRelations)
{
PHUB_DEVICE_EXTENSION HubDeviceExtension;
PDEVICE_RELATIONS DeviceRelations;
ULONG i;
ULONG ChildrenFromTop = 0;
ULONG Children = 0;
ULONG NeededSize;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
//
// Count the number of children
//
@ -1407,9 +1425,19 @@ USBHUB_FdoQueryBusRelations(
Children++;
}
NeededSize = sizeof(DEVICE_RELATIONS);
if (Children > 1)
NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT);
if (RelationsFromTop)
{
ChildrenFromTop = RelationsFromTop->Count;
if (!Children)
{
// We have nothing to add
*pDeviceRelations = RelationsFromTop;
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
return STATUS_SUCCESS;
}
}
NeededSize = sizeof(DEVICE_RELATIONS) + (Children + ChildrenFromTop - 1) * sizeof(PDEVICE_OBJECT);
//
// Allocate DeviceRelations
@ -1418,9 +1446,22 @@ USBHUB_FdoQueryBusRelations(
NeededSize);
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
DeviceRelations->Count = Children;
Children = 0;
{
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
if (!RelationsFromTop)
return STATUS_INSUFFICIENT_RESOURCES;
else
return STATUS_NOT_SUPPORTED;
}
// Copy the objects coming from top
if (ChildrenFromTop)
{
RtlCopyMemory(DeviceRelations->Objects, RelationsFromTop->Objects,
ChildrenFromTop * sizeof(PDEVICE_OBJECT));
}
DeviceRelations->Count = Children + ChildrenFromTop;
Children = ChildrenFromTop;
//
// Fill in return structure
@ -1429,12 +1470,19 @@ USBHUB_FdoQueryBusRelations(
{
if (HubDeviceExtension->ChildDeviceObject[i])
{
// The PnP Manager removes the reference when appropriate.
ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]);
HubDeviceExtension->ChildDeviceObject[i]->Flags &= ~DO_DEVICE_INITIALIZING;
DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i];
}
}
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
// We should do this, because replaced this with our's one
if (RelationsFromTop)
ExFreePool(RelationsFromTop);
ASSERT(Children == DeviceRelations->Count);
*pDeviceRelations = DeviceRelations;
@ -1551,7 +1599,8 @@ USBHUB_FdoStartDevice(
if (!Urb)
{
// no memory
return STATUS_INSUFFICIENT_RESOURCES;
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
// zero urb
@ -1566,8 +1615,7 @@ USBHUB_FdoStartDevice(
{
// failed to obtain hub pdo
DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status);
ExFreePool(Urb);
return Status;
goto cleanup;
}
// sanity checks
@ -1578,14 +1626,13 @@ USBHUB_FdoStartDevice(
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
// Send the StartDevice to RootHub
Status = ForwardIrpAndWait(RootHubDeviceObject, Irp);
Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp);
if (!NT_SUCCESS(Status))
{
// failed to start pdo
DPRINT1("Failed to start the RootHub PDO\n");
ExFreePool(Urb);
return Status;
goto cleanup;
}
// Get the current number of hubs
@ -1596,8 +1643,7 @@ USBHUB_FdoStartDevice(
{
// failed to get number of hubs
DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status);
ExFreePool(Urb);
return Status;
goto cleanup;
}
// Get the Hub Interface
@ -1611,8 +1657,7 @@ USBHUB_FdoStartDevice(
{
// failed to get root hub interface
DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
ExFreePool(Urb);
return Status;
goto cleanup;
}
HubInterfaceBusContext = HubDeviceExtension->HubInterface.BusContext;
@ -1628,8 +1673,7 @@ USBHUB_FdoStartDevice(
{
// failed to get usbdi interface
DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status);
ExFreePool(Urb);
return Status;
goto cleanup;
}
// Get Root Hub Device Handle
@ -1642,8 +1686,7 @@ USBHUB_FdoStartDevice(
{
// failed
DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status);
ExFreePool(Urb);
return Status;
goto cleanup;
}
//
@ -1687,8 +1730,7 @@ USBHUB_FdoStartDevice(
{
// failed to get device descriptor of hub
DPRINT1("Failed to get HubDeviceDescriptor!\n");
ExFreePool(Urb);
return Status;
goto cleanup;
}
// build configuration request
@ -1715,8 +1757,7 @@ USBHUB_FdoStartDevice(
{
// failed to get configuration descriptor
DPRINT1("Failed to get RootHub Configuration with status %x\n", Status);
ExFreePool(Urb);
return Status;
goto cleanup;
}
// sanity checks
@ -1742,16 +1783,15 @@ USBHUB_FdoStartDevice(
{
// failed to get hub information
DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n");
ExFreePool(Urb);
return Status;
goto cleanup;
}
if (!HubDeviceExtension->UsbExtHubInfo.NumberOfPorts)
{
// bogus port driver
DPRINT1("Failed to retrieve the number of ports\n");
ExFreePool(Urb);
return STATUS_UNSUCCESSFUL;
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
DPRINT("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts);
@ -1782,8 +1822,8 @@ USBHUB_FdoStartDevice(
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get Hub Descriptor!\n");
ExFreePool(Urb);
return STATUS_UNSUCCESSFUL;
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
// sanity checks
@ -1811,8 +1851,8 @@ USBHUB_FdoStartDevice(
{
// failed to get hub status
DPRINT1("Failed to get Hub Status!\n");
ExFreePool(Urb);
return STATUS_UNSUCCESSFUL;
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
// Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub
@ -1820,6 +1860,13 @@ USBHUB_FdoStartDevice(
sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts,
USB_HUB_TAG);
if (!HubDeviceExtension->PortStatusChange)
{
DPRINT1("Failed to allocate pool for PortStatusChange!\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
// Get the first Configuration Descriptor
Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor,
&HubDeviceExtension->HubConfigDescriptor,
@ -1828,8 +1875,8 @@ USBHUB_FdoStartDevice(
{
// failed parse hub descriptor
DPRINT1("Failed to parse configuration descriptor\n");
ExFreePool(Urb);
return STATUS_UNSUCCESSFUL;
Status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
// create configuration request
@ -1840,8 +1887,8 @@ USBHUB_FdoStartDevice(
{
// failed to build urb
DPRINT1("Failed to allocate urb\n");
ExFreePool(Urb);
return STATUS_INSUFFICIENT_RESOURCES;
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
// send request
@ -1853,9 +1900,7 @@ USBHUB_FdoStartDevice(
{
// failed to select configuration
DPRINT1("Failed to select configuration with %x\n", Status);
ExFreePool(Urb);
ExFreePool(ConfigUrb);
return Status;
goto cleanup;
}
// store configuration & pipe handle
@ -1863,12 +1908,6 @@ USBHUB_FdoStartDevice(
HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
DPRINT("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle);
FDO_QueryInterface(DeviceObject, &HubDeviceExtension->DeviceInterface);
// free urb
ExFreePool(ConfigUrb);
// check if function is available
if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed)
{
@ -1908,8 +1947,7 @@ USBHUB_FdoStartDevice(
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to set callback\n");
ExFreePool(Urb);
return Status;
goto cleanup;
}
}
else
@ -1961,8 +1999,30 @@ USBHUB_FdoStartDevice(
// free urb
ExFreePool(Urb);
// free ConfigUrb
ExFreePool(ConfigUrb);
// done
return Status;
cleanup:
if (Urb)
ExFreePool(Urb);
// Dereference interfaces
if (HubDeviceExtension->HubInterface.Size)
HubDeviceExtension->HubInterface.InterfaceDereference(HubDeviceExtension->HubInterface.BusContext);
if (HubDeviceExtension->UsbDInterface.Size)
HubDeviceExtension->UsbDInterface.InterfaceDereference(HubDeviceExtension->UsbDInterface.BusContext);
if (HubDeviceExtension->PortStatusChange)
ExFreePool(HubDeviceExtension->PortStatusChange);
if (ConfigUrb)
ExFreePool(ConfigUrb);
return Status;
}
NTSTATUS
@ -1972,17 +2032,31 @@ USBHUB_FdoHandlePnp(
{
PIO_STACK_LOCATION Stack;
NTSTATUS Status = STATUS_SUCCESS;
ULONG_PTR Information = 0;
PDEVICE_OBJECT ChildDeviceObject;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
PUSB_BUS_INTERFACE_HUB_V5 HubInterface;
PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
HubInterface = &HubDeviceExtension->HubInterface;
Stack = IoGetCurrentIrpStackLocation(Irp);
Status = IoAcquireRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
switch (Stack->MinorFunction)
{
int i;
case IRP_MN_START_DEVICE:
{
DPRINT("IRP_MN_START_DEVICE\n");
if (USBHUB_IsRootHubFDO(DeviceObject))
{
// start root hub fdo
@ -1992,7 +2066,13 @@ USBHUB_FdoHandlePnp(
{
Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp);
}
break;
SET_NEW_PNP_STATE(HubDeviceExtension->Common, Started);
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
return Status;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
@ -2002,66 +2082,197 @@ USBHUB_FdoHandlePnp(
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations = NULL;
PDEVICE_RELATIONS RelationsFromTop = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
Status = USBHUB_FdoQueryBusRelations(DeviceObject, &DeviceRelations);
Status = USBHUB_FdoQueryBusRelations(DeviceObject, RelationsFromTop, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
if (!NT_SUCCESS(Status))
{
if (Status == STATUS_NOT_SUPPORTED)
{
// We should process this to not lose relations from top.
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
}
// We should fail an IRP
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
return Status;
}
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
Irp->IoStatus.Status = Status;
break;
}
case RemovalRelations:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
return ForwardIrpAndForget(DeviceObject, Irp);
break;
}
default:
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
return ForwardIrpAndForget(DeviceObject, Irp);
break;
}
break;
}
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
{
//
// We should fail this request, because we're not handling
// IRP_MN_STOP_DEVICE for now.We'll receive this IRP ONLY when
// PnP manager rebalances resources.
//
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
}
case IRP_MN_QUERY_REMOVE_DEVICE:
{
// No action is required from FDO because it have nothing to free.
DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
SET_NEW_PNP_STATE(HubDeviceExtension->Common, RemovePending);
Irp->IoStatus.Status = STATUS_SUCCESS;
return ForwardIrpAndForget(DeviceObject, Irp);
break;
}
case IRP_MN_CANCEL_REMOVE_DEVICE:
{
DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
if (HubDeviceExtension->Common.PnPState == RemovePending)
RESTORE_PREVIOUS_PNP_STATE(HubDeviceExtension->Common);
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
}
case IRP_MN_SURPRISE_REMOVAL:
{
//
// We'll receive this IRP on HUB unexpected removal, or on USB
// controller removal from PCI port. Here we should "let know" all
// our children that their parent is removed and on next removal
// they also can be removed.
//
SET_NEW_PNP_STATE(HubDeviceExtension->Common, SurpriseRemovePending);
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
for (i = 0; i < USB_MAXCHILDREN; i++)
{
ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[i];
if (ChildDeviceObject)
{
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceObjectExtension;
ChildDeviceExtension->ParentDeviceObject = NULL;
}
}
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
// This IRP can't be failed
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
}
case IRP_MN_REMOVE_DEVICE:
{
DPRINT("IRP_MN_REMOVE_DEVICE\n");
SET_NEW_PNP_STATE(HubDeviceExtension->Common, Deleted);
IoReleaseRemoveLockAndWait(&HubDeviceExtension->Common.RemoveLock, Irp);
//
// Here we should remove all child PDOs. At this point all children
// received and returned from IRP_MN_REMOVE so remove synchronization
// isn't needed here
//
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
for (i = 0; i < USB_MAXCHILDREN; i++)
{
ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[i];
if (ChildDeviceObject)
{
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension;
SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted);
// Remove the usb device
if (UsbChildExtension->UsbDeviceHandle)
{
Status = HubInterface->RemoveUsbDevice(HubInterface->BusContext, UsbChildExtension->UsbDeviceHandle, 0);
ASSERT(Status == STATUS_SUCCESS);
}
// Free full configuration descriptor
if (UsbChildExtension->FullConfigDesc)
ExFreePool(UsbChildExtension->FullConfigDesc);
// Free ID buffers
if (UsbChildExtension->usCompatibleIds.Buffer)
ExFreePool(UsbChildExtension->usCompatibleIds.Buffer);
if (UsbChildExtension->usDeviceId.Buffer)
ExFreePool(UsbChildExtension->usDeviceId.Buffer);
if (UsbChildExtension->usHardwareIds.Buffer)
ExFreePool(UsbChildExtension->usHardwareIds.Buffer);
if (UsbChildExtension->usInstanceId.Buffer)
ExFreePool(UsbChildExtension->usInstanceId.Buffer);
DPRINT("Deleting child PDO\n");
IoDeleteDevice(DeviceObject);
ChildDeviceObject = NULL;
}
}
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
Status = ForwardIrpAndForget(DeviceObject, Irp);
IoDetachDevice(HubDeviceExtension->LowerDeviceObject);
DPRINT("Deleting FDO 0x%p\n", DeviceObject);
IoDeleteDevice(DeviceObject);
return STATUS_SUCCESS;
return Status;
}
case IRP_MN_QUERY_BUS_INFORMATION:
{
// Function drivers and filter drivers do not handle this IRP.
DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
break;
}
case IRP_MN_QUERY_ID:
{
DPRINT("IRP_MN_QUERY_ID\n");
// Function drivers and filter drivers do not handle this IRP.
break;
}
case IRP_MN_QUERY_CAPABILITIES:
{
//
// If a function or filter driver does not handle this IRP, it
// should pass that down.
//
DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
break;
}
default:
{
DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
break;
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
Status = ForwardIrpAndForget(DeviceObject, Irp);
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
return Status;
}
@ -2086,6 +2297,25 @@ USBHUB_FdoHandleDeviceControl(
// get device extension
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
Status = IoAcquireRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
// Prevent handling of control requests in remove pending state
if (HubDeviceExtension->Common.PnPState == RemovePending)
{
DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject);
Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
return STATUS_DEVICE_NOT_CONNECTED;
}
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_INFORMATION)
{
// is the buffer big enough
@ -2131,6 +2361,7 @@ USBHUB_FdoHandleDeviceControl(
// sanity checks
ASSERT(NodeConnectionInfo);
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
for(Index = 0; Index < USB_MAXCHILDREN; Index++)
{
if (HubDeviceExtension->ChildDeviceObject[Index] == NULL)
@ -2157,6 +2388,7 @@ USBHUB_FdoHandleDeviceControl(
}
break;
}
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
// done
Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION);
Status = STATUS_SUCCESS;
@ -2177,6 +2409,7 @@ USBHUB_FdoHandleDeviceControl(
// sanity checks
ASSERT(NodeKey);
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
for(Index = 0; Index < USB_MAXCHILDREN; Index++)
{
if (HubDeviceExtension->ChildDeviceObject[Index] == NULL)
@ -2216,6 +2449,7 @@ USBHUB_FdoHandleDeviceControl(
NodeKey->ActualLength = Length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME);
break;
}
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
}
}
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_CONNECTION_NAME)
@ -2247,6 +2481,7 @@ USBHUB_FdoHandleDeviceControl(
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
return Status;
}

View file

@ -211,84 +211,3 @@ SubmitRequestToRootHub(
return Status;
}
NTSTATUS
NTAPI
FDO_QueryInterfaceCompletionRoutine(
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_QueryInterface(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PUSB_BUS_INTERFACE_USBDI_V2 Interface)
{
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
/* Get device extension */
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(HubDeviceExtension->Common.IsFDO);
/* Init event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Now allocate 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_INTERFACE;
IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)Interface;
IoStack->Parameters.QueryInterface.InterfaceType = &USB_BUS_INTERFACE_USBDI_GUID;
IoStack->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_2;
IoStack->Parameters.QueryInterface.Size = sizeof(USB_BUS_INTERFACE_USBDI_V2);
/* Set completion routine */
IoSetCompletionRoutine(Irp,
FDO_QueryInterfaceCompletionRoutine,
(PVOID)&Event,
TRUE,
TRUE,
TRUE);
/* Pnp irps have default completion code */
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
/* Call lower device */
Status = IoCallDriver(HubDeviceExtension->LowerDeviceObject, 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;
}

View file

@ -146,16 +146,25 @@ IsValidPDO(
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
// This can happen when parent device was surprise removed.
if (ChildDeviceExtension->ParentDeviceObject == NULL)
return FALSE;
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
for(Index = 0; Index < USB_MAXCHILDREN; Index++)
{
if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject)
{
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
/* PDO exists */
return TRUE;
}
}
KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
/* invalid pdo */
return FALSE;
@ -190,18 +199,31 @@ USBHUB_PdoHandleInternalDeviceControl(
ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
if(!IsValidPDO(DeviceObject))
Status = IoAcquireRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
if (ChildDeviceExtension->Common.PnPState == SurpriseRemovePending ||
ChildDeviceExtension->Common.PnPState == RemovePending ||
ChildDeviceExtension->ParentDeviceObject == NULL)
{
// Parent or child device was surprise removed.
DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject);
Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
return STATUS_DEVICE_NOT_CONNECTED;
}
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
@ -301,6 +323,7 @@ USBHUB_PdoHandleInternalDeviceControl(
// Send the request to RootHub
//
Status = ForwardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL);
IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
return Status;
}
//
@ -397,6 +420,7 @@ USBHUB_PdoHandleInternalDeviceControl(
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
return Status;
}
@ -421,6 +445,8 @@ USBHUB_PdoStartDevice(
IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_DEVICE, NULL, &ChildDeviceExtension->SymbolicLinkName);
IoSetDeviceInterfaceState(&ChildDeviceExtension->SymbolicLinkName, TRUE);
SET_NEW_PNP_STATE(ChildDeviceExtension->Common, Started);
UNIMPLEMENTED
return STATUS_SUCCESS;
}
@ -563,15 +589,20 @@ USBHUB_PdoHandlePnp(
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = 0;
PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
ULONG Index;
ULONG bFound;
PDEVICE_RELATIONS DeviceRelation;
PDEVICE_OBJECT ParentDevice;
UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
Status = IoAcquireRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
switch (MinorFunction)
{
case IRP_MN_START_DEVICE:
@ -628,17 +659,20 @@ USBHUB_PdoHandlePnp(
}
case IRP_MN_QUERY_DEVICE_TEXT:
{
DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information);
break;
}
case IRP_MN_QUERY_ID:
{
DPRINT("IRP_MN_QUERY_ID\n");
Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information);
break;
}
case IRP_MN_QUERY_BUS_INFORMATION:
{
PPNP_BUS_INFORMATION BusInfo;
DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
RtlCopyMemory(&BusInfo->BusTypeGuid,
&GUID_BUS_TYPE_USB,
@ -654,42 +688,58 @@ USBHUB_PdoHandlePnp(
{
PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension;
PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface;
ParentDevice = UsbChildExtension->ParentDeviceObject;
DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
/* remove us from pdo list */
bFound = FALSE;
for(Index = 0; Index < USB_MAXCHILDREN; Index++)
ASSERT((UsbChildExtension->Common.PnPState == RemovePending) ||
(UsbChildExtension->Common.PnPState == SurpriseRemovePending));
SET_NEW_PNP_STATE(UsbChildExtension->Common, NotStarted);
if (!IsValidPDO(DeviceObject))
{
if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject)
// Parent or child device was surprise removed, freeing resources allocated for child device.
SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted);
IoReleaseRemoveLockAndWait(&UsbChildExtension->Common.RemoveLock, Irp);
// Remove the usb device
if (UsbChildExtension->UsbDeviceHandle)
{
/* Remove the device */
Status = HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0);
/* FIXME handle error */
ASSERT(Status == STATUS_SUCCESS);
/* remove us */
HubDeviceExtension->ChildDeviceObject[Index] = NULL;
bFound = TRUE;
break;
Status = HubInterface->RemoveUsbDevice(HubInterface->BusContext, UsbChildExtension->UsbDeviceHandle, 0);
ASSERT(Status == STATUS_SUCCESS);
}
// Free full configuration descriptor
if (UsbChildExtension->FullConfigDesc)
ExFreePool(UsbChildExtension->FullConfigDesc);
// Free ID buffers
if (UsbChildExtension->usCompatibleIds.Buffer)
ExFreePool(UsbChildExtension->usCompatibleIds.Buffer);
if (UsbChildExtension->usDeviceId.Buffer)
ExFreePool(UsbChildExtension->usDeviceId.Buffer);
if (UsbChildExtension->usHardwareIds.Buffer)
ExFreePool(UsbChildExtension->usHardwareIds.Buffer);
if (UsbChildExtension->usInstanceId.Buffer)
ExFreePool(UsbChildExtension->usInstanceId.Buffer);
DPRINT("Deleting child PDO\n");
IoDeleteDevice(DeviceObject);
}
else
{
IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
}
// If device is physically presented, we leave its PDO undeleted.
/* Complete the IRP */
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
/* delete device */
IoDeleteDevice(DeviceObject);
if (bFound)
{
/* invalidate device relations */
IoInvalidateDeviceRelations(ParentDevice, BusRelations);
}
return STATUS_SUCCESS;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
@ -699,6 +749,7 @@ USBHUB_PdoHandlePnp(
{
/* not supported */
Status = Irp->IoStatus.Status;
Information = Irp->IoStatus.Information;
break;
}
@ -722,13 +773,46 @@ USBHUB_PdoHandlePnp(
break;
}
case IRP_MN_QUERY_STOP_DEVICE:
{
//
// We should fail this request, because we're not handling IRP_MN_STOP_DEVICE for now.
// We'll receive this IRP ONLY when the PnP manager rebalances resources.
//
Status = STATUS_NOT_SUPPORTED;
break;
}
case IRP_MN_QUERY_REMOVE_DEVICE:
{
//
// Free interface obtained from bottom, according MSDN we should
// check interfaces provided to top, but here we are not checking.
// All checking will be performed in roothub driver's
// IRP_MN_QUERY_REMOVE_DEVICE handler. This will make problems when
// buggy driver is loaded on top of us. But we decided to keep source
// simpler, because in any case buggy driver will prevent removing of
// whole stack.
//
UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext);
SET_NEW_PNP_STATE(UsbChildExtension->Common, RemovePending);
/* Sure, no problem */
Status = STATUS_SUCCESS;
Information = 0;
break;
}
case IRP_MN_CANCEL_REMOVE_DEVICE:
{
// Check to see have we received query-remove before
if (UsbChildExtension->Common.PnPState == RemovePending)
{
RESTORE_PREVIOUS_PNP_STATE(UsbChildExtension->Common);
UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext);
}
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_INTERFACE:
{
DPRINT1("IRP_MN_QUERY_INTERFACE\n");
@ -736,17 +820,28 @@ USBHUB_PdoHandlePnp(
{
DPRINT1("USB_BUS_INTERFACE_USBDI_GUID\n");
RtlCopyMemory(Stack->Parameters.QueryInterface.Interface, &UsbChildExtension->DeviceInterface, Stack->Parameters.QueryInterface.Size);
UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext);
Status = STATUS_SUCCESS;
break;
}
// pass irp down
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp);
Status = IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp);
IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
return Status;
}
case IRP_MN_SURPRISE_REMOVAL:
{
DPRINT("[USBHUB] HandlePnp IRP_MN_SURPRISE_REMOVAL\n");
//
// Here we should free all resources and stop all access, lets just set
// the flag and do further clean-up in subsequent IRP_MN_REMOVE_DEVICE
// We can receive this IRP when device is physically connected (on stop/start fail).
//
SET_NEW_PNP_STATE(UsbChildExtension->Common, SurpriseRemovePending);
Status = STATUS_SUCCESS;
break;
}
@ -758,6 +853,8 @@ USBHUB_PdoHandlePnp(
}
}
IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);

View file

@ -62,7 +62,7 @@ USBHUB_AddDevice(
PDEVICE_OBJECT DeviceObject;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
NTSTATUS Status;
DPRINT("USBHUB: AddDevice\n");
DPRINT("USBHUB: AddDevice (%p)\n", PhysicalDeviceObject);
//
// Create the Device Object
//
@ -86,12 +86,20 @@ USBHUB_AddDevice(
HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlZeroMemory(HubDeviceExtension, sizeof(HUB_DEVICE_EXTENSION));
INITIALIZE_PNP_STATE(HubDeviceExtension->Common);
//
// Set this to Fdo
//
HubDeviceExtension->Common.IsFDO = TRUE;
DeviceObject->Flags |= DO_POWER_PAGABLE;
// initialize mutex
KeInitializeGuardedMutex(&HubDeviceExtension->HubMutexLock);
// initialize remove lock
IoInitializeRemoveLock(&HubDeviceExtension->Common.RemoveLock, 'buH', 0, 0);
//
// initialize reset complete event
//
@ -158,6 +166,18 @@ USBHUB_DispatchDeviceControl(
return USBHUB_IrpStub(DeviceObject, Irp);
}
NTSTATUS NTAPI
USBHUB_DispatchSystemControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
DPRINT("Usbhub: DispatchSystemControl\n");
if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO)
return USBHUB_IrpStub(DeviceObject, Irp);
else
return USBHUB_IrpStub(DeviceObject, Irp);
}
NTSTATUS NTAPI
USBHUB_DispatchInternalDeviceControl(
PDEVICE_OBJECT DeviceObject,
@ -188,37 +208,59 @@ USBHUB_DispatchPower(
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
PHUB_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
IoStack = IoGetCurrentIrpStackLocation(Irp);
DeviceExtension = DeviceObject->DeviceExtension;
Status = IoAcquireRemoveLock(&DeviceExtension->Common.RemoveLock, Irp);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
DPRINT1("Power Function %x\n", IoStack->MinorFunction);
if (IoStack->MinorFunction == IRP_MN_SET_POWER)
if (DeviceExtension->Common.IsFDO)
{
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(Irp);
Status = PoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
IoReleaseRemoveLock(&DeviceExtension->Common.RemoveLock, Irp);
return Status;
}
else if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
{
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
else if (IoStack->MinorFunction == IRP_MN_WAIT_WAKE)
switch (IoStack->MinorFunction)
{
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
case IRP_MN_SET_POWER:
{
DPRINT("IRP_MN_SET_POWER\n");
break;
}
case IRP_MN_QUERY_POWER:
{
DPRINT("IRP_MN_QUERY_POWER\n");
break;
}
case IRP_MN_WAIT_WAKE:
{
DPRINT("IRP_MN_WAIT_WAKE\n");
break;
}
default:
{
DPRINT1("PDO IRP_MJ_POWER / unknown minor function 0x%lx\n", IoStack->MinorFunction);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
}
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock(&DeviceExtension->Common.RemoveLock, Irp);
return STATUS_SUCCESS;
}
@ -245,6 +287,7 @@ DriverEntry(
DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBHUB_Close;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = USBHUB_Cleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBHUB_DispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBHUB_DispatchSystemControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBHUB_DispatchInternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = USBHUB_DispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] =USBHUB_DispatchPower;

View file

@ -39,9 +39,43 @@ typedef struct _WORK_ITEM_DATA
PVOID Context;
} WORK_ITEM_DATA, *PWORK_ITEM_DATA;
//
// Definitions for device's PnP state tracking, all this states are described
// in PnP Device States diagram of DDK documentation.
//
typedef enum _DEVICE_PNP_STATE {
NotStarted = 0, // Not started
Started, // After handling of START_DEVICE IRP
StopPending, // After handling of QUERY_STOP IRP
Stopped, // After handling of STOP_DEVICE IRP
RemovePending, // After handling of QUERY_REMOVE IRP
SurpriseRemovePending, // After handling of SURPRISE_REMOVE IRP
Deleted, // After handling of REMOVE_DEVICE IRP
UnKnown // Unknown state
} DEVICE_PNP_STATE;
#define INITIALIZE_PNP_STATE(Data) \
(Data).PnPState = NotStarted;\
(Data).PreviousPnPState = NotStarted;
#define SET_NEW_PNP_STATE(Data, state) \
(Data).PreviousPnPState = (Data).PnPState;\
(Data).PnPState = (state);
#define RESTORE_PREVIOUS_PNP_STATE(Data) \
(Data).PnPState = (Data).PreviousPnPState;
typedef struct
{
BOOLEAN IsFDO;
// We'll track device PnP state via this variables
DEVICE_PNP_STATE PnPState;
DEVICE_PNP_STATE PreviousPnPState;
// Remove lock
IO_REMOVE_LOCK RemoveLock;
} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
typedef struct _HUB_CHILDDEVICE_EXTENSION
@ -72,6 +106,8 @@ typedef struct _HUB_DEVICE_EXTENSION
PDEVICE_OBJECT RootHubPhysicalDeviceObject;
PDEVICE_OBJECT RootHubFunctionalDeviceObject;
KGUARDED_MUTEX HubMutexLock;
ULONG NumberOfHubs;
KEVENT ResetComplete;
@ -94,7 +130,6 @@ typedef struct _HUB_DEVICE_EXTENSION
USBD_CONFIGURATION_HANDLE ConfigurationHandle;
USBD_PIPE_HANDLE PipeHandle;
PVOID RootHubHandle;
USB_BUS_INTERFACE_USBDI_V2 DeviceInterface;
UNICODE_STRING SymbolicLinkName;
ULONG InstanceCount;

View file

@ -163,7 +163,7 @@ HidParser_StoreCollection(
//
// store offset
//
TargetCollection->Offsets[Collection->NodeCount + Index] = CurrentOffset;
TargetCollection->Offsets[Collection->ReportCount + Index] = CurrentOffset;
//
// store sub collections
@ -254,7 +254,7 @@ HidParser_SearchReportInCollection(
//
// get collection
//
SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->NodeCount + Index]);
SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->ReportCount + Index]);
//
// recursively search collection
@ -314,7 +314,7 @@ HidParser_GetCollectionCount(
//
// get offset to sub collection
//
SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->NodeCount + Index]);
SubCollection = (PHID_COLLECTION)(CollectionContext->RawData + Collection->Offsets[Collection->ReportCount + Index]);
//
// count collection for sub nodes

View file

@ -68,7 +68,7 @@ HidParser_GetCollectionDescription(
// failed to parse report descriptor
//
Parser->Debug("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus);
return TranslateHidParserStatus(ParserStatus);
return ParserStatus;
}
//
@ -126,7 +126,9 @@ HidParser_GetCollectionDescription(
//
// no memory
//
return TranslateHidParserStatus(ParserStatus);
Parser->Free(DeviceDescription->CollectionDesc);
Parser->Free(DeviceDescription->ReportIDs);
return ParserStatus;
}
//
@ -153,6 +155,13 @@ HidParser_GetCollectionDescription(
// get collection usage page
//
ParserStatus = HidParser_GetCollectionUsagePage((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage);
if (ParserStatus != HIDPARSER_STATUS_SUCCESS)
{
// collection not found
Parser->Free(DeviceDescription->CollectionDesc);
Parser->Free(DeviceDescription->ReportIDs);
return ParserStatus;
}
//
// windows seems to prepend the report id, regardless if it is required

View file

@ -713,30 +713,6 @@ HidParser_AddMainItem(
return HIDPARSER_STATUS_SUCCESS;
}
HIDPARSER_STATUS
AllocateParserContext(
IN PHID_PARSER Parser,
OUT PHID_PARSER_CONTEXT *OutParserContext)
{
PHID_PARSER_CONTEXT ParserContext;
ParserContext = Parser->Alloc(sizeof(HID_PARSER_CONTEXT));
if (!ParserContext)
{
//
// failed
//
return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
}
//
// store result
//
*OutParserContext = ParserContext;
return HIDPARSER_STATUS_SUCCESS;
}
HIDPARSER_STATUS
HidParser_ParseReportDescriptor(
IN PHID_PARSER Parser,
@ -760,12 +736,18 @@ HidParser_ParseReportDescriptor(
PMAIN_ITEM_DATA MainItemData;
PHID_PARSER_CONTEXT ParserContext;
CurrentOffset = ReportDescriptor;
ReportEnd = ReportDescriptor + ReportLength;
if (ReportDescriptor >= ReportEnd)
return HIDPARSER_STATUS_COLLECTION_NOT_FOUND;
//
// allocate parser
//
Status = AllocateParserContext(Parser, &ParserContext);
if (Status != HIDPARSER_STATUS_SUCCESS)
return Status;
ParserContext = Parser->Alloc(sizeof(HID_PARSER_CONTEXT));;
if (!ParserContext)
return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
//
@ -778,6 +760,7 @@ HidParser_ParseReportDescriptor(
//
// no memory
//
Parser->Free(ParserContext);
return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
}
@ -792,6 +775,7 @@ HidParser_ParseReportDescriptor(
//
Parser->Free(ParserContext->LocalItemState.UsageStack);
ParserContext->LocalItemState.UsageStack = NULL;
Parser->Free(ParserContext);
return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
}
@ -799,8 +783,6 @@ HidParser_ParseReportDescriptor(
// start parsing
//
CurrentCollection = ParserContext->RootCollection;
CurrentOffset = ReportDescriptor;
ReportEnd = ReportDescriptor + ReportLength;
do
{
@ -1230,8 +1212,7 @@ HidParser_ParseReportDescriptor(
//
CurrentOffset += CurrentItemSize + sizeof(ITEM_PREFIX);
}while(CurrentOffset < ReportEnd);
}while (CurrentOffset < ReportEnd);
//

View file

@ -568,7 +568,8 @@ CHubController::HandlePnp(
break;
}
}
Status = STATUS_SUCCESS;
// Here we should leave Status as is.
Status = Irp->IoStatus.Status;
break;
}
case IRP_MN_QUERY_CAPABILITIES:
@ -611,6 +612,14 @@ CHubController::HandlePnp(
// handle device interface requests
//
Status = HandleQueryInterface(IoStack);
//
// If a bus driver does not export the requested interface, it
// should leave Status as is.
//
if (Status == STATUS_NOT_SUPPORTED)
Status = Irp->IoStatus.Status;
break;
}
case IRP_MN_REMOVE_DEVICE:
@ -3736,6 +3745,7 @@ CHubController::HandleQueryInterface(
InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
}
InterfaceHub->InterfaceReference(InterfaceHub->BusContext);
//
// request completed
//
@ -3790,6 +3800,7 @@ CHubController::HandleQueryInterface(
InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
}
InterfaceDI->InterfaceReference(InterfaceDI->BusContext);
//
// request completed
//