From 4f76ebe078c6ab134d20d1e4596c3fe33e75ef8e Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Wed, 11 May 2011 02:25:11 +0000 Subject: [PATCH] [USBHUB_NEW] - Save PortNumber in child device extensions as its needed when PNP request device capabilities. - Handle IOCTL_INTERNAL_USB_SUBMIT_URB request by creating a new Irp and passing the Urb down to the miniport. - Now working with our ehci driver, we at least see a usb driver and can browse directory in Windows, though doing so results in assert as ehci doesnt support transfers over 5 Pages yet. Fix coming soon. svn path=/branches/usb-bringup/; revision=51672 --- drivers/usb/usbhub_new/fdo.c | 39 +++-- drivers/usb/usbhub_new/misc.c | 1 - drivers/usb/usbhub_new/pdo.c | 247 ++++++++++++++++++++++++++++++-- drivers/usb/usbhub_new/usbhub.h | 1 + 4 files changed, 263 insertions(+), 25 deletions(-) diff --git a/drivers/usb/usbhub_new/fdo.c b/drivers/usb/usbhub_new/fdo.c index 1bac45fdf1b..c2d1fbdee7a 100644 --- a/drivers/usb/usbhub_new/fdo.c +++ b/drivers/usb/usbhub_new/fdo.c @@ -9,8 +9,6 @@ */ #define INITGUID - -#define NDEBUG #include "usbhub.h" NTSTATUS @@ -73,12 +71,19 @@ SubmitRequestToRootHub( // Status = IoCallDriver(RootHubDeviceObject, Irp); - if (Status == STATUS_PENDING) + // + // 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; } @@ -353,11 +358,23 @@ DeviceStatusChangeThread( DPRINT1("Port %d Status %x\n", PortId, PortStatus.Status); DPRINT1("Port %d Change %x\n", PortId, PortStatus.Change); + // + // Check that reset was cleared + // if(PortStatus.Change & USB_PORT_STATUS_RESET) { DPRINT1("Port did not clear reset! Possible Hardware problem!\n"); } + // + // Check if the device is still connected + // + if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT)) + { + DPRINT1("Device has been disconnected\n"); + continue; + } + // // Make sure its Connected and Enabled // @@ -838,8 +855,8 @@ CreateDeviceIds( DevDesc->bDeviceClass) + 1; } BufferPtr[Index] = UNICODE_NULL; - DPRINT1("usCompatibleIds %wZ\n", &UsbChildExtension->usCompatibleIds); UsbChildExtension->usCompatibleIds.Buffer = BufferPtr; + DPRINT1("usCompatibleIds %wZ\n", &UsbChildExtension->usCompatibleIds); // // Initialize the DeviceId String @@ -860,8 +877,8 @@ CreateDeviceIds( // Construct DeviceId // swprintf(BufferPtr, L"USB\\Vid_%04x&Pid_%04x\0", UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct); - DPRINT1("usDeviceId) %wZ\n", &UsbChildExtension->usDeviceId); UsbChildExtension->usDeviceId.Buffer = BufferPtr; + DPRINT1("usDeviceId %wZ\n", &UsbChildExtension->usDeviceId); // // Initialize the HardwareId String @@ -889,8 +906,8 @@ CreateDeviceIds( L"USB\\Vid_%04x&Pid_%04x", UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1; BufferPtr[Index] = UNICODE_NULL; - DPRINT1("usHardWareIds %wZ\n", &UsbChildExtension->usHardwareIds); UsbChildExtension->usHardwareIds.Buffer = BufferPtr; + DPRINT1("usHardWareIds %wZ\n", &UsbChildExtension->usHardwareIds); // // FIXME: Handle Lang ids @@ -1049,6 +1066,7 @@ CreateUsbChildDeviceObject( UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)NewChildDeviceObject->DeviceExtension; RtlZeroMemory(UsbChildExtension, sizeof(HUB_CHILDDEVICE_EXTENSION)); UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject; + UsbChildExtension->PortNumber = PortId; // // Create the UsbDeviceObject @@ -1567,6 +1585,10 @@ USBHUB_FdoHandlePnp( Status = HubDeviceExtension->HubInterface.RootHubInitNotification(HubInterfaceBusContext, DeviceObject, (PRH_INIT_CALLBACK)RootHubInitCallbackFunction); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to set callback\n"); + } } else { @@ -1576,11 +1598,6 @@ USBHUB_FdoHandlePnp( QueryStatusChangeEndpoint(DeviceObject); } - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to set callback\n"); - } - ExFreePool(Urb); break; } diff --git a/drivers/usb/usbhub_new/misc.c b/drivers/usb/usbhub_new/misc.c index d0ea2322ca9..9e3d782678c 100644 --- a/drivers/usb/usbhub_new/misc.c +++ b/drivers/usb/usbhub_new/misc.c @@ -7,7 +7,6 @@ * Michael Martin (michael.martin@reactos.org) * Johannes Anderwald (johannes.anderwald@reactos.org) */ -#define NDEBUG #include "usbhub.h" #include diff --git a/drivers/usb/usbhub_new/pdo.c b/drivers/usb/usbhub_new/pdo.c index 8080be2bf16..e336c5cf103 100644 --- a/drivers/usb/usbhub_new/pdo.c +++ b/drivers/usb/usbhub_new/pdo.c @@ -9,25 +9,142 @@ * Johannes Anderwald (johannes.anderwald@reactos.org) */ -#define NDEBUG #include "usbhub.h" #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) - + +NTSTATUS +UrbCompletion( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + PVOID Context) +{ + PIRP OriginalIrp; + DPRINT("Entered Urb Completion\n"); + + // + // Get the original Irp + // + OriginalIrp = (PIRP)Context; + + // + // Update it to match what was returned for the IRP that was passed to RootHub + // + OriginalIrp->IoStatus.Status = Irp->IoStatus.Status; + OriginalIrp->IoStatus.Information = Irp->IoStatus.Information; + DPRINT("Status %x, Information %x\n", Irp->IoStatus.Status, Irp->IoStatus.Information); + + // + // Complete the original Irp + // + IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT); + + // + // Return this status so the IO Manager doesnt mess with the Irp + // + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS +FowardUrbToRootHub( + PDEVICE_OBJECT RootHubDeviceObject, + IN ULONG IoControlCode, + PIRP Irp, + OUT PVOID OutParameter1, + OUT PVOID OutParameter2) +{ + NTSTATUS Status; + PIRP ForwardIrp; + IO_STATUS_BLOCK IoStatus; + PIO_STACK_LOCATION ForwardStack, CurrentStack; + PURB Urb; + + // + // Get the current stack location for the Irp + // + CurrentStack = IoGetCurrentIrpStackLocation(Irp); + ASSERT(CurrentStack); + + // + // Pull the Urb from that stack, it will be reused in the Irp sent to RootHub + // + Urb = (PURB)CurrentStack->Parameters.Others.Argument1; + ASSERT(Urb); + + // + // Create the Irp to forward to RootHub + // + ForwardIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_SHUTDOWN, + RootHubDeviceObject, + NULL, + 0, + 0, + &IoStatus); + if (!ForwardIrp) + { + DPRINT1("Failed to allocate IRP\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Get the new Irps next stack + // + ForwardStack = IoGetNextIrpStackLocation(ForwardIrp); + + // + // Copy the stack for the current irp into the next stack of new irp + // + RtlCopyMemory(ForwardStack, CurrentStack, sizeof(IO_STACK_LOCATION)); + + IoStatus.Status = STATUS_NOT_SUPPORTED; + IoStatus.Information = 0; + + // + // Mark the Irp from upper driver as pending + // + IoMarkIrpPending(Irp); + + // + // Now set the completion routine for the new Irp. + // + IoSetCompletionRoutine(ForwardIrp, + (PIO_COMPLETION_ROUTINE)UrbCompletion, + Irp, + TRUE, + TRUE, + TRUE); + + Status = IoCallDriver(RootHubDeviceObject, ForwardIrp); + + // + // Always return pending as the completion routine will take care of it + // + return STATUS_PENDING; +} + NTSTATUS USBHUB_PdoHandleInternalDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + NTSTATUS Status; PIO_STACK_LOCATION Stack; ULONG_PTR Information = 0; - NTSTATUS Status; + PHUB_DEVICE_EXTENSION HubDeviceExtension; + PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; + PDEVICE_OBJECT RootHubDeviceObject; + PURB Urb; - DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject); + //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject); Stack = IoGetCurrentIrpStackLocation(Irp); Status = Irp->IoStatus.Status; + ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; + ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE); + HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension; + RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; + switch (Stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO: @@ -53,6 +170,102 @@ USBHUB_PdoHandleInternalDeviceControl( } break; } + case IOCTL_INTERNAL_USB_SUBMIT_URB: + { + //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n"); + // + // get current stack location + // + Stack = IoGetCurrentIrpStackLocation(Irp); + ASSERT(Stack); + + // + // Get the Urb + // + Urb = (PURB)Stack->Parameters.Others.Argument1; + ASSERT(Urb); + + // + // Set the real device handle + // + DPRINT("UsbdDeviceHandle %x, ChildDeviceHandle %x\n", Urb->UrbHeader.UsbdDeviceHandle, ChildDeviceExtension->UsbDeviceHandle); + + Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle; + + // + // Submit to RootHub + // + switch (Urb->UrbHeader.Function) + { + // + // Debugging only + // + case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: + DPRINT1("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n"); + break; + case URB_FUNCTION_CLASS_DEVICE: + DPRINT1("URB_FUNCTION_CLASS_DEVICE\n"); + break; + case URB_FUNCTION_GET_STATUS_FROM_DEVICE: + DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n"); + break; + case URB_FUNCTION_SELECT_CONFIGURATION: + DPRINT1("URB_FUNCTION_SELECT_CONFIGURATION\n"); + break; + case URB_FUNCTION_SELECT_INTERFACE: + DPRINT1("URB_FUNCTION_SELECT_INTERFACE\n"); + break; + case URB_FUNCTION_CLASS_OTHER: + DPRINT1("URB_FUNCTION_CLASS_OTHER\n"); + break; + case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: + { + /* + DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n"); + DPRINT1("PipeHandle %x\n", Urb->UrbBulkOrInterruptTransfer.PipeHandle); + DPRINT1("TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags); + DPRINT1("Buffer %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer); + DPRINT1("BufferMDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL); + DPRINT1("Length %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); + DPRINT1("UrbLink %x\n", Urb->UrbBulkOrInterruptTransfer.UrbLink); + DPRINT1("hca %x\n", Urb->UrbBulkOrInterruptTransfer.hca); + */ + break; + } + case URB_FUNCTION_CLASS_INTERFACE: + DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n"); + break; + default: + DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function); + break; + } + Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle; + //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine); + // + // Send the request to RootHub + // + Status = FowardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL); + return Status; + break; + } + // + // FIXME: Can these be sent to RootHub? + // + case IOCTL_INTERNAL_USB_RESET_PORT: + DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n"); + break; + case IOCTL_INTERNAL_USB_GET_PORT_STATUS: + DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n"); + break; + case IOCTL_INTERNAL_USB_ENABLE_PORT: + DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n"); + break; + case IOCTL_INTERNAL_USB_CYCLE_PORT: + DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n"); + break; + case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: + DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n"); + break; default: { DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); @@ -61,9 +274,12 @@ USBHUB_PdoHandleInternalDeviceControl( } } - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + if (Status != STATUS_PENDING) + { + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } return Status; } @@ -202,11 +418,13 @@ USBHUB_PdoHandlePnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + NTSTATUS Status; ULONG MinorFunction; PIO_STACK_LOCATION Stack; ULONG_PTR Information = 0; - NTSTATUS Status; + PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; + UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; Stack = IoGetCurrentIrpStackLocation(Irp); MinorFunction = Stack->MinorFunction; @@ -226,16 +444,18 @@ USBHUB_PdoHandlePnp( DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities; // FIXME: capabilities can change with connected device - DeviceCapabilities->LockSupported = TRUE; - DeviceCapabilities->EjectSupported = TRUE; + DeviceCapabilities->LockSupported = FALSE; + DeviceCapabilities->EjectSupported = FALSE; DeviceCapabilities->Removable = TRUE; DeviceCapabilities->DockDevice = FALSE; - DeviceCapabilities->UniqueID = TRUE; - DeviceCapabilities->SilentInstall = TRUE; + DeviceCapabilities->UniqueID = FALSE; + DeviceCapabilities->SilentInstall = FALSE; DeviceCapabilities->RawDeviceOK = FALSE; - DeviceCapabilities->SurpriseRemovalOK = TRUE; + DeviceCapabilities->SurpriseRemovalOK = FALSE; DeviceCapabilities->HardwareDisabled = FALSE; //DeviceCapabilities->NoDisplayInUI = FALSE; + DeviceCapabilities->Address = UsbChildExtension->PortNumber; + DeviceCapabilities->UINumber = 0; DeviceCapabilities->DeviceState[0] = PowerDeviceD0; for (i = 0; i < PowerSystemMaximum; i++) DeviceCapabilities->DeviceState[i] = PowerDeviceD3; @@ -318,6 +538,7 @@ USBHUB_PdoHandlePnp( // FIXME // Status = STATUS_SUCCESS; + break; } default: { diff --git a/drivers/usb/usbhub_new/usbhub.h b/drivers/usb/usbhub_new/usbhub.h index abe06d0351d..c84105bb1c6 100644 --- a/drivers/usb/usbhub_new/usbhub.h +++ b/drivers/usb/usbhub_new/usbhub.h @@ -56,6 +56,7 @@ typedef struct _HUB_CHILDDEVICE_EXTENSION COMMON_DEVICE_EXTENSION Common; PDEVICE_OBJECT ParentDeviceObject; PUSB_DEVICE_HANDLE UsbDeviceHandle; + ULONG PortNumber; UNICODE_STRING usDeviceId; UNICODE_STRING usInstanceId; UNICODE_STRING usHardwareIds;