2005-06-13 20:41:59 +00:00
|
|
|
|
/*
|
|
|
|
|
* 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
|
|
|
|
|
*
|
2010-09-05 19:00:37 +00:00
|
|
|
|
* PROGRAMMERS: Herv<EFBFBD> Poussineau (hpoussin@reactos.com)
|
|
|
|
|
* Michael Martin (michael.martin@reactos.org)
|
2005-06-13 20:41:59 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2005-06-20 05:54:19 +00:00
|
|
|
|
#define INITGUID
|
2010-09-05 19:00:37 +00:00
|
|
|
|
#include <stdio.h>
|
2005-06-15 17:11:36 +00:00
|
|
|
|
#define NDEBUG
|
2005-06-13 20:41:59 +00:00
|
|
|
|
#include "usbhub.h"
|
2010-09-05 19:00:37 +00:00
|
|
|
|
#include "usbdlib.h"
|
2005-06-13 20:41:59 +00:00
|
|
|
|
|
|
|
|
|
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
|
|
|
|
|
|
2010-09-14 12:04:15 +00:00
|
|
|
|
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);
|
2010-09-20 06:55:54 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
SubmitUrbToRootHub(IN PDEVICE_OBJECT Pdo, IN ULONG IoControlCode, IN PURB Urb);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
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++)
|
|
|
|
|
{
|
2010-09-20 06:55:54 +00:00
|
|
|
|
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);
|
2010-09-07 11:44:03 +00:00
|
|
|
|
|
|
|
|
|
EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)InterfaceDescriptor + sizeof(USB_INTERFACE_DESCRIPTOR));
|
|
|
|
|
|
|
|
|
|
for (j=0; j < InterfaceDescriptor->bNumEndpoints; j++)
|
|
|
|
|
{
|
2010-09-20 06:55:54 +00:00
|
|
|
|
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));
|
2010-09-07 11:44:03 +00:00
|
|
|
|
}
|
2010-09-20 06:55:54 +00:00
|
|
|
|
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ULONG_PTR)EndpointDescriptor;
|
2010-09-07 11:44:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2010-09-14 12:04:15 +00:00
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
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
|
2010-09-14 12:04:15 +00:00
|
|
|
|
WorkerThread(IN PVOID Context)
|
|
|
|
|
{
|
|
|
|
|
PHUB_DEVICE_EXTENSION DeviceExtension;
|
2010-09-20 06:55:54 +00:00
|
|
|
|
PDEVICE_OBJECT DeviceObject, Pdo;
|
2010-09-14 12:04:15 +00:00
|
|
|
|
PHUB_CHILDDEVICE_EXTENSION PdoExtension;
|
2010-09-20 06:55:54 +00:00
|
|
|
|
PURB Urb = NULL;
|
2010-09-14 12:04:15 +00:00
|
|
|
|
PORTSTATUSANDCHANGE PortStatusAndChange;
|
|
|
|
|
int PortLoop, DeviceCount;
|
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
USB_DEVICE_DESCRIPTOR DevDesc;
|
|
|
|
|
USB_CONFIGURATION_DESCRIPTOR ConfigDesc;
|
|
|
|
|
ULONG DevDescSize, ConfigDescSize;
|
|
|
|
|
PUSB_STRING_DESCRIPTOR StringDesc;
|
2010-09-20 06:55:54 +00:00
|
|
|
|
USB_STRING_DESCRIPTOR LanguageIdDescriptor;
|
|
|
|
|
PWORKITEMDATA WorkItemData = (PWORKITEMDATA)Context;
|
|
|
|
|
|
|
|
|
|
DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context;
|
2010-09-14 12:04:15 +00:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to get PortStatus!\n");
|
2010-09-20 06:55:54 +00:00
|
|
|
|
goto CleanUp;
|
2010-09-14 12:04:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to Clear the Port Reset with Status %x!\n", Status);
|
2010-09-20 06:55:54 +00:00
|
|
|
|
goto CleanUp;
|
2010-09-14 12:04:15 +00:00
|
|
|
|
}
|
2010-09-20 06:55:54 +00:00
|
|
|
|
|
2010-09-14 12:04:15 +00:00
|
|
|
|
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);
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
|
|
|
|
|
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);
|
2010-09-20 06:55:54 +00:00
|
|
|
|
goto CleanUp;
|
2010-09-14 12:04:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 */
|
2010-09-20 06:55:54 +00:00
|
|
|
|
RtlZeroMemory(&LanguageIdDescriptor, sizeof(USB_STRING_DESCRIPTOR));
|
2010-09-14 12:04:15 +00:00
|
|
|
|
UsbBuildGetDescriptorRequest(Urb,
|
|
|
|
|
sizeof(Urb->UrbControlDescriptorRequest),
|
|
|
|
|
USB_STRING_DESCRIPTOR_TYPE,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
&LanguageIdDescriptor,
|
|
|
|
|
NULL,
|
2010-09-20 06:55:54 +00:00
|
|
|
|
sizeof(USB_STRING_DESCRIPTOR),
|
2010-09-14 12:04:15 +00:00
|
|
|
|
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,
|
2010-09-20 06:55:54 +00:00
|
|
|
|
LanguageIdDescriptor.bString[0],
|
2010-09-14 12:04:15 +00:00
|
|
|
|
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,
|
2010-09-20 06:55:54 +00:00
|
|
|
|
LanguageIdDescriptor.bString[0],
|
2010-09-14 12:04:15 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
ExFreePool(WorkItemData);
|
|
|
|
|
ExFreePool(Urb);
|
|
|
|
|
|
2010-09-14 12:04:15 +00:00
|
|
|
|
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);
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to Clear the Port Connect!\n");
|
2010-09-20 06:55:54 +00:00
|
|
|
|
goto CleanUp;
|
2010-09-14 12:04:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
|
|
|
|
|
2010-09-14 12:04:15 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to Reset the port!\n");
|
2010-09-20 06:55:54 +00:00
|
|
|
|
goto CleanUp;
|
2010-09-14 12:04:15 +00:00
|
|
|
|
}
|
|
|
|
|
/* At this point the miniport will complete another SCE to inform of Reset completed */
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-20 06:55:54 +00:00
|
|
|
|
|
|
|
|
|
CleanUp:
|
|
|
|
|
ExFreePool(WorkItemData);
|
|
|
|
|
ExFreePool(Urb);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
DeviceArrivalCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
|
|
|
|
|
{
|
|
|
|
|
PHUB_DEVICE_EXTENSION DeviceExtension;
|
|
|
|
|
LONG i;
|
2010-09-20 06:55:54 +00:00
|
|
|
|
PWORKITEMDATA WorkItemData;
|
2010-09-07 11:44:03 +00:00
|
|
|
|
|
|
|
|
|
DeviceExtension = (PHUB_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
|
|
|
|
|
|
2010-09-14 12:04:15 +00:00
|
|
|
|
for (i=0; i < DeviceExtension->UsbExtHubInfo.NumberOfPorts; i++)
|
|
|
|
|
DPRINT1("Port %x DeviceExtension->PortStatus %x\n",i+1, DeviceExtension->PortStatus[i]);
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
IoFreeIrp(Irp);
|
2010-09-07 11:44:03 +00:00
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
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;
|
2010-09-07 11:44:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Urb = &DeviceExtension->Urb;
|
|
|
|
|
|
|
|
|
|
RtlZeroMemory(Urb, sizeof(URB));
|
2010-09-07 11:44:03 +00:00
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
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,
|
2010-09-07 11:44:03 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = IoCallDriver(Pdo, Irp);
|
2010-09-07 11:44:03 +00:00
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
return Status;
|
2010-09-07 11:44:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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)
|
|
|
|
|
{
|
2010-09-14 12:04:15 +00:00
|
|
|
|
DPRINT1("Usbhub: Operation pending\n");
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-13 20:41:59 +00:00
|
|
|
|
static VOID
|
2010-09-05 19:00:37 +00:00
|
|
|
|
UsbhubGetUserBuffers(IN PIRP Irp, IN ULONG IoControlCode, OUT PVOID* BufferIn, OUT PVOID* BufferOut)
|
2005-06-13 20:41:59 +00:00
|
|
|
|
{
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2005-06-13 20:41:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-05 19:00:37 +00:00
|
|
|
|
NTSTATUS
|
|
|
|
|
UsbhubFdoQueryBusRelations(IN PDEVICE_OBJECT DeviceObject, OUT PDEVICE_RELATIONS* pDeviceRelations)
|
2005-06-19 14:15:39 +00:00
|
|
|
|
{
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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");
|
2010-09-14 12:04:15 +00:00
|
|
|
|
|
2010-09-05 19:00:37 +00:00
|
|
|
|
/* Create PDOs that are missing */
|
|
|
|
|
for (i = 0; i < USB_MAXCHILDREN; i++)
|
|
|
|
|
{
|
|
|
|
|
|
2010-09-14 12:04:15 +00:00
|
|
|
|
if (DeviceExtension->UsbChildren[i] == NULL)
|
2010-09-05 19:00:37 +00:00
|
|
|
|
{
|
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
ASSERT(Children == DeviceRelations->Count);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
*pDeviceRelations = DeviceRelations;
|
2010-09-07 11:44:03 +00:00
|
|
|
|
|
|
|
|
|
WaitForUsbDeviceArrivalNotification(DeviceObject);
|
|
|
|
|
|
2010-09-05 19:00:37 +00:00
|
|
|
|
return STATUS_SUCCESS;
|
2005-06-19 14:15:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
VOID CallBackRoutine(IN PVOID Argument1)
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("RH_INIT_CALLBACK %x\n", Argument1);
|
|
|
|
|
ASSERT(FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-30 11:16:55 +00:00
|
|
|
|
NTSTATUS NTAPI
|
2010-09-05 19:00:37 +00:00
|
|
|
|
UsbhubPnpFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|
|
|
|
{
|
|
|
|
|
PIO_STACK_LOCATION IrpSp;
|
2010-09-07 11:44:03 +00:00
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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 */
|
|
|
|
|
{
|
2010-09-07 11:44:03 +00:00
|
|
|
|
PURB Urb;
|
2010-09-05 19:00:37 +00:00
|
|
|
|
ULONG Result = 0;
|
2010-09-20 06:55:54 +00:00
|
|
|
|
PUSB_INTERFACE_DESCRIPTOR Pid;
|
|
|
|
|
/* Theres only one descriptor on hub */
|
|
|
|
|
USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}};
|
|
|
|
|
PURB ConfigUrb = NULL;
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
|
|
|
|
/* We differ from windows on hubpdo because we dont have usbport.sys which manages all usb device objects */
|
2010-09-07 11:44:03 +00:00
|
|
|
|
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));
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
|
|
|
|
/* Get the hubs PDO */
|
2010-09-20 06:55:54 +00:00
|
|
|
|
QueryRootHub(DeviceExtension->LowerDevice, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, &DeviceExtension->RootHubPdo, &DeviceExtension->RootHubFdo);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
ASSERT(DeviceExtension->RootHubPdo);
|
|
|
|
|
ASSERT(DeviceExtension->RootHubFdo);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
DPRINT1("RootPdo %x, RootFdo %x\n", DeviceExtension->RootHubPdo, DeviceExtension->RootHubFdo);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
|
|
|
|
/* Send the START_DEVICE irp down to the PDO of RootHub */
|
|
|
|
|
Status = ForwardIrpAndWait(DeviceExtension->RootHubPdo, Irp);
|
2010-09-07 11:44:03 +00:00
|
|
|
|
|
2010-09-05 19:00:37 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Failed to start the RootHub PDO\n");
|
|
|
|
|
ASSERT(FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the current number of hubs */
|
2010-09-07 11:44:03 +00:00
|
|
|
|
QueryRootHub(DeviceExtension->RootHubPdo,IOCTL_INTERNAL_USB_GET_HUB_COUNT, &DeviceExtension->HubCount, NULL);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
|
|
|
|
/* Get the Direct Call Interfaces */
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Status = QueryInterface(DeviceExtension->RootHubPdo,
|
|
|
|
|
USB_BUS_INTERFACE_HUB_GUID,
|
|
|
|
|
sizeof(USB_BUS_INTERFACE_HUB_V5),
|
|
|
|
|
5,
|
|
|
|
|
(PVOID)&DeviceExtension->HubInterface);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("UsbhubM Failed to get HUB_GUID interface with status 0x%08lx\n", Status);
|
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Status = QueryInterface(DeviceExtension->RootHubPdo,
|
|
|
|
|
USB_BUS_INTERFACE_USBDI_GUID,
|
|
|
|
|
sizeof(USB_BUS_INTERFACE_USBDI_V2),
|
|
|
|
|
2,
|
|
|
|
|
(PVOID)&DeviceExtension->UsbDInterface);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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 */
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, &DeviceExtension->RootHubUsbDevice, NULL);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Usbhub: GetRootHubDeviceHandle failed with status 0x%08lx\n", Status);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Status = DeviceExtension->HubInterface.QueryDeviceInformation(DeviceExtension->RootHubPdo,
|
|
|
|
|
DeviceExtension->RootHubUsbDevice,
|
2010-09-07 11:44:03 +00:00
|
|
|
|
&DeviceExtension->DeviceInformation,
|
2010-09-05 19:00:37 +00:00
|
|
|
|
sizeof(USB_DEVICE_INFORMATION_0),
|
|
|
|
|
&Result);
|
|
|
|
|
|
|
|
|
|
|
2010-09-14 12:04:15 +00:00
|
|
|
|
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);
|
2010-09-07 11:44:03 +00:00
|
|
|
|
|
|
|
|
|
/* Get roothubs device descriptor */
|
|
|
|
|
UsbBuildGetDescriptorRequest(Urb,
|
|
|
|
|
sizeof(Urb->UrbControlDescriptorRequest),
|
2010-09-05 19:00:37 +00:00
|
|
|
|
USB_DEVICE_DESCRIPTOR_TYPE,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
&DeviceExtension->HubDeviceDescriptor,
|
|
|
|
|
NULL,
|
|
|
|
|
sizeof(USB_DEVICE_DESCRIPTOR),
|
|
|
|
|
NULL);
|
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
|
|
|
|
DPRINT1("Usbhub: Failed to get HubDeviceDescriptor!\n");
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
DumpDeviceDescriptor(&DeviceExtension->HubDeviceDescriptor);
|
|
|
|
|
|
|
|
|
|
/* Get roothubs configuration descriptor */
|
|
|
|
|
UsbBuildGetDescriptorRequest(Urb,
|
|
|
|
|
sizeof(Urb->UrbControlDescriptorRequest),
|
2010-09-05 19:00:37 +00:00
|
|
|
|
USB_CONFIGURATION_DESCRIPTOR_TYPE,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2010-09-07 11:44:03 +00:00
|
|
|
|
&DeviceExtension->HubConfigDescriptor,
|
2010-09-05 19:00:37 +00:00
|
|
|
|
NULL,
|
2010-09-07 11:44:03 +00:00
|
|
|
|
sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
|
2010-09-05 19:00:37 +00:00
|
|
|
|
NULL);
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
|
2010-09-05 19:00:37 +00:00
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
|
{
|
2010-09-07 11:44:03 +00:00
|
|
|
|
DPRINT1("Usbhub: Failed to get RootHub Configuration with status %x\n", Status);
|
|
|
|
|
ASSERT(FALSE);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
}
|
2010-09-07 11:44:03 +00:00
|
|
|
|
ASSERT(DeviceExtension->HubConfigDescriptor.wTotalLength);
|
|
|
|
|
|
|
|
|
|
DumpFullConfigurationDescriptor(&DeviceExtension->HubConfigDescriptor);
|
|
|
|
|
//DPRINT1("DeviceExtension->HubConfigDescriptor.wTotalLength %x\n", DeviceExtension->HubConfigDescriptor.wTotalLength);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
UsbBuildVendorRequest(Urb,
|
2010-09-05 19:00:37 +00:00
|
|
|
|
URB_FUNCTION_CLASS_DEVICE,
|
2010-09-07 11:44:03 +00:00
|
|
|
|
sizeof(Urb->UrbControlVendorClassRequest),
|
2010-09-05 19:00:37 +00:00
|
|
|
|
USBD_TRANSFER_DIRECTION_IN,
|
|
|
|
|
0,
|
|
|
|
|
USB_DEVICE_CLASS_RESERVED,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
&DeviceExtension->HubDescriptor,
|
|
|
|
|
NULL,
|
|
|
|
|
sizeof(USB_HUB_DESCRIPTOR),
|
|
|
|
|
NULL);
|
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Urb->UrbHeader.UsbdDeviceHandle = DeviceExtension->RootHubUsbDevice;
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
|
|
|
|
DPRINT1("bDescriptorType %x\n", DeviceExtension->HubDescriptor.bDescriptorType);
|
|
|
|
|
|
2010-09-07 11:44:03 +00:00
|
|
|
|
/* Select the configuration */
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
/* 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;
|
2010-09-07 11:44:03 +00:00
|
|
|
|
DPRINT1("Configuration Handle %x\n", DeviceExtension->ConfigurationHandle);
|
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
ExFreePool(ConfigUrb);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = DeviceExtension->HubInterface.Initialize20Hub(DeviceExtension->RootHubPdo, DeviceExtension->RootHubUsbDevice, 1);
|
2010-09-07 11:44:03 +00:00
|
|
|
|
DPRINT1("Status %x\n", Status);
|
|
|
|
|
|
2010-09-14 12:04:15 +00:00
|
|
|
|
{
|
|
|
|
|
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;
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
|
|
|
|
|
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);
|
2010-09-20 06:55:54 +00:00
|
|
|
|
Status = QueryRootHub(DeviceExtension->RootHubPdo, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL);
|
2010-09-14 12:04:15 +00:00
|
|
|
|
|
|
|
|
|
DPRINT1("Status %x\n", Status);
|
|
|
|
|
DPRINT1("PortStatus = %x\n", PortStatusAndChange[0]);
|
|
|
|
|
DPRINT1("PortChange = %x\n", PortStatusAndChange[1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExFreePool(Urb);
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2010-09-07 11:44:03 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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;
|
2005-06-13 20:41:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
2010-09-05 19:00:37 +00:00
|
|
|
|
UsbhubDeviceControlFdo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
2005-06-13 20:41:59 +00:00
|
|
|
|
{
|
2010-09-05 19:00:37 +00:00
|
|
|
|
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;
|
2005-06-13 20:41:59 +00:00
|
|
|
|
}
|