From 44cbfd23f2c306fecea4ae63149bbac6213630c5 Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Fri, 2 Apr 2010 04:49:01 +0000 Subject: [PATCH] [usb/usbehci] - Implement tracking port status and change status. - When device has connected on port, set the port status. For now assume high speed device. - Fix returning root hubs Status Change Endpoint for URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER. - Implement USB_REQUEST_GET_STATUS for functions URB_FUNCTION_GET_STATUS_FROM_DEVICE and URB_FUNCTION_CLASS_OTHER. Implement USB_REQUEST_CLEAR_FEATURE and USB_REQUEST_SET_FEATURE. - Implement IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE to return the root hubs device handle, fix IOCTL_INTERNAL_USB_GET_HUB_COUNT to return 1 vice 0 as the root hub must be accounted for. - Code based on XEN PV Drivers by James Harper. svn path=/trunk/; revision=46660 --- reactos/drivers/usb/usbehci/fdo.c | 2 +- reactos/drivers/usb/usbehci/irp.c | 131 ++++++++++++++++++++------ reactos/drivers/usb/usbehci/pdo.c | 40 ++++++-- reactos/drivers/usb/usbehci/usbehci.h | 47 +++++++-- 4 files changed, 169 insertions(+), 51 deletions(-) diff --git a/reactos/drivers/usb/usbehci/fdo.c b/reactos/drivers/usb/usbehci/fdo.c index eebc0c0905a..b1ec5503cb6 100644 --- a/reactos/drivers/usb/usbehci/fdo.c +++ b/reactos/drivers/usb/usbehci/fdo.c @@ -100,9 +100,9 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i))); - DPRINT("port tmp %x\n", tmp); GetDeviceDescriptor(FdoDeviceExtension, 0, 0, FALSE); PdoDeviceExtension->ChildDeviceCount++; + PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED | USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE; WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEM_DATA)); if (!WorkItemData) ASSERT(FALSE); WorkItemData->IoWorkItem = IoAllocateWorkItem(PdoDeviceExtension->DeviceObject); diff --git a/reactos/drivers/usb/usbehci/irp.c b/reactos/drivers/usb/usbehci/irp.c index 29af1f92ce7..06d7c50ab08 100644 --- a/reactos/drivers/usb/usbehci/irp.c +++ b/reactos/drivers/usb/usbehci/irp.c @@ -88,35 +88,65 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) if (UsbDevice == NULL) UsbDevice = DeviceExtension->UsbDevices[0]; + /* Assume URB success */ + Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; + /* Set the DeviceHandle to the Internal Device */ + Urb->UrbHeader.UsbdDeviceHandle = UsbDevice; + switch (Urb->UrbHeader.Function) { case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: { - /* Are we suppose to only return on this request when a device is connected - or is it the RootHubInitNotification Callback */ DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:\n"); DPRINT1("--->TransferBufferLength %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); DPRINT1("--->TransferBuffer %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBuffer); DPRINT1("--->PipeHandle %x\n",Urb->UrbBulkOrInterruptTransfer.PipeHandle); + DPRINT1("---->(PVOID)&UsbDevice->EndPointDescriptor %x\n", (PVOID)&UsbDevice->EndPointDescriptor); DPRINT1("--->TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags); - /* FIXME */ + RtlZeroMemory(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1; - /* Turn off Irp handling as nothing is handled beyond this */ - DeviceExtension->HaltUrbHandling = TRUE; + if (UsbDevice == DeviceExtension->UsbDevices[0]) + { + if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)) + { + LONG i; + for (i = 0; i < 8; i++) + { + if (DeviceExtension->Ports[i].PortChange) + { + DPRINT1("Inform hub driver that port %d has changed\n", i+1); + ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << (i + 1); + } + } + } + else + { + Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER; + Status = STATUS_UNSUCCESSFUL; + } + } break; } case URB_FUNCTION_GET_STATUS_FROM_DEVICE: { - DPRINT1("Get Status from Device\n"); + DPRINT("Get Status from Device\n"); + DPRINT("Index : %d\n", Urb->UrbControlGetStatusRequest.Index); + + /* Copied from pvdrivers */ + if (Urb->UrbControlGetStatusRequest.Index == 0) + { + *(PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer = USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE; + } + else + { + DPRINT1("Uknown identifier\n"); + Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION; + Status = STATUS_UNSUCCESSFUL; + } break; } case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: { - Urb->UrbHeader.Function = 0x08; - Urb->UrbHeader.UsbdFlags = 0; - Urb->UrbHeader.UsbdDeviceHandle = UsbDevice; - switch(Urb->UrbControlDescriptorRequest.DescriptorType) { case USB_DEVICE_DESCRIPTOR_TYPE: @@ -130,9 +160,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &UsbDevice->DeviceDescriptor, Urb->UrbControlDescriptorRequest.TransferBufferLength); - - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; - break; } case USB_CONFIGURATION_DESCRIPTOR_TYPE: @@ -150,9 +177,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &UsbDevice->ConfigurationDescriptor, Urb->UrbControlDescriptorRequest.TransferBufferLength); - - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; - break; } case USB_STRING_DESCRIPTOR_TYPE: @@ -232,10 +256,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) } InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length); } - - Urb->UrbHeader.UsbdDeviceHandle = UsbDevice; - Urb->UrbHeader.UsbdFlags = 0; - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; } else { @@ -252,7 +272,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags); DPRINT1("Urb->UrbControlVendorClassRequest.Value %x\n", Urb->UrbControlVendorClassRequest.Value); - switch (Urb->UrbControlVendorClassRequest.Value >> 8) { case USB_DEVICE_CLASS_AUDIO: @@ -328,10 +347,16 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) DPRINT1("Unknown UrbControlVendorClassRequest Value\n"); } } - Urb->UrbHeader.Function = 0x08; - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; - Urb->UrbHeader.UsbdDeviceHandle = UsbDevice; - Urb->UrbHeader.UsbdFlags = 0; + break; + } + case USB_REQUEST_GET_STATUS: + { + DPRINT1("DEVICE: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index); + + if (Urb->UrbControlVendorClassRequest.Index == 1) + { + ((PULONG)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = 0; + } break; } default: @@ -348,22 +373,51 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) { case USB_REQUEST_GET_STATUS: { - DPRINT1("USB_REQUEST_GET_STATUS\n"); + DPRINT1("OTHER: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index); + + ((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus; + ((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[1] = DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange; break; } case USB_REQUEST_CLEAR_FEATURE: { - DPRINT1("USB_REQUEST_CLEAR_FEATURE\n"); + DPRINT1("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index, + Urb->UrbControlVendorClassRequest.Value); + switch (Urb->UrbControlVendorClassRequest.Value) + { + case C_PORT_CONNECTION: + DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT; + break; + case C_PORT_RESET: + DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET; + break; + default: + DPRINT1("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value); + break; + } break; } case USB_REQUEST_SET_FEATURE: { - DPRINT1("USB_REQUEST_SET_FEATURE value %x\n", Urb->UrbControlVendorClassRequest.Value); + DPRINT1("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index, + Urb->UrbControlVendorClassRequest.Value); + switch(Urb->UrbControlVendorClassRequest.Value) { - /* FIXME: Needs research */ - case 0x01: + case PORT_RESET: { + DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET; + break; + } + case PORT_ENABLE: + { + DPRINT1("Unhandled Set Feature\n"); + break; + } + default: + { + DPRINT1("Unknown Set Feature!\n"); + break; } } break; @@ -371,6 +425,7 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) case USB_REQUEST_SET_ADDRESS: { DPRINT1("USB_REQUEST_SET_ADDRESS\n"); + ASSERT(FALSE); break; } case USB_REQUEST_GET_DESCRIPTOR: @@ -408,6 +463,12 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) DPRINT1("USB_REQUEST_SYNC_FRAME\n"); break; } + default: + { + DPRINT1("Unknown Function Class Unknown request\n"); + ASSERT(FALSE); + break; + } } break; } @@ -415,6 +476,7 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) { DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function); Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION; + ASSERT(FALSE); } } @@ -424,6 +486,13 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) Irp->IoStatus.Status = Status; Irp->IoStatus.Information = Information; + if (Urb->UrbHeader.Status == USBD_STATUS_SUCCESS) + { + /* Fake a successful Control Transfer */ + Urb->UrbHeader.Function = 0x08; + Urb->UrbHeader.UsbdFlags = 0; + } + IoCompleteRequest(Irp, IO_NO_INCREMENT); KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql); } diff --git a/reactos/drivers/usb/usbehci/pdo.c b/reactos/drivers/usb/usbehci/pdo.c index 3ab717f0f56..6a0d735e851 100644 --- a/reactos/drivers/usb/usbehci/pdo.c +++ b/reactos/drivers/usb/usbehci/pdo.c @@ -172,18 +172,24 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: { - DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n"); + DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE); + if (Stack->Parameters.Others.Argument1) + { + /* Return the root hubs devicehandle */ + *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)PdoDeviceExtension->UsbDevices[0]; + } + else + Status = STATUS_INVALID_DEVICE_REQUEST; break; } case IOCTL_INTERNAL_USB_GET_HUB_COUNT: { - DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n"); - + DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT); if (Stack->Parameters.Others.Argument1) { /* FIXME: Determine the number of hubs between the usb device and root hub */ - /* For now return 0 */ - *(PVOID *)Stack->Parameters.Others.Argument1 = 0; + /* For now return 1, the root hub */ + *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)1; } break; } @@ -216,9 +222,8 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) if (Stack->Parameters.Others.Argument2) *(PVOID *)Stack->Parameters.Others.Argument2 = IoGetAttachedDevice(FdoDeviceExtension->DeviceObject); - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - return STATUS_SUCCESS; + Information = 0; + Status = STATUS_SUCCESS; break; } case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: @@ -287,7 +292,6 @@ PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information) } } - /* Lifted from hpoussin */ Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &SourceString, &String); @@ -350,6 +354,7 @@ PdoDispatchPnp( PPDO_DEVICE_EXTENSION PdoDeviceExtension; PFDO_DEVICE_EXTENSION FdoDeviceExtension; UNICODE_STRING InterfaceSymLinkName; + LONG i; PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension; @@ -357,6 +362,12 @@ PdoDispatchPnp( /* Create the root hub */ RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE); + for (i = 0; i < 8; i++) + { + PdoDeviceExtension->Ports[i].PortStatus = USB_PORT_STATUS_ENABLE; + PdoDeviceExtension->Ports[i].PortChange = 0; + } + RtlCopyMemory(&RootHubDevice->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(ROOTHUB2_DEVICE_DESCRIPTOR)); @@ -409,8 +420,16 @@ PdoDispatchPnp( break; } case BusRelations: + DPRINT1("BusRelations!!!!!\n"); case RemovalRelations: case EjectionRelations: + { + /* Ignore the request */ + Information = Irp->IoStatus.Information; + Status = Irp->IoStatus.Status; + break; + + } default: { DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unhandled type 0x%lx\n", @@ -534,7 +553,8 @@ PdoDispatchPnp( else { DPRINT1("Not Supported\n"); - Status = STATUS_NOT_SUPPORTED; + Status = Irp->IoStatus.Status; + Information = Irp->IoStatus.Information; } break; } diff --git a/reactos/drivers/usb/usbehci/usbehci.h b/reactos/drivers/usb/usbehci/usbehci.h index f4c440df616..13bfabb3657 100644 --- a/reactos/drivers/usb/usbehci/usbehci.h +++ b/reactos/drivers/usb/usbehci/usbehci.h @@ -75,6 +75,25 @@ OR with QUEUE_TRANSFER_DESCRIPTOR Token.SplitTransactionState */ #define PING_STATE_DO_OUT 0x00 #define PING_STATE_DO_PING 0x01 +#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 PORT_HIGH_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 +#define USB_PORT_STATUS_CHANGE 0x4000 + /* QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN */ typedef struct _QETD_TOKEN_BITS { @@ -273,16 +292,16 @@ typedef struct _EHCI_HCC_CONTENT } EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT; typedef struct _EHCI_CAPS { - UCHAR Length; - UCHAR Reserved; - USHORT HCIVersion; + UCHAR Length; + UCHAR Reserved; + USHORT HCIVersion; union { - EHCI_HCS_CONTENT HCSParams; - ULONG HCSParamsLong; + EHCI_HCS_CONTENT HCSParams; + ULONG HCSParamsLong; }; - ULONG HCCParams; - UCHAR PortRoute [8]; + ULONG HCCParams; + UCHAR PortRoute [8]; } EHCI_CAPS, *PEHCI_CAPS; typedef struct _COMMON_DEVICE_EXTENSION @@ -292,6 +311,14 @@ typedef struct _COMMON_DEVICE_EXTENSION PDEVICE_OBJECT DeviceObject; } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; +typedef struct _EHCIPORTS +{ + ULONG PortNumber; + ULONG PortType; + USHORT PortStatus; + USHORT PortChange; +} EHCIPORTS, *PEHCIPORTS; + typedef struct _FDO_DEVICE_EXTENSION { COMMON_DEVICE_EXTENSION Common; @@ -333,8 +360,8 @@ typedef struct _FDO_DEVICE_EXTENSION PULONG PeriodicFramList; PULONG AsyncListQueueHeadPtr; - PHYSICAL_ADDRESS PeriodicFramListPhysAddr; - PHYSICAL_ADDRESS AsyncListQueueHeadPtrPhysAddr; + PHYSICAL_ADDRESS PeriodicFramListPhysAddr; + PHYSICAL_ADDRESS AsyncListQueueHeadPtrPhysAddr; BOOLEAN AsyncComplete; @@ -356,6 +383,8 @@ typedef struct _PDO_DEVICE_EXTENSION BOOLEAN HaltUrbHandling; PVOID CallbackContext; PRH_INIT_CALLBACK CallbackRoutine; + ULONG NumberOfPorts; + EHCIPORTS Ports[32]; } PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION; typedef struct _WORKITEM_DATA