From af70a910fb6083efe0209167f8b51f394b86c28a Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Wed, 4 May 2011 01:07:21 +0000 Subject: [PATCH] [USBHUB_NEW] - Start work on reimplementing UsbHub driver. - Implement SubmitRequestToRootHub, QueryStatusChangeEndpoint, QueryInterface, GetPortStatusAndChange, SetPortFeature and ClearPortFeature.Handle QueryBusRelations. - Partially implement PNP handling for FDO. When starting the device get all the information about the RootHub the driver will need and enable Power on all ports. - Partially implement PNP handling for PDO, QueryId and QueryDeviceText. - WIP svn path=/branches/usb-bringup/; revision=51569 --- drivers/usb/usbhub_new/CMakeLists.txt | 12 + drivers/usb/usbhub_new/fdo.c | 903 ++++++++++++++++++++++++++ drivers/usb/usbhub_new/misc.c | 98 +++ drivers/usb/usbhub_new/pdo.c | 282 ++++++++ drivers/usb/usbhub_new/usbhub.c | 199 ++++++ drivers/usb/usbhub_new/usbhub.h | 146 +++++ drivers/usb/usbhub_new/usbhub.rc | 5 + 7 files changed, 1645 insertions(+) create mode 100644 drivers/usb/usbhub_new/CMakeLists.txt create mode 100644 drivers/usb/usbhub_new/fdo.c create mode 100644 drivers/usb/usbhub_new/misc.c create mode 100644 drivers/usb/usbhub_new/pdo.c create mode 100644 drivers/usb/usbhub_new/usbhub.c create mode 100644 drivers/usb/usbhub_new/usbhub.h create mode 100644 drivers/usb/usbhub_new/usbhub.rc diff --git a/drivers/usb/usbhub_new/CMakeLists.txt b/drivers/usb/usbhub_new/CMakeLists.txt new file mode 100644 index 00000000000..2a23297905b --- /dev/null +++ b/drivers/usb/usbhub_new/CMakeLists.txt @@ -0,0 +1,12 @@ + +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) + +target_link_libraries(usbhub ${PSEH_LIB}) + +set_module_type(usbhub kernelmodedriver) +add_importlibs(usbhub ntoskrnl hal usbd) +add_cab_target(usbhub 2) diff --git a/drivers/usb/usbhub_new/fdo.c b/drivers/usb/usbhub_new/fdo.c new file mode 100644 index 00000000000..d3afc5e1228 --- /dev/null +++ b/drivers/usb/usbhub_new/fdo.c @@ -0,0 +1,903 @@ +/* + * PROJECT: ReactOS Universal Serial Bus Hub Driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/usb/usbhub/fdo.c + * PURPOSE: Handle FDO + * PROGRAMMERS: + * Michael Martin (michael.martin@reactos.org) + * Johannes Anderwald (johannes.anderwald@reactos.org) + */ + +#define INITGUID + +#define NDEBUG +#include "usbhub.h" + +NTSTATUS +SubmitRequestToRootHub( + IN PDEVICE_OBJECT DeviceObject, + 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, + DeviceObject, + 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(DeviceObject, Irp); + + if (Status == STATUS_PENDING) + { + DPRINT1("USBHUB: Operation pending\n"); + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + + return Status; +} + +NTSTATUS +StatusChangeEndpointCompletion( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PHUB_DEVICE_EXTENSION HubDeviceExtension; + LONG i; + + HubDeviceExtension = (PHUB_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension; + + // + // Determine which port has changed + // + for (i=0; i < HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; i++) + { + DPRINT1("Port %x HubDeviceExtension->PortStatus %x\n",i+1, HubDeviceExtension->PortStatusChange[i].Status); + DPRINT1("Port %x HubDeviceExtension->PortChange %x\n",i+1, HubDeviceExtension->PortStatusChange[i].Change); + // + // FIXME: Call function to check port before creating device object for it + // + } + + // + // Free the Irp and return more processing required so the IO Manger doesn’t try to free it + // + IoFreeIrp(Irp); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS +QueryStatusChangeEndpoint( + PDEVICE_OBJECT DeviceObject) +{ + NTSTATUS Status; + PIO_STACK_LOCATION Stack; + PHUB_DEVICE_EXTENSION HubDeviceExtension; + + HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + HubDeviceExtension->PendingSCEUrb; + RtlZeroMemory(&HubDeviceExtension->PendingSCEUrb, + sizeof(URB)); + + // + // Create URB for Status Change Endpoint request + // + UsbBuildInterruptOrBulkTransferRequest(&HubDeviceExtension->PendingSCEUrb, + sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), + HubDeviceExtension->PipeHandle, + HubDeviceExtension->PortStatusChange, + NULL, + sizeof(USHORT) * 2 * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts, + USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, + NULL); + + // + // Set the device handle to null for roothub + // + HubDeviceExtension->PendingSCEUrb.UrbHeader.UsbdDeviceHandle = NULL; + + // + // Allocate an Irp + // + HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(HubDeviceExtension->RootHubPhysicalDeviceObject->StackSize, + FALSE); + + if (!HubDeviceExtension->PendingSCEIrp) + { + DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Initialize the IRP + // + HubDeviceExtension->PendingSCEIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; + HubDeviceExtension->PendingSCEIrp->IoStatus.Information = 0; + HubDeviceExtension->PendingSCEIrp->Flags = 0; + HubDeviceExtension->PendingSCEIrp->UserBuffer = NULL; + + // + // Get the Next Stack Location and Initialize it + // + Stack = IoGetNextIrpStackLocation(HubDeviceExtension->PendingSCEIrp); + Stack->DeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; + Stack->Parameters.Others.Argument1 = &HubDeviceExtension->PendingSCEUrb; + Stack->Parameters.Others.Argument2 = NULL; + Stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB; + + // + // Set the completion routine for when device is connected to root hub + // + IoSetCompletionRoutine(HubDeviceExtension->PendingSCEIrp, + (PIO_COMPLETION_ROUTINE) StatusChangeEndpointCompletion, + DeviceObject, + TRUE, + TRUE, + TRUE); + + Status = IoCallDriver(HubDeviceExtension->RootHubPhysicalDeviceObject, HubDeviceExtension->PendingSCEIrp); + DPRINT1("SCE request status %x\n", Status); + + return STATUS_PENDING; +} + +NTSTATUS +QueryInterface( + IN PDEVICE_OBJECT DeviceObject, + 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; + + // + // Initialize the Event used to wait for Irp completion + // + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + // + // Build Control Request + // + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, + DeviceObject, + NULL, + 0, + NULL, + &Event, + &IoStatus); + + // + // Get Next Stack Location and Initialize it. + // + 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(DeviceObject, Irp); + + if (Status == STATUS_PENDING) + { + DPRINT("Operation pending\n"); + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + Status = IoStatus.Status; + } + + return Status; +} + +NTSTATUS +GetPortStatusAndChange( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG PortId, + OUT PORT_STATUS_CHANGE *StatusChange) +{ + NTSTATUS Status; + PURB Urb; + + // + // Allocate URB + // + Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); + if (!Urb) + { + DPRINT1("Failed to allocate memory for URB!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Zero it + // + RtlZeroMemory(Urb, sizeof(URB)); + + // + // Create URB for getting Port Status + // + UsbBuildVendorRequest(Urb, + URB_FUNCTION_CLASS_OTHER, + sizeof(Urb->UrbControlVendorClassRequest), + USBD_TRANSFER_DIRECTION_OUT, + 0, + USB_REQUEST_GET_STATUS, + 0, + PortId, + &StatusChange, + 0, + sizeof(PORT_STATUS_CHANGE), + 0); + + // + // Query the Root Hub + // + Status = SubmitRequestToRootHub(DeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); + + // + // Free URB + // + ExFreePool(Urb); + + return Status; +} + +NTSTATUS +SetPortFeature( + PDEVICE_OBJECT DeviceObject, + ULONG PortId, + ULONG Feature) +{ + NTSTATUS Status; + PURB Urb; + + // + // Allocate URB + // + Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); + if (!Urb) + { + DPRINT1("Failed to allocate memory for URB!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Zero it + // + RtlZeroMemory(Urb, sizeof(URB)); + + // + // Create URB for Clearing Port Reset + // + UsbBuildVendorRequest(Urb, + URB_FUNCTION_CLASS_OTHER, + sizeof(Urb->UrbControlVendorClassRequest), + USBD_TRANSFER_DIRECTION_IN, + 0, + USB_REQUEST_SET_FEATURE, + Feature, + PortId, + NULL, + 0, + 0, + 0); + // + // Query the Root Hub + // + Status = SubmitRequestToRootHub(DeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); + + // + // Free URB + // + ExFreePool(Urb); + + return Status; +} + +NTSTATUS +ClearPortFeature( + PDEVICE_OBJECT DeviceObject, + ULONG PortId, + ULONG Feature) +{ + NTSTATUS Status; + PURB Urb; + + // + // Allocate a URB + // + Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); + if (!Urb) + { + DPRINT1("Failed to allocate memory for URB!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Zero it + // + RtlZeroMemory(Urb, sizeof(URB)); + + // + // Create URB for Clearing Port Reset + // + UsbBuildVendorRequest(Urb, + URB_FUNCTION_CLASS_OTHER, + sizeof(Urb->UrbControlVendorClassRequest), + USBD_TRANSFER_DIRECTION_IN, + 0, + USB_REQUEST_CLEAR_FEATURE, + Feature, + PortId, + NULL, + 0, + 0, + 0); + // + // Query the Root Hub + // + Status = SubmitRequestToRootHub(DeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); + + // + // Free URB + // + ExFreePool(Urb); + + return Status; +} + +NTSTATUS +GetUsbDeviceDescriptor( + PDEVICE_OBJECT ChildDeviceObject, + UCHAR DescriptorType, + UCHAR Index, + USHORT LangId, + PVOID TransferBuffer, + ULONG TransferBufferLength) +{ + NTSTATUS Status; + PURB Urb; + PHUB_DEVICE_EXTENSION HubDeviceExtension; + PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; + PMDL BufferMdl; + + // + // Get the Hubs Device Extension + // + ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension; + HubDeviceExtension = (PHUB_DEVICE_EXTENSION) ChildDeviceExtension->ParentDeviceObject->DeviceExtension; + + // + // Allocate a URB + // + Urb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); + if (!Urb) + { + DPRINT1("Failed to allocate memory for URB!\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Zero it + // + RtlZeroMemory(Urb, sizeof(URB)); + + // + // Create a MDL for buffer + // + BufferMdl = IoAllocateMdl(TransferBuffer, + TransferBufferLength, + FALSE, + FALSE, + NULL); + + // + // Lock the Mdl + // + _SEH2_TRY + { + MmProbeAndLockPages(BufferMdl, KernelMode, IoWriteAccess); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + DPRINT1("MmProbeAndLockPages Failed!\n"); + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + // + // Create URB for getting device descriptor + // + UsbBuildGetDescriptorRequest(Urb, + sizeof(Urb->UrbControlDescriptorRequest), + DescriptorType, + Index, + LangId, + NULL, + BufferMdl, + TransferBufferLength, + NULL); + + // + // Set the device handle + // + Urb->UrbHeader.UsbdDeviceHandle = (PVOID)ChildDeviceObject; + + // + // Query the Root Hub + // + Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject, + IOCTL_INTERNAL_USB_SUBMIT_URB, + Urb, + NULL); + + // + // Free Mdl + // + IoFreeMdl(BufferMdl); + + return Status; +} + +NTSTATUS +CreateUsbChildDeviceObject( + IN PDEVICE_OBJECT UsbHubDeviceObject, + IN LONG PortId, + OUT PDEVICE_OBJECT *UsbChildDeviceObject) +{ + //NTSTATUS Status; + //PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; + + return STATUS_SUCCESS; +} + +NTSTATUS +USBHUB_FdoQueryBusRelations( + IN PDEVICE_OBJECT DeviceObject, + OUT PDEVICE_RELATIONS* pDeviceRelations) +{ + PHUB_DEVICE_EXTENSION HubDeviceExtension; + PDEVICE_RELATIONS DeviceRelations; + ULONG i; + ULONG Children = 0; + ULONG NeededSize; + + HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + DPRINT1("Query Bus Relations\n"); + + // + // Count the number of children + // + for (i = 0; i < USB_MAXCHILDREN; i++) + { + + if (HubDeviceExtension->ChildDeviceObject[i] == NULL) + { + continue; + } + Children++; + } + + NeededSize = sizeof(DEVICE_RELATIONS); + if (Children > 1) + NeededSize += (Children - 1) * sizeof(PDEVICE_OBJECT); + + // + // Allocate DeviceRelations + // + DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, + NeededSize); + + if (!DeviceRelations) + return STATUS_INSUFFICIENT_RESOURCES; + DeviceRelations->Count = Children; + Children = 0; + + // + // Fill in return structure + // + for (i = 0; i < USB_MAXCHILDREN; i++) + { + if (HubDeviceExtension->ChildDeviceObject[i]) + { + ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]); + DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i]; + } + } + + ASSERT(Children == DeviceRelations->Count); + *pDeviceRelations = DeviceRelations; + + // + // FIXME: Send the first SCE Request + // + + return STATUS_SUCCESS; +} + +NTSTATUS +USBHUB_FdoHandlePnp( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + NTSTATUS Status = STATUS_SUCCESS; + ULONG_PTR Information = 0; + PHUB_DEVICE_EXTENSION HubDeviceExtension; + + HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) + { + case IRP_MN_START_DEVICE: + { + PURB Urb; + ULONG Result = 0; + PUSB_INTERFACE_DESCRIPTOR Pid; + ULONG PortId; + + USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}}; + PURB ConfigUrb = NULL; + + DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); + + // + // Allocated 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)); + + // + // Get the Root Hub Pdo + // + SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, + IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, + &HubDeviceExtension->RootHubPhysicalDeviceObject, + &HubDeviceExtension->RootHubFunctionalDeviceObject); + + ASSERT(HubDeviceExtension->RootHubPhysicalDeviceObject); + ASSERT(HubDeviceExtension->RootHubFunctionalDeviceObject); + DPRINT1("RootPdo %x, RootFdo %x\n", + HubDeviceExtension->RootHubPhysicalDeviceObject, + HubDeviceExtension->RootHubFunctionalDeviceObject); + + // + // Send the StartDevice to RootHub + // + Status = ForwardIrpAndWait(HubDeviceExtension->RootHubPhysicalDeviceObject, Irp); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to start the RootHub PDO\n"); + ASSERT(FALSE); + } + + // + // Get the current number of hubs + // + Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject, + IOCTL_INTERNAL_USB_GET_HUB_COUNT, + &HubDeviceExtension->NumberOfHubs, NULL); + + // + // Get the Hub Interface + // + Status = QueryInterface(HubDeviceExtension->RootHubPhysicalDeviceObject, + USB_BUS_INTERFACE_HUB_GUID, + sizeof(USB_BUS_INTERFACE_HUB_V5), + 5, + (PVOID)&HubDeviceExtension->HubInterface); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status); + return STATUS_UNSUCCESSFUL; + } + + // + // Get the USBDI Interface + // + Status = QueryInterface(HubDeviceExtension->RootHubPhysicalDeviceObject, + USB_BUS_INTERFACE_USBDI_GUID, + sizeof(USB_BUS_INTERFACE_USBDI_V2), + 2, + (PVOID)&HubDeviceExtension->UsbDInterface); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status); + return Status; + } + + // + // Get Root Hub Device Handle + // + Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject, + IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, + &HubDeviceExtension->RootHubHandle, + NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("GetRootHubDeviceHandle failed with status 0x%08lx\n", Status); + return Status; + } + + // + // Get Hub Device Information + // + Status = HubDeviceExtension->HubInterface.QueryDeviceInformation(HubDeviceExtension->RootHubPhysicalDeviceObject, + HubDeviceExtension->RootHubHandle, + &HubDeviceExtension->DeviceInformation, + sizeof(USB_DEVICE_INFORMATION_0), + &Result); + + + DPRINT1("Status %x, Result 0x%08lx\n", Status, Result); + DPRINT1("InformationLevel %x\n", HubDeviceExtension->DeviceInformation.InformationLevel); + DPRINT1("ActualLength %x\n", HubDeviceExtension->DeviceInformation.ActualLength); + DPRINT1("PortNumber %x\n", HubDeviceExtension->DeviceInformation.PortNumber); + DPRINT1("DeviceDescriptor %x\n", HubDeviceExtension->DeviceInformation.DeviceDescriptor); + DPRINT1("HubAddress %x\n", HubDeviceExtension->DeviceInformation.HubAddress); + DPRINT1("NumberofPipes %x\n", HubDeviceExtension->DeviceInformation.NumberOfOpenPipes); + + + // + // Get Root Hubs Device Descriptor + // + UsbBuildGetDescriptorRequest(Urb, + sizeof(Urb->UrbControlDescriptorRequest), + USB_DEVICE_DESCRIPTOR_TYPE, + 0, + 0, + &HubDeviceExtension->HubDeviceDescriptor, + NULL, + sizeof(USB_DEVICE_DESCRIPTOR), + NULL); + + Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle; + + Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject, + IOCTL_INTERNAL_USB_SUBMIT_URB, + Urb, + NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to get HubDeviceDescriptor!\n"); + } + + DumpDeviceDescriptor(&HubDeviceExtension->HubDeviceDescriptor); + + // + // Get Root Hubs 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); + + Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle; + + Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject, + IOCTL_INTERNAL_USB_SUBMIT_URB, + Urb, + NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to get RootHub Configuration with status %x\n", Status); + ASSERT(FALSE); + } + ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength); + + DumpConfigurationDescriptor(&HubDeviceExtension->HubConfigDescriptor); + + Status = HubDeviceExtension->HubInterface.GetExtendedHubInformation(HubDeviceExtension->RootHubPhysicalDeviceObject, + HubDeviceExtension->RootHubPhysicalDeviceObject, + &HubDeviceExtension->UsbExtHubInfo, + sizeof(USB_EXTHUB_INFORMATION_0), + &Result); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n"); + ASSERT(FALSE); + } + + DPRINT1("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts); + + // + // Get the Hub Descriptor + // + UsbBuildVendorRequest(Urb, + URB_FUNCTION_CLASS_DEVICE, + sizeof(Urb->UrbControlVendorClassRequest), + USBD_TRANSFER_DIRECTION_IN, + 0, + USB_DEVICE_CLASS_RESERVED, + 0, + 0, + &HubDeviceExtension->HubDescriptor, + NULL, + sizeof(USB_HUB_DESCRIPTOR), + NULL); + + Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle; + + Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject, + IOCTL_INTERNAL_USB_SUBMIT_URB, + Urb, + NULL); + + DPRINT1("bDescriptorType %x\n", HubDeviceExtension->HubDescriptor.bDescriptorType); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to get Hub Descriptor!\n"); + ExFreePool(Urb); + return STATUS_UNSUCCESSFUL; + } + + // + // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub + // + HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool, + sizeof(ULONG) * HubDeviceExtension->HubDescriptor.bNumberOfPorts, + USB_HUB_TAG); + + // + // Get the first Configuration Descriptor + // + Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor, + &HubDeviceExtension->HubConfigDescriptor, + -1, -1, -1, -1, -1); + ASSERT(Pid != NULL); + InterfaceList[0].InterfaceDescriptor = Pid; + ConfigUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor, + (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); + ASSERT(ConfigUrb != NULL); + + Status = SubmitRequestToRootHub(HubDeviceExtension->RootHubPhysicalDeviceObject, + IOCTL_INTERNAL_USB_SUBMIT_URB, + ConfigUrb, + NULL); + + HubDeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle; + HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; + DPRINT1("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle); + + ExFreePool(ConfigUrb); + + // + // Initialize the Hub + // + Status = HubDeviceExtension->HubInterface.Initialize20Hub(HubDeviceExtension->RootHubPhysicalDeviceObject, + HubDeviceExtension->RootHubHandle, 1); + DPRINT1("Status %x\n", Status); + + // + // Enable power on all ports + // + for (PortId = 0; PortId < HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++) + { + SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_POWER); + } + ExFreePool(Urb); + break; + } + + case IRP_MN_QUERY_DEVICE_RELATIONS: + { + switch (Stack->Parameters.QueryDeviceRelations.Type) + { + case BusRelations: + { + PDEVICE_RELATIONS DeviceRelations = NULL; + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); + + Status = USBHUB_FdoQueryBusRelations(DeviceObject, &DeviceRelations); + + Information = (ULONG_PTR)DeviceRelations; + break; + } + case RemovalRelations: + { + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); + return ForwardIrpAndForget(DeviceObject, Irp); + } + default: + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", + Stack->Parameters.QueryDeviceRelations.Type); + return ForwardIrpAndForget(DeviceObject, Irp); + } + break; + } + 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; + } + default: + { + DPRINT1(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction); + return ForwardIrpAndForget(DeviceObject, Irp); + } + } + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + +NTSTATUS +USBHUB_FdoHandleDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT1("FdoHandleDeviceControl\n"); + UNIMPLEMENTED + return STATUS_NOT_IMPLEMENTED; +} + diff --git a/drivers/usb/usbhub_new/misc.c b/drivers/usb/usbhub_new/misc.c new file mode 100644 index 00000000000..d2c988176d3 --- /dev/null +++ b/drivers/usb/usbhub_new/misc.c @@ -0,0 +1,98 @@ +/* + * PROJECT: ReactOS Universal Serial Bus Hub Driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/usb/usbhub/fdo.c + * PURPOSE: Misc helper functions + * PROGRAMMERS: + * Michael Martin (michael.martin@reactos.org) + * Johannes Anderwald (johannes.anderwald@reactos.org) + */ +#define NDEBUG +#include "usbhub.h" +#include + +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 +DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) +{ + DPRINT1("Dumping 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); +} + +NTSTATUS +NTAPI +ForwardIrpAndWaitCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context) +{ + if (Irp->PendingReturned) + KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS +ForwardIrpAndWait( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + KEVENT Event; + NTSTATUS Status; + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + IoCopyCurrentIrpStackLocationToNext(Irp); + + IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE); + + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + if (NT_SUCCESS(Status)) + Status = Irp->IoStatus.Status; + } + + return Status; +} + +NTSTATUS +ForwardIrpAndForget( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_OBJECT LowerDevice = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDeviceObject; + + ASSERT(LowerDevice); + + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(LowerDevice, Irp); +} + diff --git a/drivers/usb/usbhub_new/pdo.c b/drivers/usb/usbhub_new/pdo.c new file mode 100644 index 00000000000..8fc0b37ad2f --- /dev/null +++ b/drivers/usb/usbhub_new/pdo.c @@ -0,0 +1,282 @@ +/* + * PROJECT: ReactOS Universal Serial Bus Hub Driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/usb/usbhub/fdo.c + * PURPOSE: Handle PDO + * PROGRAMMERS: + * Hervé Poussineau (hpoussin@reactos.org) + * Michael Martin (michael.martin@reactos.org) + * Johannes Anderwald (johannes.anderwald@reactos.org) + */ + +#define NDEBUG +#include "usbhub.h" + +#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) + +NTSTATUS +USBHUB_PdoHandleInternalDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION Stack; + ULONG_PTR Information = 0; + NTSTATUS Status; + + DPRINT1("UsbhubInternalDeviceControlPdo() called\n"); + + Stack = IoGetCurrentIrpStackLocation(Irp); + Status = Irp->IoStatus.Status; + + switch (Stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO: + { + PHUB_DEVICE_EXTENSION DeviceExtension; + + DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n"); + if (Irp->AssociatedIrp.SystemBuffer == NULL + || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID)) + { + Status = STATUS_INVALID_PARAMETER; + } + else + { + PVOID* pHubPointer; + DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer; + // FIXME + *pHubPointer = NULL; + Information = sizeof(PVOID); + Status = STATUS_SUCCESS; + } + break; + } + default: + { + DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); + Information = Irp->IoStatus.Information; + Status = Irp->IoStatus.Status; + } + } + + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + +NTSTATUS +USBHUB_PdoStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PHUB_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + DPRINT1("USBHUB_PdoStartDevice\n"); + DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + UNIMPLEMENTED + return Status; +} + +NTSTATUS +USBHUB_PdoQueryId( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + OUT ULONG_PTR* Information) +{ + PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; + ULONG IdType; + PWCHAR SourceString = NULL; + NTSTATUS Status = STATUS_SUCCESS; + + IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType; + ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + switch (IdType) + { + case BusQueryDeviceID: + { + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n"); + SourceString = ChildDeviceExtension->DeviceId; + break; + } + case BusQueryHardwareIDs: + { + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n"); + SourceString = ChildDeviceExtension->HardwareIds; + break; + } + case BusQueryCompatibleIDs: + { + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n"); + SourceString = ChildDeviceExtension->CompatibleIds; + break; + } + case BusQueryInstanceID: + { + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n"); + SourceString = ChildDeviceExtension->InstanceId; + break; + } + default: + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType); + return STATUS_NOT_SUPPORTED; + } + + *Information = (ULONG_PTR)SourceString; + return Status; +} + +NTSTATUS +USBHUB_PdoQueryDeviceText( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + OUT ULONG_PTR* Information) +{ + PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; + DEVICE_TEXT_TYPE DeviceTextType; + LCID LocaleId; + + DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType; + LocaleId = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.LocaleId; + ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + switch (DeviceTextType) + { + case DeviceTextDescription: + case DeviceTextLocationInformation: + { + if (DeviceTextType == DeviceTextDescription) + { + *Information = (ULONG_PTR)ChildDeviceExtension->TextDescription; + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n"); + } + else + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n"); + return STATUS_SUCCESS; + } + default: + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType); + return STATUS_NOT_SUPPORTED; + } +} + +NTSTATUS +USBHUB_PdoHandlePnp( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + ULONG MinorFunction; + PIO_STACK_LOCATION Stack; + ULONG_PTR Information = 0; + NTSTATUS Status; + + Stack = IoGetCurrentIrpStackLocation(Irp); + MinorFunction = Stack->MinorFunction; + + switch (MinorFunction) + { + case IRP_MN_START_DEVICE: + { + DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); + Status = USBHUB_PdoStartDevice(DeviceObject, Irp); + break; + } + case IRP_MN_QUERY_CAPABILITIES: + { + PDEVICE_CAPABILITIES DeviceCapabilities; + ULONG i; + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n"); + + DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities; + // FIXME: capabilities can change with connected device + DeviceCapabilities->LockSupported = TRUE; + DeviceCapabilities->EjectSupported = FALSE; + DeviceCapabilities->Removable = FALSE; + DeviceCapabilities->DockDevice = FALSE; + DeviceCapabilities->UniqueID = FALSE; + DeviceCapabilities->SilentInstall = TRUE; + DeviceCapabilities->RawDeviceOK = FALSE; + DeviceCapabilities->SurpriseRemovalOK = FALSE; + DeviceCapabilities->HardwareDisabled = FALSE; + //DeviceCapabilities->NoDisplayInUI = FALSE; + DeviceCapabilities->DeviceState[0] = PowerDeviceD0; + for (i = 0; i < PowerSystemMaximum; i++) + DeviceCapabilities->DeviceState[i] = PowerDeviceD3; + //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; + DeviceCapabilities->D1Latency = 0; + DeviceCapabilities->D2Latency = 0; + DeviceCapabilities->D3Latency = 0; + Status = STATUS_SUCCESS; + break; + } + case IRP_MN_QUERY_RESOURCES: + { + PCM_RESOURCE_LIST ResourceList; + + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n"); + ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST)); + if (!ResourceList) + { + DPRINT1("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + ResourceList->Count = 0; + Information = (ULONG_PTR)ResourceList; + Status = STATUS_SUCCESS; + } + break; + } + case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: + { + PIO_RESOURCE_REQUIREMENTS_LIST ResourceList; + + DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); + ResourceList = ExAllocatePool(PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST)); + if (!ResourceList) + { + DPRINT1("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + RtlZeroMemory(ResourceList, sizeof(IO_RESOURCE_REQUIREMENTS_LIST)); + ResourceList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST); + ResourceList->AlternativeLists = 1; + ResourceList->List->Version = 1; + ResourceList->List->Revision = 1; + ResourceList->List->Count = 0; + Information = (ULONG_PTR)ResourceList; + Status = STATUS_SUCCESS; + } + break; + } + case IRP_MN_QUERY_DEVICE_TEXT: + { + Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information); + break; + } + case IRP_MN_QUERY_ID: + { + Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information); + break; + } + default: + { + DPRINT1("ERROR PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); + Information = Irp->IoStatus.Information; + Status = Irp->IoStatus.Status; + } + } + + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + diff --git a/drivers/usb/usbhub_new/usbhub.c b/drivers/usb/usbhub_new/usbhub.c new file mode 100644 index 00000000000..6fce061a656 --- /dev/null +++ b/drivers/usb/usbhub_new/usbhub.c @@ -0,0 +1,199 @@ +/* + * PROJECT: ReactOS Universal Serial Bus Hub Driver + * LICENSE: GPL - See COPYING in the top level directory + * FILE: drivers/usb/usbhub/fdo.c + * PURPOSE: UsbHub Driver + * PROGRAMMERS: + * Hervé Poussineau (hpoussin@reactos.org) + * Michael Martin (michael.martin@reactos.org) + * Johannes Anderwald (johannes.anderwald@reactos.org) + */ + + +//#define NDEBUG +#include "usbhub.h" + +NTSTATUS NTAPI +USBHUB_Create( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT1("USBHUB: IRP_MJ_CREATE\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +NTSTATUS NTAPI +USBHUB_Close( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT1("USBHUB: IRP_MJ_CLOSE\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +NTSTATUS NTAPI +USBHUB_Cleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT1("USBHUB: IRP_MJ_CLEANUP\n"); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + + +NTSTATUS NTAPI +USBHUB_AddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ + PDEVICE_OBJECT DeviceObject; + PHUB_DEVICE_EXTENSION HubDeviceExtension; + NTSTATUS Status; + + // + // Create the Device Object + // + Status = IoCreateDevice(DriverObject, + sizeof(HUB_DEVICE_EXTENSION), + NULL, + FILE_DEVICE_BUS_EXTENDER, + FILE_AUTOGENERATED_DEVICE_NAME, + FALSE, + &DeviceObject); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("USBHUB: IoCreateDevice() failed with status 0x%08lx\n", Status); + return Status; + } + + // + // Zero Hub Extension + // + HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + RtlZeroMemory(HubDeviceExtension, sizeof(HUB_DEVICE_EXTENSION)); + + // + // Set this to Fdo + // + HubDeviceExtension->Common.IsFDO = TRUE; + DeviceObject->Flags |= DO_POWER_PAGABLE; + + // + // Attached to lower device + // + //Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); + HubDeviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); + if (!NT_SUCCESS(Status)) + { + DPRINT1("USBHUB: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); + IoDeleteDevice(DeviceObject); + return Status; + } + + DeviceObject->Flags |= DO_BUFFERED_IO; + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + return STATUS_SUCCESS; +} + +static NTSTATUS NTAPI +USBHUB_IrpStub( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + NTSTATUS Status; + + if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) + { + DPRINT1("Usbhub: FDO stub for major function 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->MajorFunction); + return ForwardIrpAndForget(DeviceObject, Irp); + } + else + { + // + // Cant forward as we are the PDO! + // + DPRINT1("USBHUB: ERROR- PDO stub for major function 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->MajorFunction); +#ifndef NDEBUG + DbgBreakPoint(); +#endif + } + + Status = Irp->IoStatus.Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + + +NTSTATUS NTAPI +USBHUB_DispatchDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT1("Usbhub: DispatchDeviceControl\n"); + if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) + return USBHUB_FdoHandleDeviceControl(DeviceObject, Irp); + else + return USBHUB_IrpStub(DeviceObject, Irp); +} + +NTSTATUS NTAPI +USBHUB_DispatchInternalDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + DPRINT1("Usbhub: DispatchInternalDeviceControl\n"); + if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) + return USBHUB_IrpStub(DeviceObject, Irp); + else + return USBHUB_PdoHandleInternalDeviceControl(DeviceObject, Irp); +} + +NTSTATUS NTAPI +USBHUB_DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + DPRINT1("USBHUB: DispatchPnp\n"); + if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) + return USBHUB_FdoHandlePnp(DeviceObject, Irp); + else + return USBHUB_PdoHandlePnp(DeviceObject, Irp); +} + +NTSTATUS NTAPI +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + ULONG i; + + DriverObject->DriverExtension->AddDevice = USBHUB_AddDevice; + DPRINT1("USBHUB: DriverEntry\n"); + + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + DriverObject->MajorFunction[i] = USBHUB_IrpStub; + + DriverObject->MajorFunction[IRP_MJ_CREATE] = USBHUB_Create; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBHUB_Close; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = USBHUB_Cleanup; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBHUB_DispatchDeviceControl; + DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBHUB_DispatchInternalDeviceControl; + DriverObject->MajorFunction[IRP_MJ_PNP] = USBHUB_DispatchPnp; + + return STATUS_SUCCESS; +} + diff --git a/drivers/usb/usbhub_new/usbhub.h b/drivers/usb/usbhub_new/usbhub.h new file mode 100644 index 00000000000..d8e5700bd4b --- /dev/null +++ b/drivers/usb/usbhub_new/usbhub.h @@ -0,0 +1,146 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +//BROKEN: #include +#include + +#define USB_HUB_TAG 'hbsu' +#define USB_MAXCHILDREN 127 + +// Lifted from broken header above +#define C_HUB_LOCAL_POWER 0 +#define C_HUB_OVER_CURRENT 1 +#define PORT_CONNECTION 0 +#define PORT_ENABLE 1 +#define PORT_SUSPEND 2 +#define PORT_OVER_CURRENT 3 +#define PORT_RESET 4 +#define PORT_POWER 8 +#define PORT_LOW_SPEED 9 +#define C_PORT_CONNECTION 16 +#define C_PORT_ENABLE 17 +#define C_PORT_SUSPEND 18 +#define C_PORT_OVER_CURRENT 19 +#define C_PORT_RESET 20 +#define PORT_TEST 21 +#define PORT_INDICATOR 22 + +typedef struct _PORT_STATUS_CHANGE +{ + USHORT Status; + USHORT Change; +} PORT_STATUS_CHANGE, *PPORT_STATUS_CHANGE; + +typedef struct +{ + BOOLEAN IsFDO; +} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; + +typedef struct _HUB_CHILDDEVICE_EXTENSION +{ + COMMON_DEVICE_EXTENSION Common; + PDEVICE_OBJECT ParentDeviceObject; + PWCHAR DeviceId; + PWCHAR InstanceId; + PWCHAR HardwareIds; + PWCHAR CompatibleIds; + PWCHAR TextDescription; + UNICODE_STRING SymbolicLinkName; +} HUB_CHILDDEVICE_EXTENSION, *PHUB_CHILDDEVICE_EXTENSION; + +typedef struct _HUB_DEVICE_EXTENSION +{ + COMMON_DEVICE_EXTENSION Common; + PDEVICE_OBJECT LowerDeviceObject; + ULONG ChildCount; + PDEVICE_OBJECT ChildDeviceObject[USB_MAXCHILDREN]; + PDEVICE_OBJECT RootHubPhysicalDeviceObject; + PDEVICE_OBJECT RootHubFunctionalDeviceObject; + + ULONG NumberOfHubs; + + PORT_STATUS_CHANGE *PortStatusChange; + URB PendingSCEUrb; + PIRP PendingSCEIrp; + + USB_BUS_INTERFACE_HUB_V5 HubInterface; + USB_BUS_INTERFACE_USBDI_V2 UsbDInterface; + + USB_HUB_DESCRIPTOR HubDescriptor; + USB_DEVICE_DESCRIPTOR HubDeviceDescriptor; + USB_CONFIGURATION_DESCRIPTOR HubConfigDescriptor; + USB_INTERFACE_DESCRIPTOR HubInterfaceDescriptor; + USB_ENDPOINT_DESCRIPTOR HubEndPointDescriptor; + + USB_EXTHUB_INFORMATION_0 UsbExtHubInfo; + USB_DEVICE_INFORMATION_0 DeviceInformation; + + USBD_CONFIGURATION_HANDLE ConfigurationHandle; + USBD_PIPE_HANDLE PipeHandle; + PVOID RootHubHandle; + + UNICODE_STRING SymbolicLinkName; +} HUB_DEVICE_EXTENSION, *PHUB_DEVICE_EXTENSION; + +// createclose.c +NTSTATUS NTAPI +USBHUB_Create( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS NTAPI +USBHUB_Close( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS NTAPI +USBHUB_Cleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// fdo.c +NTSTATUS +USBHUB_FdoHandleDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS +USBHUB_FdoHandlePnp( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +// misc.c +NTSTATUS +ForwardIrpAndWait( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +ForwardIrpAndForget( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +// pdo.c +NTSTATUS +USBHUB_PdoHandlePnp( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +NTSTATUS +USBHUB_PdoHandleInternalDeviceControl( + PDEVICE_OBJECT DeviceObject, + PIRP Irp); + +VOID +DumpDeviceDescriptor( + PUSB_DEVICE_DESCRIPTOR DeviceDescriptor); + +VOID +DumpConfigurationDescriptor( + PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor); diff --git a/drivers/usb/usbhub_new/usbhub.rc b/drivers/usb/usbhub_new/usbhub.rc new file mode 100644 index 00000000000..aa3f2694311 --- /dev/null +++ b/drivers/usb/usbhub_new/usbhub.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "USBHUB Driver API\0" +#define REACTOS_STR_INTERNAL_NAME "usbhub\0" +#define REACTOS_STR_ORIGINAL_FILENAME "usbhub.sys\0" +#include