- Check if FDO is root hub fdo
- Partly implement fdo hub initialization
- Implement IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO

svn path=/trunk/; revision=55927
This commit is contained in:
Johannes Anderwald 2012-02-29 18:51:07 +00:00
parent 9e6f877683
commit 82d9d774ca
6 changed files with 357 additions and 67 deletions

View file

@ -3,7 +3,7 @@ add_definitions(-DDEBUG_MODE)
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include) include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
add_library(usbhub SHARED fdo.c misc.c pdo.c usbhub.c usbhub.rc) add_library(usbhub SHARED fdo.c misc.c pdo.c hub_fdo.c usbhub.c usbhub.rc)
target_link_libraries(usbhub ${PSEH_LIB}) target_link_libraries(usbhub ${PSEH_LIB})

View file

@ -27,71 +27,6 @@ DestroyUsbChildDeviceObject(
IN PDEVICE_OBJECT UsbHubDeviceObject, IN PDEVICE_OBJECT UsbHubDeviceObject,
IN LONG PortId); IN LONG PortId);
NTSTATUS
SubmitRequestToRootHub(
IN PDEVICE_OBJECT RootHubDeviceObject,
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);
//
// Build Control Request
//
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
RootHubDeviceObject,
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;
//
// Get Next Stack Location and Initialize it
//
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Parameters.Others.Argument1 = OutParameter1;
Stack->Parameters.Others.Argument2 = OutParameter2;
//
// Call RootHub
//
Status = IoCallDriver(RootHubDeviceObject, Irp);
//
// Its ok to block here as this function is called in an nonarbitrary thread
//
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
//
// The IO Manager will free the IRP
//
return Status;
}
NTSTATUS NTSTATUS
GetPortStatusAndChange( GetPortStatusAndChange(
@ -1507,6 +1442,31 @@ RootHubInitCallbackFunction(
} }
} }
BOOLEAN
USBHUB_IsRootHubFDO(
IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS Status;
PDEVICE_OBJECT RootHubPhysicalDeviceObject = NULL;
PHUB_DEVICE_EXTENSION HubDeviceExtension;
// get hub device extension
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
// Get the Root Hub Pdo
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO,
&RootHubPhysicalDeviceObject,
NULL);
// FIXME handle error
ASSERT(NT_SUCCESS(Status));
// physical device object is only obtained for root hubs
return (RootHubPhysicalDeviceObject != NULL);
}
NTSTATUS NTSTATUS
USBHUB_FdoStartDevice( USBHUB_FdoStartDevice(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
@ -1969,7 +1929,15 @@ USBHUB_FdoHandlePnp(
{ {
case IRP_MN_START_DEVICE: case IRP_MN_START_DEVICE:
{ {
Status = USBHUB_FdoStartDevice(DeviceObject, Irp); if (USBHUB_IsRootHubFDO(DeviceObject))
{
// start root hub fdo
Status = USBHUB_FdoStartDevice(DeviceObject, Irp);
}
else
{
Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp);
}
break; break;
} }

View file

@ -0,0 +1,212 @@
/*
* PROJECT: ReactOS Universal Serial Bus Hub Driver
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/usbhub/hub_fdo.c
* PURPOSE: Hub FDO
* PROGRAMMERS:
* Michael Martin (michael.martin@reactos.org)
* Johannes Anderwald (johannes.anderwald@reactos.org)
*/
#include "usbhub.h"
NTSTATUS
USBHUB_ParentFDOStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PHUB_DEVICE_EXTENSION HubDeviceExtension;
PURB Urb, ConfigurationUrb;
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
PUSBD_INTERFACE_LIST_ENTRY InterfaceList;
ULONG Index;
NTSTATUS Status;
// get hub device extension
HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
// Send the StartDevice to lower device object
Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp);
if (!NT_SUCCESS(Status))
{
// failed to start pdo
DPRINT1("Failed to start the RootHub PDO\n");
return Status;
}
// FIXME get capabilities
Urb = ExAllocatePool(NonPagedPool, sizeof(URB));
if (!Urb)
{
// no memory
DPRINT1("No memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
// lets get device descriptor
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
&HubDeviceExtension->HubDeviceDescriptor,
NULL,
sizeof(USB_DEVICE_DESCRIPTOR),
NULL);
// get hub device descriptor
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
Urb,
NULL);
if (!NT_SUCCESS(Status))
{
// failed to get device descriptor of hub
DPRINT1("Failed to get hub device descriptor with Status %x!\n", Status);
ExFreePool(Urb);
return Status;
}
// now get configuration descriptor
UsbBuildGetDescriptorRequest(Urb,
sizeof(Urb->UrbControlDescriptorRequest),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
&HubDeviceExtension->HubConfigDescriptor,
NULL,
sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR),
NULL);
// request configuration descriptor
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
Urb,
NULL);
if (!NT_SUCCESS(Status))
{
// failed to get configuration descriptor
DPRINT1("Failed to get hub configuration descriptor with status %x\n", Status);
ExFreePool(Urb);
return Status;
}
// sanity checks
ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength == sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR));
ASSERT(HubDeviceExtension->HubConfigDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE);
ASSERT(HubDeviceExtension->HubConfigDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR));
ASSERT(HubDeviceExtension->HubConfigDescriptor.bNumInterfaces == 1);
ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bNumEndpoints == 1);
ASSERT(HubDeviceExtension->HubEndPointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE);
ASSERT(HubDeviceExtension->HubEndPointDescriptor.bLength == sizeof(USB_ENDPOINT_DESCRIPTOR));
ASSERT(HubDeviceExtension->HubEndPointDescriptor.bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT);
ASSERT(HubDeviceExtension->HubEndPointDescriptor.bEndpointAddress == 0x81); // interrupt in
// Build hub descriptor request
UsbBuildVendorRequest(Urb,
URB_FUNCTION_CLASS_DEVICE,
sizeof(Urb->UrbControlVendorClassRequest),
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
0,
USB_REQUEST_GET_DESCRIPTOR,
USB_DEVICE_CLASS_RESERVED,
0,
&HubDeviceExtension->HubDescriptor,
NULL,
sizeof(USB_HUB_DESCRIPTOR),
NULL);
// send request
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
Urb,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status);
ExFreePool(Urb);
return STATUS_UNSUCCESSFUL;
}
// sanity checks
ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR));
ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts);
ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29);
// store number of ports
DPRINT1("NumberOfPorts %lu\n", HubDeviceExtension->HubDescriptor.bNumberOfPorts);
HubDeviceExtension->UsbExtHubInfo.NumberOfPorts = HubDeviceExtension->HubDescriptor.bNumberOfPorts;
// allocate interface list
InterfaceList = ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1));
if (!InterfaceList)
{
// no memory
DPRINT1("No memory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
// zero list
RtlZeroMemory(InterfaceList, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1));
// grab all interface descriptors
for(Index = 0; Index < HubDeviceExtension->HubConfigDescriptor.bNumInterfaces; Index++)
{
// Get the first Configuration Descriptor
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor,
&HubDeviceExtension->HubConfigDescriptor,
Index, 0, -1, -1, -1);
// store in list
InterfaceList[Index].InterfaceDescriptor = InterfaceDescriptor;
}
// now create configuration request
ConfigurationUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor,
(PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList);
if (ConfigurationUrb == NULL)
{
// failed to build urb
DPRINT1("Failed to build configuration urb\n");
ExFreePool(Urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
// send request
Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject,
IOCTL_INTERNAL_USB_SUBMIT_URB,
ConfigurationUrb,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status);
ExFreePool(Urb);
ExFreePool(ConfigurationUrb);
return STATUS_UNSUCCESSFUL;
}
// store configuration & pipe handle
HubDeviceExtension->ConfigurationHandle = ConfigurationUrb->UrbSelectConfiguration.ConfigurationHandle;
HubDeviceExtension->PipeHandle = ConfigurationUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle;
DPRINT("Hub Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle);
// free urb
ExFreePool(ConfigurationUrb);
ExFreePool(Urb);
// FIXME build SCE interrupt request
// FIXME create pdos
return Status;
}

View file

@ -143,3 +143,68 @@ ForwardIrpAndForget(
return IoCallDriver(LowerDevice, Irp); return IoCallDriver(LowerDevice, Irp);
} }
NTSTATUS
SubmitRequestToRootHub(
IN PDEVICE_OBJECT RootHubDeviceObject,
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);
//
// Build Control Request
//
Irp = IoBuildDeviceIoControlRequest(IoControlCode,
RootHubDeviceObject,
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;
//
// Get Next Stack Location and Initialize it
//
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Parameters.Others.Argument1 = OutParameter1;
Stack->Parameters.Others.Argument2 = OutParameter2;
//
// Call RootHub
//
Status = IoCallDriver(RootHubDeviceObject, Irp);
//
// Its ok to block here as this function is called in an nonarbitrary thread
//
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
//
// The IO Manager will free the IRP
//
return Status;
}

View file

@ -339,8 +339,39 @@ USBHUB_PdoHandleInternalDeviceControl(
DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n"); DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
break; break;
case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
{
DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n"); DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
if (Stack->Parameters.Others.Argument1)
{
// store device handle
*(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)ChildDeviceExtension->UsbDeviceHandle;
Status = STATUS_SUCCESS;
}
else
{
// invalid parameter
Status = STATUS_INVALID_PARAMETER;
}
break; break;
}
case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
{
if (Stack->Parameters.Others.Argument1)
{
// inform caller that it is a real usb hub
*(PVOID *)Stack->Parameters.Others.Argument1 = NULL;
}
if (Stack->Parameters.Others.Argument2)
{
// output device object
*(PVOID *)Stack->Parameters.Others.Argument2 = DeviceObject;
}
// done
Status = STATUS_SUCCESS;
break;
}
default: default:
{ {
DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);

View file

@ -142,6 +142,13 @@ ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp); IN PIRP Irp);
NTSTATUS
SubmitRequestToRootHub(
IN PDEVICE_OBJECT RootHubDeviceObject,
IN ULONG IoControlCode,
OUT PVOID OutParameter1,
OUT PVOID OutParameter2);
// pdo.c // pdo.c
NTSTATUS NTSTATUS
USBHUB_PdoHandlePnp( USBHUB_PdoHandlePnp(
@ -170,3 +177,10 @@ GetPortStatusAndChange(
IN PDEVICE_OBJECT RootHubDeviceObject, IN PDEVICE_OBJECT RootHubDeviceObject,
IN ULONG PortId, IN ULONG PortId,
OUT PPORT_STATUS_CHANGE StatusChange); OUT PPORT_STATUS_CHANGE StatusChange);
// hub_fdo.c
NTSTATUS
USBHUB_ParentFDOStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);