Implement IRP_MN_QUERY_DEVICE_RELATIONS for USB hubs

Implement IRP_MN_QUERY_ID for devices enumerated by USB hubs

svn path=/trunk/; revision=16093
This commit is contained in:
Hervé Poussineau
2005-06-19 14:15:39 +00:00
parent 30eee0c5d1
commit d4719c91ec
3 changed files with 244 additions and 35 deletions
+176 -33
View File
@@ -10,8 +10,6 @@
#define NDEBUG
#include "usbhub.h"
extern struct usb_driver hub_driver;
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
static VOID
@@ -47,6 +45,147 @@ UsbhubGetUserBuffers(
}
}
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 < USB_MAXCHILDREN; 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];
RtlInitUnicodeString(
&PdoExtension->DeviceDescription,
L"USB device"); /* FIXME */
sprintf(Buffer[0], "%lu", i + 1);
Status = UsbhubInitMultiSzString(
&PdoExtension->InstanceId,
Buffer[0], NULL);
if (!NT_SUCCESS(Status))
goto ByeBye;
/* FIXME: what if it is a multiple-interface usb device? */
sprintf(Buffer[0], "USB\\Vid_%04x&Pid_%04x&Rev_%04x",
PdoExtension->dev->descriptor.idVendor,
PdoExtension->dev->descriptor.idProduct,
0 /* FIXME: need to put the revision */);
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;
/* FIXME: what if it is a multiple-interface usb device? */
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);
Status = UsbhubInitMultiSzString(
&PdoExtension->CompatibleIds,
Buffer[0], Buffer[1], Buffer[2], 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->DeviceDescription);
RtlFreeUnicodeString(&PdoExtension->DeviceId);
RtlFreeUnicodeString(&PdoExtension->InstanceId);
RtlFreeUnicodeString(&PdoExtension->HardwareIds);
RtlFreeUnicodeString(&PdoExtension->CompatibleIds);
IoDeleteDevice(Pdo);
return Status;
}
NTSTATUS STDCALL
UsbhubPnpFdo(
IN PDEVICE_OBJECT DeviceObject,
@@ -62,33 +201,35 @@ UsbhubPnpFdo(
switch (MinorFunction)
{
case IRP_MN_START_DEVICE:
case IRP_MN_START_DEVICE: /* 0x0 */
{
DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
Status = ForwardIrpAndWait(DeviceObject, Irp);
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
// Status = OHCD_PnPStartDevice(DeviceObject, Irp);
break;
}
case IRP_MN_REMOVE_DEVICE:
//case IRP_MN_QUERY_REMOVE_DEVICE:
//case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_STOP_DEVICE:
case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
{
DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
Status = STATUS_SUCCESS;
IoDeleteDevice(DeviceObject); // just delete device for now
break;
}
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
{
Status = STATUS_SUCCESS;
switch (IrpSp->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations;
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;
}
@@ -104,11 +245,6 @@ UsbhubPnpFdo(
return Status;
}
static inline struct device *hubdev (struct usb_device *dev)
{
return &dev->actconfig->interface [0].dev;
}
NTSTATUS
UsbhubDeviceControlFdo(
IN PDEVICE_OBJECT DeviceObject,
@@ -147,7 +283,7 @@ UsbhubDeviceControlFdo(
NodeInformation->NodeType = UsbHub;
RtlCopyMemory(
&NodeInformation->u.HubInformation.HubDescriptor,
((struct usb_hub *)usb_get_intfdata(to_usb_interface(hubdev(dev))))->descriptor,
((struct usb_hub *)usb_get_intfdata(to_usb_interface(&dev->actconfig->interface[0].dev)))->descriptor,
sizeof(USB_HUB_DESCRIPTOR));
NodeInformation->u.HubInformation.HubIsBusPowered = TRUE; /* FIXME */
Information = sizeof(USB_NODE_INFORMATION);
@@ -189,17 +325,24 @@ UsbhubDeviceControlFdo(
ConnectionInformation = (PUSB_NODE_CONNECTION_INFORMATION)BufferOut;
DPRINT1("Usbhub: IOCTL_USB_GET_NODE_CONNECTION_INFORMATION partially implemented\n");
dev = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->dev;
ConnectionInformation->ConnectionIndex = 0; /* FIXME */
dev = dev->children[ConnectionInformation->ConnectionIndex = 0];
if (dev == NULL)
{
/* No device connected to this port */
RtlZeroMemory(ConnectionInformation, sizeof(USB_NODE_CONNECTION_INFORMATION));
Status = STATUS_SUCCESS;
break;
}
RtlCopyMemory(
&ConnectionInformation->DeviceDescriptor,
&dev->descriptor,
sizeof(USB_DEVICE_DESCRIPTOR));
ConnectionInformation->CurrentConfigurationValue = 0; /* FIXME */
ConnectionInformation->LowSpeed = TRUE; /* FIXME */
ConnectionInformation->DeviceIsHub = TRUE;
RtlZeroMemory(&ConnectionInformation->DeviceAddress, sizeof(ConnectionInformation->DeviceAddress)); /* FIXME */
ConnectionInformation->LowSpeed = dev->speed == USB_SPEED_LOW || dev->speed == USB_SPEED_FULL;
ConnectionInformation->DeviceIsHub = dev->descriptor.bDeviceClass == USB_CLASS_HUB;
ConnectionInformation->DeviceAddress = dev->devnum;
RtlZeroMemory(&ConnectionInformation->NumberOfOpenPipes, sizeof(ConnectionInformation->NumberOfOpenPipes)); /* FIXME */
RtlZeroMemory(&ConnectionInformation->ConnectionStatus, sizeof(ConnectionInformation->ConnectionStatus)); /* FIXME */
ConnectionInformation->ConnectionStatus = DeviceConnected;
RtlZeroMemory(&ConnectionInformation->PipeList, sizeof(ConnectionInformation->PipeList)); /* FIXME */
/*for (i = 0; i < 32; i++)
{
+59 -2
View File
@@ -8,10 +8,9 @@
*/
//#define NDEBUG
#include <stdio.h>
#include "usbhub.h"
extern struct usb_driver hub_driver;
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
NTSTATUS
@@ -44,6 +43,59 @@ UsbhubDeviceControlPdo(
return Status;
}
static NTSTATUS
UsbhubPdoQueryId(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
OUT ULONG_PTR* Information)
{
PHUB_DEVICE_EXTENSION DeviceExtension;
ULONG IdType;
PUNICODE_STRING SourceString;
UNICODE_STRING String;
NTSTATUS Status;
IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlInitUnicodeString(&String, NULL);
switch (IdType)
{
case BusQueryDeviceID:
{
DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
SourceString = &DeviceExtension->DeviceId;
break;
}
case BusQueryHardwareIDs:
{
DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
SourceString = &DeviceExtension->HardwareIds;
break;
}
case BusQueryCompatibleIDs:
DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
SourceString = &DeviceExtension->CompatibleIds;
break;
case BusQueryInstanceID:
{
DPRINT("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
SourceString = &DeviceExtension->InstanceId;
break;
}
default:
DPRINT1("Usbhub: IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
return STATUS_NOT_SUPPORTED;
}
Status = UsbhubDuplicateUnicodeString(
&String,
SourceString,
PagedPool);
*Information = (ULONG_PTR)String.Buffer;
return Status;
}
NTSTATUS STDCALL
UsbhubPnpPdo(
IN PDEVICE_OBJECT DeviceObject,
@@ -59,6 +111,11 @@ UsbhubPnpPdo(
switch (MinorFunction)
{
case IRP_MN_QUERY_ID: /* 0x13 */
{
Status = UsbhubPdoQueryId(DeviceObject, Irp, &Information);
break;
}
default:
{
/* We can't forward request to the lower driver, because
@@ -19,6 +19,15 @@ typedef struct _HUB_DEVICE_EXTENSION
BOOLEAN IsFDO;
struct usb_device* dev;
PDEVICE_OBJECT LowerDevice;
PDEVICE_OBJECT Children[USB_MAXCHILDREN];
/* Fields valid only when IsFDO == FALSE */
UNICODE_STRING DeviceDescription; // REG_SZ
UNICODE_STRING DeviceId; // REG_SZ
UNICODE_STRING InstanceId; // REG_SZ
UNICODE_STRING HardwareIds; // REG_MULTI_SZ
UNICODE_STRING CompatibleIds; // REG_MULTI_SZ
} HUB_DEVICE_EXTENSION, *PHUB_DEVICE_EXTENSION;
/* createclose.c */