mirror of
https://github.com/reactos/reactos.git
synced 2025-01-11 08:38:17 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
502 lines
16 KiB
C
502 lines
16 KiB
C
/*
|
|
* 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é Poussineau (hpoussin@reactos.com)
|
|
*/
|
|
|
|
#define INITGUID
|
|
#define NDEBUG
|
|
#include "usbhub.h"
|
|
|
|
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
static NTSTATUS
|
|
UsbhubFdoQueryBusRelations(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
OUT PDEVICE_RELATIONS* pDeviceRelations)
|
|
{
|
|
PHUB_DEVICE_EXTENSION DeviceExtension;
|
|
PDEVICE_RELATIONS DeviceRelations;
|
|
PDEVICE_OBJECT Pdo;
|
|
PHUB_DEVICE_EXTENSION PdoExtension;
|
|
struct usb_device* dev;
|
|
ULONG i;
|
|
ULONG Children = 0;
|
|
ULONG NeededSize;
|
|
NTSTATUS Status;
|
|
CHAR Buffer[3][40];
|
|
|
|
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
|
dev = DeviceExtension->dev;
|
|
|
|
/* Create PDOs that are missing */
|
|
for (i = 0; i < dev->maxchild; i++)
|
|
{
|
|
if (dev->children[i] == NULL)
|
|
{
|
|
/* No child device at this place */
|
|
continue;
|
|
}
|
|
Children++;
|
|
if (DeviceExtension->Children[i] != NULL)
|
|
{
|
|
/* PDO already exists */
|
|
continue;
|
|
}
|
|
/* Need to create the PDO */
|
|
Status = IoCreateDevice(
|
|
DeviceObject->DriverObject,
|
|
sizeof(HUB_DEVICE_EXTENSION),
|
|
NULL, /* Device name */
|
|
FILE_DEVICE_CONTROLLER,
|
|
FILE_AUTOGENERATED_DEVICE_NAME,
|
|
FALSE,
|
|
&DeviceExtension->Children[i]);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT("Usbhub: IoCreateDevice() failed with status 0x%08lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
Pdo = DeviceExtension->Children[i];
|
|
Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
|
|
|
|
PdoExtension = Pdo->DeviceExtension;
|
|
RtlZeroMemory(PdoExtension, sizeof(HUB_DEVICE_EXTENSION));
|
|
|
|
PdoExtension->IsFDO = FALSE;
|
|
PdoExtension->dev = dev->children[i];
|
|
|
|
sprintf(Buffer[0], "%lu", i);
|
|
Status = UsbhubInitMultiSzString(
|
|
&PdoExtension->InstanceId,
|
|
Buffer[0], NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
goto ByeBye;
|
|
|
|
DPRINT1("child #%lu: USB\\Vid_%04x&Pid_%04x&Rev_%04x\n",
|
|
i,
|
|
PdoExtension->dev->descriptor.idVendor,
|
|
PdoExtension->dev->descriptor.idProduct,
|
|
PdoExtension->dev->descriptor.bcdDevice);
|
|
sprintf(Buffer[0], "USB\\Vid_%04x&Pid_%04x&Rev_%04x",
|
|
PdoExtension->dev->descriptor.idVendor,
|
|
PdoExtension->dev->descriptor.idProduct,
|
|
PdoExtension->dev->descriptor.bcdDevice);
|
|
sprintf(Buffer[1], "USB\\Vid_%04x&Pid_%04x",
|
|
PdoExtension->dev->descriptor.idVendor,
|
|
PdoExtension->dev->descriptor.idProduct);
|
|
Status = UsbhubInitMultiSzString(
|
|
&PdoExtension->HardwareIds,
|
|
Buffer[0], Buffer[1], NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
goto ByeBye;
|
|
|
|
Status = UsbhubInitMultiSzString(
|
|
&PdoExtension->DeviceId,
|
|
Buffer[1], NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
goto ByeBye;
|
|
|
|
if (PdoExtension->dev->actconfig->desc.bNumInterfaces == 1)
|
|
{
|
|
/* Single-interface USB device */
|
|
if (PdoExtension->dev->descriptor.bDeviceClass != 0)
|
|
{
|
|
/* Use these values for device class/sub class/protocol */
|
|
sprintf(Buffer[0], "USB\\Class_%02x&SubClass_%02x&Prot_%02x",
|
|
PdoExtension->dev->descriptor.bDeviceClass,
|
|
PdoExtension->dev->descriptor.bDeviceSubClass,
|
|
PdoExtension->dev->descriptor.bDeviceProtocol);
|
|
sprintf(Buffer[1], "USB\\Class_%02x&SubClass_%02x",
|
|
PdoExtension->dev->descriptor.bDeviceClass,
|
|
PdoExtension->dev->descriptor.bDeviceSubClass);
|
|
sprintf(Buffer[2], "USB\\Class_%02x",
|
|
PdoExtension->dev->descriptor.bDeviceClass);
|
|
}
|
|
else
|
|
{
|
|
/* Use values specified in the interface descriptor */
|
|
struct usb_host_interface *itf = PdoExtension->dev->actconfig->interface->altsetting;
|
|
sprintf(Buffer[0], "USB\\Class_%02x&SubClass_%02x&Prot_%02x",
|
|
itf->desc.bInterfaceClass,
|
|
itf->desc.bInterfaceSubClass,
|
|
itf->desc.bInterfaceProtocol);
|
|
sprintf(Buffer[1], "USB\\Class_%02x&SubClass_%02x",
|
|
itf->desc.bInterfaceClass,
|
|
itf->desc.bInterfaceSubClass);
|
|
sprintf(Buffer[2], "USB\\Class_%02x",
|
|
itf->desc.bInterfaceClass);
|
|
}
|
|
Status = UsbhubInitMultiSzString(
|
|
&PdoExtension->CompatibleIds,
|
|
Buffer[0], Buffer[1], Buffer[2], NULL);
|
|
}
|
|
else
|
|
{
|
|
/* Multiple-interface USB device */
|
|
sprintf(Buffer[0], "USB\\DevClass_%02x&SubClass_%02x&Prot_%02x",
|
|
PdoExtension->dev->descriptor.bDeviceClass,
|
|
PdoExtension->dev->descriptor.bDeviceSubClass,
|
|
PdoExtension->dev->descriptor.bDeviceProtocol);
|
|
sprintf(Buffer[1], "USB\\DevClass_%02x&SubClass_%02x",
|
|
PdoExtension->dev->descriptor.bDeviceClass,
|
|
PdoExtension->dev->descriptor.bDeviceSubClass);
|
|
sprintf(Buffer[2], "USB\\DevClass_%02x",
|
|
PdoExtension->dev->descriptor.bDeviceClass);
|
|
Status = UsbhubInitMultiSzString(
|
|
&PdoExtension->CompatibleIds,
|
|
Buffer[0], Buffer[1], Buffer[2], "USB\\COMPOSITE", NULL);
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
goto ByeBye;
|
|
|
|
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
}
|
|
|
|
/* 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;
|
|
return STATUS_SUCCESS;
|
|
|
|
ByeBye:
|
|
RtlFreeUnicodeString(&PdoExtension->DeviceId);
|
|
RtlFreeUnicodeString(&PdoExtension->InstanceId);
|
|
RtlFreeUnicodeString(&PdoExtension->HardwareIds);
|
|
RtlFreeUnicodeString(&PdoExtension->CompatibleIds);
|
|
IoDeleteDevice(Pdo);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS NTAPI
|
|
UsbhubPnpFdo(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IrpSp;
|
|
NTSTATUS Status;
|
|
ULONG MinorFunction;
|
|
ULONG_PTR Information = 0;
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
MinorFunction = IrpSp->MinorFunction;
|
|
|
|
switch (MinorFunction)
|
|
{
|
|
case IRP_MN_START_DEVICE: /* 0x0 */
|
|
{
|
|
DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
|
|
Status = ForwardIrpAndWait(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
|
|
{
|
|
switch (IrpSp->Parameters.QueryDeviceRelations.Type)
|
|
{
|
|
case BusRelations:
|
|
{
|
|
PDEVICE_RELATIONS DeviceRelations = NULL;
|
|
DPRINT("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;
|
|
}
|
|
|
|
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;
|
|
|
|
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;
|
|
struct usb_device* dev;
|
|
DPRINT("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;
|
|
|
|
DPRINT("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;
|
|
DPRINT("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;
|
|
|
|
DPRINT("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
|
|
{
|
|
dev = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->dev;
|
|
dev = dev->children[ConnectionInformation->ConnectionIndex - 1];
|
|
if (dev == NULL)
|
|
{
|
|
/* No device connected to this port */
|
|
RtlZeroMemory(
|
|
&ConnectionInformation->DeviceDescriptor,
|
|
sizeof(USB_NODE_CONNECTION_INFORMATION) - FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION, DeviceDescriptor));
|
|
ConnectionInformation->ConnectionStatus = NoDeviceConnected;
|
|
Information = sizeof(USB_NODE_CONNECTION_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
SizeOfOpenPipesArray = (LengthOut - FIELD_OFFSET(USB_NODE_CONNECTION_INFORMATION, PipeList)) / sizeof(USB_PIPE_INFO);
|
|
RtlCopyMemory(
|
|
&ConnectionInformation->DeviceDescriptor,
|
|
&dev->descriptor,
|
|
sizeof(USB_DEVICE_DESCRIPTOR));
|
|
ConnectionInformation->CurrentConfigurationValue = dev->actconfig->desc.bConfigurationValue;
|
|
ConnectionInformation->LowSpeed = dev->speed == USB_SPEED_LOW || dev->speed == USB_SPEED_FULL;
|
|
ConnectionInformation->DeviceIsHub = dev->descriptor.bDeviceClass == USB_CLASS_HUB;
|
|
ConnectionInformation->DeviceAddress = dev->devnum;
|
|
ConnectionInformation->ConnectionStatus = DeviceConnected;
|
|
|
|
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++)
|
|
for (j = 0; j < dev->actconfig->interface[i].num_altsetting; j++)
|
|
for (k = 0; k < dev->actconfig->interface[i].altsetting[j].desc.bNumEndpoints; k++)
|
|
{
|
|
if (NumberOfOpenPipes < SizeOfOpenPipesArray)
|
|
{
|
|
PUSB_PIPE_INFO Pipe = &ConnectionInformation->PipeList[NumberOfOpenPipes];
|
|
struct usb_host_endpoint* endpoint = &dev->actconfig->interface[i].altsetting[j].endpoint[k];
|
|
RtlCopyMemory(
|
|
&Pipe->EndpointDescriptor,
|
|
&endpoint->desc,
|
|
endpoint->desc.bLength);
|
|
Pipe->ScheduleOffset = 0; /* FIXME */
|
|
}
|
|
NumberOfOpenPipes++;
|
|
}
|
|
ConnectionInformation->NumberOfOpenPipes = NumberOfOpenPipes;
|
|
|
|
Information = sizeof(USB_NODE_CONNECTION_INFORMATION);
|
|
if (NumberOfOpenPipes <= SizeOfOpenPipesArray)
|
|
Status = STATUS_SUCCESS;
|
|
else
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
break;
|
|
}
|
|
case IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION:
|
|
{
|
|
//PUSB_DESCRIPTOR_REQUEST Descriptor;
|
|
DPRINT("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION\n");
|
|
DPRINT1("Usbhub: IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION unimplemented\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;
|
|
DPRINT("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;
|
|
}
|