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(
OUT PHIDP_DEVICE_DESC DeviceDescription)
{
HID_PARSER Parser;
+ NTSTATUS Status;
//
// init parser
//
// get description;
//
- return HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
+ Status = HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
+ return TranslateStatusForUpperLayer(Status);
}
HIDAPI
add_definitions(-DDEBUG_MODE)
+add_definitions(-DNTDDI_VERSION=0x05020400)
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
list(APPEND SOURCE
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)
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])
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);
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)
{
UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject;
UsbChildExtension->PortNumber = PortId;
- // copy device interface
- RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->DeviceInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2));
-
-
//
// Create the UsbDeviceObject
//
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
//
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;
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
//
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
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
{
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;
if (!Urb)
{
// no memory
- return STATUS_INSUFFICIENT_RESOURCES;
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto cleanup;
}
// zero urb
{
// 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
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
{
// 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
{
// 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;
{
// 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
{
// failed
DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status);
- ExFreePool(Urb);
- return Status;
+ goto cleanup;
}
//
{
// failed to get device descriptor of hub
DPRINT1("Failed to get HubDeviceDescriptor!\n");
- ExFreePool(Urb);
- return Status;
+ goto cleanup;
}
// build configuration request
{
// failed to get configuration descriptor
DPRINT1("Failed to get RootHub Configuration with status %x\n", Status);
- ExFreePool(Urb);
- return Status;
+ goto cleanup;
}
// sanity checks
{
// 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);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get Hub Descriptor!\n");
- ExFreePool(Urb);
- return STATUS_UNSUCCESSFUL;
+ Status = STATUS_UNSUCCESSFUL;
+ goto cleanup;
}
// sanity checks
{
// 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
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,
{
// failed parse hub descriptor
DPRINT1("Failed to parse configuration descriptor\n");
- ExFreePool(Urb);
- return STATUS_UNSUCCESSFUL;
+ Status = STATUS_UNSUCCESSFUL;
+ goto cleanup;
}
// create configuration request
{
// failed to build urb
DPRINT1("Failed to allocate urb\n");
- ExFreePool(Urb);
- return STATUS_INSUFFICIENT_RESOURCES;
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto cleanup;
}
// send request
{
// 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
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)
{
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to set callback\n");
- ExFreePool(Urb);
- return Status;
+ goto cleanup;
}
}
else
// 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
{
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
{
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:
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);
+
+ 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;
+ }
- Information = (ULONG_PTR)DeviceRelations;
+ 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;
}
// 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
// sanity checks
ASSERT(NodeConnectionInfo);
+ KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
for(Index = 0; Index < USB_MAXCHILDREN; Index++)
{
if (HubDeviceExtension->ChildDeviceObject[Index] == NULL)
}
break;
}
+ KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock);
// done
Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION);
Status = STATUS_SUCCESS;
// sanity checks
ASSERT(NodeKey);
+ KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock);
for(Index = 0; Index < USB_MAXCHILDREN; Index++)
{
if (HubDeviceExtension->ChildDeviceObject[Index] == NULL)
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)
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp);
return Status;
}
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;
-}
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;
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:
// Send the request to RootHub
//
Status = ForwardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL);
+ IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
return Status;
}
//
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
+ IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp);
return Status;
}
IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_DEVICE, NULL, &ChildDeviceExtension->SymbolicLinkName);
IoSetDeviceInterfaceState(&ChildDeviceExtension->SymbolicLinkName, TRUE);
+ SET_NEW_PNP_STATE(ChildDeviceExtension->Common, Started);
+
UNIMPLEMENTED
return STATUS_SUCCESS;
}
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:
}
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,
{
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)
- {
- /* Remove the device */
- Status = HubInterface->RemoveUsbDevice(HubDeviceExtension->UsbDInterface.BusContext, UsbChildExtension->UsbDeviceHandle, 0);
+ // Parent or child device was surprise removed, freeing resources allocated for child device.
+ SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted);
- /* FIXME handle error */
- ASSERT(Status == STATUS_SUCCESS);
+ IoReleaseRemoveLockAndWait(&UsbChildExtension->Common.RemoveLock, Irp);
- /* remove us */
- HubDeviceExtension->ChildDeviceObject[Index] = NULL;
- bFound = TRUE;
- break;
+ // 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);
- /* Complete the IRP */
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ // 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);
- /* delete device */
- IoDeleteDevice(DeviceObject);
+ if (UsbChildExtension->usInstanceId.Buffer)
+ ExFreePool(UsbChildExtension->usInstanceId.Buffer);
- if (bFound)
+ DPRINT("Deleting child PDO\n");
+ IoDeleteDevice(DeviceObject);
+ }
+ else
{
- /* invalidate device relations */
- IoInvalidateDeviceRelations(ParentDevice, BusRelations);
+ 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);
+
return STATUS_SUCCESS;
}
case IRP_MN_QUERY_DEVICE_RELATIONS:
{
/* not supported */
Status = Irp->IoStatus.Status;
+ Information = Irp->IoStatus.Information;
break;
}
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");
{
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;
}
}
}
+ IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp);
+
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
PDEVICE_OBJECT DeviceObject;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
NTSTATUS Status;
- DPRINT("USBHUB: AddDevice\n");
+ DPRINT("USBHUB: AddDevice (%p)\n", PhysicalDeviceObject);
//
// Create the Device Object
//
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
//
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,
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
-
+ PHUB_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
IoStack = IoGetCurrentIrpStackLocation(Irp);
- DPRINT1("Power Function %x\n", IoStack->MinorFunction);
+ DeviceExtension = DeviceObject->DeviceExtension;
- if (IoStack->MinorFunction == IRP_MN_SET_POWER)
+ Status = IoAcquireRemoveLock(&DeviceExtension->Common.RemoveLock, Irp);
+ if (!NT_SUCCESS(Status))
{
- PoStartNextPowerIrp(Irp);
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
-
+ return Status;
}
- else if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
+
+ DPRINT1("Power Function %x\n", IoStack->MinorFunction);
+
+ 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_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;
}
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;
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
PDEVICE_OBJECT RootHubPhysicalDeviceObject;
PDEVICE_OBJECT RootHubFunctionalDeviceObject;
+ KGUARDED_MUTEX HubMutexLock;
+
ULONG NumberOfHubs;
KEVENT ResetComplete;
USBD_CONFIGURATION_HANDLE ConfigurationHandle;
USBD_PIPE_HANDLE PipeHandle;
PVOID RootHubHandle;
- USB_BUS_INTERFACE_USBDI_V2 DeviceInterface;
UNICODE_STRING SymbolicLinkName;
ULONG InstanceCount;
//
// store offset
//
- TargetCollection->Offsets[Collection->NodeCount + Index] = CurrentOffset;
+ TargetCollection->Offsets[Collection->ReportCount + Index] = CurrentOffset;
//
// store sub collections
//
// 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
//
// 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
// failed to parse report descriptor
//
Parser->Debug("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus);
- return TranslateHidParserStatus(ParserStatus);
+ return ParserStatus;
}
//
//
// no memory
//
- return TranslateHidParserStatus(ParserStatus);
+ Parser->Free(DeviceDescription->CollectionDesc);
+ Parser->Free(DeviceDescription->ReportIDs);
+ return ParserStatus;
}
//
// 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
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,
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;
//
//
// no memory
//
+ Parser->Free(ParserContext);
return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
}
//
Parser->Free(ParserContext->LocalItemState.UsageStack);
ParserContext->LocalItemState.UsageStack = NULL;
+ Parser->Free(ParserContext);
return HIDPARSER_STATUS_INSUFFICIENT_RESOURCES;
}
// start parsing
//
CurrentCollection = ParserContext->RootCollection;
- CurrentOffset = ReportDescriptor;
- ReportEnd = ReportDescriptor + ReportLength;
do
{
//
CurrentOffset += CurrentItemSize + sizeof(ITEM_PREFIX);
-
- }while(CurrentOffset < ReportEnd);
+ }while (CurrentOffset < ReportEnd);
//
break;
}
}
- Status = STATUS_SUCCESS;
+ // Here we should leave Status as is.
+ Status = Irp->IoStatus.Status;
break;
}
case IRP_MN_QUERY_CAPABILITIES:
// 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:
InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData;
}
+ InterfaceHub->InterfaceReference(InterfaceHub->BusContext);
//
// request completed
//
InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry;
}
+ InterfaceDI->InterfaceReference(InterfaceDI->BusContext);
//
// request completed
//