reactos/drivers/usb/usbhub/fdo.c
Timo Kreuzer 912ce51ae6 [CMAKE]
Sync with trunk head (r48826)

svn path=/branches/cmake-bringup/; revision=48831
2010-09-20 17:27:52 +00:00

1191 lines
50 KiB
C
Raw Blame History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: USB hub driver
* FILE: drivers/usb/cromwell/hub/fdo.c
* PURPOSE: IRP_MJ_PNP operations for FDOs
*
* PROGRAMMERS: Herv<72> Poussineau (hpoussin@reactos.com)
* Michael Martin (michael.martin@reactos.org)
*/
#define INITGUID
#include <stdio.h>
#define NDEBUG
#include "usbhub.h"
#include "usbdlib.h"
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
typedef struct _PORTSTATUSANDCHANGE
{
USHORT Status;
USHORT Change;
} PORTSTATUSANDCHANGE, *PPORTSTATUSANDCHANGE;
NTSTATUS
QueryRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, OUT PVOID OutParameter1, OUT PVOID OutParameter2);
NTSTATUS
WaitForUsbDeviceArrivalNotification(PDEVICE_OBJECT DeviceObject);
NTSTATUS
SubmitUrbToRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, IN PURB Urb);
VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
{
DPRINT1("Dumping Device Descriptor %x\n", DeviceDescriptor);
DPRINT1("bLength %x\n", DeviceDescriptor->bLength);
DPRINT1("bDescriptorType %x\n", DeviceDescriptor->bDescriptorType);
DPRINT1("bcdUSB %x\n", DeviceDescriptor->bcdUSB);
DPRINT1("bDeviceClass %x\n", DeviceDescriptor->bDeviceClass);
DPRINT1("bDeviceSubClass %x\n", DeviceDescriptor->bDeviceSubClass);
DPRINT1("bDeviceProtocol %x\n", DeviceDescriptor->bDeviceProtocol);
DPRINT1("bMaxPacketSize0 %x\n", DeviceDescriptor->bMaxPacketSize0);
DPRINT1("idVendor %x\n", DeviceDescriptor->idVendor);
DPRINT1("idProduct %x\n", DeviceDescriptor->idProduct);
DPRINT1("bcdDevice %x\n", DeviceDescriptor->bcdDevice);
DPRINT1("iManufacturer %x\n", DeviceDescriptor->iManufacturer);
DPRINT1("iProduct %x\n", DeviceDescriptor->iProduct);
DPRINT1("iSerialNumber %x\n", DeviceDescriptor->iSerialNumber);
DPRINT1("bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations);
}
VOID DumpFullConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
{
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
LONG i, j;
DPRINT1("Duming ConfigurationDescriptor %x\n", ConfigurationDescriptor);
DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) ((ULONG_PTR)ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
for (i=0; i < ConfigurationDescriptor->bNumInterfaces; i++)
{
DPRINT1("- Dumping InterfaceDescriptor %x\n", InterfaceDescriptor);
DPRINT1(" bLength %x\n", InterfaceDescriptor->bLength);
DPRINT1(" bDescriptorType %x\n", InterfaceDescriptor->bDescriptorType);
DPRINT1(" bInterfaceNumber %x\n", InterfaceDescriptor->bInterfaceNumber);
DPRINT1(" bAlternateSetting %x\n", InterfaceDescriptor->bAlternateSetting);
DPRINT1(" bNumEndpoints %x\n", InterfaceDescriptor->bNumEndpoints);
DPRINT1(" bInterfaceClass %x\n", InterfaceDescriptor->bInterfaceClass);
DPRINT1(" bInterfaceSubClass %x\n", InterfaceDescriptor->bInterfaceSubClass);
DPRINT1(" bInterfaceProtocol %x\n", InterfaceDescriptor->bInterfaceProtocol);
DPRINT1(" iInterface %x\n", InterfaceDescriptor->iInterface);
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)InterfaceDescriptor + sizeof(USB_INTERFACE_DESCRIPTOR));
for (j=0; j < InterfaceDescriptor->bNumEndpoints; j++)
{
DPRINT1(" bLength %x\n", EndpointDescriptor->bLength);
DPRINT1(" bDescriptorType %x\n", EndpointDescriptor->bDescriptorType);
DPRINT1(" bEndpointAddress %x\n", EndpointDescriptor->bEndpointAddress);
DPRINT1(" bmAttributes %x\n", EndpointDescriptor->bmAttributes);
DPRINT1(" wMaxPacketSize %x\n", EndpointDescriptor->wMaxPacketSize);
DPRINT1(" bInterval %x\n", EndpointDescriptor->bInterval);
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)EndpointDescriptor + sizeof(USB_ENDPOINT_DESCRIPTOR));
}
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ULONG_PTR)EndpointDescriptor;
}
}
VOID DumpInterfaceInfo(PUSBD_INTERFACE_INFORMATION InterfaceInformation)
{
PUSBD_PIPE_INFORMATION PipeInformation;
ULONG i;
DPRINT1("IntefaceLenth %x\n",InterfaceInformation->Length);
DPRINT1("InterfaceNumber %x\n",InterfaceInformation->InterfaceNumber);
DPRINT1("AlternateSetting %x\n",InterfaceInformation->AlternateSetting);
DPRINT1("Class %x\n",InterfaceInformation->Class);
DPRINT1("SubClass %x\n",InterfaceInformation->SubClass);
DPRINT1("Protocol %x\n",InterfaceInformation->Protocol);
DPRINT1("Reserved %x\n",InterfaceInformation->Reserved);
DPRINT1("InterfaceHandle %x\n",InterfaceInformation->InterfaceHandle);
DPRINT1("NumberOfPipes %x\n", InterfaceInformation->NumberOfPipes);
PipeInformation = &InterfaceInformation->Pipes[0];
for (i = 0; i < InterfaceInformation->NumberOfPipes; i++)
{
DPRINT1("MaximumPacketSize %x\n", PipeInformation->MaximumPacketSize);
DPRINT1("EndpointAddress %x\n", PipeInformation->EndpointAddress);
DPRINT1("Interval %x\n", PipeInformation->Interval);
DPRINT1("PipeType %x\n", PipeInformation->PipeType);
DPRINT1("PipeHandle %x\n", PipeInformation->PipeHandle);
DPRINT1("PipeFlags %x\n", PipeInformation->PipeFlags);
DPRINT1("MaximumTransferSize %x\n", PipeInformation->MaximumTransferSize);
PipeInformation = (PUSBD_PIPE_INFORMATION)((ULONG_PTR)PipeInformation + sizeof(USBD_PIPE_INFORMATION));
}
}
VOID NTAPI
WorkerThread(IN PVOID Context)
{
PHUB_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT DeviceObject, Pdo;
PHUB_CHILDDEVICE_EXTENSION PdoExtension;
PURB Urb = NULL;
PORTSTATUSANDCHANGE PortStatusAndChange;
int PortLoop, DeviceCount;
NTSTATUS Status;
USB_DEVICE_DESCRIPTOR DevDesc;
USB_CONFIGURATION_DESCRIPTOR ConfigDesc;
ULONG DevDescSize, ConfigDescSize;
PUSB_STRING_DESCRIPTOR StringDesc;
USB_STRING_DESCRIPTOR LanguageIdDescriptor;
PWORKITEMDATA WorkItemData = (PWORKITEMDATA)Context;
DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context;
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Determine where in the children array to store this device info */
for (DeviceCount = 0; DeviceCount < USB_MAXCHILDREN; DeviceCount++)
{
if (DeviceExtension->UsbChildren[DeviceCount] == NULL)
{
break;
}
}
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG);
if (!Urb)
{
DPRINT1("Failed to allocate memory for URB!\n");
ASSERT(FALSE);
}
RtlZeroMemory(Urb, sizeof(URB));
for (PortLoop = 0; PortLoop < DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++)
{
/* Get the port status */
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_OUT,
0,
USB_REQUEST_GET_STATUS,
0,
PortLoop + 1,
&PortStatusAndChange,
0,
sizeof(PORTSTATUSANDCHANGE),
0);
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get PortStatus!\n");
goto CleanUp;
}
DPRINT("Notification Port %x:\n", PortLoop + 1);
DPRINT("Status %x\n", PortStatusAndChange.Status);
DPRINT("Change %x\n", PortStatusAndChange.Change);
if (PortStatusAndChange.Change == USB_PORT_STATUS_RESET)
{
/* Clear the Reset */
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN,
0,
USB_REQUEST_CLEAR_FEATURE,
C_PORT_RESET,
PortLoop + 1,
&PortStatusAndChange,
0,
sizeof(PORTSTATUSANDCHANGE),
0);
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to Clear the Port Reset with Status %x!\n", Status);
goto CleanUp;
}
UsbBuildVendorRequest(Urb, URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_OUT,
0,
USB_REQUEST_GET_STATUS,
0,
PortLoop + 1,
&PortStatusAndChange,
0,
sizeof(PORTSTATUSANDCHANGE),
0);
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
DPRINT("Status %x\n", PortStatusAndChange.Status);
DPRINT("Change %x\n", PortStatusAndChange.Change);
/* Create the UsbDevice */
Status = DeviceExtension->HubInterface.CreateUsbDevice(DeviceExtension->RootHubPdo,
(PVOID)&DeviceExtension->UsbChildren[DeviceCount],
DeviceExtension->RootHubUsbDevice,
PortStatusAndChange.Status,
PortLoop + 1);
DPRINT1("CreateUsbDevice Status %x\n", Status);
Status = DeviceExtension->HubInterface.InitializeUsbDevice(DeviceExtension->RootHubPdo, DeviceExtension->UsbChildren[DeviceCount]);
DPRINT1("InitializeUsbDevice Status %x\n", Status);
DevDescSize = sizeof(USB_DEVICE_DESCRIPTOR);
ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR);
Status = DeviceExtension->HubInterface.GetUsbDescriptors(DeviceExtension->RootHubPdo,
DeviceExtension->UsbChildren[DeviceCount],
(PUCHAR)&DevDesc,
&DevDescSize,
(PUCHAR)&ConfigDesc,
&ConfigDescSize);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to Get Usb Deccriptors %x!\n", Status);
}
DumpDeviceDescriptor(&DevDesc);
Status = IoCreateDevice(DeviceObject->DriverObject,
sizeof(HUB_CHILDDEVICE_EXTENSION),
NULL,
FILE_DEVICE_CONTROLLER,
FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&DeviceExtension->Children[DeviceCount]);
if (!NT_SUCCESS(Status))
{
DPRINT1("UsbHub; IoCreateDevice failed with status %x\n",Status);
goto CleanUp;
}
Pdo = DeviceExtension->Children[DeviceCount];
DPRINT1("Created New Device with %x\n", Pdo);
Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
PdoExtension = Pdo->DeviceExtension;
RtlZeroMemory(PdoExtension, sizeof(HUB_CHILDDEVICE_EXTENSION));
PdoExtension->DeviceId = ExAllocatePoolWithTag(NonPagedPool, 32 * sizeof(WCHAR), USB_HUB_TAG);
RtlZeroMemory(PdoExtension->DeviceId, 32 * sizeof(WCHAR));
swprintf(PdoExtension->DeviceId, L"USB\\Vid_%04x&Pid_%04x", DevDesc.idVendor, DevDesc.idProduct);
/* Get the LANGids */
RtlZeroMemory(&LanguageIdDescriptor, sizeof(USB_STRING_DESCRIPTOR));
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_STRING_DESCRIPTOR_TYPE,
0,
0,
&LanguageIdDescriptor,
NULL,
sizeof(USB_STRING_DESCRIPTOR),
NULL);
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount];
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
/* Get the length of the SerialNumber */
StringDesc = ExAllocatePoolWithTag(PagedPool, 64, USB_HUB_TAG);
RtlZeroMemory(StringDesc, 64);
StringDesc->bLength = 0;
StringDesc->bDescriptorType = 0;
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_STRING_DESCRIPTOR_TYPE,
DevDesc.iSerialNumber,
LanguageIdDescriptor.bString[0],
StringDesc,
NULL,
64,
NULL);
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount];
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
PdoExtension->InstanceId = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG);
DPRINT1("PdoExtension->InstanceId %x\n",PdoExtension->InstanceId);
RtlZeroMemory(PdoExtension->InstanceId, (StringDesc->bLength + 1) * sizeof(WCHAR));
RtlCopyMemory(PdoExtension->InstanceId, &StringDesc->bString[0], StringDesc->bLength);
DPRINT1("------>SerialNumber %S\n", PdoExtension->InstanceId);
RtlZeroMemory(StringDesc, 64);
StringDesc->bLength = 0;
StringDesc->bDescriptorType = 0;
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_STRING_DESCRIPTOR_TYPE,
DevDesc.iProduct,
LanguageIdDescriptor.bString[0],
StringDesc,
NULL,
64,
NULL);
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->UsbChildren[DeviceCount];
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
PdoExtension->TextDescription = ExAllocatePoolWithTag(NonPagedPool, (StringDesc->bLength + 1) * sizeof(WCHAR), USB_HUB_TAG);
RtlZeroMemory(PdoExtension->TextDescription, (StringDesc->bLength + 1) * sizeof(WCHAR));
RtlCopyMemory(PdoExtension->TextDescription, &StringDesc->bString[0], StringDesc->bLength);
ExFreePool(StringDesc);
DPRINT1("------>TextDescription %S\n", PdoExtension->TextDescription);
PdoExtension->IsFDO = FALSE;
PdoExtension->Parent = DeviceObject;
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
ExFreePool(WorkItemData);
ExFreePool(Urb);
IoInvalidateDeviceRelations(DeviceExtension->RootHubPdo, BusRelations);
return;
}
/* Is a device connected to this port */
if (PortStatusAndChange.Change == USB_PORT_STATUS_CONNECT)
{
/* Clear the Connect from ProtChange */
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN,
0,
USB_REQUEST_CLEAR_FEATURE,
C_PORT_CONNECTION,
PortLoop + 1,
&PortStatusAndChange,
0,
sizeof(PORTSTATUSANDCHANGE),
0);
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to Clear the Port Connect!\n");
goto CleanUp;
}
/* Send the miniport controller a SCE request so when the port resets we can be informed */
WaitForUsbDeviceArrivalNotification(DeviceObject);
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN,
0,
USB_REQUEST_SET_FEATURE,
PORT_RESET,
PortLoop + 1,
&PortStatusAndChange,
0,
sizeof(PORTSTATUSANDCHANGE),
0);
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to Reset the port!\n");
goto CleanUp;
}
/* At this point the miniport will complete another SCE to inform of Reset completed */
}
}
CleanUp:
ExFreePool(WorkItemData);
ExFreePool(Urb);
}
NTSTATUS
DeviceArrivalCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
PHUB_DEVICE_EXTENSION DeviceExtension;
LONG i;
PWORKITEMDATA WorkItemData;
DeviceExtension = (PHUB_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
for (i=0; i < DeviceExtension->UsbExtHubInfo.NumberOfPorts; i++)
DPRINT1("Port %x DeviceExtension->PortStatus %x\n",i+1, DeviceExtension->PortStatus[i]);
IoFreeIrp(Irp);
WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEMDATA));
if (!WorkItemData)
{
DPRINT1("Failed to allocate memory\n");
return STATUS_NO_MEMORY;
}
RtlZeroMemory(WorkItemData, sizeof(WORKITEMDATA));
WorkItemData->Context = Context;
ExInitializeWorkItem(&WorkItemData->WorkItem, (PWORKER_THREAD_ROUTINE)WorkerThread, (PVOID)WorkItemData);
ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
WaitForUsbDeviceArrivalNotification(PDEVICE_OBJECT DeviceObject)
{
PURB Urb;
PIRP Irp;
NTSTATUS Status;
PIO_STACK_LOCATION Stack = NULL;
PHUB_DEVICE_EXTENSION DeviceExtension;
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Urb = &DeviceExtension->Urb;
RtlZeroMemory(Urb, sizeof(URB));
/* Send URB to the miniports Status Change Endpoint SCE */
UsbBuildInterruptOrBulkTransferRequest(Urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
DeviceExtension->PipeHandle,
&DeviceExtension->PortStatus,
NULL,
sizeof(ULONG) * 2,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL);
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
Irp = IoAllocateIrp(DeviceExtension->RootHubPdo->StackSize, FALSE);
if (Irp == NULL)
{
DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
Irp->Flags = 0;
Irp->UserBuffer = NULL;
Stack = IoGetCurrentIrpStackLocation(Irp);
Stack->DeviceObject = DeviceExtension->RootHubPdo;
Stack = IoGetNextIrpStackLocation(Irp);
Stack->DeviceObject = DeviceExtension->RootHubPdo;
Stack->Parameters.Others.Argument1 = Urb;
Stack->Parameters.Others.Argument2 = NULL;
Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
//IoSetCompletionRoutineEx(DeviceExtension->RootHubPdo, Irp, (PIO_COMPLETION_ROUTINE)DeviceArrivalCompletion, DeviceObject, TRUE, TRUE, TRUE);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)DeviceArrivalCompletion, DeviceObject, TRUE, TRUE, TRUE);
Status = IoCallDriver(DeviceExtension->RootHubPdo, Irp);
DPRINT1("SCE request status %x\n", Status);
return STATUS_PENDING;
}
NTSTATUS
SubmitUrbToRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, IN PURB Urb)
{
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PIO_STACK_LOCATION Stack = NULL;
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
Pdo,
NULL, 0,
NULL, 0,
TRUE,
NULL,
&IoStatus);
if (Irp == NULL)
{
DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Initialize the status block before sending the IRP */
IoStatus.Status = STATUS_NOT_SUPPORTED;
IoStatus.Information = 0;
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Parameters.Others.Argument1 = Urb;
Stack->Parameters.Others.Argument2 = NULL;
Status = IoCallDriver(Pdo, Irp);
return Status;
}
NTSTATUS
QueryRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, OUT PVOID OutParameter1, OUT PVOID OutParameter2)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PIO_STACK_LOCATION Stack = NULL;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
Pdo,
NULL, 0,
NULL, 0,
TRUE,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Initialize the status block before sending the IRP */
IoStatus.Status = STATUS_NOT_SUPPORTED;
IoStatus.Information = 0;
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Parameters.Others.Argument1 = OutParameter1;
Stack->Parameters.Others.Argument2 = OutParameter2;
Status = IoCallDriver(Pdo, Irp);
if (Status == STATUS_PENDING)
{
DPRINT1("Usbhub: Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
return Status;
}
NTSTATUS QueryInterface(IN PDEVICE_OBJECT Pdo, IN CONST GUID InterfaceType, IN LONG Size, IN LONG Version, OUT PVOID Interface)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PIO_STACK_LOCATION Stack = NULL;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
Pdo,
NULL,
0,
NULL,
&Event,
&IoStatus);
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
Stack->Parameters.QueryInterface.InterfaceType= &InterfaceType;//USB_BUS_INTERFACE_HUB_GUID;
Stack->Parameters.QueryInterface.Size = Size;
Stack->Parameters.QueryInterface.Version = Version;
Stack->Parameters.QueryInterface.Interface = Interface;
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
Status = IoCallDriver(Pdo, Irp);
if (Status == STATUS_PENDING)
{
DPRINT("Usbhub: Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
return Status;
}
static VOID
UsbhubGetUserBuffers(IN PIRP Irp, IN ULONG IoControlCode, OUT PVOID* BufferIn, OUT PVOID* BufferOut)
{
ASSERT(Irp);
ASSERT(BufferIn);
ASSERT(BufferOut);
switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
{
case METHOD_BUFFERED:
*BufferIn = *BufferOut = Irp->AssociatedIrp.SystemBuffer;
break;
case METHOD_IN_DIRECT:
case METHOD_OUT_DIRECT:
*BufferIn = Irp->AssociatedIrp.SystemBuffer;
*BufferOut = MmGetSystemAddressForMdl(Irp->MdlAddress);
break;
case METHOD_NEITHER:
*BufferIn = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.Type3InputBuffer;
*BufferOut = Irp->UserBuffer;
break;
default:
/* Should never happen */
*BufferIn = NULL;
*BufferOut = NULL;
break;
}
}
NTSTATUS
UsbhubFdoQueryBusRelations(IN PDEVICE_OBJECT DeviceObject, OUT PDEVICE_RELATIONS* pDeviceRelations)
{
PHUB_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS DeviceRelations;
ULONG i;
ULONG Children = 0;
ULONG NeededSize;
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DPRINT1("USBHUB: Query Bus Relations\n");
/* Create PDOs that are missing */
for (i = 0; i < USB_MAXCHILDREN; i++)
{
if (DeviceExtension->UsbChildren[i] == NULL)
{
continue;
}
Children++;
}
/* Fill returned structure */
NeededSize = sizeof(DEVICE_RELATIONS);
if (Children > 1)
NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT);
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool,
NeededSize);
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
DeviceRelations->Count = Children;
Children = 0;
for (i = 0; i < USB_MAXCHILDREN; i++)
{
if (DeviceExtension->Children[i])
{
ObReferenceObject(DeviceExtension->Children[i]);
DeviceRelations->Objects[Children++] = DeviceExtension->Children[i];
}
}
ASSERT(Children == DeviceRelations->Count);
*pDeviceRelations = DeviceRelations;
WaitForUsbDeviceArrivalNotification(DeviceObject);
return STATUS_SUCCESS;
}
VOID CallBackRoutine(IN PVOID Argument1)
{
DPRINT1("RH_INIT_CALLBACK %x\n", Argument1);
ASSERT(FALSE);
}
NTSTATUS NTAPI
UsbhubPnpFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status = STATUS_SUCCESS;
ULONG MinorFunction;
ULONG_PTR Information = 0;
PHUB_DEVICE_EXTENSION DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = IrpSp->MinorFunction;
DeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
switch (MinorFunction)
{
case IRP_MN_START_DEVICE: /* 0x0 */
{
PURB Urb;
ULONG Result = 0;
PUSB_INTERFACE_DESCRIPTOR Pid;
/* Theres only one descriptor on hub */
USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
PURB ConfigUrb = NULL;
/* We differ from windows on hubpdo because we dont have usbport.sys which manages all usb device objects */
DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
/* Allocating size including the sizeof USBD_INTERFACE_LIST_ENTRY */
Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY), USB_HUB_TAG);
RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY));
/* Get the hubs PDO */
QueryRootHub(DeviceExtension->LowerDevice, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, &DeviceExtension->RootHubPdo, &DeviceExtension->RootHubFdo);
ASSERT(DeviceExtension->RootHubPdo);
ASSERT(DeviceExtension->RootHubFdo);
DPRINT1("RootPdo %x, RootFdo %x\n", DeviceExtension->RootHubPdo, DeviceExtension->RootHubFdo);
/* Send the START_DEVICE irp down to the PDO of RootHub */
Status = ForwardIrpAndWait(DeviceExtension->RootHubPdo, Irp);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to start the RootHub PDO\n");
ASSERT(FALSE);
}
/* Get the current number of hubs */
QueryRootHub(DeviceExtension->RootHubPdo,IOCTL_INTERNAL_USB_GET_HUB_COUNT, &DeviceExtension->HubCount, NULL);
/* Get the Direct Call Interfaces */
Status = QueryInterface(DeviceExtension->RootHubPdo,
USB_BUS_INTERFACE_HUB_GUID,
sizeof(USB_BUS_INTERFACE_HUB_V5),
5,
(PVOID)&DeviceExtension->HubInterface);
if (!NT_SUCCESS(Status))
{
DPRINT1("UsbhubM Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
return STATUS_UNSUCCESSFUL;
}
Status = QueryInterface(DeviceExtension->RootHubPdo,
USB_BUS_INTERFACE_USBDI_GUID,
sizeof(USB_BUS_INTERFACE_USBDI_V2),
2,
(PVOID)&DeviceExtension->UsbDInterface);
if (!NT_SUCCESS(Status))
{
DPRINT1("UsbhubM Failed to get USBDI_GUID interface with status 0x%08lx\n", Status);
return STATUS_UNSUCCESSFUL;
}
/* Get roothub device handle */
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, &DeviceExtension->RootHubUsbDevice, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Usbhub: GetRootHubDeviceHandle failed with status 0x%08lx\n", Status);
return Status;
}
Status = DeviceExtension->HubInterface.QueryDeviceInformation(DeviceExtension->RootHubPdo,
DeviceExtension->RootHubUsbDevice,
&DeviceExtension->DeviceInformation,
sizeof(USB_DEVICE_INFORMATION_0),
&Result);
DPRINT("Status %x, Result %x\n", Status, Result);
DPRINT("InformationLevel %x\n", DeviceExtension->DeviceInformation.InformationLevel);
DPRINT("ActualLength %x\n", DeviceExtension->DeviceInformation.ActualLength);
DPRINT("PortNumber %x\n", DeviceExtension->DeviceInformation.PortNumber);
DPRINT("DeviceDescriptor %x\n", DeviceExtension->DeviceInformation.DeviceDescriptor);
DPRINT("HubAddress %x\n", DeviceExtension->DeviceInformation.HubAddress);
DPRINT("NumberofPipes %x\n", DeviceExtension->DeviceInformation.NumberOfOpenPipes);
/* Get roothubs device descriptor */
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
&DeviceExtension->HubDeviceDescriptor,
NULL,
sizeof(USB_DEVICE_DESCRIPTOR),
NULL);
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Usbhub: Failed to get HubDeviceDescriptor!\n");
}
DumpDeviceDescriptor(&DeviceExtension->HubDeviceDescriptor);
/* Get roothubs configuration descriptor */
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
&DeviceExtension->HubConfigDescriptor,
NULL,
sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
NULL);
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Usbhub: Failed to get RootHub Configuration with status %x\n", Status);
ASSERT(FALSE);
}
ASSERT(DeviceExtension->HubConfigDescriptor.wTotalLength);
DumpFullConfigurationDescriptor(&DeviceExtension->HubConfigDescriptor);
//DPRINT1("DeviceExtension->HubConfigDescriptor.wTotalLength %x\n", DeviceExtension->HubConfigDescriptor.wTotalLength);
Status = DeviceExtension->HubInterface.GetExtendedHubInformation(DeviceExtension->RootHubPdo,
DeviceExtension->RootHubPdo,
&DeviceExtension->UsbExtHubInfo,
sizeof(USB_EXTHUB_INFORMATION_0),
&Result);
if (!NT_SUCCESS(Status))
{
DPRINT1("Usbhub: Failed to extended hub information. Unable to determine the number of ports!\n");
ASSERT(FALSE);
}
DPRINT1("DeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", DeviceExtension->UsbExtHubInfo.NumberOfPorts);
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_DEVICE,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN,
0,
USB_DEVICE_CLASS_RESERVED,
0,
0,
&DeviceExtension->HubDescriptor,
NULL,
sizeof(USB_HUB_DESCRIPTOR),
NULL);
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
DPRINT1("bDescriptorType %x\n", DeviceExtension->HubDescriptor.bDescriptorType);
/* Select the configuration */
/* Get the first one */
Pid = USBD_ParseConfigurationDescriptorEx(&DeviceExtension->HubConfigDescriptor,
&DeviceExtension->HubConfigDescriptor,
-1, -1, -1, -1, -1);
ASSERT(Pid != NULL);
InterfaceList[0].InterfaceDescriptor = Pid;
ConfigUrb = USBD_CreateConfigurationRequestEx(&DeviceExtension->HubConfigDescriptor, (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
ASSERT(ConfigUrb != NULL);
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, ConfigUrb, NULL);
DeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle;
DeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
DPRINT1("Configuration Handle %x\n", DeviceExtension->ConfigurationHandle);
ExFreePool(ConfigUrb);
Status = DeviceExtension->HubInterface.Initialize20Hub(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, 1);
DPRINT1("Status %x\n", Status);
{
int PortLoop;
USHORT PortStatusAndChange[2];
for (PortLoop=0; PortLoop< DeviceExtension->UsbExtHubInfo.NumberOfPorts; PortLoop++)
{
DPRINT1("Port %x\n", PortLoop);
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN,
0,
USB_REQUEST_SET_FEATURE,
PORT_POWER,
1,
0,
0,
0,
0);
Urb->UrbOSFeatureDescriptorRequest.MS_FeatureDescriptorIndex = PortLoop + 1;
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
DPRINT1("Status %x\n", Status);
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_OTHER,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_OUT,
0,
USB_REQUEST_GET_STATUS,
0,
PortLoop + 1,
&PortStatusAndChange,
0,
sizeof(PortStatusAndChange),
0);
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
DPRINT1("Status %x\n", Status);
DPRINT1("PortStatus = %x\n", PortStatusAndChange[0]);
DPRINT1("PortChange = %x\n", PortStatusAndChange[1]);
}
}
ExFreePool(Urb);
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
{
switch (IrpSp->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations = NULL;
DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
Status = UsbhubFdoQueryBusRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
case RemovalRelations:
{
DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
default:
DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
IrpSp->Parameters.QueryDeviceRelations.Type);
return ForwardIrpAndForget(DeviceObject, Irp);
}
break;
}
case IRP_MN_QUERY_BUS_INFORMATION:
{
DPRINT1("IRP_MN_QUERY_BUS_INFORMATION\n");
break;
}
case IRP_MN_QUERY_ID:
{
DPRINT1("IRP_MN_QUERY_ID\n");
break;
}
case IRP_MN_QUERY_CAPABILITIES:
{
DPRINT1("IRP_MN_QUERY_CAPABILITIES\n");
break;
}
default:
{
DPRINT1("Usbhub: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
UsbhubDeviceControlFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
ULONG IoControlCode;
PHUB_DEVICE_EXTENSION DeviceExtension;
ULONG LengthIn, LengthOut;
ULONG_PTR Information = 0;
PVOID BufferIn, BufferOut;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
Stack = IoGetCurrentIrpStackLocation(Irp);
LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
UsbhubGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut);
switch (IoControlCode)
{
case IOCTL_USB_GET_NODE_INFORMATION:
{
//PUSB_NODE_INFORMATION NodeInformation;
DPRINT1("Usbhub: IOCTL_USB_GET_NODE_INFORMATION\n");
if (LengthOut < sizeof(USB_NODE_INFORMATION))
Status = STATUS_BUFFER_TOO_SMALL;
else if (BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
/*NodeInformation = (PUSB_NODE_INFORMATION)BufferOut;
dev = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->dev;
NodeInformation->NodeType = UsbHub;
RtlCopyMemory(
&NodeInformation->u.HubInformation.HubDescriptor,
((struct usb_hub *)usb_get_intfdata(to_usb_interface(&dev->actconfig->interface[0].dev)))->descriptor,
sizeof(USB_HUB_DESCRIPTOR));
NodeInformation->u.HubInformation.HubIsBusPowered = dev->actconfig->desc.bmAttributes & 0x80;
Information = sizeof(USB_NODE_INFORMATION);*/
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_USB_GET_NODE_CONNECTION_NAME:
{
PHUB_DEVICE_EXTENSION DeviceExtension;
PUSB_NODE_CONNECTION_NAME ConnectionName;
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ConnectionName = (PUSB_NODE_CONNECTION_NAME)BufferOut;
DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME\n");
if (LengthOut < sizeof(USB_NODE_CONNECTION_NAME))
Status = STATUS_BUFFER_TOO_SMALL;
else if (BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else if (ConnectionName->ConnectionIndex < 1
|| ConnectionName->ConnectionIndex > USB_MAXCHILDREN)
Status = STATUS_INVALID_PARAMETER;
else if (DeviceExtension->Children[ConnectionName->ConnectionIndex - 1] == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
ULONG NeededStructureSize;
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceExtension->Children[ConnectionName->ConnectionIndex - 1]->DeviceExtension;
NeededStructureSize = DeviceExtension->SymbolicLinkName.Length + sizeof(UNICODE_NULL) + FIELD_OFFSET(USB_NODE_CONNECTION_NAME, NodeName);
if (ConnectionName->ActualLength < NeededStructureSize / sizeof(WCHAR)
|| LengthOut < NeededStructureSize)
{
/* Buffer too small */
ConnectionName->ActualLength = NeededStructureSize / sizeof(WCHAR);
Information = sizeof(USB_NODE_CONNECTION_NAME);
Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
RtlCopyMemory(
ConnectionName->NodeName,
DeviceExtension->SymbolicLinkName.Buffer,
DeviceExtension->SymbolicLinkName.Length);
ConnectionName->NodeName[DeviceExtension->SymbolicLinkName.Length / sizeof(WCHAR)] = UNICODE_NULL;
DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_NAME returns '%S'\n", ConnectionName->NodeName);
ConnectionName->ActualLength = NeededStructureSize / sizeof(WCHAR);
Information = NeededStructureSize;
Status = STATUS_SUCCESS;
}
Information = LengthOut;
}
break;
}
case IOCTL_USB_GET_NODE_CONNECTION_INFORMATION:
{
PUSB_NODE_CONNECTION_INFORMATION ConnectionInformation;
/*
ULONG i, j, k;
struct usb_device* dev;
ULONG NumberOfOpenPipes = 0;
ULONG SizeOfOpenPipesArray;
*/
ConnectionInformation = (PUSB_NODE_CONNECTION_INFORMATION)BufferOut;
DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION\n");
if (LengthOut < sizeof(USB_NODE_CONNECTION_INFORMATION))
Status = STATUS_BUFFER_TOO_SMALL;
else if (BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else if (ConnectionInformation->ConnectionIndex < 1
|| ConnectionInformation->ConnectionIndex > USB_MAXCHILDREN)
Status = STATUS_INVALID_PARAMETER;
else
{
DPRINT1("Usbhub: We should succeed\n");
}
break;
}
case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
{
//PUSB_DESCRIPTOR_REQUEST Descriptor;
DPRINT1("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
Information = 0;
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME:
{
PHUB_DEVICE_EXTENSION DeviceExtension;
PUSB_NODE_CONNECTION_DRIVERKEY_NAME StringDescriptor;
DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME\n");
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
StringDescriptor = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)BufferOut;
if (LengthOut < sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME))
Status = STATUS_BUFFER_TOO_SMALL;
else if (StringDescriptor == NULL)
Status = STATUS_INVALID_PARAMETER;
else if (StringDescriptor->ConnectionIndex < 1
|| StringDescriptor->ConnectionIndex > USB_MAXCHILDREN)
Status = STATUS_INVALID_PARAMETER;
else if (DeviceExtension->Children[StringDescriptor->ConnectionIndex - 1] == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
ULONG StringSize;
Status = IoGetDeviceProperty(
DeviceExtension->Children[StringDescriptor->ConnectionIndex - 1],
DevicePropertyDriverKeyName,
LengthOut - FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME, DriverKeyName),
StringDescriptor->DriverKeyName,
&StringSize);
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
{
StringDescriptor->ActualLength = StringSize + FIELD_OFFSET(USB_NODE_CONNECTION_DRIVERKEY_NAME, DriverKeyName);
Information = LengthOut;
Status = STATUS_SUCCESS;
}
}
break;
}
default:
{
/* Pass Irp to lower driver */
DPRINT1("Usbhub: Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}