From 82d9d774ca1fbcd893a83ebdee14fa09743b8459 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Wed, 29 Feb 2012 18:51:07 +0000 Subject: [PATCH] [USBHUB] - 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 --- reactos/drivers/usb/usbhub/CMakeLists.txt | 2 +- reactos/drivers/usb/usbhub/fdo.c | 100 ++++------ reactos/drivers/usb/usbhub/hub_fdo.c | 212 ++++++++++++++++++++++ reactos/drivers/usb/usbhub/misc.c | 65 +++++++ reactos/drivers/usb/usbhub/pdo.c | 31 ++++ reactos/drivers/usb/usbhub/usbhub.h | 14 ++ 6 files changed, 357 insertions(+), 67 deletions(-) create mode 100644 reactos/drivers/usb/usbhub/hub_fdo.c diff --git a/reactos/drivers/usb/usbhub/CMakeLists.txt b/reactos/drivers/usb/usbhub/CMakeLists.txt index a33f9dbdc8d..6e1a3cd9f6f 100644 --- a/reactos/drivers/usb/usbhub/CMakeLists.txt +++ b/reactos/drivers/usb/usbhub/CMakeLists.txt @@ -3,7 +3,7 @@ add_definitions(-DDEBUG_MODE) 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}) diff --git a/reactos/drivers/usb/usbhub/fdo.c b/reactos/drivers/usb/usbhub/fdo.c index c3a286e63b5..79ce20c64d1 100644 --- a/reactos/drivers/usb/usbhub/fdo.c +++ b/reactos/drivers/usb/usbhub/fdo.c @@ -27,71 +27,6 @@ DestroyUsbChildDeviceObject( IN PDEVICE_OBJECT UsbHubDeviceObject, 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 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 USBHUB_FdoStartDevice( IN PDEVICE_OBJECT DeviceObject, @@ -1969,7 +1929,15 @@ USBHUB_FdoHandlePnp( { 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; } diff --git a/reactos/drivers/usb/usbhub/hub_fdo.c b/reactos/drivers/usb/usbhub/hub_fdo.c new file mode 100644 index 00000000000..16847828e9c --- /dev/null +++ b/reactos/drivers/usb/usbhub/hub_fdo.c @@ -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; +} + diff --git a/reactos/drivers/usb/usbhub/misc.c b/reactos/drivers/usb/usbhub/misc.c index 9e3d782678c..a9a3f0ec6be 100644 --- a/reactos/drivers/usb/usbhub/misc.c +++ b/reactos/drivers/usb/usbhub/misc.c @@ -143,3 +143,68 @@ ForwardIrpAndForget( 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; +} diff --git a/reactos/drivers/usb/usbhub/pdo.c b/reactos/drivers/usb/usbhub/pdo.c index 43c41bf2be7..9d2aa1ee378 100644 --- a/reactos/drivers/usb/usbhub/pdo.c +++ b/reactos/drivers/usb/usbhub/pdo.c @@ -339,8 +339,39 @@ USBHUB_PdoHandleInternalDeviceControl( DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n"); break; case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: + { 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; + } + 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: { DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); diff --git a/reactos/drivers/usb/usbhub/usbhub.h b/reactos/drivers/usb/usbhub/usbhub.h index 14ea5159a74..f221ec4f17b 100644 --- a/reactos/drivers/usb/usbhub/usbhub.h +++ b/reactos/drivers/usb/usbhub/usbhub.h @@ -142,6 +142,13 @@ ForwardIrpAndForget( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); +NTSTATUS +SubmitRequestToRootHub( + IN PDEVICE_OBJECT RootHubDeviceObject, + IN ULONG IoControlCode, + OUT PVOID OutParameter1, + OUT PVOID OutParameter2); + // pdo.c NTSTATUS USBHUB_PdoHandlePnp( @@ -170,3 +177,10 @@ GetPortStatusAndChange( IN PDEVICE_OBJECT RootHubDeviceObject, IN ULONG PortId, OUT PPORT_STATUS_CHANGE StatusChange); + +// hub_fdo.c + +NTSTATUS +USBHUB_ParentFDOStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); \ No newline at end of file