diff --git a/reactos/drivers/usb/usbehci/common.c b/reactos/drivers/usb/usbehci/common.c index 5fb0cc6fe08..f31eb9be50f 100644 --- a/reactos/drivers/usb/usbehci/common.c +++ b/reactos/drivers/usb/usbehci/common.c @@ -98,7 +98,7 @@ DumpQueueHead(PQUEUE_HEAD QueueHead) DPRINT1(" PingState %x\n", QueueHead->Token.Bits.PingState); DPRINT1(" SplitTransactionState %x\n", QueueHead->Token.Bits.SplitTransactionState); DPRINT1(" ErrorCounter %x\n", QueueHead->Token.Bits.ErrorCounter); - DPRINT1(" First TransferDescriptor %x\n", QueueHead->TransferDescriptor); + DPRINT1(" First TransferDescriptor %x\n", QueueHead->FirstTransferDescriptor); } VOID diff --git a/reactos/drivers/usb/usbehci/hardware.c b/reactos/drivers/usb/usbehci/hardware.c index 0adf59e5e3b..8e9c6d58e2b 100644 --- a/reactos/drivers/usb/usbehci/hardware.c +++ b/reactos/drivers/usb/usbehci/hardware.c @@ -64,7 +64,7 @@ ResetPort(PEHCI_HOST_CONTROLLER hcd, UCHAR Port) { ULONG tmp; ULONG OpRegisters = hcd->OpRegisters; - DPRINT1("Reset Port %x\n", Port); + DPRINT("Reset Port %x\n", Port); tmp = READ_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * Port))); if (tmp & 0x400) @@ -95,7 +95,9 @@ ResetPort(PEHCI_HOST_CONTROLLER hcd, UCHAR Port) if (tmp & 0x100) { DPRINT1("EHCI ERROR: Port Reset did not complete!\n"); + ASSERT(FALSE); } + DPRINT("Reset complete\n"); } VOID @@ -107,7 +109,7 @@ StopEhci(PEHCI_HOST_CONTROLLER hcd) LONG FailSafe; LONG tmp; - DPRINT1("Stopping Ehci controller\n"); + DPRINT("Stopping Ehci controller\n"); WRITE_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBINTR), 0); @@ -117,7 +119,7 @@ StopEhci(PEHCI_HOST_CONTROLLER hcd) WRITE_REGISTER_ULONG((PULONG) (OpRegisters + EHCI_USBCMD), tmp); /* Wait for the device to stop */ - for (FailSafe = 100; FailSafe > 1; FailSafe++) + for (FailSafe = 0; FailSafe < 1000; FailSafe++) { KeStallExecutionProcessor(10); tmp = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBSTS)); @@ -129,7 +131,10 @@ StopEhci(PEHCI_HOST_CONTROLLER hcd) } } if (!UsbSts->HCHalted) + { DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n"); + ASSERT(FALSE); + } } VOID @@ -138,7 +143,7 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd) ULONG OpRegisters = hcd->OpRegisters; PEHCI_USBCMD_CONTENT UsbCmd; PEHCI_USBSTS_CONTEXT UsbSts; - LONG FailSafe; + LONG failSafe; LONG tmp; LONG tmp2; @@ -160,7 +165,7 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd) WRITE_REGISTER_ULONG ((PULONG)(OpRegisters + EHCI_USBCMD), tmp); /* Wait for the device to reset */ - for (FailSafe = 100; FailSafe > 1; FailSafe++) + for (failSafe = 0; failSafe < 1000; failSafe++) { KeStallExecutionProcessor(10); tmp = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBCMD)); @@ -176,6 +181,7 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd) if (UsbCmd->HCReset) { DPRINT1("EHCI ERROR: Controller failed to reset! Will attempt to continue.\n"); + ASSERT(FALSE); } UsbCmd = (PEHCI_USBCMD_CONTENT) &tmp; @@ -209,7 +215,7 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd) WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBCMD), tmp); /* Wait for the device to start */ - for (;;) + for (failSafe = 0; failSafe < 1000; failSafe++) { KeStallExecutionProcessor(10); tmp2 = READ_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_USBSTS)); @@ -222,10 +228,95 @@ StartEhci(PEHCI_HOST_CONTROLLER hcd) DPRINT("Waiting for start, USBSTS: %x\n", READ_REGISTER_ULONG ((PULONG)(OpRegisters + EHCI_USBSTS))); } + if (UsbSts->HCHalted) + { + DPRINT1("EHCI ERROR: Controller failed to start!!!\n"); + ASSERT(FALSE); + } /* Set all port routing to ECHI controller */ WRITE_REGISTER_ULONG((PULONG)(OpRegisters + EHCI_CONFIGFLAG), 1); } +BOOLEAN +EnumControllerPorts(PEHCI_HOST_CONTROLLER hcd) +{ + ULONG tmp, i, OpRegisters, ChildDeviceCount = 0; + BOOLEAN PortChange = FALSE; + + OpRegisters = (ULONG)hcd->OpRegisters; + /* Loop through the ports */ + for (i = 0; i < hcd->ECHICaps.HCSParams.PortCount; i++) + { + tmp = READ_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i))); + + /* Check for port change on this port */ + if (tmp & 0x02) + { + DPRINT1("Port Change\n"); + + /* Clear status change */ + tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i))); + tmp |= 0x02; + WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)), tmp); + + PortChange = TRUE; + /* Connect or Disconnect? */ + if (tmp & 0x01) + { + DPRINT1("Device connected on port %d\n", i); + + /* Check if a companion host controller exists */ + if (hcd->ECHICaps.HCSParams.CHCCount) + { + tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i))); + + /* Port should be in disabled state, as per USB 2.0 specs */ + if (tmp & 0x04) + { + DPRINT1("Warning: The port the device has just connected to is not disabled!\n"); + } + + /* Is this non high speed device */ + if (tmp & 0x400) + { + DPRINT1("Non HighSpeed device connected. Releasing ownership.\n"); + /* Release ownership to companion host controller */ + WRITE_REGISTER_ULONG((PULONG) ((OpRegisters + EHCI_PORTSC) + (4 * i)), 0x2000); + continue; + } + } + + KeStallExecutionProcessor(30); + + /* As per USB 2.0 Specs, 9.1.2. Reset the port and clear the status change */ + //tmp |= 0x100 | 0x02; + /* Sanity, Disable port */ + //tmp &= ~0x04; + + //WRITE_REGISTER_ULONG((PULONG) ((Base + EHCI_PORTSC) + (4 * i)), tmp); + + //KeStallExecutionProcessor(20); + + tmp = READ_REGISTER_ULONG((PULONG)((OpRegisters + EHCI_PORTSC) + (4 * i))); + + ChildDeviceCount++; + hcd->Ports[i].PortStatus &= ~0x8000; + DPRINT1("Removed 0x8000\n"); + ASSERT(FALSE); + hcd->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED; + hcd->Ports[i].PortStatus |= USB_PORT_STATUS_CONNECT; + hcd->Ports[i].PortChange |= USB_PORT_STATUS_CONNECT; + } + else + { + DPRINT1("Device disconnected on port %d\n", i); + ChildDeviceCount--; + } + } + } + return PortChange; +} + VOID GetCapabilities(PEHCI_CAPS PCap, ULONG CapRegister) { @@ -241,11 +332,11 @@ GetCapabilities(PEHCI_CAPS PCap, ULONG CapRegister) PCap->HCSParamsLong = READ_REGISTER_ULONG((PULONG)(CapRegister + 4)); PCap->HCCParams = READ_REGISTER_ULONG((PULONG)(CapRegister + 8)); - DPRINT1("Length %d\n", PCap->Length); - DPRINT1("Reserved %d\n", PCap->Reserved); - DPRINT1("HCIVersion %x\n", PCap->HCIVersion); - DPRINT1("HCSParams %x\n", PCap->HCSParamsLong); - DPRINT1("HCCParams %x\n", PCap->HCCParams); + DPRINT("Length %d\n", PCap->Length); + DPRINT("Reserved %d\n", PCap->Reserved); + DPRINT("HCIVersion %x\n", PCap->HCIVersion); + DPRINT("HCSParams %x\n", PCap->HCSParamsLong); + DPRINT("HCCParams %x\n", PCap->HCCParams); if (PCap->HCCParams & 0x02) DPRINT1("Frame list size is configurable\n"); diff --git a/reactos/drivers/usb/usbehci/physmem.c b/reactos/drivers/usb/usbehci/physmem.c index eb696da9f09..09a964ff32e 100644 --- a/reactos/drivers/usb/usbehci/physmem.c +++ b/reactos/drivers/usb/usbehci/physmem.c @@ -22,21 +22,32 @@ DumpPages() ULONG AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress) { - PMEM_HEADER MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA; + PMEM_HEADER MemoryPage = NULL; ULONG PageCount = 0; ULONG NumberOfPages = hcd->CommonBufferSize / PAGE_SIZE; - ULONG BlocksNeeded; + ULONG BlocksNeeded = 0; ULONG i,j, freeCount; ULONG RetAddr = 0; + MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[0]; Size = ((Size + SMALL_ALLOCATION_SIZE - 1) / SMALL_ALLOCATION_SIZE) * SMALL_ALLOCATION_SIZE; BlocksNeeded = Size / SMALL_ALLOCATION_SIZE; + do { if (MemoryPage->IsFull) { PageCount++; - MemoryPage = (PMEM_HEADER)((ULONG)MemoryPage + PAGE_SIZE); + + if (!(PMEM_HEADER)hcd->CommonBufferVA[PageCount]) + { + hcd->CommonBufferVA[PageCount] = + hcd->pDmaAdapter->DmaOperations->AllocateCommonBuffer(hcd->pDmaAdapter, + PAGE_SIZE, + &hcd->CommonBufferPA[PageCount], + FALSE); + } + MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[PageCount]; continue; } freeCount = 0; @@ -54,8 +65,9 @@ AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress) if ((i-freeCount+1 + BlocksNeeded) > sizeof(MemoryPage->Entry)) { freeCount = 0; - continue; + break; } + if (freeCount == BlocksNeeded) { for (j = 0; j < freeCount; j++) @@ -68,20 +80,35 @@ AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress) RetAddr = (ULONG)MemoryPage + (SMALL_ALLOCATION_SIZE * (i - freeCount + 1)) + sizeof(MEM_HEADER); - *PhysicalAddress = (ULONG)hcd->CommonBufferPA.LowPart + (RetAddr - (ULONG)hcd->CommonBufferVA); + *(ULONG*)PhysicalAddress = (ULONG)hcd->CommonBufferPA[PageCount].LowPart + (RetAddr - (ULONG)hcd->CommonBufferVA[PageCount]); + return RetAddr; } } PageCount++; - MemoryPage = (PMEM_HEADER)((ULONG)MemoryPage + PAGE_SIZE); + if (!(PMEM_HEADER)hcd->CommonBufferVA[PageCount]) + { + + hcd->CommonBufferVA[PageCount] = + hcd->pDmaAdapter->DmaOperations->AllocateCommonBuffer(hcd->pDmaAdapter, + PAGE_SIZE, + &hcd->CommonBufferPA[PageCount], + FALSE); + DPRINT1("Allocated CommonBuffer VA %x, PA %x\n", hcd->CommonBufferVA[PageCount], hcd->CommonBufferPA[PageCount]); + } + MemoryPage = (PMEM_HEADER)hcd->CommonBufferVA[PageCount]; + } while (PageCount < NumberOfPages); + if (PageCount == NumberOfPages) + ASSERT(FALSE); + return 0; } VOID -ReleaseMemory(ULONG Address) +ReleaseMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Address) { PMEM_HEADER MemoryPage; ULONG Index, i, BlockSize; @@ -90,9 +117,25 @@ ReleaseMemory(ULONG Address) Index = (Address - ((ULONG)MemoryPage + sizeof(MEM_HEADER))) / SMALL_ALLOCATION_SIZE; BlockSize = MemoryPage->Entry[Index].Blocks; + for (i = 0; i < BlockSize; i++) { MemoryPage->Entry[Index + i].InUse = 0; MemoryPage->Entry[Index + i].Blocks = 0; } + + if (MemoryPage != (PMEM_HEADER)hcd->CommonBufferVA[0]) + { + for (i=0; i < sizeof(MemoryPage->Entry) / 2; i++) + { + if ((MemoryPage->Entry[i].InUse) || (MemoryPage->Entry[sizeof(MemoryPage->Entry) - i].InUse)) + return; + } + DPRINT1("Freeing CommonBuffer VA %x, PA %x\n", MemoryPage, MmGetPhysicalAddress(MemoryPage)); + hcd->pDmaAdapter->DmaOperations->FreeCommonBuffer(hcd->pDmaAdapter, + PAGE_SIZE, + MmGetPhysicalAddress(MemoryPage), + MemoryPage, + FALSE); + } } diff --git a/reactos/drivers/usb/usbehci/physmem.h b/reactos/drivers/usb/usbehci/physmem.h index a49f1bbda6d..b88f702ba0b 100644 --- a/reactos/drivers/usb/usbehci/physmem.h +++ b/reactos/drivers/usb/usbehci/physmem.h @@ -22,5 +22,4 @@ ULONG AllocateMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Size, ULONG *PhysicalAddress); VOID -ReleaseMemory(ULONG Address); - +ReleaseMemory(PEHCI_HOST_CONTROLLER hcd, ULONG Address); diff --git a/reactos/drivers/usb/usbehci/usbehci.c b/reactos/drivers/usb/usbehci/usbehci.c index f88cde8b886..d4e85be245a 100644 --- a/reactos/drivers/usb/usbehci/usbehci.c +++ b/reactos/drivers/usb/usbehci/usbehci.c @@ -69,7 +69,7 @@ UsbEhciClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) VOID NTAPI DriverUnload(PDRIVER_OBJECT DriverObject) { - DPRINT1("Unloading Driver\n"); + DPRINT("Unloading Driver\n"); /* FIXME: Clean up */ } @@ -94,7 +94,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl; DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalDeviceControl; DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; - + DriverObject->DriverUnload = DriverUnload; DPRINT1("Driver entry done\n"); diff --git a/reactos/drivers/usb/usbehci/usbehci.h b/reactos/drivers/usb/usbehci/usbehci.h index 210d9194d57..09e29479111 100644 --- a/reactos/drivers/usb/usbehci/usbehci.h +++ b/reactos/drivers/usb/usbehci/usbehci.h @@ -93,14 +93,6 @@ 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; @@ -109,10 +101,7 @@ typedef struct _FDO_DEVICE_EXTENSION PDEVICE_OBJECT LowerDevice; PDEVICE_OBJECT Pdo; ULONG DeviceState; - PVOID RootHubDeviceHandle; - PDMA_ADAPTER pDmaAdapter; - ULONG Vector; KIRQL Irql; @@ -125,8 +114,6 @@ typedef struct _FDO_DEVICE_EXTENSION KAFFINITY Affinity; - ULONG MapRegisters; - ULONG BusNumber; ULONG BusAddress; ULONG PCIAddress; @@ -148,8 +135,6 @@ typedef struct _FDO_DEVICE_EXTENSION BOOLEAN AsyncComplete; - //PULONG ResourceBase; - //ULONG Size; } FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION; typedef struct _PDO_DEVICE_EXTENSION @@ -168,8 +153,6 @@ typedef struct _PDO_DEVICE_EXTENSION RH_INIT_CALLBACK *CallbackRoutine; USB_IDLE_CALLBACK IdleCallback; PVOID IdleContext; - ULONG NumberOfPorts; - EHCIPORTS Ports[32]; KTIMER Timer; KEVENT QueueDrainedEvent; FAST_MUTEX ListLock; diff --git a/reactos/drivers/usb/usbehci/usbiffn.c b/reactos/drivers/usb/usbehci/usbiffn.c index 6f4932091fd..1bc74d6878f 100644 --- a/reactos/drivers/usb/usbehci/usbiffn.c +++ b/reactos/drivers/usb/usbehci/usbiffn.c @@ -7,12 +7,15 @@ * Michael Martin (michael.martin@reactos.org) */ +/* Many of these direct calls are documented on http://www.osronline.com */ + #include "usbehci.h" #include #include +#include "hardware.h" #include "transfer.h" -PVOID InternalCreateUsbDevice(UCHAR DeviceNumber, ULONG Port, PUSB_DEVICE Parent, BOOLEAN Hub) +PVOID InternalCreateUsbDevice(ULONG Port, PUSB_DEVICE Parent, BOOLEAN Hub) { PUSB_DEVICE UsbDevicePointer = NULL; @@ -31,7 +34,6 @@ PVOID InternalCreateUsbDevice(UCHAR DeviceNumber, ULONG Port, PUSB_DEVICE Parent DPRINT1("This is the root hub\n"); } - UsbDevicePointer->Address = 0;//DeviceNumber; UsbDevicePointer->Port = Port - 1; UsbDevicePointer->ParentDevice = Parent; @@ -57,6 +59,11 @@ InterfaceDereference(PVOID BusContext) /* Bus Interface Hub V5 Functions */ +/* Hub Driver calls this routine for each new device it is informed about on USB Bus + osronline documents that this is where the device address is assigned. It also + states the same for InitializeUsbDevice. This function only gets the device descriptor + from the device and checks that the members for device are correct. */ + NTSTATUS USB_BUSIFFN CreateUsbDevice(PVOID BusContext, @@ -65,11 +72,18 @@ CreateUsbDevice(PVOID BusContext, USHORT PortStatus, USHORT PortNumber) { PPDO_DEVICE_EXTENSION PdoDeviceExtension; + PFDO_DEVICE_EXTENSION FdoDeviceExtension; + USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + PEHCI_HOST_CONTROLLER hcd; PUSB_DEVICE UsbDevice; - LONG i = 0; + LONG i; - PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension; DPRINT1("Ehci: CreateUsbDevice: HubDeviceHandle %x, PortStatus %x, PortNumber %x\n", HubDeviceHandle, PortStatus, PortNumber); + + PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension; + FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension; + + hcd = &FdoDeviceExtension->hcd; if (PdoDeviceExtension->UsbDevices[0] != HubDeviceHandle) { @@ -77,29 +91,62 @@ CreateUsbDevice(PVOID BusContext, return STATUS_DEVICE_NOT_CONNECTED; } - UsbDevice = InternalCreateUsbDevice(PdoDeviceExtension->ChildDeviceCount, PortNumber, HubDeviceHandle, FALSE); - - if (!UsbDevice) - return STATUS_INSUFFICIENT_RESOURCES; - + UsbDevice = NULL; /* Add it to the list */ - while (TRUE) + for (i=0; i < MAX_USB_DEVICES; i++) { if (PdoDeviceExtension->UsbDevices[i] == NULL) { - PdoDeviceExtension->UsbDevices[i] = (PUSB_DEVICE)UsbDevice; + PdoDeviceExtension->UsbDevices[i] = InternalCreateUsbDevice(PortNumber, HubDeviceHandle, FALSE); + + if (!PdoDeviceExtension->UsbDevices[i]) + return STATUS_INSUFFICIENT_RESOURCES; + UsbDevice = PdoDeviceExtension->UsbDevices[i]; break; } - i++; } - PdoDeviceExtension->Ports[PortNumber - 1].PortStatus = PortStatus; + /* Check that a device was created */ + if (!UsbDevice) + { + DPRINT1("Too many usb devices attached. Max is %d\n", MAX_USB_DEVICES); + return STATUS_UNSUCCESSFUL; + } + + hcd->Ports[PortNumber - 1].PortStatus = PortStatus; + + /* Get the device descriptor */ + CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR; + CtrlSetup.wValue.LowByte = 0; + CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE; + CtrlSetup.wIndex.W = 0; + CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR); + CtrlSetup.bmRequestType.B = 0x80; + ExecuteTransfer(FdoDeviceExtension->DeviceObject, + UsbDevice, + 0, + &CtrlSetup, + 0, + &UsbDevice->DeviceDescriptor, + sizeof(USB_DEVICE_DESCRIPTOR), + NULL); + + /* Check status and bLength and bDescriptor members */ + if ((UsbDevice->DeviceDescriptor.bLength != 0x12) || (UsbDevice->DeviceDescriptor.bDescriptorType != 0x1)) + { + return STATUS_DEVICE_DATA_ERROR; + } + + DumpDeviceDescriptor(&UsbDevice->DeviceDescriptor); /* Return it */ *NewDevice = UsbDevice; return STATUS_SUCCESS; } +/* Assigns the device an address, gets the configuration, interface, and endpoint descriptors + from the device. All this data is saved as part of this driver */ + NTSTATUS USB_BUSIFFN InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle) @@ -107,13 +154,16 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle) PPDO_DEVICE_EXTENSION PdoDeviceExtension; PFDO_DEVICE_EXTENSION FdoDeviceExtension; USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; + USB_DEVICE_DESCRIPTOR DeviceDesc; PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc; PUSB_INTERFACE_DESCRIPTOR InterfaceDesc; PUSB_ENDPOINT_DESCRIPTOR EndpointDesc; PUSB_DEVICE UsbDevice; PVOID Buffer; PUCHAR Ptr; - LONG i, j, k; + UCHAR NewAddress = 0; + + LONG i, j, k, InitAttept; PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)BusContext)->DeviceExtension; FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension; @@ -126,30 +176,90 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle) return STATUS_DEVICE_NOT_CONNECTED; } - CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR; - CtrlSetup.wValue.LowByte = 0; - CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE; - CtrlSetup.wIndex.W = 0; - CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR); - CtrlSetup.bmRequestType.B = 0x80; - - SubmitControlTransfer(&FdoDeviceExtension->hcd, - &CtrlSetup, - &UsbDevice->DeviceDescriptor, - sizeof(USB_DEVICE_DESCRIPTOR), - NULL); - - //DumpDeviceDescriptor(&UsbDevice->DeviceDescriptor); - - if (UsbDevice->DeviceDescriptor.bLength != 0x12) + for (i=0; i<127; i++) { - DPRINT1("Failed to get Device Descriptor from device connected on port %d\n", UsbDevice->Port); + if (UsbDevice == PdoDeviceExtension->UsbDevices[i]) + { + NewAddress = i; + break; + } + } + + ASSERT(NewAddress); + + /* Linux drivers make 3 attemps to set the device address because of problems with some devices. Do the same */ + InitAttept = 0; + while (InitAttept < 3) + { + /* Set the device address */ + CtrlSetup.bmRequestType.B = 0x00; + CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS; + CtrlSetup.wValue.W = NewAddress; + CtrlSetup.wIndex.W = 0; + CtrlSetup.wLength = 0; + + DPRINT1("Setting Address to %x\n", NewAddress); + ExecuteTransfer(PdoDeviceExtension->ControllerFdo, + UsbDevice, + 0, + &CtrlSetup, + 0, + NULL, + 0, + NULL); + + KeStallExecutionProcessor(300 * InitAttept); + + /* Send 0 length packet to endpoint 0 for ack */ +/* + ExecuteTransfer(PdoDeviceExtension->ControllerFdo, + UsbDevice, + 0, + NULL, + 0, + NULL, + 0, + NULL); +*/ + + CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR; + CtrlSetup.wValue.LowByte = 0; + CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE; + CtrlSetup.wIndex.W = 0; + CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR); + CtrlSetup.bmRequestType.B = 0x80; + + UsbDevice->Address = NewAddress; + ExecuteTransfer(FdoDeviceExtension->DeviceObject, + UsbDevice, + 0, + &CtrlSetup, + 0, + &DeviceDesc, + sizeof(USB_DEVICE_DESCRIPTOR), + NULL); + + DPRINT1("Length %d, DescriptorType %d\n", DeviceDesc.bLength, DeviceDesc.bDescriptorType); + if ((DeviceDesc.bLength == 0x12) && (DeviceDesc.bDescriptorType == 0x01)) + break; + + /* If the descriptor was not gotten */ + UsbDevice->Address = 0; + InitAttept++; + } + + if (InitAttept == 3) + { + DPRINT1("Unable to initialize usb device connected on port %d!\n", UsbDevice->Port); + /* FIXME: Should the memory allocated for this device be deleted? */ return STATUS_DEVICE_DATA_ERROR; } + DumpDeviceDescriptor(&DeviceDesc); if (UsbDevice->DeviceDescriptor.bNumConfigurations == 0) { DPRINT1("Device on port %d has no configurations!\n", UsbDevice->Port); + /* FIXME: Should the memory allocated for this device be deleted? */ return STATUS_DEVICE_DATA_ERROR; } UsbDevice->Configs = ExAllocatePoolWithTag(NonPagedPool, @@ -159,6 +269,7 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle) if (!UsbDevice->Configs) { DPRINT1("Out of memory\n"); + /* FIXME: Should the memory allocated for this device be deleted? */ return STATUS_NO_MEMORY; } @@ -167,6 +278,7 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle) if (!Buffer) { DPRINT1("Out of memory\n"); + /* FIXME: Should the memory allocated for this device be deleted? */ return STATUS_NO_MEMORY; } @@ -184,16 +296,18 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle) CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE; CtrlSetup.wIndex.W = 0; CtrlSetup.wLength = PAGE_SIZE; - - SubmitControlTransfer(&FdoDeviceExtension->hcd, - &CtrlSetup, - Buffer, - PAGE_SIZE, - NULL); + ExecuteTransfer(PdoDeviceExtension->ControllerFdo, + UsbDevice, + 0, + &CtrlSetup, + 0, + Buffer, + PAGE_SIZE, + NULL); ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)Ptr; - //DumpFullConfigurationDescriptor(ConfigDesc); + DumpFullConfigurationDescriptor(ConfigDesc); ASSERT(ConfigDesc->wTotalLength <= PAGE_SIZE); UsbDevice->Configs[i] = ExAllocatePoolWithTag(NonPagedPool, @@ -230,30 +344,13 @@ InitializeUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle) UsbDevice->ActiveConfig = UsbDevice->Configs[0]; UsbDevice->ActiveInterface = UsbDevice->Configs[0]->Interfaces[0]; - return STATUS_SUCCESS; - /* Set the device address */ - CtrlSetup.bmRequestType._BM.Recipient = BMREQUEST_TO_DEVICE; - CtrlSetup.bmRequestType._BM.Type = BMREQUEST_STANDARD; - CtrlSetup.bmRequestType._BM.Reserved = 0; - CtrlSetup.bmRequestType._BM.Dir = BMREQUEST_HOST_TO_DEVICE; - CtrlSetup.bRequest = USB_REQUEST_SET_ADDRESS; - CtrlSetup.wValue.W = UsbDevice->Address; - CtrlSetup.wIndex.W = 0; - CtrlSetup.wLength = 0; + UsbDevice->DeviceState = DEVICEINTIALIZED; - DPRINT1("Setting Address to %x\n", UsbDevice->Address); - - SubmitControlTransfer(&FdoDeviceExtension->hcd, - &CtrlSetup, - NULL, - 0, - NULL); - - PdoDeviceExtension->UsbDevices[i]->DeviceState = DEVICEINTIALIZED; return STATUS_SUCCESS; } +/* Return the descriptors that will fit. Descriptors were saved when the InitializeUsbDevice function was called */ NTSTATUS USB_BUSIFFN GetUsbDescriptors(PVOID BusContext, @@ -290,6 +387,7 @@ GetUsbDescriptors(PVOID BusContext, return STATUS_SUCCESS; } +/* Documented http://www.osronline.com/ddkx/buses/usbinterkr_1m7m.htm */ NTSTATUS USB_BUSIFFN RemoveUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle, ULONG Flags) @@ -347,15 +445,18 @@ RemoveUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE DeviceHandle, ULONG Flags) return STATUS_SUCCESS; } +/* Documented at http://www.osronline.com/ddkx/buses/usbinterkr_01te.htm */ NTSTATUS USB_BUSIFFN RestoreUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE OldDeviceHandle, PUSB_DEVICE_HANDLE NewDeviceHandle) { PUSB_DEVICE OldUsbDevice; PUSB_DEVICE NewUsbDevice; + PUSB_CONFIGURATION ConfigToDelete; + int i; DPRINT1("Ehci: RestoreUsbDevice %x, %x, %x\n", BusContext, OldDeviceHandle, NewDeviceHandle); - +ASSERT(FALSE); OldUsbDevice = DeviceHandleToUsbDevice(BusContext, OldDeviceHandle); NewUsbDevice = DeviceHandleToUsbDevice(BusContext, NewDeviceHandle); @@ -380,9 +481,6 @@ RestoreUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE OldDeviceHandle, PUSB_DEVI if ((OldUsbDevice->DeviceDescriptor.idVendor == NewUsbDevice->DeviceDescriptor.idVendor) && (OldUsbDevice->DeviceDescriptor.idProduct == NewUsbDevice->DeviceDescriptor.idProduct)) { - PUSB_CONFIGURATION ConfigToDelete; - int i; - NewUsbDevice->DeviceState &= ~DEVICEBUSY; NewUsbDevice->DeviceState &= ~DEVICEREMOVED; @@ -407,6 +505,7 @@ RestoreUsbDevice(PVOID BusContext, PUSB_DEVICE_HANDLE OldDeviceHandle, PUSB_DEVI } } +/* FIXME: Research this */ NTSTATUS USB_BUSIFFN GetPortHackFlags(PVOID BusContext, PULONG Flags) @@ -497,6 +596,9 @@ GetControllerInformation(PVOID BusContext, DPRINT1("Ehci: GetControllerInformation called\n"); + if (!LengthReturned) + return STATUS_INVALID_PARAMETER; + ControllerInfo = ControllerInformationBuffer; if (ControllerInformationBufferLength < sizeof(USB_CONTROLLER_INFORMATION_0)) @@ -653,7 +755,7 @@ FlushTransfers(PVOID BusContext, PVOID DeviceHandle) DPRINT1("Invalid DeviceHandle or device not connected\n"); } - DPRINT1("FlushTransfers\n"); + DPRINT1("FlushTransfers not implemented.\n"); } VOID @@ -725,5 +827,6 @@ USB_BUSIFFN EnumLogEntry(PVOID BusContext, ULONG DriverTag, ULONG EnumTag, ULONG P1, ULONG P2) { DPRINT1("Ehci: EnumLogEntry called %x, %x, %x, %x\n", DriverTag, EnumTag, P1, P2); + return STATUS_SUCCESS; }