diff --git a/CODEOWNERS b/CODEOWNERS index 571825b6a90..04a24a76bc2 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -275,7 +275,6 @@ # R: Extravert-ir, extravert34, Victor Perevertkin # S: Maintained /drivers/usb/ @ThFabba @Extravert-ir -/sdk/lib/drivers/libusb/ @ThFabba @Extravert-ir /sdk/include/reactos/drivers/usbport/ @ThFabba @Extravert-ir # Virtual CD-ROM diff --git a/drivers/usb/CMakeLists.txt b/drivers/usb/CMakeLists.txt index 1315f1a571e..3f33c2b2c4f 100644 --- a/drivers/usb/CMakeLists.txt +++ b/drivers/usb/CMakeLists.txt @@ -1,13 +1,9 @@ add_subdirectory(usbccgp) add_subdirectory(usbd) -#add_subdirectory(usbehci) add_subdirectory(usbehci_new) -#add_subdirectory(usbhub) add_subdirectory(usbhub_new) -#add_subdirectory(usbohci) add_subdirectory(usbohci_new) add_subdirectory(usbport) add_subdirectory(usbstor) #add_subdirectory(usbstor_new) -#add_subdirectory(usbuhci) add_subdirectory(usbuhci_new) diff --git a/drivers/usb/usbehci/CMakeLists.txt b/drivers/usb/usbehci/CMakeLists.txt deleted file mode 100644 index f515915899e..00000000000 --- a/drivers/usb/usbehci/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ - -set_cpp() - -remove_definitions(-D_WIN32_WINNT=0x502) -add_definitions(-D_WIN32_WINNT=0x600) - -include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/drivers/libusb) - -list(APPEND SOURCE - usbehci.cpp - usb_request.cpp - usb_queue.cpp - hardware.cpp - usbehci.h) - -add_library(usbehci MODULE - ${SOURCE} - guid.cpp - usbehci.rc) - -target_link_libraries(usbehci uuid libusb libcntpr ${PSEH_LIB}) -set_module_type(usbehci kernelmodedriver) -add_importlibs(usbehci ntoskrnl hal usbd) -add_pch(usbehci usbehci.h SOURCE) -add_cd_file(TARGET usbehci DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/usb/usbehci/guid.cpp b/drivers/usb/usbehci/guid.cpp deleted file mode 100644 index 50a60369ff3..00000000000 --- a/drivers/usb/usbehci/guid.cpp +++ /dev/null @@ -1,9 +0,0 @@ -/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */ - -#include -#include -#include -#include -#include - -/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */ diff --git a/drivers/usb/usbehci/hardware.cpp b/drivers/usb/usbehci/hardware.cpp deleted file mode 100644 index 8562eaa4b3c..00000000000 --- a/drivers/usb/usbehci/hardware.cpp +++ /dev/null @@ -1,1490 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbehci/hcd_controller.cpp - * PURPOSE: USB EHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbehci.h" - -#define NDEBUG -#include - -typedef VOID __stdcall HD_INIT_CALLBACK(IN PVOID CallBackContext); - -BOOLEAN -NTAPI -InterruptServiceRoutine( - IN PKINTERRUPT Interrupt, - IN PVOID ServiceContext); - -VOID -NTAPI -EhciDeferredRoutine( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2); - -VOID -NTAPI -StatusChangeWorkItemRoutine(PVOID Context); - -class CUSBHardwareDevice : public IEHCIHardwareDevice -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - // com - IMP_IUSBHARDWAREDEVICE - IMP_IUSBEHCIHARDWARE - - // local - BOOLEAN InterruptService(); - VOID PrintCapabilities(); - NTSTATUS StartController(); - NTSTATUS StopController(); - NTSTATUS ResetController(); - - // friend function - friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); - friend VOID NTAPI EhciDeferredRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); - friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context); - // constructor / destructor - CUSBHardwareDevice(IUnknown *OuterUnknown){} - virtual ~CUSBHardwareDevice(){} - -protected: - LONG m_Ref; // reference count - PDRIVER_OBJECT m_DriverObject; // driver object - PDEVICE_OBJECT m_PhysicalDeviceObject; // pdo - PDEVICE_OBJECT m_FunctionalDeviceObject; // fdo (hcd controller) - PDEVICE_OBJECT m_NextDeviceObject; // lower device object - KSPIN_LOCK m_Lock; // hardware lock - PKINTERRUPT m_Interrupt; // interrupt object - KDPC m_IntDpcObject; // dpc object for deferred isr processing - PVOID VirtualBase; // virtual base for memory manager - PHYSICAL_ADDRESS PhysicalAddress; // physical base for memory manager - PULONG m_Base; // EHCI operational port base registers - PDMA_ADAPTER m_Adapter; // dma adapter object - ULONG m_MapRegisters; // map registers count - EHCI_CAPS m_Capabilities; // EHCI caps - USHORT m_VendorID; // vendor id - USHORT m_DeviceID; // device id - PQUEUE_HEAD AsyncQueueHead; // async queue head terminator - PEHCIQUEUE m_UsbQueue; // usb request queue - PDMAMEMORYMANAGER m_MemoryManager; // memory manager - HD_INIT_CALLBACK* m_SCECallBack; // status change callback routine - PVOID m_SCEContext; // status change callback routine context - BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress - WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback - volatile LONG m_StatusChangeWorkItemStatus; // work item status - ULONG m_SyncFramePhysAddr; // periodic frame list physical address - BUS_INTERFACE_STANDARD m_BusInterface; // pci bus interface - BOOLEAN m_PortResetInProgress[0xF]; // stores reset in progress (vbox hack) - - // read register - ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset); - - // write register - VOID EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value); -}; - -//================================================================================================= -// COM -// -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - if (IsEqualGUIDAligned(refiid, IID_IUnknown)) - { - *Output = PVOID(PUNKNOWN(this)); - PUNKNOWN(*Output)->AddRef(); - return STATUS_SUCCESS; - } - - return STATUS_UNSUCCESSFUL; -} - -LPCSTR -STDMETHODCALLTYPE -CUSBHardwareDevice::GetUSBType() -{ - return "USBEHCI"; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::Initialize( - PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT FunctionalDeviceObject, - PDEVICE_OBJECT PhysicalDeviceObject, - PDEVICE_OBJECT LowerDeviceObject) -{ - PCI_COMMON_CONFIG PciConfig; - NTSTATUS Status; - ULONG BytesRead; - - DPRINT("CUSBHardwareDevice::Initialize\n"); - - // - // Create DMAMemoryManager for use with QueueHeads and Transfer Descriptors. - // - Status = CreateDMAMemoryManager(&m_MemoryManager); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create DMAMemoryManager Object\n"); - return Status; - } - - // - // Create the UsbQueue class that will handle the Asynchronous and Periodic Schedules - // - Status = CreateUSBQueue((PUSBQUEUE*)&m_UsbQueue); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create UsbQueue!\n"); - return Status; - } - - // - // store device objects - // - m_DriverObject = DriverObject; - m_FunctionalDeviceObject = FunctionalDeviceObject; - m_PhysicalDeviceObject = PhysicalDeviceObject; - m_NextDeviceObject = LowerDeviceObject; - - // - // initialize device lock - // - KeInitializeSpinLock(&m_Lock); - - // - // initialize status change work item - // - ExInitializeWorkItem(&m_StatusChangeWorkItem, StatusChangeWorkItemRoutine, PVOID(this)); - - m_VendorID = 0; - m_DeviceID = 0; - - Status = GetBusInterface(PhysicalDeviceObject, &m_BusInterface); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get BusInterface!\n"); - return Status; - } - - BytesRead = (*m_BusInterface.GetBusData)(m_BusInterface.Context, - PCI_WHICHSPACE_CONFIG, - &PciConfig, - 0, - PCI_COMMON_HDR_LENGTH); - - if (BytesRead != PCI_COMMON_HDR_LENGTH) - { - DPRINT1("Failed to get pci config information!\n"); - return STATUS_SUCCESS; - } - - m_VendorID = PciConfig.VendorID; - m_DeviceID = PciConfig.DeviceID; - - return STATUS_SUCCESS; -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd) -{ - PULONG Register; - Register = (PULONG)UsbCmd; - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + EHCI_USBCMD), *Register); -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd) -{ - PULONG Register; - Register = (PULONG)UsbCmd; - *Register = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + EHCI_USBCMD)); -} - -ULONG -CUSBHardwareDevice::EHCI_READ_REGISTER_ULONG(ULONG Offset) -{ - return READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + Offset)); -} - -VOID -CUSBHardwareDevice::EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value) -{ - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + Offset), Value); -} - -VOID -CUSBHardwareDevice::PrintCapabilities() -{ - if (m_Capabilities.HCSParams.PortPowerControl) - { - DPRINT1("Controller EHCI has Port Power Control\n"); - } - - DPRINT1("Controller Port Routing Rules %lu\n", m_Capabilities.HCSParams.PortRouteRules); - DPRINT1("Number of Ports per Companion Controller %lu\n", m_Capabilities.HCSParams.PortPerCHC); - DPRINT1("Number of Companion Controller %lu\n", m_Capabilities.HCSParams.CHCCount); - - if (m_Capabilities.HCSParams.PortIndicator) - { - DPRINT1("Controller has Port Indicators Support\n"); - } - - if (m_Capabilities.HCSParams.DbgPortNum) - { - DPRINT1("Controller has Debug Port Support At Port %x\n", m_Capabilities.HCSParams.DbgPortNum); - } - - if (m_Capabilities.HCCParams.EECPCapable) - { - DPRINT1("Controller has Extended Capabilities Support\n"); - } - - if (m_Capabilities.HCCParams.ParkMode) - { - DPRINT1("Controller supports Asynchronous Schedule Park\n"); - } - - if (m_Capabilities.HCCParams.VarFrameList) - { - DPRINT1("Controller supports Programmable Frame List Size\n"); - } - - if (m_Capabilities.HCCParams.CurAddrBits) - { - DPRINT1("Controller uses 64-Bit Addressing\n"); - } -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::PnpStart( - PCM_RESOURCE_LIST RawResources, - PCM_RESOURCE_LIST TranslatedResources) -{ - ULONG Index, Count; - PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor; - DEVICE_DESCRIPTION DeviceDescription; - PHYSICAL_ADDRESS AsyncPhysicalAddress; - PVOID ResourceBase; - NTSTATUS Status; - UCHAR Value; - UCHAR PortCount; - - DPRINT("CUSBHardwareDevice::PnpStart\n"); - for(Index = 0; Index < TranslatedResources->List[0].PartialResourceList.Count; Index++) - { - // - // get resource descriptor - // - ResourceDescriptor = &TranslatedResources->List[0].PartialResourceList.PartialDescriptors[Index]; - - switch(ResourceDescriptor->Type) - { - case CmResourceTypeInterrupt: - { - KeInitializeDpc(&m_IntDpcObject, - EhciDeferredRoutine, - this); - - Status = IoConnectInterrupt(&m_Interrupt, - InterruptServiceRoutine, - (PVOID)this, - NULL, - ResourceDescriptor->u.Interrupt.Vector, - (KIRQL)ResourceDescriptor->u.Interrupt.Level, - (KIRQL)ResourceDescriptor->u.Interrupt.Level, - (KINTERRUPT_MODE)(ResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED), - (ResourceDescriptor->ShareDisposition != CmResourceShareDeviceExclusive), - ResourceDescriptor->u.Interrupt.Affinity, - FALSE); - - if (!NT_SUCCESS(Status)) - { - // - // failed to register interrupt - // - DPRINT1("IoConnect Interrupt failed with %x\n", Status); - return Status; - } - break; - } - case CmResourceTypeMemory: - { - // - // get resource base - // - ResourceBase = MmMapIoSpace(ResourceDescriptor->u.Memory.Start, ResourceDescriptor->u.Memory.Length, MmNonCached); - if (!ResourceBase) - { - // - // failed to map registers - // - DPRINT1("MmMapIoSpace failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Get controllers capabilities - // - m_Capabilities.Length = READ_REGISTER_UCHAR((PUCHAR)ResourceBase + EHCI_CAPLENGTH); - m_Capabilities.HCIVersion = READ_REGISTER_USHORT((PUSHORT)((ULONG_PTR)ResourceBase + EHCI_HCIVERSION)); - m_Capabilities.HCSParamsLong = READ_REGISTER_ULONG((PULONG)((ULONG_PTR)ResourceBase + EHCI_HCSPARAMS)); - m_Capabilities.HCCParamsLong = READ_REGISTER_ULONG((PULONG)((ULONG_PTR)ResourceBase + EHCI_HCCPARAMS)); - - DPRINT1("Controller Capabilities Length 0x%x\n", m_Capabilities.Length); - DPRINT1("Controller EHCI Version 0x%x\n", m_Capabilities.HCIVersion); - DPRINT1("Controller EHCI Caps HCSParamsLong 0x%lx\n", m_Capabilities.HCSParamsLong); - DPRINT1("Controller EHCI Caps HCCParamsLong 0x%lx\n", m_Capabilities.HCCParamsLong); - DPRINT1("Controller has %lu Ports\n", m_Capabilities.HCSParams.PortCount); - - // - // print capabilities - // - PrintCapabilities(); - - if (m_Capabilities.HCSParams.PortRouteRules) - { - Count = 0; - PortCount = max(m_Capabilities.HCSParams.PortCount/2, (m_Capabilities.HCSParams.PortCount+1)/2); - do - { - // - // each entry is a 4 bit field EHCI 2.2.5 - // - Value = READ_REGISTER_UCHAR((PUCHAR)(ULONG_PTR)ResourceBase + EHCI_HCSP_PORTROUTE + Count); - m_Capabilities.PortRoute[Count*2] = (Value & 0xF0); - - if ((Count*2) + 1 < m_Capabilities.HCSParams.PortCount) - m_Capabilities.PortRoute[(Count*2)+1] = (Value & 0x0F); - - Count++; - } while(Count < PortCount); - } - - // - // Set m_Base to the address of Operational Register Space - // - m_Base = (PULONG)((ULONG_PTR)ResourceBase + m_Capabilities.Length); - break; - } - } - } - - - // - // zero device description - // - RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION)); - - // - // initialize device description - // - DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; - DeviceDescription.Master = TRUE; - DeviceDescription.ScatterGather = TRUE; - DeviceDescription.Dma32BitAddresses = TRUE; - DeviceDescription.DmaWidth = Width32Bits; - DeviceDescription.InterfaceType = PCIBus; - DeviceDescription.MaximumLength = MAXULONG; - - // - // get dma adapter - // - m_Adapter = IoGetDmaAdapter(m_PhysicalDeviceObject, &DeviceDescription, &m_MapRegisters); - if (!m_Adapter) - { - // - // failed to get dma adapter - // - DPRINT1("Failed to acquire dma adapter\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Create Common Buffer - // - VirtualBase = m_Adapter->DmaOperations->AllocateCommonBuffer(m_Adapter, - PAGE_SIZE * 4, - &PhysicalAddress, - FALSE); - if (!VirtualBase) - { - DPRINT1("Failed to allocate a common buffer\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Initialize the DMAMemoryManager - // - Status = m_MemoryManager->Initialize(this, &m_Lock, PAGE_SIZE * 4, VirtualBase, PhysicalAddress, 32); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize the DMAMemoryManager\n"); - return Status; - } - - // - // Create a queuehead for the Async Register - // - m_MemoryManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&AsyncQueueHead, &AsyncPhysicalAddress); - - AsyncQueueHead->PhysicalAddr = AsyncPhysicalAddress.LowPart; - AsyncQueueHead->HorizontalLinkPointer = AsyncQueueHead->PhysicalAddr | QH_TYPE_QH; - AsyncQueueHead->EndPointCharacteristics.HeadOfReclamation = TRUE; - AsyncQueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED; - AsyncQueueHead->Token.Bits.Halted = TRUE; - - AsyncQueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01; - AsyncQueueHead->NextPointer = TERMINATE_POINTER; - AsyncQueueHead->CurrentLinkPointer = TERMINATE_POINTER; - - InitializeListHead(&AsyncQueueHead->LinkedQueueHeads); - - // - // Initialize the UsbQueue now that we have an AdapterObject. - // - Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, m_MemoryManager, &m_Lock); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to Initialize the UsbQueue\n"); - return Status; - } - - // - // Start the controller - // - DPRINT1("Starting Controller\n"); - Status = StartController(); - - // - // done - // - return Status; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::PnpStop(void) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::GetDeviceDetails( - OUT OPTIONAL PUSHORT VendorId, - OUT OPTIONAL PUSHORT DeviceId, - OUT OPTIONAL PULONG NumberOfPorts, - OUT OPTIONAL PULONG Speed) -{ - if (VendorId) - *VendorId = m_VendorID; - if (DeviceId) - *DeviceId = m_DeviceID; - if (NumberOfPorts) - *NumberOfPorts = m_Capabilities.HCSParams.PortCount; - //FIXME: What to returned here? - if (Speed) - *Speed = 0x200; - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::GetDMA( - OUT struct IDMAMemoryManager **OutDMAMemoryManager) -{ - if (!m_MemoryManager) - return STATUS_UNSUCCESSFUL; - *OutDMAMemoryManager = m_MemoryManager; - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::GetUSBQueue( - OUT struct IUSBQueue **OutUsbQueue) -{ - if (!m_UsbQueue) - return STATUS_UNSUCCESSFUL; - *OutUsbQueue = m_UsbQueue; - return STATUS_SUCCESS; -} - - -NTSTATUS -CUSBHardwareDevice::StartController(void) -{ - EHCI_USBCMD_CONTENT UsbCmd; - ULONG UsbSts, FailSafe, ExtendedCapsSupport, Caps, Index; - UCHAR Value; - LARGE_INTEGER Timeout; - - // - // are extended caps supported - // - ExtendedCapsSupport = (m_Capabilities.HCCParamsLong >> EHCI_ECP_SHIFT) & EHCI_ECP_MASK; - if (ExtendedCapsSupport) - { - DPRINT1("[EHCI] Extended Caps Support detected!\n"); - - // - // sanity check - // - ASSERT(ExtendedCapsSupport >= PCI_COMMON_HDR_LENGTH); - m_BusInterface.GetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Caps, ExtendedCapsSupport, sizeof(ULONG)); - - // - // OS Handoff Synchronization support capability. EHCI 5.1 - // - if ((Caps & EHCI_LEGSUP_CAPID_MASK) == EHCI_LEGSUP_CAPID) - { - // - // is it bios owned - // - if ((Caps & EHCI_LEGSUP_BIOSOWNED)) - { - DPRINT1("[EHCI] Controller is BIOS owned, acquiring control\n"); - - // - // acquire ownership - // - Value = 1; - m_BusInterface.SetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Value, ExtendedCapsSupport+3, sizeof(UCHAR)); - - for(Index = 0; Index < 20; Index++) - { - // - // get status - // - m_BusInterface.GetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Caps, ExtendedCapsSupport, sizeof(ULONG)); - if ((Caps & EHCI_LEGSUP_BIOSOWNED)) - { - // - // lets wait a bit - // - Timeout.QuadPart = 50; - DPRINT1("Waiting %lu milliseconds for port reset\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - } - } - if ((Caps & EHCI_LEGSUP_BIOSOWNED)) - { - // - // failed to acquire ownership - // - DPRINT1("[EHCI] failed to acquire ownership\n"); - } - else if ((Caps & EHCI_LEGSUP_OSOWNED)) - { - // - // HC OS Owned Semaphore EHCI 2.1.7 - // - DPRINT1("[EHCI] acquired ownership\n"); - } -#if 0 - // - // explicitly clear the bios owned flag 2.1.7 - // - Value = 0; - m_BusInterface.SetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Value, ExtendedCapsSupport+2, sizeof(UCHAR)); - - // - // clear SMI interrupt EHCI 2.1.8 - // - Caps = 4; - m_BusInterface.SetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Caps, ExtendedCapsSupport+4, sizeof(ULONG)); -#endif - } - } - } - - // - // get command register - // - GetCommandRegister(&UsbCmd); - - // - // disable running schedules - // - UsbCmd.PeriodicEnable = FALSE; - UsbCmd.AsyncEnable = FALSE; - SetCommandRegister(&UsbCmd); - - // - // Wait for execution to start - // - for (FailSafe = 100; FailSafe > 1; FailSafe--) - { - KeStallExecutionProcessor(100); - UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS); - - if (!(UsbSts & EHCI_STS_PSS) && (UsbSts & EHCI_STS_ASS)) - { - break; - } - } - - if ((UsbSts & (EHCI_STS_PSS | EHCI_STS_ASS))) - { - DPRINT1("Failed to stop running schedules %x\n", UsbSts); - //ASSERT(FALSE); - } - - - // - // Stop the controller if its running - // - UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS); - if (!(UsbSts & EHCI_STS_HALT)) - { - DPRINT1("Stopping Controller %x\n", UsbSts); - StopController(); - } - - // - // Reset the controller - // - ResetController(); - - // - // check caps - // - if (m_Capabilities.HCCParams.CurAddrBits) - { - // - // disable 64-bit addressing - // - EHCI_WRITE_REGISTER_ULONG(EHCI_CTRLDSSEGMENT, 0x0); - } - - // - // Enable Interrupts and start execution - // - ULONG Mask = EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR | EHCI_USBINTR_PC; - EHCI_WRITE_REGISTER_ULONG(EHCI_USBINTR, Mask); - - KeStallExecutionProcessor(10); - - ULONG Status = EHCI_READ_REGISTER_ULONG(EHCI_USBINTR); - - DPRINT1("Interrupt Mask %x\n", Status); - ASSERT((Status & Mask) == Mask); - - // - // Assign the SyncList Register - // - EHCI_WRITE_REGISTER_ULONG(EHCI_PERIODICLISTBASE, m_SyncFramePhysAddr); - - // - // Set Schedules to Enable and Interrupt Threshold to 1ms. - // - RtlZeroMemory(&UsbCmd, sizeof(EHCI_USBCMD_CONTENT)); - - UsbCmd.PeriodicEnable = TRUE; - UsbCmd.IntThreshold = 0x8; //1ms - UsbCmd.Run = TRUE; - UsbCmd.FrameListSize = 0x0; //1024 - - if (m_Capabilities.HCCParams.ParkMode) - { - // - // enable async park mode - // - UsbCmd.AsyncParkEnable = TRUE; - UsbCmd.AsyncParkCount = 3; - } - - SetCommandRegister(&UsbCmd); - - - // - // Wait for execution to start - // - for (FailSafe = 100; FailSafe > 1; FailSafe--) - { - KeStallExecutionProcessor(100); - UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS); - - if (!(UsbSts & EHCI_STS_HALT) && (UsbSts & EHCI_STS_PSS)) - { - break; - } - } - - if (UsbSts & EHCI_STS_HALT) - { - DPRINT1("Could not start execution on the controller\n"); - //ASSERT(FALSE); - return STATUS_UNSUCCESSFUL; - } - - if (!(UsbSts & EHCI_STS_PSS)) - { - DPRINT1("Could not enable periodic scheduling\n"); - //ASSERT(FALSE); - return STATUS_UNSUCCESSFUL; - } - - // - // Assign the AsyncList Register - // - EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, AsyncQueueHead->PhysicalAddr); - - // - // get command register - // - GetCommandRegister(&UsbCmd); - - // - // preserve bits - // - UsbCmd.AsyncEnable = TRUE; - - // - // enable async - // - SetCommandRegister(&UsbCmd); - - // - // Wait for execution to start - // - for (FailSafe = 100; FailSafe > 1; FailSafe--) - { - KeStallExecutionProcessor(100); - UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS); - - if ((UsbSts & EHCI_STS_ASS)) - { - break; - } - } - - if (!(UsbSts & EHCI_STS_ASS)) - { - DPRINT1("Failed to enable async schedule UsbSts %x\n", UsbSts); - //ASSERT(FALSE); - return STATUS_UNSUCCESSFUL; - } - - DPRINT1("UsbSts %x\n", UsbSts); - GetCommandRegister(&UsbCmd); - - DPRINT1("UsbCmd.PeriodicEnable %x\n", UsbCmd.PeriodicEnable); - DPRINT1("UsbCmd.AsyncEnable %x\n", UsbCmd.AsyncEnable); - DPRINT1("UsbCmd.IntThreshold %x\n", UsbCmd.IntThreshold); - DPRINT1("UsbCmd.Run %x\n", UsbCmd.Run); - DPRINT1("UsbCmd.FrameListSize %x\n", UsbCmd.FrameListSize); - - // - // Set port routing to EHCI controller - // - EHCI_WRITE_REGISTER_ULONG(EHCI_CONFIGFLAG, 1); - - DPRINT1("EHCI Started!\n"); - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::StopController(void) -{ - EHCI_USBCMD_CONTENT UsbCmd; - ULONG UsbSts, FailSafe; - - // - // Disable Interrupts and stop execution - // - EHCI_WRITE_REGISTER_ULONG (EHCI_USBINTR, 0); - - GetCommandRegister(&UsbCmd); - UsbCmd.Run = FALSE; - SetCommandRegister(&UsbCmd); - - for (FailSafe = 100; FailSafe > 1; FailSafe--) - { - KeStallExecutionProcessor(10); - UsbSts = EHCI_READ_REGISTER_ULONG(EHCI_USBSTS); - if (UsbSts & EHCI_STS_HALT) - { - break; - } - } - - if (!(UsbSts & EHCI_STS_HALT)) - { - DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n"); - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::ResetController(void) -{ - EHCI_USBCMD_CONTENT UsbCmd; - ULONG FailSafe; - - GetCommandRegister(&UsbCmd); - UsbCmd.HCReset = TRUE; - SetCommandRegister(&UsbCmd); - - for (FailSafe = 100; FailSafe > 1; FailSafe--) - { - KeStallExecutionProcessor(100); - GetCommandRegister(&UsbCmd); - if (!UsbCmd.HCReset) - break; - } - - if (UsbCmd.HCReset) - { - DPRINT1("EHCI ERROR: Controller is not responding to reset request!\n"); - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::ResetPort( - IN ULONG PortIndex) -{ - ULONG PortStatus; - LARGE_INTEGER Timeout; - - if (PortIndex > m_Capabilities.HCSParams.PortCount) - return STATUS_UNSUCCESSFUL; - - PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex)); - - ASSERT(!EHCI_IS_LOW_SPEED(PortStatus)); - ASSERT(PortStatus & EHCI_PRT_CONNECTED); - - // - // Reset and clean enable - // - PortStatus |= EHCI_PRT_RESET; - PortStatus &= EHCI_PORTSC_DATAMASK; - EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex), PortStatus); - - // - // delay is 50 ms for port reset as per USB 2.0 spec - // - Timeout.QuadPart = 50; - DPRINT1("Waiting %lu milliseconds for port reset\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::GetPortStatus( - ULONG PortId, - OUT USHORT *PortStatus, - OUT USHORT *PortChange) -{ - ULONG Value; - USHORT Status = 0, Change = 0; - - if (PortId > m_Capabilities.HCSParams.PortCount) - return STATUS_UNSUCCESSFUL; - - // - // Get the value of the Port Status and Control Register - // - Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); - - // - // If the PowerPortControl is 0 then host controller does not have power control switches - if (!m_Capabilities.HCSParams.PortPowerControl) - { - Status |= USB_PORT_STATUS_POWER; - } - else - { - // Check the value of PortPower - if (Value & EHCI_PRT_POWER) - { - Status |= USB_PORT_STATUS_POWER; - } - } - - // Get Connected Status - if (Value & EHCI_PRT_CONNECTED) - { - Status |= USB_PORT_STATUS_CONNECT; - - // EHCI only supports high speed - Status |= USB_PORT_STATUS_HIGH_SPEED; - } - - // Get Enabled Status - if (Value & EHCI_PRT_ENABLED) - Status |= USB_PORT_STATUS_ENABLE; - - // Is it suspended? - if (Value & EHCI_PRT_SUSPEND) - Status |= USB_PORT_STATUS_SUSPEND; - - // a overcurrent is active? - if (Value & EHCI_PRT_OVERCURRENTACTIVE) - Status |= USB_PORT_STATUS_OVER_CURRENT; - - // In a reset state? - if ((Value & EHCI_PRT_RESET) || m_PortResetInProgress[PortId]) - { - Status |= USB_PORT_STATUS_RESET; - Change |= USB_PORT_STATUS_RESET; - } - - // This indicates a connect or disconnect - if (Value & EHCI_PRT_CONNECTSTATUSCHANGE) - Change |= USB_PORT_STATUS_CONNECT; - - // This is set to indicate a critical port error - if (Value & EHCI_PRT_ENABLEDSTATUSCHANGE) - Change |= USB_PORT_STATUS_ENABLE; - - *PortStatus = Status; - *PortChange = Change; - - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::ClearPortStatus( - ULONG PortId, - ULONG Status) -{ - ULONG Value; - LARGE_INTEGER Timeout; - - DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status); - - if (PortId > m_Capabilities.HCSParams.PortCount) - return STATUS_UNSUCCESSFUL; - - if (Status == C_PORT_RESET) - { - // reset done - m_PortResetInProgress[PortId] = FALSE; - - // Clear reset - Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); - Value &= (EHCI_PORTSC_DATAMASK | EHCI_PRT_ENABLED); - Value &= ~EHCI_PRT_RESET; - EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value); - - // - // wait for reset bit to clear - // - do - { - Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); - - if (!(Value & EHCI_PRT_RESET)) - break; - - KeStallExecutionProcessor(20); - } while (TRUE); - - // - // delay is 50 ms - // - Timeout.QuadPart = 50; - DPRINT1("Waiting %lu milliseconds for port to recover after reset\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - - // - // check the port status after reset - // - Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); - if (!(Value & EHCI_PRT_CONNECTED)) - { - DPRINT1("No device is here after reset. Bad controller/device?\n"); - return STATUS_UNSUCCESSFUL; - } - else if (EHCI_IS_LOW_SPEED(Value)) - { - DPRINT1("Low speed device connected. Releasing ownership\n"); - EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value | EHCI_PRT_RELEASEOWNERSHIP); - return STATUS_DEVICE_NOT_CONNECTED; - } - else if (!(Value & EHCI_PRT_ENABLED)) - { - DPRINT1("Full speed device connected. Releasing ownership\n"); - EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value | EHCI_PRT_RELEASEOWNERSHIP); - return STATUS_DEVICE_NOT_CONNECTED; - } - else - { - DPRINT1("High speed device connected\n"); - return STATUS_SUCCESS; - } - } - else if (Status == C_PORT_CONNECTION) - { - // - // reset status change bits - // - Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)); - EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value); - - if (Value & EHCI_PRT_CONNECTED) - { - // - // delay is 100 ms - // - Timeout.QuadPart = 100; - DPRINT1("Waiting %lu milliseconds for port to stabilize after connection\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - } - } - - return STATUS_SUCCESS; -} - - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::SetPortFeature( - ULONG PortId, - ULONG Feature) -{ - DPRINT("CUSBHardwareDevice::SetPortFeature\n"); - - if (PortId > m_Capabilities.HCSParams.PortCount) - return STATUS_UNSUCCESSFUL; - - if (Feature == PORT_ENABLE) - { - // - // FIXME: EHCI Ports can only be disabled via reset - // - DPRINT1("PORT_ENABLE not supported for EHCI\n"); - } - - if (Feature == PORT_RESET) - { - // - // call the helper - // - ResetPort(PortId); - - // reset in progress - m_PortResetInProgress[PortId] = TRUE; - - // - // is there a status change callback - // - if (m_SCECallBack != NULL) - { - // - // issue callback - // - m_SCECallBack(m_SCEContext); - } - } - - if (Feature == PORT_POWER) - { - if (m_Capabilities.HCSParams.PortPowerControl) - { - ULONG Value; - LARGE_INTEGER Timeout; - - // - // enable port power - // - Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId)) | EHCI_PRT_POWER; - EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value); - - // - // delay is 20 ms - // - Timeout.QuadPart = 20; - DPRINT1("Waiting %lu milliseconds for port power up\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - } - } - return STATUS_SUCCESS; -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::SetAsyncListRegister( - ULONG PhysicalAddress) -{ - EHCI_WRITE_REGISTER_ULONG(EHCI_ASYNCLISTBASE, PhysicalAddress); -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::SetPeriodicListRegister( - ULONG PhysicalAddress) -{ - // - // store physical address - // - m_SyncFramePhysAddr = PhysicalAddress; -} - -struct _QUEUE_HEAD * -STDMETHODCALLTYPE -CUSBHardwareDevice::GetAsyncListQueueHead() -{ - return AsyncQueueHead; -} - -ULONG -STDMETHODCALLTYPE -CUSBHardwareDevice::GetPeriodicListRegister() -{ - UNIMPLEMENTED; - return NULL; -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::SetStatusChangeEndpointCallBack( - PVOID CallBack, - PVOID Context) -{ - m_SCECallBack = (HD_INIT_CALLBACK*)CallBack; - m_SCEContext = Context; -} - -BOOLEAN -NTAPI -InterruptServiceRoutine( - IN PKINTERRUPT Interrupt, - IN PVOID ServiceContext) -{ - CUSBHardwareDevice *This; - ULONG CStatus; - - This = (CUSBHardwareDevice*) ServiceContext; - CStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_USBSTS); - - CStatus &= (EHCI_ERROR_INT | EHCI_STS_INT | EHCI_STS_IAA | EHCI_STS_PCD | EHCI_STS_FLR); - DPRINT("InterruptServiceRoutine CStatus %lx\n", CStatus); - - // - // Check that it belongs to EHCI - // - if (!CStatus) - return FALSE; - - // - // Clear the Status - // - This->EHCI_WRITE_REGISTER_ULONG(EHCI_USBSTS, CStatus); - - if (CStatus & EHCI_STS_FATAL) - { - This->StopController(); - DPRINT1("EHCI: Host System Error!\n"); - return TRUE; - } - - if (CStatus & EHCI_ERROR_INT) - { - DPRINT1("EHCI Status = 0x%x\n", CStatus); - } - - if (CStatus & EHCI_STS_HALT) - { - DPRINT1("Host Error Unexpected Halt\n"); - // FIXME: Reset controller\n"); - return TRUE; - } - - KeInsertQueueDpc(&This->m_IntDpcObject, This, UlongToPtr(CStatus)); - return TRUE; -} - -VOID NTAPI -EhciDeferredRoutine( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2) -{ - CUSBHardwareDevice *This; - ULONG CStatus, PortStatus, PortCount, i, ShouldRingDoorBell, QueueSCEWorkItem; - NTSTATUS Status = STATUS_SUCCESS; - EHCI_USBCMD_CONTENT UsbCmd; - - This = (CUSBHardwareDevice*) SystemArgument1; - CStatus = PtrToUlong(SystemArgument2); - - DPRINT("EhciDeferredRoutine CStatus %lx\n", CStatus); - - // - // check for completion of async schedule - // - if (CStatus & (EHCI_STS_RECL| EHCI_STS_INT | EHCI_ERROR_INT)) - { - // - // check if there is a door bell ring in progress - // - if (This->m_DoorBellRingInProgress == FALSE) - { - if (CStatus & EHCI_ERROR_INT) - { - // - // controller reported error - // - DPRINT1("CStatus %lx\n", CStatus); - //ASSERT(FALSE); - } - - // - // inform IUSBQueue of a completed queue head - // - This->m_UsbQueue->InterruptCallback(Status, &ShouldRingDoorBell); - - // - // was a queue head completed? - // - if (ShouldRingDoorBell) - { - // - // set door ring bell in progress status flag - // - This->m_DoorBellRingInProgress = TRUE; - - // - // get command register - // - This->GetCommandRegister(&UsbCmd); - - // - // set door rang bell bit - // - UsbCmd.DoorBell = TRUE; - - // - // update command status - // - This->SetCommandRegister(&UsbCmd); - } - } - } - - // - // check if the controller has acknowledged the door bell - // - if (CStatus & EHCI_STS_IAA) - { - // - // controller has acknowledged, assert we rang the bell - // - PC_ASSERT(This->m_DoorBellRingInProgress == TRUE); - - // - // now notify IUSBQueue that it can free completed requests - // - This->m_UsbQueue->CompleteAsyncRequests(); - - // - // door ring bell completed - // - This->m_DoorBellRingInProgress = FALSE; - } - - This->GetDeviceDetails(NULL, NULL, &PortCount, NULL); - if (CStatus & EHCI_STS_PCD) - { - QueueSCEWorkItem = FALSE; - for (i = 0; i < PortCount; i++) - { - PortStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * i)); - - // - // Device connected or removed - // - if (PortStatus & EHCI_PRT_CONNECTSTATUSCHANGE) - { - if (PortStatus & EHCI_PRT_CONNECTED) - { - DPRINT1("Device connected on port %lu\n", i); - - if (This->m_Capabilities.HCSParams.CHCCount) - { - if (PortStatus & EHCI_PRT_ENABLED) - { - DPRINT1("Misbehaving controller. Port should be disabled at this point\n"); - } - - if (EHCI_IS_LOW_SPEED(PortStatus)) - { - DPRINT1("Low speed device connected. Releasing ownership\n"); - This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus | EHCI_PRT_RELEASEOWNERSHIP); - continue; - } - } - - // - // work to do - // - QueueSCEWorkItem = TRUE; - } - else - { - DPRINT1("Device disconnected on port %lu\n", i); - - // - // work to do - // - QueueSCEWorkItem = TRUE; - } - } - } - - // - // is there a status change callback and a high speed device connected / disconnected - // - if (QueueSCEWorkItem && This->m_SCECallBack != NULL) - { - if (InterlockedCompareExchange(&This->m_StatusChangeWorkItemStatus, 1, 0) == 0) - { - // - // queue work item for processing - // - ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue); - } - } - } - return; -} - -VOID -NTAPI -StatusChangeWorkItemRoutine( - PVOID Context) -{ - // - // cast to hardware object - // - CUSBHardwareDevice * This = (CUSBHardwareDevice*)Context; - - // - // is there a callback - // - if (This->m_SCECallBack) - { - // - // issue callback - // - This->m_SCECallBack(This->m_SCEContext); - } - - // - // reset active status - // - InterlockedDecrement(&This->m_StatusChangeWorkItemStatus); -} - -NTSTATUS -NTAPI -CreateUSBHardware( - PUSBHARDWAREDEVICE *OutHardware) -{ - PUSBHARDWAREDEVICE This; - - This = new(NonPagedPool, TAG_USBEHCI) CUSBHardwareDevice(0); - - if (!This) - return STATUS_INSUFFICIENT_RESOURCES; - - This->AddRef(); - - // return result - *OutHardware = (PUSBHARDWAREDEVICE)This; - - return STATUS_SUCCESS; -} diff --git a/drivers/usb/usbehci/hardware.h b/drivers/usb/usbehci/hardware.h deleted file mode 100644 index b0ea4811be5..00000000000 --- a/drivers/usb/usbehci/hardware.h +++ /dev/null @@ -1,325 +0,0 @@ -#pragma once - -// -// Host Controller Capability Registers -// -#define EHCI_CAPLENGTH 0x00 -#define EHCI_HCIVERSION 0x02 -#define EHCI_HCSPARAMS 0x04 -#define EHCI_HCCPARAMS 0x08 -#define EHCI_HCSP_PORTROUTE 0x0c - - -// -// Extended Capabilities -// -#define EHCI_ECP_SHIFT 8 -#define EHCI_ECP_MASK 0xff -#define EHCI_LEGSUP_CAPID_MASK 0xff -#define EHCI_LEGSUP_CAPID 0x01 -#define EHCI_LEGSUP_OSOWNED (1 << 24) -#define EHCI_LEGSUP_BIOSOWNED (1 << 16) - - -// -// EHCI Operational Registers -// -#define EHCI_USBCMD 0x00 -#define EHCI_USBSTS 0x04 -#define EHCI_USBINTR 0x08 -#define EHCI_FRINDEX 0x0C -#define EHCI_CTRLDSSEGMENT 0x10 -#define EHCI_PERIODICLISTBASE 0x14 -#define EHCI_ASYNCLISTBASE 0x18 -#define EHCI_CONFIGFLAG 0x40 -#define EHCI_PORTSC 0x44 - -// -// Interrupt Register Flags -// -#define EHCI_USBINTR_INTE 0x01 -#define EHCI_USBINTR_ERR 0x02 -#define EHCI_USBINTR_PC 0x04 -#define EHCI_USBINTR_FLROVR 0x08 -#define EHCI_USBINTR_HSERR 0x10 -#define EHCI_USBINTR_ASYNC 0x20 -// Bits 6:31 Reserved - -// -// Status Register Flags -// -#define EHCI_STS_INT 0x01 -#define EHCI_STS_ERR 0x02 -#define EHCI_STS_PCD 0x04 -#define EHCI_STS_FLR 0x08 -#define EHCI_STS_FATAL 0x10 -#define EHCI_STS_IAA 0x20 -// Bits 11:6 Reserved -#define EHCI_STS_HALT 0x1000 -#define EHCI_STS_RECL 0x2000 -#define EHCI_STS_PSS 0x4000 -#define EHCI_STS_ASS 0x8000 -#define EHCI_ERROR_INT (EHCI_STS_FATAL | EHCI_STS_ERR) - -// -// Port Register Flags -// -#define EHCI_PRT_CONNECTED 0x01 -#define EHCI_PRT_CONNECTSTATUSCHANGE 0x02 -#define EHCI_PRT_ENABLED 0x04 -#define EHCI_PRT_ENABLEDSTATUSCHANGE 0x08 -#define EHCI_PRT_OVERCURRENTACTIVE 0x10 -#define EHCI_PRT_OVERCURRENTCHANGE 0x20 -#define EHCI_PRT_FORCERESUME 0x40 -#define EHCI_PRT_SUSPEND 0x80 -#define EHCI_PRT_RESET 0x100 -#define EHCI_PRT_LINESTATUSA 0x400 -#define EHCI_PRT_LINESTATUSB 0x800 -#define EHCI_PRT_POWER 0x1000 -#define EHCI_PRT_RELEASEOWNERSHIP 0x2000 - -#define EHCI_PORTSC_DATAMASK 0xffffffd1 - -#define EHCI_IS_LOW_SPEED(x) (((x) & EHCI_PRT_LINESTATUSA) && !((x) & EHCI_PRT_LINESTATUSB)) -// -// Terminate Pointer used for QueueHeads and Element Transfer Descriptors to mark Pointers as the end -// -#define TERMINATE_POINTER 0x01 - -// -// QUEUE ELEMENT TRANSFER DESCRIPTOR, defines and structs -// - -// -// Token Flags -// -#define PID_CODE_OUT_TOKEN 0x00 -#define PID_CODE_IN_TOKEN 0x01 -#define PID_CODE_SETUP_TOKEN 0x02 - -#define DO_START_SPLIT 0x00 -#define DO_COMPLETE_SPLIT 0x01 - -#define PING_STATE_DO_OUT 0x00 -#define PING_STATE_DO_PING 0x01 - -typedef struct _PERIODICFRAMELIST -{ - PULONG VirtualAddr; - PHYSICAL_ADDRESS PhysicalAddr; - ULONG Size; -} PERIODICFRAMELIST, *PPERIODICFRAMELIST; - -// -// QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN -// -typedef struct _QETD_TOKEN_BITS -{ - ULONG PingState:1; - ULONG SplitTransactionState:1; - ULONG MissedMicroFrame:1; - ULONG TransactionError:1; - ULONG BabbleDetected:1; - ULONG DataBufferError:1; - ULONG Halted:1; - ULONG Active:1; - ULONG PIDCode:2; - ULONG ErrorCounter:2; - ULONG CurrentPage:3; - ULONG InterruptOnComplete:1; - ULONG TotalBytesToTransfer:15; - ULONG DataToggle:1; -} QETD_TOKEN_BITS, *PQETD_TOKEN_BITS; - -// -// QUEUE ELEMENT TRANSFER DESCRIPTOR -// -typedef struct _QUEUE_TRANSFER_DESCRIPTOR -{ - //Hardware - ULONG NextPointer; - ULONG AlternateNextPointer; - union - { - QETD_TOKEN_BITS Bits; - ULONG DWord; - } Token; - ULONG BufferPointer[5]; - ULONG ExtendedBufferPointer[5]; - - //Software - ULONG PhysicalAddr; - LIST_ENTRY DescriptorEntry; - ULONG TotalBytesToTransfer; -} QUEUE_TRANSFER_DESCRIPTOR, *PQUEUE_TRANSFER_DESCRIPTOR; - -C_ASSERT(FIELD_OFFSET(QUEUE_TRANSFER_DESCRIPTOR, PhysicalAddr) == 0x34); - -// -// EndPointSpeeds Flags and END_POINT_CHARACTERISTICS -// -#define QH_ENDPOINT_FULLSPEED 0x00 -#define QH_ENDPOINT_LOWSPEED 0x01 -#define QH_ENDPOINT_HIGHSPEED 0x02 -typedef struct _END_POINT_CHARACTERISTICS -{ - ULONG DeviceAddress:7; - ULONG InactiveOnNextTransaction:1; - ULONG EndPointNumber:4; - ULONG EndPointSpeed:2; - ULONG QEDTDataToggleControl:1; - ULONG HeadOfReclamation:1; - ULONG MaximumPacketLength:11; - ULONG ControlEndPointFlag:1; - ULONG NakCountReload:4; -} END_POINT_CHARACTERISTICS, *PEND_POINT_CHARACTERISTICS; - -// -// Capabilities -// -typedef struct _END_POINT_CAPABILITIES -{ - ULONG InterruptScheduleMask:8; - ULONG SplitCompletionMask:8; - ULONG HubAddr:7; - ULONG PortNumber:7; - ULONG NumberOfTransactionPerFrame:2; -} END_POINT_CAPABILITIES, *PEND_POINT_CAPABILITIES; - -// -// QUEUE HEAD Flags and Struct -// -#define QH_TYPE_IDT 0x00 -#define QH_TYPE_QH 0x02 -#define QH_TYPE_SITD 0x04 -#define QH_TYPE_FSTN 0x06 - -typedef struct _QUEUE_HEAD -{ - //Hardware - ULONG HorizontalLinkPointer; - END_POINT_CHARACTERISTICS EndPointCharacteristics; - END_POINT_CAPABILITIES EndPointCapabilities; - // TERMINATE_POINTER not valid for this member - ULONG CurrentLinkPointer; - // TERMINATE_POINTER valid - ULONG NextPointer; - // TERMINATE_POINTER valid, bits 1:4 is NAK_COUNTERd - ULONG AlternateNextPointer; - // Only DataToggle, InterruptOnComplete, ErrorCounter, PingState valid - union - { - QETD_TOKEN_BITS Bits; - ULONG DWord; - } Token; - ULONG BufferPointer[5]; - ULONG ExtendedBufferPointer[5]; - - //Software - ULONG PhysicalAddr; - LIST_ENTRY LinkedQueueHeads; - LIST_ENTRY TransferDescriptorListHead; - PVOID NextQueueHead; - PVOID Request; -} QUEUE_HEAD, *PQUEUE_HEAD; - -C_ASSERT(sizeof(END_POINT_CHARACTERISTICS) == 4); -C_ASSERT(sizeof(END_POINT_CAPABILITIES) == 4); - -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, HorizontalLinkPointer) == 0x00); -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCharacteristics) == 0x04); -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, EndPointCapabilities) == 0x08); -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, CurrentLinkPointer) == 0xC); -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, NextPointer) == 0x10); -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, AlternateNextPointer) == 0x14); -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, Token) == 0x18); -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, BufferPointer) == 0x1C); -C_ASSERT(FIELD_OFFSET(QUEUE_HEAD, PhysicalAddr) == 0x44); - - -// -// Command register content -// -typedef struct _EHCI_USBCMD_CONTENT -{ - ULONG Run : 1; - ULONG HCReset : 1; - ULONG FrameListSize : 2; - ULONG PeriodicEnable : 1; - ULONG AsyncEnable : 1; - ULONG DoorBell : 1; - ULONG LightReset : 1; - ULONG AsyncParkCount : 2; - ULONG Reserved : 1; - ULONG AsyncParkEnable : 1; - ULONG Reserved1 : 4; - ULONG IntThreshold : 8; - ULONG Reserved2 : 8; -} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT; - -typedef struct _EHCI_HCS_CONTENT -{ - ULONG PortCount : 4; - ULONG PortPowerControl: 1; - ULONG Reserved : 2; - ULONG PortRouteRules : 1; - ULONG PortPerCHC : 4; - ULONG CHCCount : 4; - ULONG PortIndicator : 1; - ULONG Reserved2 : 3; - ULONG DbgPortNum : 4; - ULONG Reserved3 : 8; - -} EHCI_HCS_CONTENT, *PEHCI_HCS_CONTENT; - -typedef struct _EHCI_HCC_CONTENT -{ - ULONG CurAddrBits : 1; - ULONG VarFrameList : 1; - ULONG ParkMode : 1; - ULONG Reserved : 1; - ULONG IsoSchedThreshold : 4; - ULONG EECPCapable : 8; - ULONG Reserved2 : 16; - -} EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT; - -typedef struct _EHCI_CAPS { - UCHAR Length; - UCHAR Reserved; - USHORT HCIVersion; - union - { - EHCI_HCS_CONTENT HCSParams; - ULONG HCSParamsLong; - }; - union - { - EHCI_HCC_CONTENT HCCParams; - ULONG HCCParamsLong; - }; - UCHAR PortRoute [15]; -} EHCI_CAPS, *PEHCI_CAPS; - -typedef struct -{ - ULONG PortStatus; - ULONG PortChange; -}EHCI_PORT_STATUS; - -#define EHCI_INTERRUPT_ENTRIES_COUNT (10 + 1) -#define EHCI_VFRAMELIST_ENTRIES_COUNT 128 -#define EHCI_FRAMELIST_ENTRIES_COUNT 1024 - -#define MAX_AVAILABLE_BANDWIDTH 125 // Microseconds - -#define EHCI_QH_CAPS_MULT_SHIFT 30 // Transactions per Micro-Frame -#define EHCI_QH_CAPS_MULT_MASK 0x03 -#define EHCI_QH_CAPS_PORT_SHIFT 23 // Hub Port (Split-Transaction) -#define EHCI_QH_CAPS_PORT_MASK 0x7f -#define EHCI_QH_CAPS_HUB_SHIFT 16 // Hub Address (Split-Transaction) -#define EHCI_QH_CAPS_HUB_MASK 0x7f -#define EHCI_QH_CAPS_SCM_SHIFT 8 // Split Completion Mask -#define EHCI_QH_CAPS_SCM_MASK 0xff -#define EHCI_QH_CAPS_ISM_SHIFT 0 // Interrupt Schedule Mask -#define EHCI_QH_CAPS_ISM_MASK 0xff diff --git a/drivers/usb/usbehci/interfaces.h b/drivers/usb/usbehci/interfaces.h deleted file mode 100644 index 58160fa1475..00000000000 --- a/drivers/usb/usbehci/interfaces.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef INTERFACES_HPP -#define INTERFACES_HPP - -//========================================================================================= -// -// class IUSBHardwareDevice -// -// Description: This class provides access to the usb hardware controller -// - -#define DEFINE_ABSTRACT_USBEHCIHARDWARE() \ - STDMETHOD_(VOID, SetAsyncListRegister)( THIS_ \ - IN ULONG PhysicalAddress) PURE; \ - \ - STDMETHOD_(VOID, SetPeriodicListRegister)( THIS_ \ - IN ULONG PhysicalAddress) PURE; \ - \ - STDMETHOD_(struct _QUEUE_HEAD *, GetAsyncListQueueHead)( THIS) PURE; \ - \ - STDMETHOD_(ULONG, GetPeriodicListRegister)( THIS) PURE; \ - \ - STDMETHOD_(VOID, SetCommandRegister)( THIS_ \ - IN struct _EHCI_USBCMD_CONTENT *UsbCmd) PURE; \ - \ - STDMETHOD_(VOID, GetCommandRegister)( THIS_ \ - OUT struct _EHCI_USBCMD_CONTENT *UsbCmd) PURE; - -#define IMP_IUSBEHCIHARDWARE \ - STDMETHODIMP_(VOID) SetAsyncListRegister( \ - IN ULONG PhysicalAddress); \ - \ - STDMETHODIMP_(VOID) SetPeriodicListRegister( \ - IN ULONG PhysicalAddress); \ - \ - STDMETHODIMP_(struct _QUEUE_HEAD *) GetAsyncListQueueHead(); \ - \ - STDMETHODIMP_(ULONG) GetPeriodicListRegister(); \ - \ - STDMETHODIMP_(VOID) SetCommandRegister( \ - IN struct _EHCI_USBCMD_CONTENT *UsbCmd); \ - STDMETHODIMP_(VOID) GetCommandRegister( \ - OUT struct _EHCI_USBCMD_CONTENT *UsbCmd); - -DECLARE_INTERFACE_(IEHCIHardwareDevice, IUSBHardwareDevice) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBHARDWAREDEVICE() - DEFINE_ABSTRACT_USBEHCIHARDWARE() -}; - -typedef IEHCIHardwareDevice *PEHCIHARDWAREDEVICE; - -//========================================================================================= -// -// class IUSBRequest -// -// Description: This class is used to issue request to usb controller. The class is -// initialized using InitializeXXX methods. You also need to call SetEndpoint to define the endpoint -// In addition you can call SetCompletionDetails if you need to wait for the end of -// the request or want to complete an irp. You call AddUSBRequest to add the request to the queue. -// Once the request is completed the CompletionCallback is invoked. The CompletionCallback -// will take care of any completion details which have been set. If the request is cancelled, the -// CancelCallback routine is invoked. -// - -struct _QUEUE_HEAD; -struct _USB_ENDPOINT; - -#define DEFINE_ABSTRACT_USBEHCIREQUEST() \ - STDMETHOD_(VOID, CompletionCallback)( THIS_ \ - IN NTSTATUS NtStatusCode, \ - IN ULONG UrbStatusCode, \ - IN struct _QUEUE_HEAD *QueueHead) PURE; \ - \ - STDMETHOD_(NTSTATUS, GetQueueHead)( THIS_ \ - IN struct _QUEUE_HEAD ** OutHead) PURE; \ - \ - STDMETHOD_(BOOLEAN, ShouldReleaseRequestAfterCompletion)( THIS) PURE; \ - \ - \ - STDMETHOD_(VOID, FreeQueueHead)( THIS_ \ - IN struct _QUEUE_HEAD * QueueHead) PURE; \ - \ - STDMETHOD_(BOOLEAN, IsQueueHeadComplete)( THIS_ \ - IN struct _QUEUE_HEAD * QueueHead) PURE; \ - \ - STDMETHOD_(USB_DEVICE_SPEED, GetSpeed)( THIS) PURE; \ - \ - STDMETHOD_(UCHAR, GetInterval)( THIS) PURE; - -#define IMP_IEHCIREQUEST \ - STDMETHODIMP_(VOID) CompletionCallback( \ - IN NTSTATUS NtStatusCode, \ - IN ULONG UrbStatusCode, \ - IN struct _QUEUE_HEAD *QueueHead); \ - \ - STDMETHODIMP_(NTSTATUS) GetQueueHead( \ - IN struct _QUEUE_HEAD ** OutHead); \ - \ - STDMETHODIMP_(BOOLEAN) ShouldReleaseRequestAfterCompletion(); \ - \ - STDMETHODIMP_(VOID) FreeQueueHead(struct _QUEUE_HEAD * QueueHead); \ - \ - STDMETHODIMP_(BOOLEAN) IsQueueHeadComplete( \ - IN struct _QUEUE_HEAD * QueueHead); \ - \ - STDMETHODIMP_(USB_DEVICE_SPEED) GetSpeed( THIS); \ - \ - STDMETHODIMP_(UCHAR) GetInterval( THIS); - -DECLARE_INTERFACE_(IEHCIRequest, IUSBRequest) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBREQUEST() - DEFINE_ABSTRACT_USBEHCIREQUEST() -}; - - -typedef IEHCIRequest *PEHCIREQUEST; - -//========================================================================================= -// -// class IUSBQueue -// -// Description: This class manages pending requests -// - -#define DEFINE_ABSTRACT_USBEHCIQUEUE() \ - STDMETHOD_(VOID, InterruptCallback)( THIS_ \ - IN NTSTATUS Status, \ - OUT PULONG ShouldRingDoorBell) PURE; \ - \ - STDMETHOD_(VOID, CompleteAsyncRequests)( THIS) PURE; - -#define IMP_IEHCIQUEUE \ - STDMETHODIMP_(VOID) InterruptCallback( \ - IN NTSTATUS Status, \ - OUT PULONG ShouldRingDoorBell); \ - \ - STDMETHODIMP_(VOID) CompleteAsyncRequests(); - -DECLARE_INTERFACE_(IEHCIQueue, IUSBQueue) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBQUEUE() - DEFINE_ABSTRACT_USBEHCIQUEUE() -}; - -typedef IEHCIQueue *PEHCIQUEUE; - -#endif /* INTERFACES_HPP */ diff --git a/drivers/usb/usbehci/usb_queue.cpp b/drivers/usb/usbehci/usb_queue.cpp deleted file mode 100644 index 48a06d62c2d..00000000000 --- a/drivers/usb/usbehci/usb_queue.cpp +++ /dev/null @@ -1,1236 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbehci/usb_queue.cpp - * PURPOSE: USB EHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbehci.h" - -#define NDEBUG -#include - -class CUSBQueue : public IEHCIQueue -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // IUSBQueue functions - IMP_IUSBQUEUE - - // IEHCIQueue functions - IMP_IEHCIQUEUE - - // constructor / destructor - CUSBQueue(IUnknown *OuterUnknown){} - virtual ~CUSBQueue(){} - -protected: - LONG m_Ref; // reference count - PKSPIN_LOCK m_Lock; // list lock - PDMA_ADAPTER m_Adapter; // dma adapter - PEHCIHARDWAREDEVICE m_Hardware; // stores hardware object - PQUEUE_HEAD AsyncListQueueHead; // async queue head - LIST_ENTRY m_CompletedRequestAsyncList; // completed async request list - LIST_ENTRY m_PendingRequestAsyncList; // pending async request list - ULONG m_MaxPeriodicListEntries; // max periodic list entries - ULONG m_MaxPollingInterval; // max polling interval - PHYSICAL_ADDRESS m_SyncFrameListAddr; // physical address of sync frame list - PULONG m_SyncFrameList; // virtual address of sync frame list - - // queue head manipulation functions - VOID LinkQueueHead(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead); - VOID UnlinkQueueHead(PQUEUE_HEAD QueueHead); - VOID LinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, PQUEUE_HEAD NewQueueHead); - PQUEUE_HEAD UnlinkQueueHeadChain(PQUEUE_HEAD HeadQueueHead, ULONG Count); - - // processes the async list - VOID ProcessAsyncList(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell); - - // processes the async list - VOID ProcessPeriodicSchedule(IN NTSTATUS Status, OUT PULONG ShouldRingDoorBell); - - // called for each completed queue head - VOID QueueHeadCompletion(PQUEUE_HEAD QueueHead, NTSTATUS Status); - - // called for each completed queue head - VOID QueueHeadInterruptCompletion(PQUEUE_HEAD QueueHead, NTSTATUS Status); - - // called when the completion queue is cleaned up - VOID QueueHeadCleanup(PQUEUE_HEAD QueueHead); - - // initializes the sync schedule - NTSTATUS InitializeSyncSchedule(IN PEHCIHARDWAREDEVICE Hardware, IN PDMAMEMORYMANAGER MemManager); - - // links interrupt queue head - VOID LinkInterruptQueueHead(PQUEUE_HEAD QueueHead); - - // interval index - UCHAR GetIntervalIndex(UCHAR Interval); - - - // interrupt queue heads - PQUEUE_HEAD m_InterruptQueueHeads[EHCI_INTERRUPT_ENTRIES_COUNT]; - - // contains the periodic queue heads - LIST_ENTRY m_PeriodicQueueHeads; -}; - -//================================================================================================= -// COM -// -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - if (IsEqualGUIDAligned(refiid, IID_IUnknown)) - { - *Output = PVOID(PUNKNOWN(this)); - PUNKNOWN(*Output)->AddRef(); - return STATUS_SUCCESS; - } - - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::Initialize( - IN PUSBHARDWAREDEVICE Hardware, - IN PDMA_ADAPTER AdapterObject, - IN PDMAMEMORYMANAGER MemManager, - IN OPTIONAL PKSPIN_LOCK Lock) -{ - NTSTATUS Status = STATUS_SUCCESS; - - DPRINT("CUSBQueue::Initialize()\n"); - - ASSERT(Hardware); - - // - // store device lock - // - m_Lock = Lock; - - // - // store hardware object - // - m_Hardware = PEHCIHARDWAREDEVICE(Hardware); - - - // - // Get the AsyncQueueHead - // - AsyncListQueueHead = (PQUEUE_HEAD)m_Hardware->GetAsyncListQueueHead(); - - // - // Initialize the List Head - // - InitializeListHead(&AsyncListQueueHead->LinkedQueueHeads); - - // - // Initialize completed async list head - // - InitializeListHead(&m_CompletedRequestAsyncList); - - // - // Initialize pending async list head - // - InitializeListHead(&m_PendingRequestAsyncList); - - // - // initialize periodic queue heads - // - InitializeListHead(&m_PeriodicQueueHeads); - - // - // now initialize sync schedule - // - Status = InitializeSyncSchedule(m_Hardware, MemManager); - - - return Status; -} - -NTSTATUS -CUSBQueue::InitializeSyncSchedule( - IN PEHCIHARDWAREDEVICE Hardware, - IN PDMAMEMORYMANAGER MemManager) -{ - PHYSICAL_ADDRESS QueueHeadPhysAddr; - NTSTATUS Status; - ULONG Index, Interval, IntervalIndex; - PQUEUE_HEAD QueueHead; - - // - // FIXME: check if smaller list sizes are supported - // - m_MaxPeriodicListEntries = 1024; - - // - // use polling scheme of 512ms - // - m_MaxPollingInterval = 512; - - // - // first allocate a page to hold the queue array - // - Status = MemManager->Allocate(m_MaxPeriodicListEntries * sizeof(PVOID), (PVOID*)&m_SyncFrameList, &m_SyncFrameListAddr); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate sync frame list array - // - DPRINT1("Failed to allocate sync frame list\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - for(Index = 0; Index < EHCI_INTERRUPT_ENTRIES_COUNT; Index++) - { - // - // allocate queue head - // - Status = MemManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysAddr); - if (!NT_SUCCESS(Status)) - { - // - // failed to create queue head - // - DPRINT1("Failed to create queue head\n"); - return Status; - } - - // - // initialize queue head - // - QueueHead->HorizontalLinkPointer = TERMINATE_POINTER; - QueueHead->AlternateNextPointer = TERMINATE_POINTER; - QueueHead->NextPointer = TERMINATE_POINTER; - QueueHead->EndPointCharacteristics.MaximumPacketLength = 64; - QueueHead->EndPointCharacteristics.NakCountReload = 0x3; - QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED; - QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01; - QueueHead->PhysicalAddr = QueueHeadPhysAddr.LowPart; - QueueHead->Token.Bits.Halted = TRUE; //FIXME - m_InterruptQueueHeads[Index]= QueueHead; - - if (Index > 0) - { - // link all to the first queue head - QueueHead->HorizontalLinkPointer = m_InterruptQueueHeads[0]->PhysicalAddr | QH_TYPE_QH; - QueueHead->NextQueueHead = m_InterruptQueueHeads[0]; - } - } - - // - // build interrupt tree - // - Interval = EHCI_FRAMELIST_ENTRIES_COUNT; - IntervalIndex = EHCI_INTERRUPT_ENTRIES_COUNT - 1; - while (Interval > 1) - { - for (Index = Interval / 2; Index < EHCI_FRAMELIST_ENTRIES_COUNT; Index += Interval) - { - DPRINT("Index %lu IntervalIndex %lu\n", Index, IntervalIndex); - m_SyncFrameList[Index] = m_InterruptQueueHeads[IntervalIndex]->PhysicalAddr | QH_TYPE_QH; - } - IntervalIndex--; - Interval /= 2; - } - - // - // now set the sync base - // - Hardware->SetPeriodicListRegister(m_SyncFrameListAddr.LowPart); - - // - // sync frame list initialized - // - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::AddUSBRequest( - IUSBRequest * Req) -{ - PQUEUE_HEAD QueueHead; - NTSTATUS Status; - ULONG Type; - KIRQL OldLevel; - PEHCIREQUEST Request; - - // sanity check - ASSERT(Req != NULL); - - // get internal req - Request = PEHCIREQUEST(Req); - - // get request type - Type = Request->GetTransferType(); - - // check if supported - switch(Type) - { - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - /* NOT IMPLEMENTED IN QUEUE */ - Status = STATUS_NOT_SUPPORTED; - break; - case USB_ENDPOINT_TYPE_INTERRUPT: - case USB_ENDPOINT_TYPE_BULK: - case USB_ENDPOINT_TYPE_CONTROL: - Status = STATUS_SUCCESS; - break; - default: - /* BUG */ - PC_ASSERT(FALSE); - Status = STATUS_NOT_SUPPORTED; - } - - // check for success - if (!NT_SUCCESS(Status)) - { - // request not supported, please try later - return Status; - } - - // get queue head - Status = Request->GetQueueHead(&QueueHead); - - // check for success - if (!NT_SUCCESS(Status)) - { - // failed to get queue head - return Status; - } - - // acquire lock - KeAcquireSpinLock(m_Lock, &OldLevel); - - if (Type == USB_ENDPOINT_TYPE_BULK || Type == USB_ENDPOINT_TYPE_CONTROL) - { - // Add to list - LinkQueueHead(AsyncListQueueHead, QueueHead); - } - else if (Type == USB_ENDPOINT_TYPE_INTERRUPT) - { - // get interval - LinkInterruptQueueHead(QueueHead); - } - - // release lock - KeReleaseSpinLock(m_Lock, OldLevel); - - - // add extra reference which is released when the request is completed - Request->AddRef(); - - // done - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::CreateUSBRequest( - IUSBRequest **OutRequest) -{ - PUSBREQUEST UsbRequest; - NTSTATUS Status; - - *OutRequest = NULL; - Status = InternalCreateUSBRequest(&UsbRequest); - - if (NT_SUCCESS(Status)) - { - *OutRequest = UsbRequest; - } - - return Status; -} - -UCHAR -CUSBQueue::GetIntervalIndex( - UCHAR Interval) -{ - UCHAR IntervalIndex; - - ASSERT(Interval != 0); - if (Interval == 1) - IntervalIndex = 1; - else if (Interval == 2) - IntervalIndex = 2; - else if (Interval <= 4) - IntervalIndex = 3; - else if (Interval <= 8) - IntervalIndex = 4; - else if (Interval <= 16) - IntervalIndex = 5; - else if (Interval <= 32) - IntervalIndex = 6; - else if (Interval <= 64) - IntervalIndex = 7; - else if (Interval <= 128) - IntervalIndex = 8; - else - IntervalIndex = 9; - - ASSERT(IntervalIndex < EHCI_INTERRUPT_ENTRIES_COUNT); - return IntervalIndex; -} - -VOID -CUSBQueue::LinkInterruptQueueHead( - PQUEUE_HEAD QueueHead) -{ - PEHCIREQUEST Request; - UCHAR Interval, IntervalIndex; - USB_DEVICE_SPEED DeviceSpeed; - PQUEUE_HEAD InterruptQueueHead; - - // get internal req - Request = PEHCIREQUEST(QueueHead->Request); - ASSERT(Request); - - // get interval - Interval = Request->GetInterval(); - - // get device speed - DeviceSpeed = Request->GetSpeed(); - if (DeviceSpeed == UsbHighSpeed) - { - // interrupt queue head can be scheduled on each possible micro frame - QueueHead->EndPointCapabilities.InterruptScheduleMask = 0xFF; - } - else - { - // As we do not yet support FSTNs to correctly reference low/full - // speed interrupt transfers, we simply put them into the 1 interval - // queue. This way we ensure that we reach them on every micro frame - // and can do the corresponding start/complete split transactions. - // ToDo: use FSTNs to correctly link non high speed interrupt transfers - Interval = 1; - - // For now we also force start splits to be in micro frame 0 and - // complete splits to be in micro frame 2, 3 and 4. - QueueHead->EndPointCapabilities.InterruptScheduleMask = 0x01; - QueueHead->EndPointCapabilities.SplitCompletionMask = 0x1C; - } - - // sanitize interrupt interval - Interval = max(1, Interval); - - // get interval index - IntervalIndex = GetIntervalIndex(Interval); - - - // get interrupt queue head - InterruptQueueHead = m_InterruptQueueHeads[IntervalIndex]; - - // link queue head - QueueHead->HorizontalLinkPointer = InterruptQueueHead->HorizontalLinkPointer; - QueueHead->NextQueueHead = InterruptQueueHead->NextQueueHead; - - InterruptQueueHead->HorizontalLinkPointer = QueueHead->PhysicalAddr | QH_TYPE_QH; - InterruptQueueHead->NextQueueHead = QueueHead; - - // store in periodic list - InsertTailList(&m_PeriodicQueueHeads, &QueueHead->LinkedQueueHeads); -} - -// -// LinkQueueHead - Links one QueueHead to the end of HeadQueueHead list, updating HorizontalLinkPointer. -// -VOID -CUSBQueue::LinkQueueHead( - PQUEUE_HEAD HeadQueueHead, - PQUEUE_HEAD NewQueueHead) -{ - PQUEUE_HEAD LastQueueHead, NextQueueHead; - PLIST_ENTRY Entry; - ASSERT(HeadQueueHead); - ASSERT(NewQueueHead); - - // - // Link the LIST_ENTRYs - // - //ASSERT(IsListEmpty(&HeadQueueHead->LinkedQueueHeads)); - InsertTailList(&HeadQueueHead->LinkedQueueHeads, &NewQueueHead->LinkedQueueHeads); - - // - // Update HLP for NewQueueHead to point to next, which should be the HeadQueueHead - // - Entry = NewQueueHead->LinkedQueueHeads.Flink; - NextQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - //ASSERT(NextQueueHead == HeadQueueHead); - NewQueueHead->HorizontalLinkPointer = (NextQueueHead->PhysicalAddr | QH_TYPE_QH); - - _ReadWriteBarrier(); - - // - // Update HLP for Previous QueueHead, which should be the last in list. - // - Entry = NewQueueHead->LinkedQueueHeads.Blink; - LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - //ASSERT(LastQueueHead == HeadQueueHead); - LastQueueHead->HorizontalLinkPointer = (NewQueueHead->PhysicalAddr | QH_TYPE_QH); - - // - // head queue head must be halted - // - //PC_ASSERT(HeadQueueHead->Token.Bits.Halted == TRUE); -} - -// -// UnlinkQueueHead - Unlinks one QueueHead, updating HorizontalLinkPointer. -// -VOID -CUSBQueue::UnlinkQueueHead( - PQUEUE_HEAD QueueHead) -{ - PQUEUE_HEAD PreviousQH, NextQH; - PLIST_ENTRY Entry; - - // - // sanity check: there must be at least one queue head with halted bit set - // - //PC_ASSERT(QueueHead->Token.Bits.Halted == 0); - - // - // get previous link - // - Entry = QueueHead->LinkedQueueHeads.Blink; - - // - // get queue head structure - // - PreviousQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - - // - // get next link - // - Entry = QueueHead->LinkedQueueHeads.Flink; - - // - // get queue head structure - // - NextQH = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - - // - // sanity check - // - ASSERT(QueueHead->HorizontalLinkPointer == (NextQH->PhysicalAddr | QH_TYPE_QH)); - - // - // remove queue head from linked list - // - PreviousQH->HorizontalLinkPointer = NextQH->PhysicalAddr | QH_TYPE_QH; - - // - // remove software link - // - RemoveEntryList(&QueueHead->LinkedQueueHeads); -} - -// -// LinkQueueHeadChain - Links a list of QueueHeads to the HeadQueueHead list, updating HorizontalLinkPointer. -// -VOID -CUSBQueue::LinkQueueHeadChain( - PQUEUE_HEAD HeadQueueHead, - PQUEUE_HEAD NewQueueHead) -{ - PQUEUE_HEAD LastQueueHead; - PLIST_ENTRY Entry; - ASSERT(HeadQueueHead); - ASSERT(NewQueueHead); - - // - // Find the last QueueHead in NewQueueHead - // - Entry = NewQueueHead->LinkedQueueHeads.Blink; - ASSERT(Entry != NewQueueHead->LinkedQueueHeads.Flink); - LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - - // - // Set the LinkPointer and Flink - // - LastQueueHead->HorizontalLinkPointer = HeadQueueHead->PhysicalAddr | QH_TYPE_QH; - LastQueueHead->LinkedQueueHeads.Flink = &HeadQueueHead->LinkedQueueHeads; - - // - // Fine the last QueueHead in HeadQueueHead - // - Entry = HeadQueueHead->LinkedQueueHeads.Blink; - HeadQueueHead->LinkedQueueHeads.Blink = &LastQueueHead->LinkedQueueHeads; - LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - LastQueueHead->LinkedQueueHeads.Flink = &NewQueueHead->LinkedQueueHeads; - LastQueueHead->HorizontalLinkPointer = NewQueueHead->PhysicalAddr | QH_TYPE_QH; -} - -// -// UnlinkQueueHeadChain - Unlinks a list number of QueueHeads from HeadQueueHead list, updating HorizontalLinkPointer. -// returns the chain of QueueHeads removed from HeadQueueHead. -// -PQUEUE_HEAD -CUSBQueue::UnlinkQueueHeadChain( - PQUEUE_HEAD HeadQueueHead, - ULONG Count) -{ - PQUEUE_HEAD LastQueueHead, FirstQueueHead; - PLIST_ENTRY Entry; - ULONG Index; - - // - // Find the last QueueHead in NewQueueHead - // - Entry = &HeadQueueHead->LinkedQueueHeads; - FirstQueueHead = CONTAINING_RECORD(Entry->Flink, QUEUE_HEAD, LinkedQueueHeads); - - for (Index = 0; Index < Count; Index++) - { - Entry = Entry->Flink; - - if (Entry == &HeadQueueHead->LinkedQueueHeads) - { - DPRINT1("Warning; Only %lu QueueHeads in HeadQueueHead\n", Index); - Count = Index + 1; - break; - } - } - - LastQueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - HeadQueueHead->LinkedQueueHeads.Flink = LastQueueHead->LinkedQueueHeads.Flink; - if (Count + 1 == Index) - { - HeadQueueHead->LinkedQueueHeads.Blink = &HeadQueueHead->LinkedQueueHeads; - } - else - HeadQueueHead->LinkedQueueHeads.Blink = LastQueueHead->LinkedQueueHeads.Flink; - - FirstQueueHead->LinkedQueueHeads.Blink = &LastQueueHead->LinkedQueueHeads; - LastQueueHead->LinkedQueueHeads.Flink = &FirstQueueHead->LinkedQueueHeads; - LastQueueHead->HorizontalLinkPointer = TERMINATE_POINTER; - return FirstQueueHead; -} - -VOID -CUSBQueue::QueueHeadInterruptCompletion( - PQUEUE_HEAD QueueHead, - NTSTATUS Status) -{ - PEHCIREQUEST Request; - UCHAR Interval, IntervalIndex; - PQUEUE_HEAD InterruptQueueHead, LastQueueHead = NULL; - - - // - // sanity check - // - PC_ASSERT(QueueHead->Request); - - // - // get IUSBRequest interface - // - Request = (PEHCIREQUEST)QueueHead->Request; - - // get interval - Interval = Request->GetInterval(); - - // sanitize interval - Interval = max(1, Interval); - - // get interval index - IntervalIndex = GetIntervalIndex(Interval); - - // get interrupt queue head from index - InterruptQueueHead = m_InterruptQueueHeads[IntervalIndex]; - - while(InterruptQueueHead != NULL) - { - if (InterruptQueueHead == QueueHead) - break; - - // move to next queue head - LastQueueHead = InterruptQueueHead; - InterruptQueueHead = (PQUEUE_HEAD)InterruptQueueHead->NextQueueHead; - } - - if (InterruptQueueHead != QueueHead) - { - // queue head not in list - ASSERT(FALSE); - return; - } - - // now unlink queue head - LastQueueHead->HorizontalLinkPointer = QueueHead->HorizontalLinkPointer; - LastQueueHead->NextQueueHead = QueueHead->NextQueueHead; - - DPRINT1("Periodic QueueHead %p Addr %x unlinked\n", QueueHead, QueueHead->PhysicalAddr); - - // insert into completed list - InsertTailList(&m_CompletedRequestAsyncList, &QueueHead->LinkedQueueHeads); -} - - - -VOID -CUSBQueue::QueueHeadCompletion( - PQUEUE_HEAD CurrentQH, - NTSTATUS Status) -{ - // - // now unlink the queue head - // FIXME: implement chained queue heads - // no need to acquire locks, as it is called with locks held - // - - // - // unlink queue head - // - UnlinkQueueHead(CurrentQH); - - // - // insert into completed list - // - InsertTailList(&m_CompletedRequestAsyncList, &CurrentQH->LinkedQueueHeads); -} - - -VOID -CUSBQueue::ProcessPeriodicSchedule( - IN NTSTATUS Status, - OUT PULONG ShouldRingDoorBell) -{ - KIRQL OldLevel; - PLIST_ENTRY Entry; - PQUEUE_HEAD QueueHead; - PEHCIREQUEST Request; - BOOLEAN IsQueueHeadComplete; - - // - // lock completed async list - // - KeAcquireSpinLock(m_Lock, &OldLevel); - - // - // walk async list - // - ASSERT(AsyncListQueueHead); - Entry = m_PeriodicQueueHeads.Flink; - - while(Entry != &m_PeriodicQueueHeads) - { - // - // get queue head structure - // - QueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - - // - // sanity check - // - PC_ASSERT(QueueHead->Request); - - // - // get IUSBRequest interface - // - Request = (PEHCIREQUEST)QueueHead->Request; - - // - // move to next entry - // - Entry = Entry->Flink; - - // - // check if queue head is complete - // - IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead); - - DPRINT("Request %p QueueHead %p Complete %c\n", Request, QueueHead, IsQueueHeadComplete); - - // - // check if queue head is complete - // - if (IsQueueHeadComplete) - { - // - // current queue head is complete - // - QueueHeadInterruptCompletion(QueueHead, Status); - - // - // ring door bell is going to be necessary - // - *ShouldRingDoorBell = TRUE; - } - } - - // - // release lock - // - KeReleaseSpinLock(m_Lock, OldLevel); - -} - -VOID -CUSBQueue::ProcessAsyncList( - IN NTSTATUS Status, - OUT PULONG ShouldRingDoorBell) -{ - KIRQL OldLevel; - PLIST_ENTRY Entry; - PQUEUE_HEAD QueueHead; - PEHCIREQUEST Request; - BOOLEAN IsQueueHeadComplete; - - // - // lock completed async list - // - KeAcquireSpinLock(m_Lock, &OldLevel); - - // - // walk async list - // - ASSERT(AsyncListQueueHead); - Entry = AsyncListQueueHead->LinkedQueueHeads.Flink; - - while(Entry != &AsyncListQueueHead->LinkedQueueHeads) - { - // - // get queue head structure - // - QueueHead = CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - - // - // sanity check - // - PC_ASSERT(QueueHead->Request); - - // - // get IUSBRequest interface - // - Request = (PEHCIREQUEST)QueueHead->Request; - - // - // move to next entry - // - Entry = Entry->Flink; - - // - // check if queue head is complete - // - IsQueueHeadComplete = Request->IsQueueHeadComplete(QueueHead); - - DPRINT("Request %p QueueHead %p Complete %c\n", Request, QueueHead, IsQueueHeadComplete); - - // - // check if queue head is complete - // - if (IsQueueHeadComplete) - { - // - // current queue head is complete - // - QueueHeadCompletion(QueueHead, Status); - - // - // ring door bell is going to be necessary - // - *ShouldRingDoorBell = TRUE; - } - } - - // - // release lock - // - KeReleaseSpinLock(m_Lock, OldLevel); -} - - -VOID -STDMETHODCALLTYPE -CUSBQueue::InterruptCallback( - IN NTSTATUS Status, - OUT PULONG ShouldRingDoorBell) -{ - DPRINT("CUSBQueue::InterruptCallback\n"); - - // - // process periodic schedule - // - ProcessPeriodicSchedule(Status, ShouldRingDoorBell); - - // - // iterate asynchronous list - // - *ShouldRingDoorBell = FALSE; - ProcessAsyncList(Status, ShouldRingDoorBell); -} - -VOID -CUSBQueue::QueueHeadCleanup( - PQUEUE_HEAD CurrentQH) -{ - PQUEUE_HEAD NewQueueHead; - PEHCIREQUEST Request; - BOOLEAN ShouldReleaseWhenDone; - USBD_STATUS UrbStatus; - KIRQL OldLevel; - - // - // sanity checks - // - PC_ASSERT(CurrentQH->Token.Bits.Active == 0); - PC_ASSERT(CurrentQH->Request); - - - // - // get request - // - Request = (PEHCIREQUEST)CurrentQH->Request; - - // - // sanity check - // - PC_ASSERT(Request); - - // - // check if the queue head was completed with errors - // - if (CurrentQH->Token.Bits.Halted) - { - if (CurrentQH->Token.Bits.DataBufferError) - { - // - // data buffer error - // - UrbStatus = USBD_STATUS_DATA_BUFFER_ERROR; - } - else if (CurrentQH->Token.Bits.BabbleDetected) - { - // - // babble detected - // - UrbStatus = USBD_STATUS_BABBLE_DETECTED; - } - else - { - // - // stall pid - // - UrbStatus = USBD_STATUS_STALL_PID; - } - } - else - { - // - // well done ;) - // - UrbStatus = USBD_STATUS_SUCCESS; - } - - // - // Check if the transfer was completed and if UrbStatus is ok - // - if ((Request->IsRequestComplete() == FALSE) && (UrbStatus == USBD_STATUS_SUCCESS)) - { - // - // request is incomplete, get new queue head - // - if (Request->GetQueueHead(&NewQueueHead) == STATUS_SUCCESS) - { - // - // let IUSBRequest free the queue head - // - Request->FreeQueueHead(CurrentQH); - - // - // first acquire request lock - // - KeAcquireSpinLock(m_Lock, &OldLevel); - - // - // add to pending list - // - InsertTailList(&m_PendingRequestAsyncList, &NewQueueHead->LinkedQueueHeads); - - // - // release queue head - // - KeReleaseSpinLock(m_Lock, OldLevel); - - // - // Done for now - // - return; - } - DPRINT1("Unable to create a new QueueHead\n"); - //ASSERT(FALSE); - - // - // Else there was a problem - // FIXME: Find better return - UrbStatus = USBD_STATUS_INSUFFICIENT_RESOURCES; - } - - if (UrbStatus != USBD_STATUS_SUCCESS) - { - DPRINT1("URB failed with status 0x%x\n", UrbStatus); - //PC_ASSERT(FALSE); - } - - // - // notify request that a transfer has completed - // - Request->CompletionCallback(UrbStatus != USBD_STATUS_SUCCESS ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS, - UrbStatus, - CurrentQH); - - // - // let IUSBRequest free the queue head - // - Request->FreeQueueHead(CurrentQH); - - // - // check if we should release request when done - // - ShouldReleaseWhenDone = Request->ShouldReleaseRequestAfterCompletion(); - - // - // release reference when the request was added - // - Request->Release(); - - // - // check if the operation was asynchronous - // - if (ShouldReleaseWhenDone) - { - // - // release outstanding reference count - // - Request->Release(); - } - - // - // request is now released - // -} - -VOID -STDMETHODCALLTYPE -CUSBQueue::CompleteAsyncRequests() -{ - KIRQL OldLevel; - PLIST_ENTRY Entry; - PQUEUE_HEAD CurrentQH; - - DPRINT("CUSBQueue::CompleteAsyncRequests\n"); - - // - // first acquire request lock - // - KeAcquireSpinLock(m_Lock, &OldLevel); - - // - // the list should not be empty - // - PC_ASSERT(!IsListEmpty(&m_CompletedRequestAsyncList)); - - while(!IsListEmpty(&m_CompletedRequestAsyncList)) - { - // - // remove first entry - // - Entry = RemoveHeadList(&m_CompletedRequestAsyncList); - - // - // get queue head structure - // - CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - - // - // release lock - // - KeReleaseSpinLock(m_Lock, OldLevel); - - // - // complete request now - // - QueueHeadCleanup(CurrentQH); - - // - // first acquire request lock - // - KeAcquireSpinLock(m_Lock, &OldLevel); - } - - // - // is there a pending async entry - // - if (!IsListEmpty(&m_PendingRequestAsyncList)) - { - // - // remove first entry - // - Entry = RemoveHeadList(&m_PendingRequestAsyncList); - - // - // get queue head structure - // - CurrentQH = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - - // - // Add it to the AsyncList list - // - LinkQueueHead(AsyncListQueueHead, CurrentQH); - } - - // - // release lock - // - KeReleaseSpinLock(m_Lock, OldLevel); -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::AbortDevicePipe( - IN UCHAR DeviceAddress, - IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) -{ - KIRQL OldLevel; - PLIST_ENTRY Entry; - PQUEUE_HEAD QueueHead; - LIST_ENTRY ListHead; - - // - // lock completed async list - // - KeAcquireSpinLock(m_Lock, &OldLevel); - - DPRINT1("AbortDevicePipe DeviceAddress %x EndpointDescriptor %p Addr %x\n", DeviceAddress, EndpointDescriptor, EndpointDescriptor->bEndpointAddress); - - // - // init list head - // - InitializeListHead(&ListHead); - - - // - // walk async list - // - ASSERT(AsyncListQueueHead); - Entry = AsyncListQueueHead->LinkedQueueHeads.Flink; - - while(Entry != &AsyncListQueueHead->LinkedQueueHeads) - { - // - // get queue head structure - // - QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - ASSERT(QueueHead); - - // - // move to next entry - // - Entry = Entry->Flink; - - if (QueueHead->EndPointCharacteristics.DeviceAddress == DeviceAddress && - QueueHead->EndPointCharacteristics.EndPointNumber == (EndpointDescriptor->bEndpointAddress & 0xF) && QueueHead->Token.Bits.Halted) - { - // - // unlink queue head - // - UnlinkQueueHead(QueueHead); - - // - // add to temp list - // - InsertTailList(&ListHead, &QueueHead->LinkedQueueHeads); - } - } - - // - // release lock - // - KeReleaseSpinLock(m_Lock, OldLevel); - - while(!IsListEmpty(&ListHead)) - { - // - // remove entry - // - Entry = RemoveHeadList(&ListHead); - - // - // get queue head structure - // - QueueHead = (PQUEUE_HEAD)CONTAINING_RECORD(Entry, QUEUE_HEAD, LinkedQueueHeads); - ASSERT(QueueHead); - - // - // cleanup queue head - // - QueueHeadCleanup(QueueHead); - } - return STATUS_SUCCESS; -} - - -NTSTATUS -NTAPI -CreateUSBQueue( - PUSBQUEUE *OutUsbQueue) -{ - PUSBQUEUE This; - - // - // allocate controller - // - This = new(NonPagedPool, TAG_USBEHCI) CUSBQueue(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutUsbQueue = (PUSBQUEUE)This; - - // - // done - // - return STATUS_SUCCESS; -} - diff --git a/drivers/usb/usbehci/usb_request.cpp b/drivers/usb/usbehci/usb_request.cpp deleted file mode 100644 index abffd0dc679..00000000000 --- a/drivers/usb/usbehci/usb_request.cpp +++ /dev/null @@ -1,1852 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbehci/usb_request.cpp - * PURPOSE: USB EHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbehci.h" - -#define NDEBUG -#include - -class CUSBRequest : public IEHCIRequest -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // IUSBRequest interface functions - IMP_IUSBREQUEST - // IEHCI Request interface functions - IMP_IEHCIREQUEST - - // local functions - ULONG InternalGetTransferType(); - UCHAR InternalGetPidDirection(); - NTSTATUS BuildControlTransferQueueHead(PQUEUE_HEAD * OutHead); - NTSTATUS BuildBulkInterruptTransferQueueHead(PQUEUE_HEAD * OutHead); - NTSTATUS STDMETHODCALLTYPE CreateDescriptor(PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor); - NTSTATUS CreateQueueHead(PQUEUE_HEAD *OutQueueHead); - UCHAR STDMETHODCALLTYPE GetDeviceAddress(); - NTSTATUS BuildSetupPacket(); - NTSTATUS BuildSetupPacketFromURB(); - ULONG InternalCalculateTransferLength(); - NTSTATUS STDMETHODCALLTYPE BuildTransferDescriptorChain(IN PQUEUE_HEAD QueueHead, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PUCHAR OutDataToggle, OUT PULONG OutTransferBufferOffset); - VOID STDMETHODCALLTYPE InitDescriptor(IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR DataToggle, OUT PULONG OutDescriptorLength); - VOID DumpQueueHead(IN PQUEUE_HEAD QueueHead); - - // constructor / destructor - CUSBRequest(IUnknown *OuterUnknown); - virtual ~CUSBRequest(); - -protected: - LONG m_Ref; - - // - // memory manager for allocating setup packet / queue head / transfer descriptors - // - PDMAMEMORYMANAGER m_DmaManager; - - // - // caller provided irp packet containing URB request - // - PIRP m_Irp; - - // - // transfer buffer length - // - ULONG m_TransferBufferLength; - - // - // current transfer length - // - ULONG m_TransferBufferLengthCompleted; - - // - // Total Transfer Length - // - ULONG m_TotalBytesTransferred; - - // - // transfer buffer MDL - // - PMDL m_TransferBufferMDL; - - // - // caller provided setup packet - // - PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket; - - // - // completion event for callers who initialized request with setup packet - // - PKEVENT m_CompletionEvent; - - // - // device address for callers who initialized it with device address - // - UCHAR m_DeviceAddress; - - // - // store end point address - // - PUSB_ENDPOINT m_EndpointDescriptor; - - // - // DMA queue head - // - PQUEUE_HEAD m_QueueHead; - - // - // allocated setup packet from the DMA pool - // - PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket; - PHYSICAL_ADDRESS m_DescriptorSetupPacket; - - // - // stores the result of the operation - // - NTSTATUS m_NtStatusCode; - ULONG m_UrbStatusCode; - - // buffer base address - PVOID m_Base; - - // device speed - USB_DEVICE_SPEED m_Speed; - -}; - -//---------------------------------------------------------------------------------------- -CUSBRequest::CUSBRequest(IUnknown *OuterUnknown) : - m_CompletionEvent(NULL) -{ - UNREFERENCED_PARAMETER(OuterUnknown); -} - -//---------------------------------------------------------------------------------------- -CUSBRequest::~CUSBRequest() -{ - if (m_CompletionEvent != NULL) - { - ExFreePoolWithTag(m_CompletionEvent, TAG_USBEHCI); - } -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - return STATUS_UNSUCCESSFUL; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::InitializeWithSetupPacket( - IN PDMAMEMORYMANAGER DmaManager, - IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, - IN PUSBDEVICE Device, - IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, - IN OUT ULONG TransferBufferLength, - IN OUT PMDL TransferBuffer) -{ - // - // sanity checks - // - PC_ASSERT(DmaManager); - PC_ASSERT(SetupPacket); - - // - // initialize packet - // - m_DmaManager = DmaManager; - m_SetupPacket = SetupPacket; - m_TransferBufferLength = TransferBufferLength; - m_TransferBufferMDL = TransferBuffer; - m_DeviceAddress = Device->GetDeviceAddress(); - m_Speed = Device->GetSpeed(); - m_EndpointDescriptor = EndpointDescriptor; - m_TotalBytesTransferred = 0; - - // - // Set Length Completed to 0 - // - m_TransferBufferLengthCompleted = 0; - - // - // allocate completion event - // - m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_USBEHCI); - if (!m_CompletionEvent) - { - // - // failed to allocate completion event - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize completion event - // - KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE); - - // - // done - // - return STATUS_SUCCESS; -} -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::InitializeWithIrp( - IN PDMAMEMORYMANAGER DmaManager, - IN PUSBDEVICE Device, - IN OUT PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - - // - // sanity checks - // - PC_ASSERT(DmaManager); - PC_ASSERT(Irp); - - m_DmaManager = DmaManager; - m_TotalBytesTransferred = 0; - m_Speed = Device->GetSpeed(); - - // - // get current irp stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - - // - // sanity check - // - PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL); - PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB); - PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0); - - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // store irp - // - m_Irp = Irp; - - // - // check function type - // - switch (Urb->UrbHeader.Function) - { - // - // luckily those request have the same structure layout - // - case URB_FUNCTION_CLASS_INTERFACE: - case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: - case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: - { - // - // bulk interrupt transfer - // - if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength) - { - // - // Check if there is a MDL - // - if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) - { - // - // sanity check - // - PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer); - - // - // Create one using TransferBuffer - // - DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, - Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, - FALSE, - FALSE, - NULL); - - if (!m_TransferBufferMDL) - { - // - // failed to allocate mdl - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // build mdl for non paged pool - // FIXME: Does hub driver already do this when passing MDL? - // - MmBuildMdlForNonPagedPool(m_TransferBufferMDL); - - // - // Keep that ehci created the MDL and needs to free it. - // - } - else - { - m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL; - } - - // - // save buffer length - // - m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; - - // - // Set Length Completed to 0 - // - m_TransferBufferLengthCompleted = 0; - - // - // get endpoint descriptor - // - m_EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle; - - } - break; - } - default: - DPRINT1("URB Function: not supported %x\n", Urb->UrbHeader.Function); - //ASSERT(FALSE); - } - - // - // done - // - return STATUS_SUCCESS; - -} - -//---------------------------------------------------------------------------------------- -VOID -STDMETHODCALLTYPE -CUSBRequest::CompletionCallback( - IN NTSTATUS NtStatusCode, - IN ULONG UrbStatusCode, - IN struct _QUEUE_HEAD *QueueHead) -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - - // - // FIXME: support linked queue heads - // - - // - // store completion code - // - m_NtStatusCode = NtStatusCode; - m_UrbStatusCode = UrbStatusCode; - - if (m_Irp) - { - // - // set irp completion status - // - m_Irp->IoStatus.Status = NtStatusCode; - - // - // get current irp stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // store urb status - // - Urb->UrbHeader.Status = UrbStatusCode; - - // - // Check if the MDL was created - // - if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) - { - // - // Free Mdl - // - IoFreeMdl(m_TransferBufferMDL); - } - - // - // check if the request was successful - // - if (!NT_SUCCESS(NtStatusCode)) - { - // - // set returned length to zero in case of error - // - Urb->UrbHeader.Length = 0; - } - else - { - // - // calculate transfer length - // - Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = InternalCalculateTransferLength(); - } - - DPRINT("Request %p Completing Irp %p NtStatusCode %x UrbStatusCode %x Transferred Length %lu\n", this, m_Irp, NtStatusCode, UrbStatusCode, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - - // - // FIXME: check if the transfer was split - // if yes dont complete irp yet - // - IoCompleteRequest(m_Irp, IO_NO_INCREMENT); - } - else - { - // - // signal completion event - // - PC_ASSERT(m_CompletionEvent); - KeSetEvent(m_CompletionEvent, 0, FALSE); - } -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::GetQueueHead( - struct _QUEUE_HEAD ** OutHead) -{ - ULONG TransferType; - NTSTATUS Status; - - // - // first get transfer type - // - TransferType = InternalGetTransferType(); - - // - // build request depending on type - // - switch(TransferType) - { - case USB_ENDPOINT_TYPE_CONTROL: - Status = BuildControlTransferQueueHead(OutHead); - break; - case USB_ENDPOINT_TYPE_INTERRUPT: - case USB_ENDPOINT_TYPE_BULK: - Status = BuildBulkInterruptTransferQueueHead(OutHead); - break; - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - DPRINT1("USB_ENDPOINT_TYPE_ISOCHRONOUS not implemented\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - default: - PC_ASSERT(FALSE); - Status = STATUS_NOT_IMPLEMENTED; - break; - } - - if (NT_SUCCESS(Status)) - { - // - // store queue head - // - m_QueueHead = *OutHead; - - // - // store request object - // - (*OutHead)->Request = PVOID(this); - } - - // - // done - // - return Status; -} - -//---------------------------------------------------------------------------------------- -BOOLEAN -STDMETHODCALLTYPE -CUSBRequest::IsRequestComplete() -{ - // - // FIXME: check if request was split - // - - // - // Check if the transfer was completed, only valid for Bulk Transfers - // - if ((m_TransferBufferLengthCompleted < m_TransferBufferLength) - && (GetTransferType() == USB_ENDPOINT_TYPE_BULK)) - { - // - // Transfer not completed - // - return FALSE; - } - return TRUE; -} -//---------------------------------------------------------------------------------------- -ULONG -STDMETHODCALLTYPE -CUSBRequest::GetTransferType() -{ - // - // call internal implementation - // - return InternalGetTransferType(); -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBRequest::InternalGetTransferType() -{ - ULONG TransferType; - - // - // check if an irp is provided - // - if (m_Irp) - { - ASSERT(m_EndpointDescriptor); - - // - // end point is defined in the low byte of bmAttributes - // - TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK); - } - else - { - // - // initialized with setup packet, must be a control transfer - // - TransferType = USB_ENDPOINT_TYPE_CONTROL; - ASSERT(m_EndpointDescriptor == NULL); - } - - // - // done - // - return TransferType; -} - -UCHAR -CUSBRequest::InternalGetPidDirection() -{ - if (m_EndpointDescriptor) - { - // - // end point direction is highest bit in bEndpointAddress - // - return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7; - } - else - { - // - // request arrives on the control pipe, extract direction from setup packet - // - ASSERT(m_DescriptorPacket); - return (m_DescriptorPacket->bmRequestType.B >> 7); - } -} - -VOID -STDMETHODCALLTYPE -CUSBRequest::InitDescriptor( - IN PQUEUE_TRANSFER_DESCRIPTOR CurrentDescriptor, - IN PVOID TransferBuffer, - IN ULONG TransferBufferLength, - IN UCHAR PidCode, - IN UCHAR DataToggle, - OUT PULONG OutDescriptorLength) -{ - ULONG Index, Length = 0, PageOffset, BufferLength; - PHYSICAL_ADDRESS Address; - - // - // init transfer descriptor - // - CurrentDescriptor->Token.Bits.PIDCode = PidCode; - CurrentDescriptor->Token.Bits.TotalBytesToTransfer = 0; - CurrentDescriptor->Token.Bits.DataToggle = DataToggle; - - // - // sanity check - // - ASSERT(TransferBufferLength); - - // - // store buffers - // - Index = 0; - do - { - // - // get address (HACK) - // - *(volatile char *)TransferBuffer; - Address = MmGetPhysicalAddress(TransferBuffer); - - // - // use physical address - // - CurrentDescriptor->BufferPointer[Index] = Address.LowPart; - CurrentDescriptor->ExtendedBufferPointer[Index] = Address.HighPart; - - // - // Get the offset from page size - // - PageOffset = BYTE_OFFSET(CurrentDescriptor->BufferPointer[Index]); - if (PageOffset != 0) - { - // - // move to next page - // - TransferBuffer = (PVOID)ROUND_TO_PAGES(TransferBuffer); - } - else - { - // - // move to next page - // - TransferBuffer = (PVOID)((ULONG_PTR)TransferBuffer + PAGE_SIZE); - } - - // - // calculate buffer length - // - BufferLength = min(TransferBufferLength, PAGE_SIZE - PageOffset); - - // - // increment transfer bytes - // - CurrentDescriptor->Token.Bits.TotalBytesToTransfer += BufferLength; - CurrentDescriptor->TotalBytesToTransfer += BufferLength; - Length += BufferLength; - DPRINT("Index %lu TransferBufferLength %lu PageOffset %x BufferLength %lu Buffer Phy %p TransferBuffer %p\n", Index, TransferBufferLength, PageOffset, BufferLength, CurrentDescriptor->BufferPointer[Index], TransferBuffer); - - // - // decrement available byte count - // - TransferBufferLength -= BufferLength; - if (TransferBufferLength == 0) - { - // - // end reached - // - break; - } - - // - // sanity check - // - if (Index > 1) - { - // - // no equal buffers - // - ASSERT(CurrentDescriptor->BufferPointer[Index] != CurrentDescriptor->BufferPointer[Index-1]); - } - - // - // next descriptor index - // - Index++; - }while(Index < 5); - - // - // store result - // - *OutDescriptorLength = Length; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::BuildTransferDescriptorChain( - IN PQUEUE_HEAD QueueHead, - IN PVOID TransferBuffer, - IN ULONG TransferBufferLength, - IN UCHAR PidCode, - IN UCHAR InitialDataToggle, - OUT PQUEUE_TRANSFER_DESCRIPTOR * OutFirstDescriptor, - OUT PQUEUE_TRANSFER_DESCRIPTOR * OutLastDescriptor, - OUT PUCHAR OutDataToggle, - OUT PULONG OutTransferBufferOffset) -{ - PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL; - NTSTATUS Status; - ULONG DescriptorLength, TransferBufferOffset = 0; - ULONG MaxPacketSize = 0, TransferSize; - - // - // is there an endpoint descriptor - // - if (m_EndpointDescriptor) - { - // - // use endpoint packet size - // - MaxPacketSize = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; - } - - do - { - // - // allocate transfer descriptor - // - Status = CreateDescriptor(&CurrentDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate transfer descriptor - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - if (MaxPacketSize) - { - // - // transfer size is minimum available buffer or endpoint size - // - TransferSize = min(TransferBufferLength - TransferBufferOffset, MaxPacketSize); - } - else - { - // - // use available buffer - // - TransferSize = TransferBufferLength - TransferBufferOffset; - } - - // - // now init the descriptor - // - InitDescriptor(CurrentDescriptor, - (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset), - TransferSize, - PidCode, - InitialDataToggle, - &DescriptorLength); - - // - // insert into queue head - // - InsertTailList(&QueueHead->TransferDescriptorListHead, &CurrentDescriptor->DescriptorEntry); - - // - // adjust offset - // - TransferBufferOffset += DescriptorLength; - - if (LastDescriptor) - { - // - // link to current descriptor - // - LastDescriptor->NextPointer = CurrentDescriptor->PhysicalAddr; - LastDescriptor = CurrentDescriptor; - } - else - { - // - // first descriptor in chain - // - LastDescriptor = FirstDescriptor = CurrentDescriptor; - } - - // - // flip data toggle - // - InitialDataToggle = !InitialDataToggle; - - if(TransferBufferLength == TransferBufferOffset) - { - // - // end reached - // - break; - } - - }while(TRUE); - - if (OutFirstDescriptor) - { - // - // store first descriptor - // - *OutFirstDescriptor = FirstDescriptor; - } - - if (OutLastDescriptor) - { - // - // store last descriptor - // - *OutLastDescriptor = CurrentDescriptor; - } - - if (OutDataToggle) - { - // - // store result data toggle - // - *OutDataToggle = InitialDataToggle; - } - - if (OutTransferBufferOffset) - { - // - // store offset - // - *OutTransferBufferOffset = TransferBufferOffset; - } - - // - // done - // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::BuildControlTransferQueueHead( - PQUEUE_HEAD * OutHead) -{ - NTSTATUS Status; - ULONG DescriptorChainLength; - PQUEUE_HEAD QueueHead; - PQUEUE_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor, LastDescriptor; - - // - // first allocate the queue head - // - Status = CreateQueueHead(&QueueHead); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate queue head - // - DPRINT1("[EHCI] Failed to create queue head\n"); - return Status; - } - - // - // sanity check - // - PC_ASSERT(QueueHead); - - // - // create setup packet - // - Status = BuildSetupPacket(); - if (!NT_SUCCESS(Status)) - { - // failed to create setup packet - DPRINT1("[EHCI] Failed to create setup packet\n"); - - // release queue head - m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD)); - return Status; - } - - // - // create setup descriptor - // - Status = CreateDescriptor(&SetupDescriptor); - if (!NT_SUCCESS(Status)) - { - // failed to create setup transfer descriptor - DPRINT1("[EHCI] Failed to create setup descriptor\n"); - - if (m_DescriptorPacket) - { - // release packet descriptor - m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - } - - // release queue head - m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD)); - return Status; - } - - // - // create status descriptor - // - Status = CreateDescriptor(&StatusDescriptor); - if (!NT_SUCCESS(Status)) - { - // failed to create status transfer descriptor - DPRINT1("[EHCI] Failed to create status descriptor\n"); - - // release setup transfer descriptor - m_DmaManager->Release(SetupDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR)); - - if (m_DescriptorPacket) - { - // release packet descriptor - m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - } - - // release queue head - m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD)); - return Status; - } - - // - // now initialize the queue head - // - QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress(); - - ASSERT(m_EndpointDescriptor == NULL); - - // - // init setup descriptor - // - SetupDescriptor->Token.Bits.PIDCode = PID_CODE_SETUP_TOKEN; - SetupDescriptor->Token.Bits.TotalBytesToTransfer = sizeof(USB_DEFAULT_PIPE_SETUP_PACKET); - SetupDescriptor->Token.Bits.DataToggle = FALSE; - SetupDescriptor->BufferPointer[0] = m_DescriptorSetupPacket.LowPart; - SetupDescriptor->ExtendedBufferPointer[0] = m_DescriptorSetupPacket.HighPart; - InsertTailList(&QueueHead->TransferDescriptorListHead, &SetupDescriptor->DescriptorEntry); - - - // - // init status descriptor - // - StatusDescriptor->Token.Bits.TotalBytesToTransfer = 0; - StatusDescriptor->Token.Bits.DataToggle = TRUE; - StatusDescriptor->Token.Bits.InterruptOnComplete = TRUE; - - // - // is there data - // - if (m_TransferBufferLength) - { - Status = BuildTransferDescriptorChain(QueueHead, - MmGetMdlVirtualAddress(m_TransferBufferMDL), - m_TransferBufferLength, - InternalGetPidDirection(), - TRUE, - &FirstDescriptor, - &LastDescriptor, - NULL, - &DescriptorChainLength); - if (!NT_SUCCESS(Status)) - { - // failed to create descriptor chain - DPRINT1("[EHCI] Failed to create descriptor chain\n"); - - // release status transfer descriptor - m_DmaManager->Release(StatusDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR)); - - // release setup transfer descriptor - m_DmaManager->Release(SetupDescriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR)); - - if (m_DescriptorPacket) - { - // release packet descriptor - m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - } - - // release queue head - m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD)); - return Status; - } - - if (m_TransferBufferLength != DescriptorChainLength) - { - DPRINT1("DescriptorChainLength %x\n", DescriptorChainLength); - DPRINT1("m_TransferBufferLength %x\n", m_TransferBufferLength); - ASSERT(FALSE); - } - - // - // now link the descriptors - // - SetupDescriptor->NextPointer = FirstDescriptor->PhysicalAddr; - SetupDescriptor->AlternateNextPointer = FirstDescriptor->PhysicalAddr; - LastDescriptor->NextPointer = StatusDescriptor->PhysicalAddr; - LastDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr; - - - // - // pid code is flipped for ops with data stage - // - StatusDescriptor->Token.Bits.PIDCode = !InternalGetPidDirection(); - } - else - { - // - // direct link - // - SetupDescriptor->NextPointer = StatusDescriptor->PhysicalAddr; - SetupDescriptor->AlternateNextPointer = StatusDescriptor->PhysicalAddr; - - // - // retrieve result of operation - // - StatusDescriptor->Token.Bits.PIDCode = PID_CODE_IN_TOKEN; - } - - // - // insert status descriptor - // - InsertTailList(&QueueHead->TransferDescriptorListHead, &StatusDescriptor->DescriptorEntry); - - - // - // link transfer descriptors to queue head - // - QueueHead->NextPointer = SetupDescriptor->PhysicalAddr; - - // - // store result - // - *OutHead = QueueHead; - - // - // displays the current request - // - //DumpQueueHead(QueueHead); - - DPRINT("BuildControlTransferQueueHead done\n"); - // - // done - // - return STATUS_SUCCESS; -} - -VOID -CUSBRequest::DumpQueueHead( - IN PQUEUE_HEAD QueueHead) -{ - PLIST_ENTRY Entry; - PQUEUE_TRANSFER_DESCRIPTOR Descriptor; - ULONG Index = 0; - - DPRINT1("QueueHead %p Addr %x\n", QueueHead, QueueHead->PhysicalAddr); - DPRINT1("QueueHead AlternateNextPointer %x\n", QueueHead->AlternateNextPointer); - DPRINT1("QueueHead NextPointer %x\n", QueueHead->NextPointer); - - DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCharacteristics.ControlEndPointFlag); - DPRINT1("QueueHead DeviceAddress %x\n", QueueHead->EndPointCharacteristics.DeviceAddress); - DPRINT1("QueueHead EndPointNumber %x\n", QueueHead->EndPointCharacteristics.EndPointNumber); - DPRINT1("QueueHead EndPointSpeed %x\n", QueueHead->EndPointCharacteristics.EndPointSpeed); - DPRINT1("QueueHead HeadOfReclamation %x\n", QueueHead->EndPointCharacteristics.HeadOfReclamation); - DPRINT1("QueueHead InactiveOnNextTransaction %x\n", QueueHead->EndPointCharacteristics.InactiveOnNextTransaction); - DPRINT1("QueueHead MaximumPacketLength %x\n", QueueHead->EndPointCharacteristics.MaximumPacketLength); - DPRINT1("QueueHead NakCountReload %x\n", QueueHead->EndPointCharacteristics.NakCountReload); - DPRINT1("QueueHead QEDTDataToggleControl %x\n", QueueHead->EndPointCharacteristics.QEDTDataToggleControl); - DPRINT1("QueueHead HubAddr %x\n", QueueHead->EndPointCapabilities.HubAddr); - DPRINT1("QueueHead InterruptScheduleMask %x\n", QueueHead->EndPointCapabilities.InterruptScheduleMask); - DPRINT1("QueueHead NumberOfTransactionPerFrame %x\n", QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame); - DPRINT1("QueueHead PortNumber %x\n", QueueHead->EndPointCapabilities.PortNumber); - DPRINT1("QueueHead SplitCompletionMask %x\n", QueueHead->EndPointCapabilities.SplitCompletionMask); - - Entry = QueueHead->TransferDescriptorListHead.Flink; - while(Entry != &QueueHead->TransferDescriptorListHead) - { - // - // get transfer descriptor - // - Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry); - - DPRINT1("TransferDescriptor %lu Addr %x\n", Index, Descriptor->PhysicalAddr); - DPRINT1("TransferDescriptor %lu Next %x\n", Index, Descriptor->NextPointer); - DPRINT1("TransferDescriptor %lu AlternateNextPointer %x\n", Index, Descriptor->AlternateNextPointer); - DPRINT1("TransferDescriptor %lu Active %lu\n", Index, Descriptor->Token.Bits.Active); - DPRINT1("TransferDescriptor %lu BabbleDetected %lu\n", Index, Descriptor->Token.Bits.BabbleDetected); - DPRINT1("TransferDescriptor %lu CurrentPage %lu\n", Index, Descriptor->Token.Bits.CurrentPage); - DPRINT1("TransferDescriptor %lu DataBufferError %lu\n", Index, Descriptor->Token.Bits.DataBufferError); - DPRINT1("TransferDescriptor %lu DataToggle %lu\n", Index, Descriptor->Token.Bits.DataToggle); - DPRINT1("TransferDescriptor %lu ErrorCounter %lu\n", Index, Descriptor->Token.Bits.ErrorCounter); - DPRINT1("TransferDescriptor %lu Halted %lu\n", Index, Descriptor->Token.Bits.Halted); - DPRINT1("TransferDescriptor %lu InterruptOnComplete %x\n", Index, Descriptor->Token.Bits.InterruptOnComplete); - DPRINT1("TransferDescriptor %lu MissedMicroFrame %lu\n", Index, Descriptor->Token.Bits.MissedMicroFrame); - DPRINT1("TransferDescriptor %lu PIDCode %lu\n", Index, Descriptor->Token.Bits.PIDCode); - DPRINT1("TransferDescriptor %lu PingState %lu\n", Index, Descriptor->Token.Bits.PingState); - DPRINT1("TransferDescriptor %lu SplitTransactionState %lu\n", Index, Descriptor->Token.Bits.SplitTransactionState); - DPRINT1("TransferDescriptor %lu TotalBytesToTransfer %lu\n", Index, Descriptor->Token.Bits.TotalBytesToTransfer); - DPRINT1("TransferDescriptor %lu TransactionError %lu\n", Index, Descriptor->Token.Bits.TransactionError); - - DPRINT1("TransferDescriptor %lu Buffer Pointer 0 %x\n", Index, Descriptor->BufferPointer[0]); - DPRINT1("TransferDescriptor %lu Buffer Pointer 1 %x\n", Index, Descriptor->BufferPointer[1]); - DPRINT1("TransferDescriptor %lu Buffer Pointer 2 %x\n", Index, Descriptor->BufferPointer[2]); - DPRINT1("TransferDescriptor %lu Buffer Pointer 3 %x\n", Index, Descriptor->BufferPointer[3]); - DPRINT1("TransferDescriptor %lu Buffer Pointer 4 %x\n", Index, Descriptor->BufferPointer[4]); - Entry = Entry->Flink; - Index++; - } -} - - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::BuildBulkInterruptTransferQueueHead( - PQUEUE_HEAD * OutHead) -{ - NTSTATUS Status; - PQUEUE_HEAD QueueHead; - PVOID Base; - ULONG ChainDescriptorLength; - PQUEUE_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor; - - // - // Allocate the queue head - // - Status = CreateQueueHead(&QueueHead); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate queue head - // - DPRINT1("[EHCI] Failed to create queue head\n"); - return Status; - } - - // - // sanity checks - // - PC_ASSERT(QueueHead); - PC_ASSERT(m_TransferBufferLength); - - if (!m_Base) - { - // - // get virtual base of mdl - // - m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); - } - - // - // Increase the size of last transfer, 0 in case this is the first - // - Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted); - - PC_ASSERT(m_EndpointDescriptor); - PC_ASSERT(Base); - - // - // sanity check - // - ASSERT(m_EndpointDescriptor); - - // - // use 4 * PAGE_SIZE at max for each new request - // - ULONG MaxTransferLength = min(4 * PAGE_SIZE, m_TransferBufferLength - m_TransferBufferLengthCompleted); - - // - // build bulk transfer descriptor chain - // - Status = BuildTransferDescriptorChain(QueueHead, - Base, - MaxTransferLength, - InternalGetPidDirection(), - m_EndpointDescriptor->DataToggle, - &FirstDescriptor, - &LastDescriptor, - &m_EndpointDescriptor->DataToggle, - &ChainDescriptorLength); - if (!NT_SUCCESS(Status)) - { - // - // failed to build transfer descriptor chain - // - DPRINT1("[EHCI] Failed to create descriptor chain\n"); - m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD)); - return Status; - } - - // - // move to next offset - // - m_TransferBufferLengthCompleted += ChainDescriptorLength; - - // - // init queue head - // - QueueHead->EndPointCharacteristics.DeviceAddress = GetDeviceAddress(); - QueueHead->EndPointCharacteristics.EndPointNumber = m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F; - QueueHead->EndPointCharacteristics.MaximumPacketLength = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; - QueueHead->NextPointer = FirstDescriptor->PhysicalAddr; - QueueHead->CurrentLinkPointer = FirstDescriptor->PhysicalAddr; - QueueHead->AlternateNextPointer = TERMINATE_POINTER; - - ASSERT(QueueHead->EndPointCharacteristics.DeviceAddress); - ASSERT(QueueHead->EndPointCharacteristics.EndPointNumber); - ASSERT(QueueHead->EndPointCharacteristics.MaximumPacketLength); - ASSERT(QueueHead->NextPointer); - - // - // interrupt on last descriptor - // - LastDescriptor->Token.Bits.InterruptOnComplete = TRUE; - - // - // store result - // - *OutHead = QueueHead; - - // - // dump status - // - //DumpQueueHead(QueueHead); - - // - // done - // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::CreateDescriptor( - PQUEUE_TRANSFER_DESCRIPTOR *OutDescriptor) -{ - PQUEUE_TRANSFER_DESCRIPTOR Descriptor; - NTSTATUS Status; - PHYSICAL_ADDRESS TransferDescriptorPhysicalAddress; - - // - // allocate descriptor - // - Status = m_DmaManager->Allocate(sizeof(QUEUE_TRANSFER_DESCRIPTOR), (PVOID*)&Descriptor, &TransferDescriptorPhysicalAddress); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate transfer descriptor - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize transfer descriptor - // - Descriptor->NextPointer = TERMINATE_POINTER; - Descriptor->AlternateNextPointer = TERMINATE_POINTER; - Descriptor->Token.Bits.DataToggle = TRUE; - Descriptor->Token.Bits.ErrorCounter = 0x03; - Descriptor->Token.Bits.Active = TRUE; - Descriptor->PhysicalAddr = TransferDescriptorPhysicalAddress.LowPart; - - // - // store result - // - *OutDescriptor = Descriptor; - - // - // done - // - return Status; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::CreateQueueHead( - PQUEUE_HEAD *OutQueueHead) -{ - PQUEUE_HEAD QueueHead; - PHYSICAL_ADDRESS QueueHeadPhysicalAddress; - NTSTATUS Status; - - // - // allocate queue head - // - Status = m_DmaManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&QueueHead, &QueueHeadPhysicalAddress); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate queue head - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize queue head - // - QueueHead->HorizontalLinkPointer = TERMINATE_POINTER; - QueueHead->AlternateNextPointer = TERMINATE_POINTER; - QueueHead->NextPointer = TERMINATE_POINTER; - InitializeListHead(&QueueHead->TransferDescriptorListHead); - - // - // 1 for non high speed, 0 for high speed device - // - QueueHead->EndPointCharacteristics.ControlEndPointFlag = 0; - QueueHead->EndPointCharacteristics.HeadOfReclamation = FALSE; - QueueHead->EndPointCharacteristics.MaximumPacketLength = 64; - - // - // Set NakCountReload to max value possible - // - QueueHead->EndPointCharacteristics.NakCountReload = 0x3; - - // - // Get the Initial Data Toggle from the QEDT - // - QueueHead->EndPointCharacteristics.QEDTDataToggleControl = TRUE; - - // - // FIXME: check if High Speed Device - // - QueueHead->EndPointCharacteristics.EndPointSpeed = QH_ENDPOINT_HIGHSPEED; - QueueHead->EndPointCapabilities.NumberOfTransactionPerFrame = 0x01; - QueueHead->Token.DWord = 0; - QueueHead->Token.Bits.InterruptOnComplete = FALSE; - - // - // store address - // - QueueHead->PhysicalAddr = QueueHeadPhysicalAddress.LowPart; - - // - // output queue head - // - *OutQueueHead = QueueHead; - - // - // done - // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -UCHAR -STDMETHODCALLTYPE -CUSBRequest::GetDeviceAddress() -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - PUSBDEVICE UsbDevice; - - // - // check if there is an irp provided - // - if (!m_Irp) - { - // - // used provided address - // - return m_DeviceAddress; - } - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // get contained urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // check if there is a pipe handle provided - // - if (Urb->UrbHeader.UsbdDeviceHandle) - { - // - // there is a device handle provided - // - UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle; - - // - // return device address - // - return UsbDevice->GetDeviceAddress(); - } - - // - // no device handle provided, it is the host root bus - // - return 0; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::BuildSetupPacket() -{ - NTSTATUS Status; - - // - // allocate common buffer setup packet - // - Status = m_DmaManager->Allocate(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), (PVOID*)&m_DescriptorPacket, &m_DescriptorSetupPacket); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - return Status; - } - - if (m_SetupPacket) - { - // - // copy setup packet - // - RtlCopyMemory(m_DescriptorPacket, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - } - else - { - // - // build setup packet from urb - // - Status = BuildSetupPacketFromURB(); - } - - // - // done - // - return Status; -} - - -NTSTATUS -CUSBRequest::BuildSetupPacketFromURB() -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - NTSTATUS Status = STATUS_NOT_IMPLEMENTED; - - // - // sanity checks - // - PC_ASSERT(m_Irp); - PC_ASSERT(m_DescriptorPacket); - - // - // get stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // zero descriptor packet - // - RtlZeroMemory(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - - - switch (Urb->UrbHeader.Function) - { - /* CLEAR FEATURE */ - case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE: - case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE: - case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT: - UNIMPLEMENTED; - break; - - /* GET CONFIG */ - case URB_FUNCTION_GET_CONFIGURATION: - m_DescriptorPacket->bRequest = USB_REQUEST_GET_CONFIGURATION; - m_DescriptorPacket->bmRequestType.B = 0x80; - m_DescriptorPacket->wLength = 1; - break; - - /* GET DESCRIPTOR */ - case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: - m_DescriptorPacket->bRequest = USB_REQUEST_GET_DESCRIPTOR; - m_DescriptorPacket->wValue.LowByte = Urb->UrbControlDescriptorRequest.Index; - m_DescriptorPacket->wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType; - m_DescriptorPacket->wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId; - m_DescriptorPacket->wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength; - m_DescriptorPacket->bmRequestType.B = 0x80; - break; - - /* GET INTERFACE */ - case URB_FUNCTION_GET_INTERFACE: - m_DescriptorPacket->bRequest = USB_REQUEST_GET_CONFIGURATION; - m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index; - m_DescriptorPacket->bmRequestType.B = 0x80; - m_DescriptorPacket->wLength = 1; - break; - - /* GET STATUS */ - case URB_FUNCTION_GET_STATUS_FROM_DEVICE: - m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS; - ASSERT(Urb->UrbControlGetStatusRequest.Index == 0); - m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index; - m_DescriptorPacket->bmRequestType.B = 0x80; - m_DescriptorPacket->wLength = 2; - break; - - case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: - m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS; - ASSERT(Urb->UrbControlGetStatusRequest.Index != 0); - m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index; - m_DescriptorPacket->bmRequestType.B = 0x81; - m_DescriptorPacket->wLength = 2; - break; - - case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: - m_DescriptorPacket->bRequest = USB_REQUEST_GET_STATUS; - ASSERT(Urb->UrbControlGetStatusRequest.Index != 0); - m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index; - m_DescriptorPacket->bmRequestType.B = 0x82; - m_DescriptorPacket->wLength = 2; - break; - - /* SET ADDRESS */ - - /* SET CONFIG */ - case URB_FUNCTION_SELECT_CONFIGURATION: - m_DescriptorPacket->bRequest = USB_REQUEST_SET_CONFIGURATION; - m_DescriptorPacket->wValue.W = Urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue; - m_DescriptorPacket->wIndex.W = 0; - m_DescriptorPacket->wLength = 0; - m_DescriptorPacket->bmRequestType.B = 0x00; - break; - - /* SET DESCRIPTOR */ - case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE: - case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE: - case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT: - UNIMPLEMENTED; - break; - - /* SET FEATURE */ - case URB_FUNCTION_SET_FEATURE_TO_DEVICE: - m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE; - ASSERT(Urb->UrbControlGetStatusRequest.Index == 0); - m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index; - m_DescriptorPacket->bmRequestType.B = 0x80; - break; - - case URB_FUNCTION_SET_FEATURE_TO_INTERFACE: - m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE; - ASSERT(Urb->UrbControlGetStatusRequest.Index == 0); - m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index; - m_DescriptorPacket->bmRequestType.B = 0x81; - break; - - case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT: - m_DescriptorPacket->bRequest = USB_REQUEST_SET_FEATURE; - ASSERT(Urb->UrbControlGetStatusRequest.Index == 0); - m_DescriptorPacket->wIndex.W = Urb->UrbControlGetStatusRequest.Index; - m_DescriptorPacket->bmRequestType.B = 0x82; - break; - - /* SET INTERFACE*/ - case URB_FUNCTION_SELECT_INTERFACE: - m_DescriptorPacket->bRequest = USB_REQUEST_SET_INTERFACE; - m_DescriptorPacket->wValue.W = Urb->UrbSelectInterface.Interface.AlternateSetting; - m_DescriptorPacket->wIndex.W = Urb->UrbSelectInterface.Interface.InterfaceNumber; - m_DescriptorPacket->wLength = 0; - m_DescriptorPacket->bmRequestType.B = 0x01; - break; - - /* SYNC FRAME */ - case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: - UNIMPLEMENTED; - break; - default: - UNIMPLEMENTED; - break; - } - - return Status; -} - -//---------------------------------------------------------------------------------------- -VOID -STDMETHODCALLTYPE -CUSBRequest::GetResultStatus( - OUT OPTIONAL NTSTATUS * NtStatusCode, - OUT OPTIONAL PULONG UrbStatusCode) -{ - // - // sanity check - // - PC_ASSERT(m_CompletionEvent); - - // - // wait for the operation to complete - // - KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL); - - // - // copy status - // - if (NtStatusCode) - { - *NtStatusCode = m_NtStatusCode; - } - - // - // copy urb status - // - if (UrbStatusCode) - { - *UrbStatusCode = m_UrbStatusCode; - } - -} - -//----------------------------------------------------------------------------------------- -BOOLEAN -STDMETHODCALLTYPE -CUSBRequest::ShouldReleaseRequestAfterCompletion() -{ - if (m_Irp) - { - // - // the request is completed, release it - // - return TRUE; - } - else - { - // - // created with an setup packet, don't release - // - return FALSE; - } -} - -//----------------------------------------------------------------------------------------- -VOID -STDMETHODCALLTYPE -CUSBRequest::FreeQueueHead( - IN struct _QUEUE_HEAD * QueueHead) -{ - PLIST_ENTRY Entry; - PQUEUE_TRANSFER_DESCRIPTOR Descriptor; - - // - // sanity checks - // - ASSERT(m_DmaManager); - ASSERT(QueueHead); - ASSERT(!IsListEmpty(&QueueHead->TransferDescriptorListHead)); - - do - { - // - // get transfer descriptors - // - Entry = RemoveHeadList(&QueueHead->TransferDescriptorListHead); - ASSERT(Entry); - - // - // obtain descriptor from entry - // - Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry); - ASSERT(Descriptor); - - // - // add transfer count - // - m_TotalBytesTransferred += (Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer); - DPRINT("TotalBytes Transferred in Descriptor %p Phys Addr %x TotalBytesSoftware %lu Length %lu\n", Descriptor, Descriptor->PhysicalAddr, Descriptor->TotalBytesToTransfer, Descriptor->TotalBytesToTransfer - Descriptor->Token.Bits.TotalBytesToTransfer); - - // - // release transfer descriptors - // - m_DmaManager->Release(Descriptor, sizeof(QUEUE_TRANSFER_DESCRIPTOR)); - - }while(!IsListEmpty(&QueueHead->TransferDescriptorListHead)); - - if (m_DescriptorPacket) - { - // - // release packet descriptor - // - m_DmaManager->Release(m_DescriptorPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - } - - // - // release queue head - // - m_DmaManager->Release(QueueHead, sizeof(QUEUE_HEAD)); - - // - // nullify pointers - // - m_QueueHead = 0; - m_DescriptorPacket = 0; -} - -//----------------------------------------------------------------------------------------- -BOOLEAN -STDMETHODCALLTYPE -CUSBRequest::IsQueueHeadComplete( - struct _QUEUE_HEAD * QueueHead) -{ - PLIST_ENTRY Entry; - PQUEUE_TRANSFER_DESCRIPTOR Descriptor; - - // - // first check - is the queue head currently active - // - if (QueueHead->Token.Bits.Active) - { - // - // queue head is active (currently processed) - // - return FALSE; - } - - if (QueueHead->Token.Bits.Halted) - { - // - // error occured - // - DPRINT1("Found halted queue head %p\n", QueueHead); - DumpQueueHead(QueueHead); - //ASSERT(FALSE); - return TRUE; - } - - // - // loop list and see if there are any active descriptors - // - Entry = QueueHead->TransferDescriptorListHead.Flink; - while(Entry != &QueueHead->TransferDescriptorListHead) - { - // - // obtain descriptor from entry - // - Descriptor = (PQUEUE_TRANSFER_DESCRIPTOR)CONTAINING_RECORD(Entry, QUEUE_TRANSFER_DESCRIPTOR, DescriptorEntry); - ASSERT(Descriptor); - if (Descriptor->Token.Bits.Active) - { - // - // descriptor is still active - // - return FALSE; - } - - // - // move to next entry - // - Entry = Entry->Flink; - } - - DPRINT("QueueHead %p Addr %x is complete\n", QueueHead, QueueHead->PhysicalAddr); - - // - // no active descriptors found, queue head is finished - // - return TRUE; -} - -//----------------------------------------------------------------------------------------- -ULONG -CUSBRequest::InternalCalculateTransferLength() -{ - if (!m_Irp) - { - // - // FIXME: get length for control request - // - return m_TransferBufferLength; - } - - // - // sanity check - // - ASSERT(m_EndpointDescriptor); - if (USB_ENDPOINT_DIRECTION_IN(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress)) - { - // - // bulk in request - // HACK: Properly determine transfer length - // - return m_TransferBufferLength;//m_TotalBytesTransferred; - } - - // - // bulk out transfer - // - return m_TransferBufferLength; -} - -USB_DEVICE_SPEED -CUSBRequest::GetSpeed() -{ - return m_Speed; -} - -UCHAR -CUSBRequest::GetInterval() -{ - if (!m_EndpointDescriptor) - return 0; - - return m_EndpointDescriptor->EndPointDescriptor.bInterval; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -NTAPI -InternalCreateUSBRequest( - PUSBREQUEST *OutRequest) -{ - PUSBREQUEST This; - - // - // allocate requests - // - This = new(NonPagedPool, TAG_USBEHCI) CUSBRequest(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutRequest = (PUSBREQUEST)This; - - // - // done - // - return STATUS_SUCCESS; -} diff --git a/drivers/usb/usbehci/usbehci.cpp b/drivers/usb/usbehci/usbehci.cpp deleted file mode 100644 index 41e630fd126..00000000000 --- a/drivers/usb/usbehci/usbehci.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbehci/usbehci.cpp - * PURPOSE: USB EHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbehci.h" - -#define NDEBUG -#include - -extern -"C" -NTSTATUS -NTAPI -DriverEntry( - PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath) -{ - - /* initialize driver object */ - DriverObject->DriverExtension->AddDevice = USBLIB_AddDevice; - - DriverObject->MajorFunction[IRP_MJ_CREATE] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_POWER] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_PNP] = USBLIB_Dispatch; - return STATUS_SUCCESS; -} - -extern "C" { - void - __cxa_pure_virtual() - { - // put error handling here - - DbgBreakPoint(); - - } -} - -extern "C" { - void free(void * ptr) - { - ExFreePool(ptr); - } -} - - diff --git a/drivers/usb/usbehci/usbehci.h b/drivers/usb/usbehci/usbehci.h deleted file mode 100644 index 171d39bb82e..00000000000 --- a/drivers/usb/usbehci/usbehci.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef USBEHCI_H__ -#define USBEHCI_H__ - -#include - -#include "hardware.h" -#include "interfaces.h" - -// -// tag for allocations -// -#define TAG_USBEHCI 'ICHE' - -// -// assert for c++ - taken from portcls -// -#define PC_ASSERT(exp) \ - (VOID)((!(exp)) ? \ - RtlAssert((PVOID) #exp, (PVOID)__FILE__, __LINE__, NULL ), FALSE : TRUE) - -// -// hardware.cpp -// -NTSTATUS NTAPI CreateUSBHardware(PUSBHARDWAREDEVICE *OutHardware); - -// -// usb_queue.cpp -// -NTSTATUS NTAPI CreateUSBQueue(PUSBQUEUE *OutUsbQueue); - -// -// usb_request.cpp -// -NTSTATUS NTAPI InternalCreateUSBRequest(PUSBREQUEST *OutRequest); - -#endif /* USBEHCI_H__ */ diff --git a/drivers/usb/usbehci/usbehci.rc b/drivers/usb/usbehci/usbehci.rc deleted file mode 100644 index 508f8ff4bb4..00000000000 --- a/drivers/usb/usbehci/usbehci.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "USBEHCI Driver API" -#define REACTOS_STR_INTERNAL_NAME "usbehci" -#define REACTOS_STR_ORIGINAL_FILENAME "usbehci.sys" -#include diff --git a/drivers/usb/usbhub/CMakeLists.txt b/drivers/usb/usbhub/CMakeLists.txt deleted file mode 100644 index d7d060c8588..00000000000 --- a/drivers/usb/usbhub/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ - -add_definitions(-DDEBUG_MODE) -add_definitions(-DNTDDI_VERSION=0x05020400) -include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include) - -list(APPEND SOURCE - fdo.c - hub_fdo.c - misc.c - pdo.c - usbhub.c - usbhub.h) - -add_library(usbhub MODULE - ${SOURCE} - guid.c - usbhub.rc) - -target_link_libraries(usbhub ${PSEH_LIB}) -set_module_type(usbhub kernelmodedriver) -add_importlibs(usbhub ntoskrnl hal usbd) -add_pch(usbhub usbhub.h SOURCE) -add_cd_file(TARGET usbhub DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/usb/usbhub/fdo.c b/drivers/usb/usbhub/fdo.c deleted file mode 100644 index 13b2081a63e..00000000000 --- a/drivers/usb/usbhub/fdo.c +++ /dev/null @@ -1,2487 +0,0 @@ -/* - * 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) - */ - -#include "usbhub.h" - -#include - -#define NDEBUG -#include - -NTSTATUS -QueryStatusChangeEndpoint( - IN PDEVICE_OBJECT DeviceObject); - -NTSTATUS -CreateUsbChildDeviceObject( - IN PDEVICE_OBJECT UsbHubDeviceObject, - IN LONG PortId, - OUT PDEVICE_OBJECT *UsbChildDeviceObject, - IN ULONG PortStatus); - -NTSTATUS -DestroyUsbChildDeviceObject( - IN PDEVICE_OBJECT UsbHubDeviceObject, - IN LONG PortId); - - -NTSTATUS -GetPortStatusAndChange( - IN PDEVICE_OBJECT RootHubDeviceObject, - IN ULONG PortId, - OUT PPORT_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)); - - // - // Initialize 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); - - // FIXME: support usb hubs - Urb->UrbHeader.UsbdDeviceHandle = NULL; - - - // - // Query the Root Hub - // - Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); - - // - // Free URB - // - ExFreePool(Urb); - - return Status; -} - -NTSTATUS -SetPortFeature( - IN PDEVICE_OBJECT RootHubDeviceObject, - IN ULONG PortId, - IN 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)); - - // - // Initialize 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); - - // FIXME support usbhubs - Urb->UrbHeader.UsbdDeviceHandle = NULL; - - // - // Query the Root Hub - // - Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); - - // - // Free URB - // - ExFreePool(Urb); - - return Status; -} - -NTSTATUS -ClearPortFeature( - IN PDEVICE_OBJECT RootHubDeviceObject, - IN ULONG PortId, - IN 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)); - - // - // Initialize 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); - - // FIXME: support usb hubs - Urb->UrbHeader.UsbdDeviceHandle = NULL; - - // - // Query the Root Hub - // - Status = SubmitRequestToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Urb, NULL); - - // - // Free URB - // - ExFreePool(Urb); - - return Status; -} - -VOID NTAPI -DeviceStatusChangeThread( - IN PVOID Context) -{ - NTSTATUS Status; - PDEVICE_OBJECT DeviceObject, RootHubDeviceObject; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PWORK_ITEM_DATA WorkItemData; - PORT_STATUS_CHANGE PortStatus; - ULONG PortId; - BOOLEAN SignalResetComplete = FALSE; - - DPRINT("Entered DeviceStatusChangeThread, Context %x\n", Context); - - WorkItemData = (PWORK_ITEM_DATA)Context; - DeviceObject = (PDEVICE_OBJECT)WorkItemData->Context; - HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; - // - // Loop all ports - // - for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++) - { - // - // Get Port Status - // - Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status); - // FIXME: Do we really want to halt further SCE requests? - return; - } - - DPRINT("Port %d Status %x\n", PortId, PortStatus.Status); - DPRINT("Port %d Change %x\n", PortId, PortStatus.Change); - - - // - // Check for new device connection - // - if (PortStatus.Change & USB_PORT_STATUS_CONNECT) - { - // - // Clear Port Connect - // - Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to clear connection change for port %d\n", PortId); - continue; - } - - // - // Is this a connect or disconnect? - // - if (!(PortStatus.Status & USB_PORT_STATUS_CONNECT)) - { - DPRINT1("Device disconnected from port %d\n", PortId); - - Status = DestroyUsbChildDeviceObject(DeviceObject, PortId); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to delete child device object after disconnect\n"); - continue; - } - } - else - { - DPRINT1("Device connected from port %d\n", PortId); - - // No SCE completion done for clearing C_PORT_CONNECT - - // - // Reset Port - // - Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to reset port %d\n", PortId); - SignalResetComplete = TRUE; - continue; - } - } - } - else if (PortStatus.Change & USB_PORT_STATUS_ENABLE) - { - // - // Clear Enable - // - Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_ENABLE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to clear enable change on port %d\n", PortId); - continue; - } - } - else if (PortStatus.Change & USB_PORT_STATUS_RESET) - { - // - // Request event signalling later - // - SignalResetComplete = TRUE; - - // - // Clear Reset - // - Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_RESET); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to clear reset change on port %d\n", PortId); - continue; - } - - // - // Get Port Status - // - Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get port status for port %d, Status %x\n", PortId, Status); - // FIXME: Do we really want to halt further SCE requests? - return; - } - - DPRINT("Port %d Status %x\n", PortId, PortStatus.Status); - DPRINT("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"); - continue; - } - - // - // 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 - // - if (!(PortStatus.Status & (USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE))) - { - DPRINT1("Usb Device is not connected and enabled!\n"); - // - // Attempt another reset - // - Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_RESET); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to reset port %d\n", PortId); - } - continue; - } - - // - // This is a new device - // - Status = CreateUsbChildDeviceObject(DeviceObject, PortId, NULL, PortStatus.Status); - } - } - - ExFreePool(WorkItemData); - - // - // Send another SCE Request - // - DPRINT("Sending another SCE!\n"); - QueryStatusChangeEndpoint(DeviceObject); - - // - // Check if a reset event was satisfied - // - if (SignalResetComplete) - { - // - // Signal anyone waiting on it - // - KeSetEvent(&HubDeviceExtension->ResetComplete, IO_NO_INCREMENT, FALSE); - } -} - -NTSTATUS -NTAPI -StatusChangeEndpointCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context) -{ - PDEVICE_OBJECT RealDeviceObject; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PWORK_ITEM_DATA WorkItemData; - - RealDeviceObject = (PDEVICE_OBJECT)Context; - HubDeviceExtension = (PHUB_DEVICE_EXTENSION)RealDeviceObject->DeviceExtension; - - // - // NOTE: USBPORT frees this IRP - // - DPRINT("Received Irp %x, HubDeviceExtension->PendingSCEIrp %x\n", Irp, HubDeviceExtension->PendingSCEIrp); - //IoFreeIrp(Irp); - - // - // Create and initialize work item data - // - WorkItemData = ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_ITEM_DATA), USB_HUB_TAG); - if (!WorkItemData) - { - DPRINT1("Failed to allocate memory!n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - WorkItemData->Context = RealDeviceObject; - - DPRINT("Queuing work item\n"); - - // - // Queue the work item to handle initializing the device - // - ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData); - ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue); - - // - // Return more processing required so the IO Manger doesn’t try to mess with IRP just freed - // - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -QueryStatusChangeEndpoint( - IN PDEVICE_OBJECT DeviceObject) -{ - PDEVICE_OBJECT RootHubDeviceObject; - PIO_STACK_LOCATION Stack; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PURB PendingSCEUrb; - - HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; - - // - // Allocate a URB - // - PendingSCEUrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(URB), USB_HUB_TAG); - - // - // Initialize URB for Status Change Endpoint request - // - UsbBuildInterruptOrBulkTransferRequest(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 - PendingSCEUrb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle; - - // - // Allocate an Irp - // - HubDeviceExtension->PendingSCEIrp = ExAllocatePoolWithTag(NonPagedPool, - IoSizeOfIrp(RootHubDeviceObject->StackSize), - USB_HUB_TAG); -/* - HubDeviceExtension->PendingSCEIrp = IoAllocateIrp(RootHubDeviceObject->StackSize, - FALSE); -*/ - DPRINT("Allocated IRP %x\n", HubDeviceExtension->PendingSCEIrp); - - if (!HubDeviceExtension->PendingSCEIrp) - { - DPRINT1("USBHUB: Failed to allocate IRP for SCE request!\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Initialize the IRP - // - IoInitializeIrp(HubDeviceExtension->PendingSCEIrp, - IoSizeOfIrp(RootHubDeviceObject->StackSize), - RootHubDeviceObject->StackSize); - - 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 = DeviceObject; - Stack->Parameters.Others.Argument1 = 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, - StatusChangeEndpointCompletion, - DeviceObject, - TRUE, - TRUE, - TRUE); - - // - // Send to RootHub - // - DPRINT("DeviceObject is %x\n", DeviceObject); - DPRINT("Iocalldriver %x with irp %x\n", RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp); - IoCallDriver(RootHubDeviceObject, HubDeviceExtension->PendingSCEIrp); - - 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; - - // - // Initialize the status block before sending the IRP - // - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - - Status = IoCallDriver(DeviceObject, Irp); - - if (Status == STATUS_PENDING) - { - DPRINT("Operation pending\n"); - KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); - Status = IoStatus.Status; - } - - return Status; -} - -NTSTATUS -GetUsbDeviceDescriptor( - IN PDEVICE_OBJECT ChildDeviceObject, - IN UCHAR DescriptorType, - IN UCHAR Index, - IN USHORT LangId, - OUT PVOID TransferBuffer, - IN ULONG TransferBufferLength) -{ - NTSTATUS Status; - PDEVICE_OBJECT RootHubDeviceObject; - PURB Urb; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; - - // - // Get the Hubs Device Extension - // - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension; - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) ChildDeviceExtension->ParentDeviceObject->DeviceExtension; - RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; - - // - // 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)); - - // - // Initialize URB for getting device descriptor - // - UsbBuildGetDescriptorRequest(Urb, - sizeof(Urb->UrbControlDescriptorRequest), - DescriptorType, - Index, - LangId, - TransferBuffer, - NULL, - TransferBufferLength, - NULL); - - // - // Set the device handle - // - Urb->UrbHeader.UsbdDeviceHandle = (PVOID)ChildDeviceExtension->UsbDeviceHandle; - - // - // Query the Root Hub - // - Status = SubmitRequestToRootHub(RootHubDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - Urb, - NULL); - - return Status; -} - -NTSTATUS -GetUsbStringDescriptor( - IN PDEVICE_OBJECT ChildDeviceObject, - IN UCHAR Index, - IN USHORT LangId, - OUT PVOID *TransferBuffer, - OUT USHORT *Size) -{ - NTSTATUS Status; - PUSB_STRING_DESCRIPTOR StringDesc = NULL; - ULONG SizeNeeded; - LPWSTR Buffer; - - StringDesc = ExAllocatePoolWithTag(NonPagedPool, - sizeof(USB_STRING_DESCRIPTOR), - USB_HUB_TAG); - if (!StringDesc) - { - DPRINT1("Failed to allocate buffer for string!\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Get the index string descriptor length - // FIXME: Implement LangIds - // - Status = GetUsbDeviceDescriptor(ChildDeviceObject, - USB_STRING_DESCRIPTOR_TYPE, - Index, - 0x0409, - StringDesc, - sizeof(USB_STRING_DESCRIPTOR)); - if (!NT_SUCCESS(Status)) - { - DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status); - ExFreePool(StringDesc); - return Status; - } - DPRINT1("StringDesc->bLength %d\n", StringDesc->bLength); - - // - // Did we get something more than the length of the first two fields of structure? - // - if (StringDesc->bLength == 2) - { - DPRINT1("USB Device Error!\n"); - ExFreePool(StringDesc); - return STATUS_DEVICE_DATA_ERROR; - } - SizeNeeded = StringDesc->bLength + sizeof(WCHAR); - - // - // Free String - // - ExFreePool(StringDesc); - - // - // Recreate with appropriate size - // - StringDesc = ExAllocatePoolWithTag(NonPagedPool, - SizeNeeded, - USB_HUB_TAG); - if (!StringDesc) - { - DPRINT1("Failed to allocate buffer for string!\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory(StringDesc, SizeNeeded); - - // - // Get the string - // - Status = GetUsbDeviceDescriptor(ChildDeviceObject, - USB_STRING_DESCRIPTOR_TYPE, - Index, - 0x0409, - StringDesc, - SizeNeeded); - if (!NT_SUCCESS(Status)) - { - DPRINT1("GetUsbDeviceDescriptor failed with status %x\n", Status); - ExFreePool(StringDesc); - return Status; - } - - // - // Allocate Buffer to return - // - Buffer = ExAllocatePoolWithTag(NonPagedPool, - SizeNeeded, - USB_HUB_TAG); - if (!Buffer) - { - DPRINT1("Failed to allocate buffer for string!\n"); - ExFreePool(StringDesc); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlZeroMemory(Buffer, SizeNeeded); - - // - // Copy the string to destination - // - RtlCopyMemory(Buffer, StringDesc->bString, SizeNeeded - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)); - *Size = SizeNeeded; - *TransferBuffer = Buffer; - - ExFreePool(StringDesc); - - return STATUS_SUCCESS; -} - -ULONG -IsCompositeDevice( - IN PUSB_DEVICE_DESCRIPTOR DeviceDescriptor, - IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) -{ - if (DeviceDescriptor->bNumConfigurations != 1) - { - // - // composite device must have only one configuration - // - DPRINT1("IsCompositeDevice bNumConfigurations %x\n", DeviceDescriptor->bNumConfigurations); - return FALSE; - } - - if (ConfigurationDescriptor->bNumInterfaces < 2) - { - // - // composite device must have multiple interfaces - // - DPRINT1("IsCompositeDevice bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces); - return FALSE; - } - - if (DeviceDescriptor->bDeviceClass == 0) - { - // - // composite device - // - ASSERT(DeviceDescriptor->bDeviceSubClass == 0); - ASSERT(DeviceDescriptor->bDeviceProtocol == 0); - DPRINT1("IsCompositeDevice: TRUE\n"); - return TRUE; - } - - if (DeviceDescriptor->bDeviceClass == 0xEF && - DeviceDescriptor->bDeviceSubClass == 0x02 && - DeviceDescriptor->bDeviceProtocol == 0x01) - { - // - // USB-IF association descriptor - // - DPRINT1("IsCompositeDevice: TRUE\n"); - return TRUE; - } - - DPRINT1("DeviceDescriptor bDeviceClass %x bDeviceSubClass %x bDeviceProtocol %x\n", DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol); - - // - // not a composite device - // - return FALSE; -} - -NTSTATUS -CreateDeviceIds( - PDEVICE_OBJECT UsbChildDeviceObject) -{ - NTSTATUS Status = STATUS_SUCCESS; - ULONG Index = 0; - LPWSTR DeviceString; - WCHAR Buffer[200]; - PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; - PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; - PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - - // - // get child device extension - // - UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)UsbChildDeviceObject->DeviceExtension; - - // get hub device extension - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbChildExtension->ParentDeviceObject->DeviceExtension; - - // - // get device descriptor - // - DeviceDescriptor = &UsbChildExtension->DeviceDesc; - - // - // get configuration descriptor - // - ConfigurationDescriptor = UsbChildExtension->FullConfigDesc; - - // - // use first interface descriptor available - // - InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, 0, -1, -1, -1, -1); - if (InterfaceDescriptor == NULL) - { - DPRINT1("Error USBD_ParseConfigurationDescriptorEx failed to parse interface descriptor\n"); - return STATUS_INVALID_PARAMETER; - } - - ASSERT(InterfaceDescriptor); - - // - // Construct the CompatibleIds - // - if (IsCompositeDevice(DeviceDescriptor, ConfigurationDescriptor)) - { - // - // sanity checks - // - ASSERT(DeviceDescriptor->bNumConfigurations == 1); - ASSERT(ConfigurationDescriptor->bNumInterfaces > 1); - Index += swprintf(&Buffer[Index], - L"USB\\DevClass_%02x&SubClass_%02x&Prot_%02x", - DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1; - Index += swprintf(&Buffer[Index], - L"USB\\DevClass_%02x&SubClass_%02x", - DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1; - Index += swprintf(&Buffer[Index], - L"USB\\DevClass_%02x", - DeviceDescriptor->bDeviceClass) + 1; - Index += swprintf(&Buffer[Index], - L"USB\\COMPOSITE") + 1; - } - else - { - // - // FIXME: support multiple configurations - // - ASSERT(DeviceDescriptor->bNumConfigurations == 1); - - if (DeviceDescriptor->bDeviceClass == 0) - { - Index += swprintf(&Buffer[Index], - L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", - InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass, InterfaceDescriptor->bInterfaceProtocol) + 1; - Index += swprintf(&Buffer[Index], - L"USB\\Class_%02x&SubClass_%02x", - InterfaceDescriptor->bInterfaceClass, InterfaceDescriptor->bInterfaceSubClass) + 1; - Index += swprintf(&Buffer[Index], - L"USB\\Class_%02x", - InterfaceDescriptor->bInterfaceClass) + 1; - } - else - { - Index += swprintf(&Buffer[Index], - L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", - DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass, DeviceDescriptor->bDeviceProtocol) + 1; - Index += swprintf(&Buffer[Index], - L"USB\\Class_%02x&SubClass_%02x", - DeviceDescriptor->bDeviceClass, DeviceDescriptor->bDeviceSubClass) + 1; - Index += swprintf(&Buffer[Index], - L"USB\\Class_%02x", - DeviceDescriptor->bDeviceClass) + 1; - } - } - - // - // now allocate the buffer - // - DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR)); - if (!DeviceString) - { - // - // no memory - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // copy buffer - // - RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR)); - DeviceString[Index] = UNICODE_NULL; - UsbChildExtension->usCompatibleIds.Buffer = DeviceString; - UsbChildExtension->usCompatibleIds.Length = Index * sizeof(WCHAR); - UsbChildExtension->usCompatibleIds.MaximumLength = (Index + 1) * sizeof(WCHAR); - DPRINT("usCompatibleIds %wZ\n", &UsbChildExtension->usCompatibleIds); - - // - // Construct DeviceId string - // - Index = swprintf(Buffer, L"USB\\Vid_%04x&Pid_%04x", UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1; - - // - // now allocate the buffer - // - DeviceString = ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR)); - if (!DeviceString) - { - // - // no memory - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // copy buffer - // - RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR)); - UsbChildExtension->usDeviceId.Buffer = DeviceString; - UsbChildExtension->usDeviceId.Length = (Index-1) * sizeof(WCHAR); - UsbChildExtension->usDeviceId.MaximumLength = Index * sizeof(WCHAR); - DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usDeviceId); - - // - // Construct HardwareIds - // - Index = 0; - Index += swprintf(&Buffer[Index], - L"USB\\Vid_%04x&Pid_%04x&Rev_%04x", - UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct, UsbChildExtension->DeviceDesc.bcdDevice) + 1; - Index += swprintf(&Buffer[Index], - L"USB\\Vid_%04x&Pid_%04x", - UsbChildExtension->DeviceDesc.idVendor, UsbChildExtension->DeviceDesc.idProduct) + 1; - - // - // now allocate the buffer - // - DeviceString = ExAllocatePool(NonPagedPool, (Index + 1) * sizeof(WCHAR)); - if (!DeviceString) - { - // - // no memory - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // copy buffer - // - RtlCopyMemory(DeviceString, Buffer, Index * sizeof(WCHAR)); - DeviceString[Index] = UNICODE_NULL; - UsbChildExtension->usHardwareIds.Buffer = DeviceString; - UsbChildExtension->usHardwareIds.Length = (Index + 1) * sizeof(WCHAR); - UsbChildExtension->usHardwareIds.MaximumLength = (Index + 1) * sizeof(WCHAR); - DPRINT("usHardWareIds %wZ\n", &UsbChildExtension->usHardwareIds); - - // - // FIXME: Handle Lang ids - // - - // - // Get the product string if obe provided - // - if (UsbChildExtension->DeviceDesc.iProduct) - { - Status = GetUsbStringDescriptor(UsbChildDeviceObject, - UsbChildExtension->DeviceDesc.iProduct, - 0, - (PVOID*)&UsbChildExtension->usTextDescription.Buffer, - &UsbChildExtension->usTextDescription.Length); - if (!NT_SUCCESS(Status)) - { - DPRINT1("USBHUB: GetUsbStringDescriptor failed with status %x\n", Status); - RtlInitUnicodeString(&UsbChildExtension->usTextDescription, L"USB Device"); // FIXME NON-NLS - } - else - { - UsbChildExtension->usTextDescription.MaximumLength = UsbChildExtension->usTextDescription.Length; - DPRINT("Usb TextDescription %wZ\n", &UsbChildExtension->usTextDescription); - } - } - - // - // Get the Serial Number string if obe provided - // - if (UsbChildExtension->DeviceDesc.iSerialNumber) - { - LPWSTR SerialBuffer = NULL; - - Status = GetUsbStringDescriptor(UsbChildDeviceObject, - UsbChildExtension->DeviceDesc.iSerialNumber, - 0, - (PVOID*)&SerialBuffer, - &UsbChildExtension->usInstanceId.Length); - if (NT_SUCCESS(Status)) - { - // construct instance id buffer - Index = swprintf(Buffer, L"%04d&%s", HubDeviceExtension->InstanceCount, SerialBuffer) + 1; - - ExFreePool(SerialBuffer); - - UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR)); - if (UsbChildExtension->usInstanceId.Buffer == NULL) - { - DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR)); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // copy instance id - // - RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR)); - UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR); - - DPRINT("Usb InstanceId %wZ InstanceCount %x\n", &UsbChildExtension->usInstanceId, HubDeviceExtension->InstanceCount); - return Status; - } - } - - // - // the device did not provide a serial number, or failed to retrieve the serial number - // lets create a pseudo instance id - // - Index = swprintf(Buffer, L"%04d&%04d", HubDeviceExtension->InstanceCount, UsbChildExtension->PortNumber) + 1; - UsbChildExtension->usInstanceId.Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, Index * sizeof(WCHAR)); - if (UsbChildExtension->usInstanceId.Buffer == NULL) - { - DPRINT1("Error: failed to allocate %lu bytes\n", Index * sizeof(WCHAR)); - Status = STATUS_INSUFFICIENT_RESOURCES; - return Status; - } - - // - // copy instance id - // - RtlCopyMemory(UsbChildExtension->usInstanceId.Buffer, Buffer, Index * sizeof(WCHAR)); - UsbChildExtension->usInstanceId.Length = UsbChildExtension->usInstanceId.MaximumLength = Index * sizeof(WCHAR); - - DPRINT("usDeviceId %wZ\n", &UsbChildExtension->usInstanceId); - return STATUS_SUCCESS; -} - -NTSTATUS -DestroyUsbChildDeviceObject( - IN PDEVICE_OBJECT UsbHubDeviceObject, - IN LONG PortId) -{ - PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbHubDeviceObject->DeviceExtension; - PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = NULL; - PDEVICE_OBJECT ChildDeviceObject = NULL; - ULONG Index = 0; - - KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); - for (Index = 0; Index < USB_MAXCHILDREN; Index++) - { - if (HubDeviceExtension->ChildDeviceObject[Index]) - { - UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension; - - /* Check if it matches the port ID */ - if (UsbChildExtension->PortNumber == PortId) - { - /* We found it */ - ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[Index]; - break; - } - } - } - - /* Fail the request if the device doesn't exist */ - if (!ChildDeviceObject) - { - DPRINT1("Removal request for non-existant device!\n"); - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - return STATUS_UNSUCCESSFUL; - } - - DPRINT("Removing device on port %d (Child index: %d)\n", PortId, Index); - - /* Remove the device from the table */ - HubDeviceExtension->ChildDeviceObject[Index] = NULL; - - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - - /* Invalidate device relations for the root hub */ - IoInvalidateDeviceRelations(HubDeviceExtension->RootHubPhysicalDeviceObject, BusRelations); - - /* The rest of the removal process takes place in IRP_MN_REMOVE_DEVICE handling for the PDO */ - return STATUS_SUCCESS; -} - -NTSTATUS -CreateUsbChildDeviceObject( - IN PDEVICE_OBJECT UsbHubDeviceObject, - IN LONG PortId, - OUT PDEVICE_OBJECT *UsbChildDeviceObject, - IN ULONG PortStatus) -{ - NTSTATUS Status; - PDEVICE_OBJECT RootHubDeviceObject, NewChildDeviceObject; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; - PUSB_BUS_INTERFACE_HUB_V5 HubInterface; - ULONG ChildDeviceCount, UsbDeviceNumber = 0; - WCHAR CharDeviceName[64]; - UNICODE_STRING DeviceName; - ULONG ConfigDescSize, DeviceDescSize, DeviceInfoSize; - PVOID HubInterfaceBusContext; - USB_CONFIGURATION_DESCRIPTOR ConfigDesc; - - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) UsbHubDeviceObject->DeviceExtension; - HubInterface = &HubDeviceExtension->HubInterface; - RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; - HubInterfaceBusContext = HubDeviceExtension->UsbDInterface.BusContext; - - while (TRUE) - { - // - // Create a Device Name - // - swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber); - - // - // Initialize UnicodeString - // - RtlInitUnicodeString(&DeviceName, CharDeviceName); - - // - // Create a DeviceObject - // - Status = IoCreateDevice(UsbHubDeviceObject->DriverObject, - sizeof(HUB_CHILDDEVICE_EXTENSION), - NULL, - FILE_DEVICE_CONTROLLER, - FILE_AUTOGENERATED_DEVICE_NAME, - FALSE, - &NewChildDeviceObject); - - // - // Check if the name is already in use - // - if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION)) - { - // - // Try next name - // - UsbDeviceNumber++; - continue; - } - - // - // Check for other errors - // - if (!NT_SUCCESS(Status)) - { - DPRINT1("USBHUB: IoCreateDevice failed with status %x\n", Status); - return Status; - } - - DPRINT("USBHUB: Created Device %x\n", NewChildDeviceObject); - break; - } - - NewChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE; - - // - // Assign the device extensions - // - UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)NewChildDeviceObject->DeviceExtension; - RtlZeroMemory(UsbChildExtension, sizeof(HUB_CHILDDEVICE_EXTENSION)); - UsbChildExtension->ParentDeviceObject = UsbHubDeviceObject; - UsbChildExtension->PortNumber = PortId; - - // - // Create the UsbDeviceObject - // - Status = HubInterface->CreateUsbDevice(HubInterfaceBusContext, - (PVOID)&UsbChildExtension->UsbDeviceHandle, - HubDeviceExtension->RootHubHandle, - PortStatus, - PortId); - if (!NT_SUCCESS(Status)) - { - DPRINT1("USBHUB: CreateUsbDevice failed with status %x\n", Status); - goto Cleanup; - } - - // - // Initialize UsbDevice - // - Status = HubInterface->InitializeUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT1("USBHUB: InitializeUsbDevice failed with status %x\n", Status); - goto Cleanup; - } - - DPRINT("Usb Device Handle %x\n", UsbChildExtension->UsbDeviceHandle); - - ConfigDescSize = sizeof(USB_CONFIGURATION_DESCRIPTOR); - DeviceDescSize = sizeof(USB_DEVICE_DESCRIPTOR); - - // - // Get the descriptors - // - Status = HubInterface->GetUsbDescriptors(HubInterfaceBusContext, - UsbChildExtension->UsbDeviceHandle, - (PUCHAR)&UsbChildExtension->DeviceDesc, - &DeviceDescSize, - (PUCHAR)&ConfigDesc, - &ConfigDescSize); - if (!NT_SUCCESS(Status)) - { - DPRINT1("USBHUB: GetUsbDescriptors failed with status %x\n", Status); - goto Cleanup; - } - - //DumpDeviceDescriptor(&UsbChildExtension->DeviceDesc); - //DumpConfigurationDescriptor(&ConfigDesc); - - // - // FIXME: Support more than one configuration and one interface? - // - if (UsbChildExtension->DeviceDesc.bNumConfigurations > 1) - { - DPRINT1("Warning: Device has more than one configuration. Only one configuration (the first) is supported!\n"); - } - - if (ConfigDesc.bNumInterfaces > 1) - { - DPRINT1("Warning: Device has more than one interface. Only one interface (the first) is currently supported\n"); - } - - ConfigDescSize = ConfigDesc.wTotalLength; - - // - // Allocate memory for the first full descriptor, including interfaces and endpoints. - // - UsbChildExtension->FullConfigDesc = ExAllocatePoolWithTag(PagedPool, ConfigDescSize, USB_HUB_TAG); - - // - // Retrieve the full configuration descriptor - // - Status = GetUsbDeviceDescriptor(NewChildDeviceObject, - USB_CONFIGURATION_DESCRIPTOR_TYPE, - 0, - 0, - UsbChildExtension->FullConfigDesc, - ConfigDescSize); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("USBHUB: GetUsbDeviceDescriptor failed with status %x\n", Status); - goto Cleanup; - } - - // query device details - Status = HubInterface->QueryDeviceInformation(HubInterfaceBusContext, - UsbChildExtension->UsbDeviceHandle, - &UsbChildExtension->DeviceInformation, - sizeof(USB_DEVICE_INFORMATION_0), - &DeviceInfoSize); - - - //DumpFullConfigurationDescriptor(UsbChildExtension->FullConfigDesc); - - // - // Construct all the strings that will describe the device to PNP - // - Status = CreateDeviceIds(NewChildDeviceObject); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create strings needed to describe device to PNP.\n"); - goto Cleanup; - } - - // copy device interface - RtlCopyMemory(&UsbChildExtension->DeviceInterface, &HubDeviceExtension->UsbDInterface, sizeof(USB_BUS_INTERFACE_USBDI_V2)); - UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext); - - INITIALIZE_PNP_STATE(UsbChildExtension->Common); - - IoInitializeRemoveLock(&UsbChildExtension->Common.RemoveLock, 'pbuH', 0, 0); - - KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); - - // - // Find an empty slot in the child device array - // - for (ChildDeviceCount = 0; ChildDeviceCount < USB_MAXCHILDREN; ChildDeviceCount++) - { - if (HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] == NULL) - { - DPRINT("Found unused entry at %d\n", ChildDeviceCount); - break; - } - } - - // - // Check if the limit has been reached for maximum usb devices - // - if (ChildDeviceCount == USB_MAXCHILDREN) - { - DPRINT1("USBHUB: Too many child devices!\n"); - Status = STATUS_UNSUCCESSFUL; - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext); - goto Cleanup; - } - - HubDeviceExtension->ChildDeviceObject[ChildDeviceCount] = NewChildDeviceObject; - HubDeviceExtension->InstanceCount++; - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - - IoInvalidateDeviceRelations(RootHubDeviceObject, BusRelations); - return STATUS_SUCCESS; - -Cleanup: - - // - // Remove the usb device if it was created - // - if (UsbChildExtension->UsbDeviceHandle) - HubInterface->RemoveUsbDevice(HubInterfaceBusContext, UsbChildExtension->UsbDeviceHandle, 0); - - // - // Free full configuration descriptor if one was allocated - // - if (UsbChildExtension->FullConfigDesc) - ExFreePool(UsbChildExtension->FullConfigDesc); - - // - // Free ID buffers if they were allocated in CreateDeviceIds() - // - if (UsbChildExtension->usCompatibleIds.Buffer) - ExFreePool(UsbChildExtension->usCompatibleIds.Buffer); - - if (UsbChildExtension->usDeviceId.Buffer) - ExFreePool(UsbChildExtension->usDeviceId.Buffer); - - if (UsbChildExtension->usHardwareIds.Buffer) - ExFreePool(UsbChildExtension->usHardwareIds.Buffer); - - if (UsbChildExtension->usInstanceId.Buffer) - ExFreePool(UsbChildExtension->usInstanceId.Buffer); - - // - // Delete the device object - // - IoDeleteDevice(NewChildDeviceObject); - return Status; -} - -NTSTATUS -USBHUB_FdoQueryBusRelations( - IN PDEVICE_OBJECT DeviceObject, - IN PDEVICE_RELATIONS RelationsFromTop, - OUT PDEVICE_RELATIONS* pDeviceRelations) -{ - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PDEVICE_RELATIONS DeviceRelations; - ULONG i; - ULONG ChildrenFromTop = 0; - ULONG Children = 0; - ULONG NeededSize; - - HubDeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); - - // - // Count the number of children - // - for (i = 0; i < USB_MAXCHILDREN; i++) - { - - if (HubDeviceExtension->ChildDeviceObject[i] == NULL) - { - continue; - } - Children++; - } - - if (RelationsFromTop) - { - ChildrenFromTop = RelationsFromTop->Count; - if (!Children) - { - // We have nothing to add - *pDeviceRelations = RelationsFromTop; - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - return STATUS_SUCCESS; - } - } - - NeededSize = sizeof(DEVICE_RELATIONS) + (Children + ChildrenFromTop - 1) * sizeof(PDEVICE_OBJECT); - - // - // Allocate DeviceRelations - // - DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, - NeededSize); - - if (!DeviceRelations) - { - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - if (!RelationsFromTop) - return STATUS_INSUFFICIENT_RESOURCES; - else - return STATUS_NOT_SUPPORTED; - } - // Copy the objects coming from top - if (ChildrenFromTop) - { - RtlCopyMemory(DeviceRelations->Objects, RelationsFromTop->Objects, - ChildrenFromTop * sizeof(PDEVICE_OBJECT)); - } - - DeviceRelations->Count = Children + ChildrenFromTop; - Children = ChildrenFromTop; - - // - // Fill in return structure - // - for (i = 0; i < USB_MAXCHILDREN; i++) - { - if (HubDeviceExtension->ChildDeviceObject[i]) - { - // The PnP Manager removes the reference when appropriate. - ObReferenceObject(HubDeviceExtension->ChildDeviceObject[i]); - HubDeviceExtension->ChildDeviceObject[i]->Flags &= ~DO_DEVICE_INITIALIZING; - DeviceRelations->Objects[Children++] = HubDeviceExtension->ChildDeviceObject[i]; - } - } - - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - - // We should do this, because replaced this with our's one - if (RelationsFromTop) - ExFreePool(RelationsFromTop); - - ASSERT(Children == DeviceRelations->Count); - *pDeviceRelations = DeviceRelations; - - return STATUS_SUCCESS; -} - -VOID -NTAPI -RootHubInitCallbackFunction( - PVOID Context) -{ - PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context; - NTSTATUS Status; - ULONG PortId; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PORT_STATUS_CHANGE StatusChange; - - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; - - DPRINT("RootHubInitCallbackFunction Sending the initial SCE Request %x\n", DeviceObject); - - // - // Send the first SCE Request - // - QueryStatusChangeEndpoint(DeviceObject); - - for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++) - { - // - // get port status - // - Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange); - if (NT_SUCCESS(Status)) - { - // - // is there a device connected - // - if (StatusChange.Status & USB_PORT_STATUS_CONNECT) - { - // - // reset port - // - Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to reset on port %d\n", PortId); - } - else - { - // - // wait for the reset to be handled since we want to enumerate synchronously - // - KeWaitForSingleObject(&HubDeviceExtension->ResetComplete, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(&HubDeviceExtension->ResetComplete); - } - } - } - } -} - -BOOLEAN -USBHUB_IsRootHubFDO( - IN PDEVICE_OBJECT DeviceObject) -{ - NTSTATUS Status; - PDEVICE_OBJECT RootHubPhysicalDeviceObject = NULL; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - - // get hub device extension - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; - - // Get the Root Hub Pdo - Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, - IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, - &RootHubPhysicalDeviceObject, - NULL); - - // FIXME handle error - ASSERT(NT_SUCCESS(Status)); - - // physical device object is only obtained for root hubs - return (RootHubPhysicalDeviceObject != NULL); -} - - -NTSTATUS -USBHUB_FdoStartDevice( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PURB Urb; - PUSB_INTERFACE_DESCRIPTOR Pid; - ULONG Result = 0, PortId; - USBD_INTERFACE_LIST_ENTRY InterfaceList[2] = {{NULL, NULL}, {NULL, NULL}}; - PURB ConfigUrb = NULL; - ULONG HubStatus; - NTSTATUS Status = STATUS_SUCCESS; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PDEVICE_OBJECT RootHubDeviceObject; - PVOID HubInterfaceBusContext; - PORT_STATUS_CHANGE StatusChange; - - // get hub device extension - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; - - DPRINT("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); - if (!Urb) - { - // no memory - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - - // zero urb - RtlZeroMemory(Urb, sizeof(URB) + sizeof(USBD_INTERFACE_LIST_ENTRY)); - - // Get the Root Hub Pdo - Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, - IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO, - &HubDeviceExtension->RootHubPhysicalDeviceObject, - &HubDeviceExtension->RootHubFunctionalDeviceObject); - if (!NT_SUCCESS(Status)) - { - // failed to obtain hub pdo - DPRINT1("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO failed with %x\n", Status); - goto cleanup; - } - - // sanity checks - ASSERT(HubDeviceExtension->RootHubPhysicalDeviceObject); - ASSERT(HubDeviceExtension->RootHubFunctionalDeviceObject); - - // get roothub - RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; - - // Send the StartDevice to RootHub - Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp); - - if (!NT_SUCCESS(Status)) - { - // failed to start pdo - DPRINT1("Failed to start the RootHub PDO\n"); - goto cleanup; - } - - // Get the current number of hubs - Status = SubmitRequestToRootHub(RootHubDeviceObject, - IOCTL_INTERNAL_USB_GET_HUB_COUNT, - &HubDeviceExtension->NumberOfHubs, NULL); - if (!NT_SUCCESS(Status)) - { - // failed to get number of hubs - DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT failed with %x\n", Status); - goto cleanup; - } - - // Get the Hub Interface - Status = QueryInterface(RootHubDeviceObject, - USB_BUS_INTERFACE_HUB_GUID, - sizeof(USB_BUS_INTERFACE_HUB_V5), - USB_BUSIF_HUB_VERSION_5, - (PVOID)&HubDeviceExtension->HubInterface); - - if (!NT_SUCCESS(Status)) - { - // failed to get root hub interface - DPRINT1("Failed to get HUB_GUID interface with status 0x%08lx\n", Status); - goto cleanup; - } - - HubInterfaceBusContext = HubDeviceExtension->HubInterface.BusContext; - - // Get the USBDI Interface - Status = QueryInterface(RootHubDeviceObject, - USB_BUS_INTERFACE_USBDI_GUID, - sizeof(USB_BUS_INTERFACE_USBDI_V2), - USB_BUSIF_USBDI_VERSION_2, - (PVOID)&HubDeviceExtension->UsbDInterface); - - if (!NT_SUCCESS(Status)) - { - // failed to get usbdi interface - DPRINT1("Failed to get USBDI_GUID interface with status 0x%08lx\n", Status); - goto cleanup; - } - - // Get Root Hub Device Handle - Status = SubmitRequestToRootHub(RootHubDeviceObject, - IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE, - &HubDeviceExtension->RootHubHandle, - NULL); - - if (!NT_SUCCESS(Status)) - { - // failed - DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE failed with status 0x%08lx\n", Status); - goto cleanup; - } - - // - // Get Hub Device Information - // - Status = HubDeviceExtension->HubInterface.QueryDeviceInformation(HubInterfaceBusContext, - HubDeviceExtension->RootHubHandle, - &HubDeviceExtension->DeviceInformation, - sizeof(USB_DEVICE_INFORMATION_0), - &Result); - - DPRINT("Status %x, Result 0x%08lx\n", Status, Result); - DPRINT("InformationLevel %x\n", HubDeviceExtension->DeviceInformation.InformationLevel); - DPRINT("ActualLength %x\n", HubDeviceExtension->DeviceInformation.ActualLength); - DPRINT("PortNumber %x\n", HubDeviceExtension->DeviceInformation.PortNumber); - DPRINT("DeviceDescriptor %x\n", HubDeviceExtension->DeviceInformation.DeviceDescriptor); - DPRINT("HubAddress %x\n", HubDeviceExtension->DeviceInformation.HubAddress); - DPRINT("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); - - // set device handle - Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle; - - // get hub device descriptor - Status = SubmitRequestToRootHub(RootHubDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - Urb, - NULL); - - if (!NT_SUCCESS(Status)) - { - // failed to get device descriptor of hub - DPRINT1("Failed to get HubDeviceDescriptor!\n"); - goto cleanup; - } - - // build configuration request - 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); - - // set device handle - Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle; - - // request configuration descriptor - Status = SubmitRequestToRootHub(RootHubDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - Urb, - NULL); - - if (!NT_SUCCESS(Status)) - { - // failed to get configuration descriptor - DPRINT1("Failed to get RootHub Configuration with status %x\n", Status); - goto cleanup; - } - - // sanity checks - ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength == sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubConfigDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE); - ASSERT(HubDeviceExtension->HubConfigDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubConfigDescriptor.bNumInterfaces == 1); - ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bLength == sizeof(USB_INTERFACE_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE); - ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bNumEndpoints == 1); - ASSERT(HubDeviceExtension->HubEndPointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE); - ASSERT(HubDeviceExtension->HubEndPointDescriptor.bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubEndPointDescriptor.bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT); - ASSERT(HubDeviceExtension->HubEndPointDescriptor.bEndpointAddress == 0x81); // interrupt in - - // get hub information - Status = HubDeviceExtension->HubInterface.GetExtendedHubInformation(HubInterfaceBusContext, - RootHubDeviceObject, - &HubDeviceExtension->UsbExtHubInfo, - sizeof(USB_EXTHUB_INFORMATION_0), - &Result); - if (!NT_SUCCESS(Status)) - { - // failed to get hub information - DPRINT1("Failed to extended hub information. Unable to determine the number of ports!\n"); - goto cleanup; - } - - if (!HubDeviceExtension->UsbExtHubInfo.NumberOfPorts) - { - // bogus port driver - DPRINT1("Failed to retrieve the number of ports\n"); - Status = STATUS_UNSUCCESSFUL; - goto cleanup; - } - - DPRINT("HubDeviceExtension->UsbExtHubInfo.NumberOfPorts %x\n", HubDeviceExtension->UsbExtHubInfo.NumberOfPorts); - - // Build hub descriptor request - UsbBuildVendorRequest(Urb, - URB_FUNCTION_CLASS_DEVICE, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, - 0, - USB_REQUEST_GET_DESCRIPTOR, - USB_DEVICE_CLASS_RESERVED, - 0, - &HubDeviceExtension->HubDescriptor, - NULL, - sizeof(USB_HUB_DESCRIPTOR), - NULL); - - // set device handle - Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle; - - // send request - Status = SubmitRequestToRootHub(RootHubDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - Urb, - NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get Hub Descriptor!\n"); - Status = STATUS_UNSUCCESSFUL; - goto cleanup; - } - - // sanity checks - ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts == HubDeviceExtension->UsbExtHubInfo.NumberOfPorts); - ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29); - - // build get status request - HubStatus = 0; - UsbBuildGetStatusRequest(Urb, - URB_FUNCTION_GET_STATUS_FROM_DEVICE, - 0, - &HubStatus, - 0, - NULL); - // set device handle - Urb->UrbHeader.UsbdDeviceHandle = HubDeviceExtension->RootHubHandle; - - // send request - Status = SubmitRequestToRootHub(RootHubDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - Urb, - NULL); - if (!NT_SUCCESS(Status)) - { - // failed to get hub status - DPRINT1("Failed to get Hub Status!\n"); - Status = STATUS_UNSUCCESSFUL; - goto cleanup; - } - - // Allocate memory for PortStatusChange to hold 2 USHORTs for each port on hub - HubDeviceExtension->PortStatusChange = ExAllocatePoolWithTag(NonPagedPool, - sizeof(ULONG) * HubDeviceExtension->UsbExtHubInfo.NumberOfPorts, - USB_HUB_TAG); - - if (!HubDeviceExtension->PortStatusChange) - { - DPRINT1("Failed to allocate pool for PortStatusChange!\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - - // Get the first Configuration Descriptor - Pid = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor, - &HubDeviceExtension->HubConfigDescriptor, - -1, -1, -1, -1, -1); - if (Pid == NULL) - { - // failed parse hub descriptor - DPRINT1("Failed to parse configuration descriptor\n"); - Status = STATUS_UNSUCCESSFUL; - goto cleanup; - } - - // create configuration request - InterfaceList[0].InterfaceDescriptor = Pid; - ConfigUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor, - (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); - if (ConfigUrb == NULL) - { - // failed to build urb - DPRINT1("Failed to allocate urb\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - - // send request - Status = SubmitRequestToRootHub(RootHubDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - ConfigUrb, - NULL); - if (!NT_SUCCESS(Status)) - { - // failed to select configuration - DPRINT1("Failed to select configuration with %x\n", Status); - goto cleanup; - } - - // store configuration & pipe handle - HubDeviceExtension->ConfigurationHandle = ConfigUrb->UrbSelectConfiguration.ConfigurationHandle; - HubDeviceExtension->PipeHandle = ConfigUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; - DPRINT("Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle); - - // check if function is available - if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed) - { - // is it high speed bus - if (HubDeviceExtension->UsbDInterface.IsDeviceHighSpeed(HubInterfaceBusContext)) - { - // initialize usb 2.0 hub - Status = HubDeviceExtension->HubInterface.Initialize20Hub(HubInterfaceBusContext, - HubDeviceExtension->RootHubHandle, 1); - DPRINT("Status %x\n", Status); - - // FIXME handle error - ASSERT(Status == STATUS_SUCCESS); - } - } - - - // Enable power on all ports - DPRINT("Enabling PortPower on all ports!\n"); - for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++) - { - Status = SetPortFeature(RootHubDeviceObject, PortId, PORT_POWER); - if (!NT_SUCCESS(Status)) - DPRINT1("Failed to power on port %d\n", PortId); - - Status = ClearPortFeature(RootHubDeviceObject, PortId, C_PORT_CONNECTION); - if (!NT_SUCCESS(Status)) - DPRINT1("Failed to power on port %d\n", PortId); - } - - // init root hub notification - if (HubDeviceExtension->HubInterface.RootHubInitNotification) - { - Status = HubDeviceExtension->HubInterface.RootHubInitNotification(HubInterfaceBusContext, - DeviceObject, - RootHubInitCallbackFunction); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to set callback\n"); - goto cleanup; - } - } - else - { - // Send the first SCE Request - QueryStatusChangeEndpoint(DeviceObject); - - // - // reset ports - // - for (PortId = 1; PortId <= HubDeviceExtension->HubDescriptor.bNumberOfPorts; PortId++) - { - // - // get port status - // - Status = GetPortStatusAndChange(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, &StatusChange); - if (NT_SUCCESS(Status)) - { - // - // is there a device connected - // - if (StatusChange.Status & USB_PORT_STATUS_CONNECT) - { - // - // reset port - // - Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to reset on port %d\n", PortId); - } - else - { - // - // wait for the reset to be handled since we want to enumerate synchronously - // - KeWaitForSingleObject(&HubDeviceExtension->ResetComplete, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(&HubDeviceExtension->ResetComplete); - } - } - } - } - } - - // free urb - ExFreePool(Urb); - - // free ConfigUrb - ExFreePool(ConfigUrb); - - // done - return Status; - -cleanup: - if (Urb) - ExFreePool(Urb); - - // Dereference interfaces - if (HubDeviceExtension->HubInterface.Size) - HubDeviceExtension->HubInterface.InterfaceDereference(HubDeviceExtension->HubInterface.BusContext); - - if (HubDeviceExtension->UsbDInterface.Size) - HubDeviceExtension->UsbDInterface.InterfaceDereference(HubDeviceExtension->UsbDInterface.BusContext); - - if (HubDeviceExtension->PortStatusChange) - ExFreePool(HubDeviceExtension->PortStatusChange); - - if (ConfigUrb) - ExFreePool(ConfigUrb); - - return Status; -} - -NTSTATUS -USBHUB_FdoHandlePnp( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION Stack; - NTSTATUS Status = STATUS_SUCCESS; - PDEVICE_OBJECT ChildDeviceObject; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PUSB_BUS_INTERFACE_HUB_V5 HubInterface; - PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; - - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; - - HubInterface = &HubDeviceExtension->HubInterface; - Stack = IoGetCurrentIrpStackLocation(Irp); - - Status = IoAcquireRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); - if (!NT_SUCCESS(Status)) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - - switch (Stack->MinorFunction) - { - int i; - - case IRP_MN_START_DEVICE: - { - DPRINT("IRP_MN_START_DEVICE\n"); - if (USBHUB_IsRootHubFDO(DeviceObject)) - { - // start root hub fdo - Status = USBHUB_FdoStartDevice(DeviceObject, Irp); - } - else - { - Status = USBHUB_ParentFDOStartDevice(DeviceObject, Irp); - } - - SET_NEW_PNP_STATE(HubDeviceExtension->Common, Started); - - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); - return Status; - } - - case IRP_MN_QUERY_DEVICE_RELATIONS: - { - switch (Stack->Parameters.QueryDeviceRelations.Type) - { - case BusRelations: - { - PDEVICE_RELATIONS DeviceRelations = NULL; - PDEVICE_RELATIONS RelationsFromTop = (PDEVICE_RELATIONS)Irp->IoStatus.Information; - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); - - Status = USBHUB_FdoQueryBusRelations(DeviceObject, RelationsFromTop, &DeviceRelations); - - if (!NT_SUCCESS(Status)) - { - if (Status == STATUS_NOT_SUPPORTED) - { - // We should process this to not lose relations from top. - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - } - // We should fail an IRP - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); - return Status; - } - - Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; - Irp->IoStatus.Status = Status; - break; - } - case RemovalRelations: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n"); - break; - } - default: - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", - Stack->Parameters.QueryDeviceRelations.Type); - break; - } - break; - } - case IRP_MN_QUERY_STOP_DEVICE: - { - // - // We should fail this request, because we're not handling - // IRP_MN_STOP_DEVICE for now.We'll receive this IRP ONLY when - // PnP manager rebalances resources. - // - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_SUPPORTED; - } - case IRP_MN_QUERY_REMOVE_DEVICE: - { - // No action is required from FDO because it have nothing to free. - DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n"); - - SET_NEW_PNP_STATE(HubDeviceExtension->Common, RemovePending); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - } - case IRP_MN_CANCEL_REMOVE_DEVICE: - { - DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n"); - - if (HubDeviceExtension->Common.PnPState == RemovePending) - RESTORE_PREVIOUS_PNP_STATE(HubDeviceExtension->Common); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - } - case IRP_MN_SURPRISE_REMOVAL: - { - // - // We'll receive this IRP on HUB unexpected removal, or on USB - // controller removal from PCI port. Here we should "let know" all - // our children that their parent is removed and on next removal - // they also can be removed. - // - SET_NEW_PNP_STATE(HubDeviceExtension->Common, SurpriseRemovePending); - - KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); - - for (i = 0; i < USB_MAXCHILDREN; i++) - { - ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[i]; - if (ChildDeviceObject) - { - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceObjectExtension; - ChildDeviceExtension->ParentDeviceObject = NULL; - } - } - - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - - // This IRP can't be failed - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - } - case IRP_MN_REMOVE_DEVICE: - { - DPRINT("IRP_MN_REMOVE_DEVICE\n"); - - SET_NEW_PNP_STATE(HubDeviceExtension->Common, Deleted); - - IoReleaseRemoveLockAndWait(&HubDeviceExtension->Common.RemoveLock, Irp); - - // - // Here we should remove all child PDOs. At this point all children - // received and returned from IRP_MN_REMOVE so remove synchronization - // isn't needed here - // - - KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); - - for (i = 0; i < USB_MAXCHILDREN; i++) - { - ChildDeviceObject = HubDeviceExtension->ChildDeviceObject[i]; - if (ChildDeviceObject) - { - PHUB_CHILDDEVICE_EXTENSION UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)ChildDeviceObject->DeviceExtension; - - SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted); - - // Remove the usb device - if (UsbChildExtension->UsbDeviceHandle) - { - Status = HubInterface->RemoveUsbDevice(HubInterface->BusContext, UsbChildExtension->UsbDeviceHandle, 0); - ASSERT(Status == STATUS_SUCCESS); - } - - // Free full configuration descriptor - if (UsbChildExtension->FullConfigDesc) - ExFreePool(UsbChildExtension->FullConfigDesc); - - // Free ID buffers - if (UsbChildExtension->usCompatibleIds.Buffer) - ExFreePool(UsbChildExtension->usCompatibleIds.Buffer); - - if (UsbChildExtension->usDeviceId.Buffer) - ExFreePool(UsbChildExtension->usDeviceId.Buffer); - - if (UsbChildExtension->usHardwareIds.Buffer) - ExFreePool(UsbChildExtension->usHardwareIds.Buffer); - - if (UsbChildExtension->usInstanceId.Buffer) - ExFreePool(UsbChildExtension->usInstanceId.Buffer); - - DPRINT("Deleting child PDO\n"); - IoDeleteDevice(DeviceObject); - ChildDeviceObject = NULL; - } - } - - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Status = ForwardIrpAndForget(DeviceObject, Irp); - - IoDetachDevice(HubDeviceExtension->LowerDeviceObject); - DPRINT("Deleting FDO 0x%p\n", DeviceObject); - IoDeleteDevice(DeviceObject); - - return Status; - } - case IRP_MN_QUERY_BUS_INFORMATION: - { - // Function drivers and filter drivers do not handle this IRP. - DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n"); - break; - } - case IRP_MN_QUERY_ID: - { - DPRINT("IRP_MN_QUERY_ID\n"); - // Function drivers and filter drivers do not handle this IRP. - break; - } - case IRP_MN_QUERY_CAPABILITIES: - { - // - // If a function or filter driver does not handle this IRP, it - // should pass that down. - // - DPRINT("IRP_MN_QUERY_CAPABILITIES\n"); - break; - } - default: - { - DPRINT(" IRP_MJ_PNP / unknown minor function 0x%lx\n", Stack->MinorFunction); - break; - } - } - - Status = ForwardIrpAndForget(DeviceObject, Irp); - IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); - return Status; -} - -NTSTATUS -USBHUB_FdoHandleDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - NTSTATUS Status = STATUS_NOT_IMPLEMENTED; - PUSB_NODE_INFORMATION NodeInformation; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PUSB_NODE_CONNECTION_INFORMATION NodeConnectionInfo; - PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; - PUSB_NODE_CONNECTION_DRIVERKEY_NAME NodeKey; - PUSB_NODE_CONNECTION_NAME ConnectionName; - ULONG Index, Length; - - // get stack location - IoStack = IoGetCurrentIrpStackLocation(Irp); - - // get device extension - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; - - Status = IoAcquireRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); - if (!NT_SUCCESS(Status)) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - - // Prevent handling of control requests in remove pending state - if (HubDeviceExtension->Common.PnPState == RemovePending) - { - DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject); - Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); - return STATUS_DEVICE_NOT_CONNECTED; - } - - if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_INFORMATION) - { - // is the buffer big enough - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USB_NODE_INFORMATION)) - { - // buffer too small - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - // get buffer - NodeInformation = (PUSB_NODE_INFORMATION)Irp->AssociatedIrp.SystemBuffer; - - // sanity check - ASSERT(NodeInformation); - - // init buffer - NodeInformation->NodeType = UsbHub; - RtlCopyMemory(&NodeInformation->u.HubInformation.HubDescriptor, &HubDeviceExtension->HubDescriptor, sizeof(USB_HUB_DESCRIPTOR)); - - // FIXME is hub powered - NodeInformation->u.HubInformation.HubIsBusPowered = TRUE; - - // done - Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION); - Status = STATUS_SUCCESS; - } - - - } - else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_CONNECTION_INFORMATION) - { - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USB_NODE_CONNECTION_INFORMATION)) - { - // buffer too small - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - // get node connection info - NodeConnectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; - - // sanity checks - ASSERT(NodeConnectionInfo); - - KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); - for(Index = 0; Index < USB_MAXCHILDREN; Index++) - { - if (HubDeviceExtension->ChildDeviceObject[Index] == NULL) - continue; - - // get child device extension - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension; - - if (ChildDeviceExtension->PortNumber != NodeConnectionInfo->ConnectionIndex) - continue; - - // init node connection info - RtlCopyMemory(&NodeConnectionInfo->DeviceDescriptor, &ChildDeviceExtension->DeviceDesc, sizeof(USB_DEVICE_DESCRIPTOR)); - NodeConnectionInfo->CurrentConfigurationValue = ChildDeviceExtension->FullConfigDesc->bConfigurationValue; - NodeConnectionInfo->DeviceIsHub = FALSE; //FIXME support hubs - NodeConnectionInfo->LowSpeed = ChildDeviceExtension->DeviceInformation.DeviceSpeed == UsbLowSpeed; - NodeConnectionInfo->DeviceAddress = ChildDeviceExtension->DeviceInformation.DeviceAddress; - NodeConnectionInfo->NumberOfOpenPipes = ChildDeviceExtension->DeviceInformation.NumberOfOpenPipes; - NodeConnectionInfo->ConnectionStatus = DeviceConnected; //FIXME - - if (NodeConnectionInfo->NumberOfOpenPipes) - { - DPRINT1("Need to copy pipe information\n"); - } - break; - } - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - // done - Irp->IoStatus.Information = sizeof(USB_NODE_INFORMATION); - Status = STATUS_SUCCESS; - } - } - else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME) - { - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USB_NODE_CONNECTION_INFORMATION)) - { - // buffer too small - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - // get node connection info - NodeKey = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer; - - // sanity checks - ASSERT(NodeKey); - - KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); - for(Index = 0; Index < USB_MAXCHILDREN; Index++) - { - if (HubDeviceExtension->ChildDeviceObject[Index] == NULL) - continue; - - // get child device extension - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)HubDeviceExtension->ChildDeviceObject[Index]->DeviceExtension; - - if (ChildDeviceExtension->PortNumber != NodeKey->ConnectionIndex) - continue; - - // get driver key - Status = IoGetDeviceProperty(HubDeviceExtension->ChildDeviceObject[Index], DevicePropertyDriverKeyName, - IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME), - NodeKey->DriverKeyName, - &Length); - - if (Status == STATUS_BUFFER_TOO_SMALL) - { - // normalize status - Status = STATUS_SUCCESS; - } - - if (Length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME) > IoStack->Parameters.DeviceIoControl.OutputBufferLength) - { - // terminate node key name - NodeKey->DriverKeyName[0] = UNICODE_NULL; - Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME); - } - else - { - // result size - Irp->IoStatus.Information = Length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME); - } - - // length of driver name - NodeKey->ActualLength = Length + sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME); - break; - } - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - } - } - else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_NODE_CONNECTION_NAME) - { - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USB_NODE_CONNECTION_NAME)) - { - // buffer too small - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - // FIXME support hubs - ConnectionName = (PUSB_NODE_CONNECTION_NAME)Irp->AssociatedIrp.SystemBuffer; - ConnectionName->ActualLength = 0; - ConnectionName->NodeName[0] = UNICODE_NULL; - - // done - Irp->IoStatus.Information = sizeof(USB_NODE_CONNECTION_NAME); - Status = STATUS_SUCCESS; - } - } - else - { - DPRINT1("UNIMPLEMENTED FdoHandleDeviceControl IoCtl %x InputBufferLength %x OutputBufferLength %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, - IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength); - } - - // finish irp - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - IoReleaseRemoveLock(&HubDeviceExtension->Common.RemoveLock, Irp); - return Status; -} - diff --git a/drivers/usb/usbhub/guid.c b/drivers/usb/usbhub/guid.c deleted file mode 100644 index 50a60369ff3..00000000000 --- a/drivers/usb/usbhub/guid.c +++ /dev/null @@ -1,9 +0,0 @@ -/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */ - -#include -#include -#include -#include -#include - -/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */ diff --git a/drivers/usb/usbhub/hub_fdo.c b/drivers/usb/usbhub/hub_fdo.c deleted file mode 100644 index 019328b73e4..00000000000 --- a/drivers/usb/usbhub/hub_fdo.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Hub Driver - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbhub/hub_fdo.c - * PURPOSE: Hub FDO - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbhub.h" - -#define NDEBUG -#include - -NTSTATUS -USBHUB_ParentFDOStartDevice( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PURB Urb, ConfigurationUrb; - PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - PUSBD_INTERFACE_LIST_ENTRY InterfaceList; - ULONG Index; - NTSTATUS Status; - - // get hub device extension - HubDeviceExtension = (PHUB_DEVICE_EXTENSION) DeviceObject->DeviceExtension; - - // Send the StartDevice to lower device object - Status = ForwardIrpAndWait(HubDeviceExtension->LowerDeviceObject, Irp); - - if (!NT_SUCCESS(Status)) - { - // failed to start pdo - DPRINT1("Failed to start the RootHub PDO\n"); - return Status; - } - - // FIXME get capabilities - - Urb = ExAllocatePool(NonPagedPool, sizeof(URB)); - if (!Urb) - { - // no memory - DPRINT1("No memory\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - - // lets get device descriptor - UsbBuildGetDescriptorRequest(Urb, - sizeof(Urb->UrbControlDescriptorRequest), - USB_DEVICE_DESCRIPTOR_TYPE, - 0, - 0, - &HubDeviceExtension->HubDeviceDescriptor, - NULL, - sizeof(USB_DEVICE_DESCRIPTOR), - NULL); - - - // get hub device descriptor - Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - Urb, - NULL); - - if (!NT_SUCCESS(Status)) - { - // failed to get device descriptor of hub - DPRINT1("Failed to get hub device descriptor with Status %x!\n", Status); - ExFreePool(Urb); - return Status; - } - - // now get configuration descriptor - UsbBuildGetDescriptorRequest(Urb, - sizeof(Urb->UrbControlDescriptorRequest), - USB_CONFIGURATION_DESCRIPTOR_TYPE, - 0, - 0, - &HubDeviceExtension->HubConfigDescriptor, - NULL, - sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR), - NULL); - - // request configuration descriptor - Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - Urb, - NULL); - - if (!NT_SUCCESS(Status)) - { - // failed to get configuration descriptor - DPRINT1("Failed to get hub configuration descriptor with status %x\n", Status); - ExFreePool(Urb); - return Status; - } - - // sanity checks - ASSERT(HubDeviceExtension->HubConfigDescriptor.wTotalLength == sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubConfigDescriptor.bDescriptorType == USB_CONFIGURATION_DESCRIPTOR_TYPE); - ASSERT(HubDeviceExtension->HubConfigDescriptor.bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubConfigDescriptor.bNumInterfaces == 1); - ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bLength == sizeof(USB_INTERFACE_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE); - ASSERT(HubDeviceExtension->HubInterfaceDescriptor.bNumEndpoints == 1); - ASSERT(HubDeviceExtension->HubEndPointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE); - ASSERT(HubDeviceExtension->HubEndPointDescriptor.bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubEndPointDescriptor.bmAttributes == USB_ENDPOINT_TYPE_INTERRUPT); - ASSERT(HubDeviceExtension->HubEndPointDescriptor.bEndpointAddress == 0x81); // interrupt in - - // Build hub descriptor request - UsbBuildVendorRequest(Urb, - URB_FUNCTION_CLASS_DEVICE, - sizeof(Urb->UrbControlVendorClassRequest), - USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK, - 0, - USB_REQUEST_GET_DESCRIPTOR, - USB_DEVICE_CLASS_RESERVED, - 0, - &HubDeviceExtension->HubDescriptor, - NULL, - sizeof(USB_HUB_DESCRIPTOR), - NULL); - - // send request - Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - Urb, - NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status); - ExFreePool(Urb); - return STATUS_UNSUCCESSFUL; - } - - // sanity checks - ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorLength == sizeof(USB_HUB_DESCRIPTOR)); - ASSERT(HubDeviceExtension->HubDescriptor.bNumberOfPorts); - ASSERT(HubDeviceExtension->HubDescriptor.bDescriptorType == 0x29); - - // store number of ports - DPRINT1("NumberOfPorts %lu\n", HubDeviceExtension->HubDescriptor.bNumberOfPorts); - HubDeviceExtension->UsbExtHubInfo.NumberOfPorts = HubDeviceExtension->HubDescriptor.bNumberOfPorts; - - // allocate interface list - InterfaceList = ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1)); - if (!InterfaceList) - { - // no memory - DPRINT1("No memory\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // zero list - RtlZeroMemory(InterfaceList, sizeof(USBD_INTERFACE_LIST_ENTRY) * (HubDeviceExtension->HubConfigDescriptor.bNumInterfaces + 1)); - - // grab all interface descriptors - for(Index = 0; Index < HubDeviceExtension->HubConfigDescriptor.bNumInterfaces; Index++) - { - // Get the first Configuration Descriptor - InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(&HubDeviceExtension->HubConfigDescriptor, - &HubDeviceExtension->HubConfigDescriptor, - Index, 0, -1, -1, -1); - - // store in list - InterfaceList[Index].InterfaceDescriptor = InterfaceDescriptor; - } - - // now create configuration request - ConfigurationUrb = USBD_CreateConfigurationRequestEx(&HubDeviceExtension->HubConfigDescriptor, - (PUSBD_INTERFACE_LIST_ENTRY)&InterfaceList); - if (ConfigurationUrb == NULL) - { - // failed to build urb - DPRINT1("Failed to build configuration urb\n"); - ExFreePool(Urb); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // send request - Status = SubmitRequestToRootHub(HubDeviceExtension->LowerDeviceObject, - IOCTL_INTERNAL_USB_SUBMIT_URB, - ConfigurationUrb, - NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get Hub Descriptor Status %x!\n", Status); - ExFreePool(Urb); - ExFreePool(ConfigurationUrb); - return STATUS_UNSUCCESSFUL; - } - - // store configuration & pipe handle - HubDeviceExtension->ConfigurationHandle = ConfigurationUrb->UrbSelectConfiguration.ConfigurationHandle; - HubDeviceExtension->PipeHandle = ConfigurationUrb->UrbSelectConfiguration.Interface.Pipes[0].PipeHandle; - DPRINT("Hub Configuration Handle %x\n", HubDeviceExtension->ConfigurationHandle); - - // free urb - ExFreePool(ConfigurationUrb); - ExFreePool(Urb); - - // FIXME build SCE interrupt request - - // FIXME create pdos - - return Status; -} - diff --git a/drivers/usb/usbhub/misc.c b/drivers/usb/usbhub/misc.c deleted file mode 100644 index 33eacbe8b1c..00000000000 --- a/drivers/usb/usbhub/misc.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Hub Driver - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbhub/misc.c - * PURPOSE: Misc helper functions - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbhub.h" - -#define NDEBUG -#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); -} - -VOID -DumpFullConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) -{ - PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - LONG i, j; - - 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); - - InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) ((ULONG_PTR)ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR)); - - for (i=0; i < ConfigurationDescriptor->bNumInterfaces; i++) - { - DPRINT1("- Dumping InterfaceDescriptor %x\n", InterfaceDescriptor); - DPRINT1(" bLength %x\n", InterfaceDescriptor->bLength); - DPRINT1(" bDescriptorType %x\n", InterfaceDescriptor->bDescriptorType); - DPRINT1(" bInterfaceNumber %x\n", InterfaceDescriptor->bInterfaceNumber); - DPRINT1(" bAlternateSetting %x\n", InterfaceDescriptor->bAlternateSetting); - DPRINT1(" bNumEndpoints %x\n", InterfaceDescriptor->bNumEndpoints); - DPRINT1(" bInterfaceClass %x\n", InterfaceDescriptor->bInterfaceClass); - DPRINT1(" bInterfaceSubClass %x\n", InterfaceDescriptor->bInterfaceSubClass); - DPRINT1(" bInterfaceProtocol %x\n", InterfaceDescriptor->bInterfaceProtocol); - DPRINT1(" iInterface %x\n", InterfaceDescriptor->iInterface); - - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)InterfaceDescriptor + sizeof(USB_INTERFACE_DESCRIPTOR)); - - for (j=0; j < InterfaceDescriptor->bNumEndpoints; j++) - { - DPRINT1(" bLength %x\n", EndpointDescriptor->bLength); - DPRINT1(" bDescriptorType %x\n", EndpointDescriptor->bDescriptorType); - DPRINT1(" bEndpointAddress %x\n", EndpointDescriptor->bEndpointAddress); - DPRINT1(" bmAttributes %x\n", EndpointDescriptor->bmAttributes); - DPRINT1(" wMaxPacketSize %x\n", EndpointDescriptor->wMaxPacketSize); - DPRINT1(" bInterval %x\n", EndpointDescriptor->bInterval); - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) ((ULONG_PTR)EndpointDescriptor + sizeof(USB_ENDPOINT_DESCRIPTOR)); - } - InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)(ULONG_PTR)EndpointDescriptor; - } -} - -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); -} - -NTSTATUS -SubmitRequestToRootHub( - IN PDEVICE_OBJECT RootHubDeviceObject, - IN ULONG IoControlCode, - OUT PVOID OutParameter1, - OUT PVOID OutParameter2) -{ - KEVENT Event; - PIRP Irp; - IO_STATUS_BLOCK IoStatus; - NTSTATUS Status; - PIO_STACK_LOCATION Stack = NULL; - - KeInitializeEvent(&Event, NotificationEvent, FALSE); - - // - // Build Control Request - // - Irp = IoBuildDeviceIoControlRequest(IoControlCode, - RootHubDeviceObject, - NULL, 0, - NULL, 0, - TRUE, - &Event, - &IoStatus); - - if (Irp == NULL) - { - DPRINT("Usbhub: IoBuildDeviceIoControlRequest() failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Initialize the status block before sending the IRP - // - IoStatus.Status = STATUS_NOT_SUPPORTED; - IoStatus.Information = 0; - - // - // Get Next Stack Location and Initialize it - // - Stack = IoGetNextIrpStackLocation(Irp); - Stack->Parameters.Others.Argument1 = OutParameter1; - Stack->Parameters.Others.Argument2 = OutParameter2; - - // - // Call RootHub - // - Status = IoCallDriver(RootHubDeviceObject, Irp); - - // - // Its ok to block here as this function is called in an nonarbitrary thread - // - if (Status == STATUS_PENDING) - { - KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); - Status = IoStatus.Status; - } - - // - // The IO Manager will free the IRP - // - - return Status; -} diff --git a/drivers/usb/usbhub/pdo.c b/drivers/usb/usbhub/pdo.c deleted file mode 100644 index b39098f9f8b..00000000000 --- a/drivers/usb/usbhub/pdo.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Hub Driver - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbhub/pdo.c - * PURPOSE: Handle PDO - * PROGRAMMERS: - * Hervé Poussineau (hpoussin@reactos.org) - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbhub.h" - -#include - -#define NDEBUG -#include - -#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) - -DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, - 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); - -NTSTATUS -NTAPI -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); - - // - // Free our allocated IRP - // - IoFreeIrp(Irp); - - // - // Return this status so the IO Manager doesnt mess with the Irp - // - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -ForwardUrbToRootHub( - PDEVICE_OBJECT RootHubDeviceObject, - IN ULONG IoControlCode, - PIRP Irp, - OUT PVOID OutParameter1, - OUT PVOID OutParameter2) -{ - 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, - UrbCompletion, - Irp, - TRUE, - TRUE, - TRUE); - - IoCallDriver(RootHubDeviceObject, ForwardIrp); - - // - // Always return pending as the completion routine will take care of it - // - return STATUS_PENDING; -} - -BOOLEAN -IsValidPDO( - IN PDEVICE_OBJECT DeviceObject) -{ - ULONG Index; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; - - - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; - ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE); - - // This can happen when parent device was surprise removed. - if (ChildDeviceExtension->ParentDeviceObject == NULL) - return FALSE; - - HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension; - - KeAcquireGuardedMutex(&HubDeviceExtension->HubMutexLock); - for(Index = 0; Index < USB_MAXCHILDREN; Index++) - { - if (HubDeviceExtension->ChildDeviceObject[Index] == DeviceObject) - { - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - - /* PDO exists */ - return TRUE; - } - } - KeReleaseGuardedMutex(&HubDeviceExtension->HubMutexLock); - - /* invalid pdo */ - return FALSE; -} - - -NTSTATUS -USBHUB_PdoHandleInternalDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - NTSTATUS Status; - PIO_STACK_LOCATION Stack; - ULONG_PTR Information = 0; - PHUB_DEVICE_EXTENSION HubDeviceExtension; - PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; - PDEVICE_OBJECT RootHubDeviceObject; - PURB Urb; - - //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject); - - // - // get current stack location - // - Stack = IoGetCurrentIrpStackLocation(Irp); - ASSERT(Stack); - - // - // Set default status - // - Status = Irp->IoStatus.Status; - - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; - ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE); - - Status = IoAcquireRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); - if (!NT_SUCCESS(Status)) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - - if (ChildDeviceExtension->Common.PnPState == SurpriseRemovePending || - ChildDeviceExtension->Common.PnPState == RemovePending || - ChildDeviceExtension->ParentDeviceObject == NULL) - { - // Parent or child device was surprise removed. - DPRINT1("[USBHUB] Request for removed device object %p\n", DeviceObject); - Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); - return STATUS_DEVICE_NOT_CONNECTED; - } - - HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension; - RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject; - - switch (Stack->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO: - { - DPRINT("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; - - pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer; - // FIXME - *pHubPointer = NULL; - Information = sizeof(PVOID); - Status = STATUS_SUCCESS; - } - break; - } - case IOCTL_INTERNAL_USB_SUBMIT_URB: - { - //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n"); - - // - // 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: - DPRINT("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n"); - break; - case URB_FUNCTION_CLASS_DEVICE: - DPRINT("URB_FUNCTION_CLASS_DEVICE\n"); - break; - case URB_FUNCTION_GET_STATUS_FROM_DEVICE: - DPRINT("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n"); - break; - case URB_FUNCTION_SELECT_CONFIGURATION: - DPRINT("URB_FUNCTION_SELECT_CONFIGURATION\n"); - break; - case URB_FUNCTION_SELECT_INTERFACE: - DPRINT("URB_FUNCTION_SELECT_INTERFACE\n"); - break; - case URB_FUNCTION_CLASS_OTHER: - DPRINT("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); - if (Urb->UrbBulkOrInterruptTransfer.TransferFlags == USBD_SHORT_TRANSFER_OK) - { - } - */ - break; - - } - case URB_FUNCTION_CLASS_INTERFACE: - DPRINT("URB_FUNCTION_CLASS_INTERFACE\n"); - break; - case URB_FUNCTION_VENDOR_DEVICE: - DPRINT("URB_FUNCTION_VENDOR_DEVICE\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 = ForwardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL); - IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); - return Status; - } - // - // 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: - { - PORT_STATUS_CHANGE PortStatus; - ULONG PortId; - PUCHAR PortStatusBits; - - PortStatusBits = (PUCHAR)Stack->Parameters.Others.Argument1; - // - // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1) - // - DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n"); - DPRINT("Arg1 %x\n", *PortStatusBits); - *PortStatusBits = 0; - if (Stack->Parameters.Others.Argument1) - { - for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++) - { - Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus); - if (NT_SUCCESS(Status)) - { - DPRINT("Connect %x\n", ((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)); - DPRINT("Enable %x\n", ((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2)); - *PortStatusBits += - (((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)) + - (((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2)); - - } - } - } - - DPRINT1("Arg1 %x\n", *PortStatusBits); - Status = STATUS_SUCCESS; - 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"); - if (Stack->Parameters.Others.Argument1) - { - // store device handle - *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)ChildDeviceExtension->UsbDeviceHandle; - Status = STATUS_SUCCESS; - } - else - { - // invalid parameter - Status = STATUS_INVALID_PARAMETER; - } - break; - } - case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO: - { - if (Stack->Parameters.Others.Argument1) - { - // inform caller that it is a real usb hub - *(PVOID *)Stack->Parameters.Others.Argument1 = NULL; - } - - if (Stack->Parameters.Others.Argument2) - { - // output device object - *(PVOID *)Stack->Parameters.Others.Argument2 = DeviceObject; - } - - // done - Status = STATUS_SUCCESS; - break; - } - default: - { - DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode); - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - } - } - - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - IoReleaseRemoveLock(&ChildDeviceExtension->Common.RemoveLock, Irp); - return Status; -} - -NTSTATUS -USBHUB_PdoStartDevice( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; - //NTSTATUS Status; - DPRINT("USBHUB_PdoStartDevice %x\n", DeviceObject); - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; - - // - // This should be a PDO - // - ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE); - - // - // register device interface - // - IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_DEVICE, NULL, &ChildDeviceExtension->SymbolicLinkName); - IoSetDeviceInterfaceState(&ChildDeviceExtension->SymbolicLinkName, TRUE); - - SET_NEW_PNP_STATE(ChildDeviceExtension->Common, Started); - - UNIMPLEMENTED; - return STATUS_SUCCESS; -} - -NTSTATUS -USBHUB_PdoQueryId( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - OUT ULONG_PTR* Information) -{ - PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; - ULONG IdType; - PUNICODE_STRING SourceString = NULL; - PWCHAR ReturnString = NULL; - NTSTATUS Status = STATUS_SUCCESS; - - IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType; - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; - - switch (IdType) - { - case BusQueryDeviceID: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n"); - SourceString = &ChildDeviceExtension->usDeviceId; - break; - } - case BusQueryHardwareIDs: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n"); - SourceString = &ChildDeviceExtension->usHardwareIds; - break; - } - case BusQueryCompatibleIDs: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n"); - SourceString = &ChildDeviceExtension->usCompatibleIds; - break; - } - case BusQueryInstanceID: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n"); - SourceString = &ChildDeviceExtension->usInstanceId; - break; - } - default: - DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType); - return STATUS_NOT_SUPPORTED; - } - - if (SourceString) - { - // - // allocate buffer - // - ReturnString = ExAllocatePool(PagedPool, SourceString->MaximumLength); - if (!ReturnString) - { - // - // no memory - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // copy buffer - // - RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->MaximumLength); - } - - *Information = (ULONG_PTR)ReturnString; - - return Status; -} - -NTSTATUS -USBHUB_PdoQueryDeviceText( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - OUT ULONG_PTR* Information) -{ - PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension; - DEVICE_TEXT_TYPE DeviceTextType; - PUNICODE_STRING SourceString = NULL; - PWCHAR ReturnString = NULL; - NTSTATUS Status = STATUS_SUCCESS; - - DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType; - ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; - - // - // FIXME: LocaleId - // - - switch (DeviceTextType) - { - case DeviceTextDescription: - case DeviceTextLocationInformation: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n"); - - // - // does the device provide a text description - // - if (ChildDeviceExtension->usTextDescription.Buffer && ChildDeviceExtension->usTextDescription.Length) - { - // - // use device text - // - SourceString = &ChildDeviceExtension->usTextDescription; - } - break; - } - default: - { - DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType); - Status = STATUS_NOT_SUPPORTED; - break; - } - } - - if (SourceString) - { - ReturnString = ExAllocatePool(PagedPool, SourceString->MaximumLength); - RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->MaximumLength); - DPRINT1("%S\n", ReturnString); - *Information = (ULONG_PTR)ReturnString; - } - - return Status; -} - -NTSTATUS -USBHUB_PdoHandlePnp( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - NTSTATUS Status; - ULONG MinorFunction; - PIO_STACK_LOCATION Stack; - ULONG_PTR Information = 0; - PHUB_CHILDDEVICE_EXTENSION UsbChildExtension; - PDEVICE_RELATIONS DeviceRelation; - - UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension; - Stack = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = Stack->MinorFunction; - - Status = IoAcquireRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); - if (!NT_SUCCESS(Status)) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - - switch (MinorFunction) - { - case IRP_MN_START_DEVICE: - { - DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); - Status = USBHUB_PdoStartDevice(DeviceObject, Irp); - break; - } - case IRP_MN_QUERY_CAPABILITIES: - { - PDEVICE_CAPABILITIES DeviceCapabilities; - ULONG i; - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n"); - - DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities; - // FIXME: capabilities can change with connected device - DeviceCapabilities->LockSupported = FALSE; - DeviceCapabilities->EjectSupported = FALSE; - DeviceCapabilities->Removable = TRUE; - DeviceCapabilities->DockDevice = FALSE; - DeviceCapabilities->UniqueID = FALSE; - DeviceCapabilities->SilentInstall = FALSE; - DeviceCapabilities->RawDeviceOK = FALSE; - DeviceCapabilities->SurpriseRemovalOK = FALSE; - DeviceCapabilities->HardwareDisabled = FALSE; - //DeviceCapabilities->NoDisplayInUI = FALSE; - DeviceCapabilities->Address = UsbChildExtension->PortNumber; - DeviceCapabilities->UINumber = 0; - DeviceCapabilities->DeviceState[0] = PowerDeviceD0; - for (i = 1; 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: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n"); - - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - break; - } - case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); - - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - break; - } - case IRP_MN_QUERY_DEVICE_TEXT: - { - DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n"); - Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information); - break; - } - case IRP_MN_QUERY_ID: - { - DPRINT("IRP_MN_QUERY_ID\n"); - Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information); - break; - } - case IRP_MN_QUERY_BUS_INFORMATION: - { - PPNP_BUS_INFORMATION BusInfo; - DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n"); - BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION)); - RtlCopyMemory(&BusInfo->BusTypeGuid, - &GUID_BUS_TYPE_USB, - sizeof(BusInfo->BusTypeGuid)); - BusInfo->LegacyBusType = PNPBus; - // FIXME - BusInfo->BusNumber = 0; - Information = (ULONG_PTR)BusInfo; - Status = STATUS_SUCCESS; - break; - } - case IRP_MN_REMOVE_DEVICE: - { - PHUB_DEVICE_EXTENSION HubDeviceExtension = (PHUB_DEVICE_EXTENSION)UsbChildExtension->ParentDeviceObject->DeviceExtension; - PUSB_BUS_INTERFACE_HUB_V5 HubInterface = &HubDeviceExtension->HubInterface; - - DPRINT("IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n"); - - ASSERT((UsbChildExtension->Common.PnPState == RemovePending) || - (UsbChildExtension->Common.PnPState == SurpriseRemovePending)); - - SET_NEW_PNP_STATE(UsbChildExtension->Common, NotStarted); - - if (!IsValidPDO(DeviceObject)) - { - // Parent or child device was surprise removed, freeing resources allocated for child device. - SET_NEW_PNP_STATE(UsbChildExtension->Common, Deleted); - - IoReleaseRemoveLockAndWait(&UsbChildExtension->Common.RemoveLock, Irp); - - // Remove the usb device - if (UsbChildExtension->UsbDeviceHandle) - { - Status = HubInterface->RemoveUsbDevice(HubInterface->BusContext, UsbChildExtension->UsbDeviceHandle, 0); - ASSERT(Status == STATUS_SUCCESS); - } - // Free full configuration descriptor - if (UsbChildExtension->FullConfigDesc) - ExFreePool(UsbChildExtension->FullConfigDesc); - - // Free ID buffers - if (UsbChildExtension->usCompatibleIds.Buffer) - ExFreePool(UsbChildExtension->usCompatibleIds.Buffer); - - if (UsbChildExtension->usDeviceId.Buffer) - ExFreePool(UsbChildExtension->usDeviceId.Buffer); - - if (UsbChildExtension->usHardwareIds.Buffer) - ExFreePool(UsbChildExtension->usHardwareIds.Buffer); - - if (UsbChildExtension->usInstanceId.Buffer) - ExFreePool(UsbChildExtension->usInstanceId.Buffer); - - DPRINT("Deleting child PDO\n"); - IoDeleteDevice(DeviceObject); - } - else - { - IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); - } - - // If device is physically presented, we leave its PDO undeleted. - - /* Complete the IRP */ - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_SUCCESS; - } - case IRP_MN_QUERY_DEVICE_RELATIONS: - { - /* only target relations are supported */ - if (Stack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) - { - /* not supported */ - Status = Irp->IoStatus.Status; - Information = Irp->IoStatus.Information; - break; - } - - /* allocate device relations */ - DeviceRelation = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS)); - if (!DeviceRelation) - { - /* no memory */ - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - /* init device relation */ - DeviceRelation->Count = 1; - DeviceRelation->Objects[0] = DeviceObject; - ObReferenceObject(DeviceRelation->Objects[0]); - - /* store result */ - Information = (ULONG_PTR)DeviceRelation; - Status = STATUS_SUCCESS; - break; - } - case IRP_MN_QUERY_STOP_DEVICE: - { - // - // We should fail this request, because we're not handling IRP_MN_STOP_DEVICE for now. - // We'll receive this IRP ONLY when the PnP manager rebalances resources. - // - Status = STATUS_NOT_SUPPORTED; - break; - } - case IRP_MN_QUERY_REMOVE_DEVICE: - { - // - // Free interface obtained from bottom, according MSDN we should - // check interfaces provided to top, but here we are not checking. - // All checking will be performed in roothub driver's - // IRP_MN_QUERY_REMOVE_DEVICE handler. This will make problems when - // buggy driver is loaded on top of us. But we decided to keep source - // simpler, because in any case buggy driver will prevent removing of - // whole stack. - // - UsbChildExtension->DeviceInterface.InterfaceDereference(UsbChildExtension->DeviceInterface.BusContext); - - SET_NEW_PNP_STATE(UsbChildExtension->Common, RemovePending); - - /* Sure, no problem */ - Status = STATUS_SUCCESS; - Information = 0; - break; - } - case IRP_MN_CANCEL_REMOVE_DEVICE: - { - // Check to see have we received query-remove before - if (UsbChildExtension->Common.PnPState == RemovePending) - { - RESTORE_PREVIOUS_PNP_STATE(UsbChildExtension->Common); - UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext); - } - - Status = STATUS_SUCCESS; - break; - } - case IRP_MN_QUERY_INTERFACE: - { - DPRINT1("IRP_MN_QUERY_INTERFACE\n"); - if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID)) - { - DPRINT1("USB_BUS_INTERFACE_USBDI_GUID\n"); - RtlCopyMemory(Stack->Parameters.QueryInterface.Interface, &UsbChildExtension->DeviceInterface, Stack->Parameters.QueryInterface.Size); - UsbChildExtension->DeviceInterface.InterfaceReference(UsbChildExtension->DeviceInterface.BusContext); - Status = STATUS_SUCCESS; - break; - } - - // pass irp down - IoSkipCurrentIrpStackLocation(Irp); - Status = IoCallDriver(UsbChildExtension->ParentDeviceObject, Irp); - IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); - return Status; - } - case IRP_MN_SURPRISE_REMOVAL: - { - DPRINT("[USBHUB] HandlePnp IRP_MN_SURPRISE_REMOVAL\n"); - - // - // Here we should free all resources and stop all access, lets just set - // the flag and do further clean-up in subsequent IRP_MN_REMOVE_DEVICE - // We can receive this IRP when device is physically connected (on stop/start fail). - // - SET_NEW_PNP_STATE(UsbChildExtension->Common, SurpriseRemovePending); - - Status = STATUS_SUCCESS; - break; - } - default: - { - DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); - Information = Irp->IoStatus.Information; - Status = Irp->IoStatus.Status; - } - } - - IoReleaseRemoveLock(&UsbChildExtension->Common.RemoveLock, Irp); - - Irp->IoStatus.Information = Information; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} - diff --git a/drivers/usb/usbhub/usbhub.c b/drivers/usb/usbhub/usbhub.c deleted file mode 100644 index da2b80dbe22..00000000000 --- a/drivers/usb/usbhub/usbhub.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Hub Driver - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbhub/usbhub.c - * PURPOSE: UsbHub Driver - * PROGRAMMERS: - * Hervé Poussineau (hpoussin@reactos.org) - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbhub.h" - -#define NDEBUG -#include - -NTSTATUS NTAPI -USBHUB_Create( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - DPRINT("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) -{ - DPRINT("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) -{ - DPRINT("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; - DPRINT("USBHUB: AddDevice (%p)\n", PhysicalDeviceObject); - // - // 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)); - - INITIALIZE_PNP_STATE(HubDeviceExtension->Common); - - // - // Set this to Fdo - // - HubDeviceExtension->Common.IsFDO = TRUE; - DeviceObject->Flags |= DO_POWER_PAGABLE; - - // initialize mutex - KeInitializeGuardedMutex(&HubDeviceExtension->HubMutexLock); - - // initialize remove lock - IoInitializeRemoveLock(&HubDeviceExtension->Common.RemoveLock, 'buH', 0, 0); - - // - // initialize reset complete event - // - KeInitializeEvent(&HubDeviceExtension->ResetComplete, NotificationEvent, FALSE); - - // - // 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) -{ - DPRINT("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_DispatchSystemControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - DPRINT("Usbhub: DispatchSystemControl\n"); - if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) - return USBHUB_IrpStub(DeviceObject, Irp); - else - return USBHUB_IrpStub(DeviceObject, Irp); -} - -NTSTATUS NTAPI -USBHUB_DispatchInternalDeviceControl( - PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - DPRINT("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) -{ - DPRINT("USBHUB: DispatchPnp\n"); - if (((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.IsFDO) - return USBHUB_FdoHandlePnp(DeviceObject, Irp); - else - return USBHUB_PdoHandlePnp(DeviceObject, Irp); -} - -NTSTATUS NTAPI -USBHUB_DispatchPower( - PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PHUB_DEVICE_EXTENSION DeviceExtension; - NTSTATUS Status; - IoStack = IoGetCurrentIrpStackLocation(Irp); - DeviceExtension = DeviceObject->DeviceExtension; - - Status = IoAcquireRemoveLock(&DeviceExtension->Common.RemoveLock, Irp); - if (!NT_SUCCESS(Status)) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - - DPRINT1("Power Function %x\n", IoStack->MinorFunction); - - if (DeviceExtension->Common.IsFDO) - { - PoStartNextPowerIrp(Irp); - IoSkipCurrentIrpStackLocation(Irp); - Status = PoCallDriver(DeviceExtension->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&DeviceExtension->Common.RemoveLock, Irp); - return Status; - } - - switch (IoStack->MinorFunction) - { - case IRP_MN_SET_POWER: - { - DPRINT("IRP_MN_SET_POWER\n"); - break; - } - case IRP_MN_QUERY_POWER: - { - DPRINT("IRP_MN_QUERY_POWER\n"); - break; - } - case IRP_MN_WAIT_WAKE: - { - DPRINT("IRP_MN_WAIT_WAKE\n"); - break; - } - default: - { - DPRINT1("PDO IRP_MJ_POWER / unknown minor function 0x%lx\n", IoStack->MinorFunction); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Irp->IoStatus.Status; - } - } - - PoStartNextPowerIrp(Irp); - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - IoReleaseRemoveLock(&DeviceExtension->Common.RemoveLock, Irp); - return STATUS_SUCCESS; -} - -VOID -NTAPI -USBHUB_Unload( - IN PDRIVER_OBJECT DriverObject) -{ - UNIMPLEMENTED; -} - - -NTSTATUS NTAPI -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath) -{ - DriverObject->DriverExtension->AddDevice = USBHUB_AddDevice; - DriverObject->DriverUnload = USBHUB_Unload; - - DPRINT("USBHUB: DriverEntry\n"); - - 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_SYSTEM_CONTROL] = USBHUB_DispatchSystemControl; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBHUB_DispatchInternalDeviceControl; - DriverObject->MajorFunction[IRP_MJ_PNP] = USBHUB_DispatchPnp; - DriverObject->MajorFunction[IRP_MJ_POWER] =USBHUB_DispatchPower; - - return STATUS_SUCCESS; -} - diff --git a/drivers/usb/usbhub/usbhub.h b/drivers/usb/usbhub/usbhub.h deleted file mode 100644 index 6265fb0cb48..00000000000 --- a/drivers/usb/usbhub/usbhub.h +++ /dev/null @@ -1,225 +0,0 @@ -#ifndef _USBHUB_H_ -#define _USBHUB_H_ - -#include -#include -#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 _WORK_ITEM_DATA -{ - WORK_QUEUE_ITEM WorkItem; - PVOID Context; -} WORK_ITEM_DATA, *PWORK_ITEM_DATA; - - -// -// Definitions for device's PnP state tracking, all this states are described -// in PnP Device States diagram of DDK documentation. -// -typedef enum _DEVICE_PNP_STATE { - - NotStarted = 0, // Not started - Started, // After handling of START_DEVICE IRP - StopPending, // After handling of QUERY_STOP IRP - Stopped, // After handling of STOP_DEVICE IRP - RemovePending, // After handling of QUERY_REMOVE IRP - SurpriseRemovePending, // After handling of SURPRISE_REMOVE IRP - Deleted, // After handling of REMOVE_DEVICE IRP - UnKnown // Unknown state - -} DEVICE_PNP_STATE; - -#define INITIALIZE_PNP_STATE(Data) \ -(Data).PnPState = NotStarted;\ -(Data).PreviousPnPState = NotStarted; - -#define SET_NEW_PNP_STATE(Data, state) \ -(Data).PreviousPnPState = (Data).PnPState;\ -(Data).PnPState = (state); - -#define RESTORE_PREVIOUS_PNP_STATE(Data) \ -(Data).PnPState = (Data).PreviousPnPState; - -typedef struct -{ - BOOLEAN IsFDO; - // We'll track device PnP state via this variables - DEVICE_PNP_STATE PnPState; - DEVICE_PNP_STATE PreviousPnPState; - // Remove lock - IO_REMOVE_LOCK RemoveLock; -} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; - -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; - UNICODE_STRING usCompatibleIds; - UNICODE_STRING usTextDescription; - UNICODE_STRING usLocationInformation; - USB_DEVICE_DESCRIPTOR DeviceDesc; - PUSB_CONFIGURATION_DESCRIPTOR FullConfigDesc; - UNICODE_STRING SymbolicLinkName; - USB_BUS_INTERFACE_USBDI_V2 DeviceInterface; - USB_DEVICE_INFORMATION_0 DeviceInformation; -} 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; - - KGUARDED_MUTEX HubMutexLock; - - ULONG NumberOfHubs; - KEVENT ResetComplete; - - 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; - ULONG InstanceCount; - -} 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); - -NTSTATUS -SubmitRequestToRootHub( - IN PDEVICE_OBJECT RootHubDeviceObject, - IN ULONG IoControlCode, - OUT PVOID OutParameter1, - OUT PVOID OutParameter2); - -NTSTATUS -FDO_QueryInterface( - IN PDEVICE_OBJECT DeviceObject, - IN OUT PUSB_BUS_INTERFACE_USBDI_V2 Interface); - -// 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); - -VOID -DumpFullConfigurationDescriptor( - PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor); - -NTSTATUS -GetPortStatusAndChange( - IN PDEVICE_OBJECT RootHubDeviceObject, - IN ULONG PortId, - OUT PPORT_STATUS_CHANGE StatusChange); - -// hub_fdo.c - -NTSTATUS -USBHUB_ParentFDOStartDevice( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - -#endif /* _USBHUB_H_ */ diff --git a/drivers/usb/usbhub/usbhub.rc b/drivers/usb/usbhub/usbhub.rc deleted file mode 100644 index 7ccaaec66bd..00000000000 --- a/drivers/usb/usbhub/usbhub.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "USBHUB Driver API" -#define REACTOS_STR_INTERNAL_NAME "usbhub" -#define REACTOS_STR_ORIGINAL_FILENAME "usbhub.sys" -#include diff --git a/drivers/usb/usbohci/CMakeLists.txt b/drivers/usb/usbohci/CMakeLists.txt deleted file mode 100644 index b8586088ad2..00000000000 --- a/drivers/usb/usbohci/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ - -set_cpp() - -remove_definitions(-D_WIN32_WINNT=0x502) -add_definitions(-D_WIN32_WINNT=0x600) - -include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/drivers/libusb) - -list(APPEND SOURCE - usbohci.cpp - usb_request.cpp - usb_queue.cpp - hardware.cpp - usbohci.h) - -add_library(usbohci MODULE - ${SOURCE} - guid.cpp - usbohci.rc) - -target_link_libraries(usbohci uuid libusb libcntpr ${PSEH_LIB}) -set_module_type(usbohci kernelmodedriver) -add_importlibs(usbohci ntoskrnl hal usbd) -add_pch(usbohci usbohci.h SOURCE) -add_cd_file(TARGET usbohci DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/usb/usbohci/guid.cpp b/drivers/usb/usbohci/guid.cpp deleted file mode 100644 index 50a60369ff3..00000000000 --- a/drivers/usb/usbohci/guid.cpp +++ /dev/null @@ -1,9 +0,0 @@ -/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */ - -#include -#include -#include -#include -#include - -/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */ diff --git a/drivers/usb/usbohci/hardware.cpp b/drivers/usb/usbohci/hardware.cpp deleted file mode 100644 index 4ff9bebd8b2..00000000000 --- a/drivers/usb/usbohci/hardware.cpp +++ /dev/null @@ -1,1584 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbohci/hcd_controller.cpp - * PURPOSE: USB OHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbohci.h" - -#define NDEBUG -#include - -typedef VOID __stdcall HD_INIT_CALLBACK(IN PVOID CallBackContext); - -BOOLEAN -NTAPI -InterruptServiceRoutine( - IN PKINTERRUPT Interrupt, - IN PVOID ServiceContext); - -VOID -NTAPI -OhciDeferredRoutine( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2); - -VOID -NTAPI -StatusChangeWorkItemRoutine(PVOID Context); - -class CUSBHardwareDevice : public IOHCIHardwareDevice -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - // com - IMP_IUSBHARDWAREDEVICE - IMP_IUSBOHCIHARDWAREDEVICE - - - // local - NTSTATUS StartController(); - NTSTATUS StopController(); - BOOLEAN InterruptService(); - NTSTATUS InitializeController(); - NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor); - - // friend function - friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); - friend VOID NTAPI OhciDeferredRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); - friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context); - // constructor / destructor - CUSBHardwareDevice(IUnknown *OuterUnknown){} - virtual ~CUSBHardwareDevice(){} - -protected: - LONG m_Ref; // reference count - PDRIVER_OBJECT m_DriverObject; // driver object - PDEVICE_OBJECT m_PhysicalDeviceObject; // pdo - PDEVICE_OBJECT m_FunctionalDeviceObject; // fdo (hcd controller) - PDEVICE_OBJECT m_NextDeviceObject; // lower device object - KSPIN_LOCK m_Lock; // hardware lock - PKINTERRUPT m_Interrupt; // interrupt object - KDPC m_IntDpcObject; // dpc object for deferred isr processing - PVOID VirtualBase; // virtual base for memory manager - PHYSICAL_ADDRESS PhysicalAddress; // physical base for memory manager - PULONG m_Base; // OHCI operational port base registers - PDMA_ADAPTER m_Adapter; // dma adapter object - ULONG m_MapRegisters; // map registers count - USHORT m_VendorID; // vendor id - USHORT m_DeviceID; // device id - POHCIQUEUE m_UsbQueue; // usb request queue - POHCIHCCA m_HCCA; // hcca virtual base - PHYSICAL_ADDRESS m_HCCAPhysicalAddress; // hcca physical address - POHCI_ENDPOINT_DESCRIPTOR m_ControlEndpointDescriptor; // dummy control endpoint descriptor - POHCI_ENDPOINT_DESCRIPTOR m_BulkEndpointDescriptor; // dummy control endpoint descriptor - POHCI_ENDPOINT_DESCRIPTOR m_IsoEndpointDescriptor; // iso endpoint descriptor - POHCI_ENDPOINT_DESCRIPTOR m_InterruptEndpoints[OHCI_STATIC_ENDPOINT_COUNT]; // endpoints for interrupt / iso transfers - ULONG m_NumberOfPorts; // number of ports - PDMAMEMORYMANAGER m_MemoryManager; // memory manager - HD_INIT_CALLBACK* m_SCECallBack; // status change callback routine - PVOID m_SCEContext; // status change callback routine context - WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback - volatile LONG m_StatusChangeWorkItemStatus; // work item active status - ULONG m_SyncFramePhysAddr; // periodic frame list physical address - ULONG m_IntervalValue; // periodic interval value -}; - -//================================================================================================= -// COM -// -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - if (IsEqualGUIDAligned(refiid, IID_IUnknown)) - { - *Output = PVOID(PUNKNOWN(this)); - PUNKNOWN(*Output)->AddRef(); - return STATUS_SUCCESS; - } - - return STATUS_UNSUCCESSFUL; -} - -LPCSTR -STDMETHODCALLTYPE -CUSBHardwareDevice::GetUSBType() -{ - return "USBOHCI"; -} - - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::Initialize( - PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT FunctionalDeviceObject, - PDEVICE_OBJECT PhysicalDeviceObject, - PDEVICE_OBJECT LowerDeviceObject) -{ - BUS_INTERFACE_STANDARD BusInterface; - PCI_COMMON_CONFIG PciConfig; - NTSTATUS Status; - ULONG BytesRead; - PUSBQUEUE Queue; - - DPRINT("CUSBHardwareDevice::Initialize\n"); - - // - // Create DMAMemoryManager for use with QueueHeads and Transfer Descriptors. - // - Status = CreateDMAMemoryManager(&m_MemoryManager); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create DMAMemoryManager Object\n"); - return Status; - } - - // - // Create the UsbQueue class that will handle the Asynchronous and Periodic Schedules - // - Status = CreateUSBQueue(&Queue); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create UsbQueue!\n"); - return Status; - } - - // get ohci queue - m_UsbQueue = POHCIQUEUE(Queue); - - // sanity check - ASSERT(m_UsbQueue); - - // - // store device objects - // - m_DriverObject = DriverObject; - m_FunctionalDeviceObject = FunctionalDeviceObject; - m_PhysicalDeviceObject = PhysicalDeviceObject; - m_NextDeviceObject = LowerDeviceObject; - - // - // initialize device lock - // - KeInitializeSpinLock(&m_Lock); - - // - // initialize status change work item - // - ExInitializeWorkItem(&m_StatusChangeWorkItem, StatusChangeWorkItemRoutine, PVOID(this)); - - m_VendorID = 0; - m_DeviceID = 0; - - Status = GetBusInterface(PhysicalDeviceObject, &BusInterface); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get BusInterface!\n"); - return Status; - } - - BytesRead = (*BusInterface.GetBusData)(BusInterface.Context, - PCI_WHICHSPACE_CONFIG, - &PciConfig, - 0, - PCI_COMMON_HDR_LENGTH); - - if (BytesRead != PCI_COMMON_HDR_LENGTH) - { - DPRINT1("Failed to get pci config information!\n"); - return STATUS_SUCCESS; - } - - m_VendorID = PciConfig.VendorID; - m_DeviceID = PciConfig.DeviceID; - - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::PnpStart( - PCM_RESOURCE_LIST RawResources, - PCM_RESOURCE_LIST TranslatedResources) -{ - ULONG Index; - PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor; - DEVICE_DESCRIPTION DeviceDescription; - PVOID ResourceBase; - NTSTATUS Status; - ULONG Version; - - DPRINT("CUSBHardwareDevice::PnpStart\n"); - for(Index = 0; Index < TranslatedResources->List[0].PartialResourceList.Count; Index++) - { - // - // get resource descriptor - // - ResourceDescriptor = &TranslatedResources->List[0].PartialResourceList.PartialDescriptors[Index]; - - switch(ResourceDescriptor->Type) - { - case CmResourceTypeInterrupt: - { - KeInitializeDpc(&m_IntDpcObject, - OhciDeferredRoutine, - this); - - Status = IoConnectInterrupt(&m_Interrupt, - InterruptServiceRoutine, - (PVOID)this, - NULL, - ResourceDescriptor->u.Interrupt.Vector, - (KIRQL)ResourceDescriptor->u.Interrupt.Level, - (KIRQL)ResourceDescriptor->u.Interrupt.Level, - (KINTERRUPT_MODE)(ResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED), - (ResourceDescriptor->ShareDisposition != CmResourceShareDeviceExclusive), - ResourceDescriptor->u.Interrupt.Affinity, - FALSE); - - if (!NT_SUCCESS(Status)) - { - // - // failed to register interrupt - // - DPRINT1("IoConnect Interrupt failed with %x\n", Status); - return Status; - } - break; - } - case CmResourceTypeMemory: - { - // - // get resource base - // - ResourceBase = MmMapIoSpace(ResourceDescriptor->u.Memory.Start, ResourceDescriptor->u.Memory.Length, MmNonCached); - if (!ResourceBase) - { - // - // failed to map registers - // - DPRINT1("MmMapIoSpace failed\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Get controllers capabilities - // - Version = READ_REGISTER_ULONG((PULONG)((ULONG_PTR)ResourceBase + OHCI_REVISION_OFFSET)); - - DPRINT("Version %x\n", Version & 0xFFFF); - - // - // Store Resource base - // - m_Base = (PULONG)ResourceBase; - break; - } - } - } - - - // - // zero device description - // - RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION)); - - // - // initialize device description - // - DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; - DeviceDescription.Master = TRUE; - DeviceDescription.ScatterGather = TRUE; - DeviceDescription.Dma32BitAddresses = TRUE; - DeviceDescription.DmaWidth = Width32Bits; - DeviceDescription.InterfaceType = PCIBus; - DeviceDescription.MaximumLength = MAXULONG; - - // - // get dma adapter - // - m_Adapter = IoGetDmaAdapter(m_PhysicalDeviceObject, &DeviceDescription, &m_MapRegisters); - if (!m_Adapter) - { - // - // failed to get dma adapter - // - DPRINT1("Failed to acquire dma adapter\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Create Common Buffer - // - VirtualBase = m_Adapter->DmaOperations->AllocateCommonBuffer(m_Adapter, - PAGE_SIZE * 4, - &PhysicalAddress, - FALSE); - if (!VirtualBase) - { - DPRINT1("Failed to allocate a common buffer\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Initialize the DMAMemoryManager - // - Status = m_MemoryManager->Initialize(this, &m_Lock, PAGE_SIZE * 4, VirtualBase, PhysicalAddress, 32); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize the DMAMemoryManager\n"); - return Status; - } - - // - // initializes the controller - // - Status = InitializeController(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to Initialize the controller \n"); - return Status; - } - - // - // Initialize the UsbQueue now that we have an AdapterObject. - // - Status = m_UsbQueue->Initialize(this, m_Adapter, m_MemoryManager, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to Initialize the UsbQueue\n"); - return Status; - } - - // - // Start the controller - // - DPRINT("Starting Controller\n"); - Status = StartController(); - - // - // done - // - return Status; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::PnpStop(void) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::GetDeviceDetails( - OUT OPTIONAL PUSHORT VendorId, - OUT OPTIONAL PUSHORT DeviceId, - OUT OPTIONAL PULONG NumberOfPorts, - OUT OPTIONAL PULONG Speed) -{ - if (VendorId) - { - // - // get vendor - // - *VendorId = m_VendorID; - } - - if (DeviceId) - { - // - // get device id - // - *DeviceId = m_DeviceID; - } - - if (NumberOfPorts) - { - // - // get number of ports - // - *NumberOfPorts = m_NumberOfPorts; - } - - if (Speed) - { - // - // speed is 0x100 - // - *Speed = 0x100; - } - - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::GetDMA( - OUT struct IDMAMemoryManager **OutDMAMemoryManager) -{ - if (!m_MemoryManager) - return STATUS_UNSUCCESSFUL; - *OutDMAMemoryManager = m_MemoryManager; - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::GetUSBQueue( - OUT struct IUSBQueue **OutUsbQueue) -{ - if (!m_UsbQueue) - return STATUS_UNSUCCESSFUL; - *OutUsbQueue = m_UsbQueue; - return STATUS_SUCCESS; -} - - -NTSTATUS -CUSBHardwareDevice::StartController(void) -{ - ULONG Control, Descriptor, FrameInterval, Periodic, Port, Reset, Index; - ULONG NewControl, WaitInMs; - LARGE_INTEGER Timeout; - BOOLEAN Again = FALSE; - - // - // check context - // - Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET)); - - //Save this - NewControl = Control & OHCI_REMOTE_WAKEUP_CONNECTED; - - if ((Control & OHCI_INTERRUPT_ROUTING)) - { - // - // change ownership - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_OWNERSHIP_CHANGE_REQUEST); - for(Index = 0; Index < 100; Index++) - { - // - // wait a bit - // - KeStallExecutionProcessor(100); - - // - // check control - // - Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET)); - if (!(Control & OHCI_INTERRUPT_ROUTING)) - { - // - // acquired ownership - // - break; - } - } - - // - // if the ownership is still not changed, perform reset - // - if (Control & OHCI_INTERRUPT_ROUTING) - { - DPRINT1("SMM not responding\n"); - } - else - { - DPRINT1("SMM has given up ownership\n"); - } - } - - // - // read contents of control register - // - - Control = (READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET)) & OHCI_HC_FUNCTIONAL_STATE_MASK); - DPRINT("Controller State %x\n", Control); - - switch (Control) - { - case OHCI_HC_FUNCTIONAL_STATE_RESET: - NewControl |= OHCI_HC_FUNCTIONAL_STATE_RESET; - WaitInMs = 50; - break; - - case OHCI_HC_FUNCTIONAL_STATE_SUSPEND: - case OHCI_HC_FUNCTIONAL_STATE_RESUME: - NewControl |= OHCI_HC_FUNCTIONAL_STATE_RESUME; - WaitInMs = 10; - break; - - default: - WaitInMs = 0; - break; - } - -retry: - if (WaitInMs != 0) - { - // Do the state transition - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET), NewControl); - - if (!Again) - { - // - // delay is 100 ms - // - Timeout.QuadPart = WaitInMs; - DPRINT("Waiting %lu milliseconds for controller to transition state\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - } - } - - // - // now reset controller - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_HOST_CONTROLLER_RESET); - - // - // reset time is 10ms - // - for(Index = 0; Index < 100; Index++) - { - // - // wait a bit - // - KeStallExecutionProcessor(10); - - // - // read command status - // - Reset = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET)); - - // - // was reset bit cleared - // - if ((Reset & OHCI_HOST_CONTROLLER_RESET) == 0) - { - // - // controller completed reset - // - break; - } - } - - if ((Reset & OHCI_HOST_CONTROLLER_RESET)) - { - // - // failed to reset controller - // - return STATUS_UNSUCCESSFUL; - } - - // - // get frame interval - // - FrameInterval = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET)); - m_IntervalValue = OHCI_GET_INTERVAL_VALUE(FrameInterval); - - FrameInterval = ((FrameInterval & OHCI_FRAME_INTERVAL_TOGGLE) ^ OHCI_FRAME_INTERVAL_TOGGLE); - - DPRINT("FrameInterval %x IntervalValue %x\n", FrameInterval, m_IntervalValue); - FrameInterval |= OHCI_FSMPS(m_IntervalValue) | m_IntervalValue; - DPRINT("Computed FrameInterval %x\n", FrameInterval); - - // - // write frame interval - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET), FrameInterval); - - FrameInterval = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET)); - DPRINT("Read FrameInterval %x\n", FrameInterval); - - // - // 90 % periodic - // - Periodic = OHCI_PERIODIC(m_IntervalValue); - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_PERIODIC_START_OFFSET), Periodic); - DPRINT("Computed Periodic Start %x\n", Periodic); - - Periodic = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_PERIODIC_START_OFFSET)); - DPRINT("Read Periodic Start %x\n", Periodic); - - // Linux does this hack for some bad controllers - if (!(FrameInterval & 0x3FFF0000) || - !(Periodic)) - { - if (!Again) - { - DPRINT1("Trying reset again on faulty controller\n"); - Again = TRUE; - goto retry; - } - else - { - DPRINT1("Second reset didn't solve the problem, failing\n"); - return STATUS_UNSUCCESSFUL; - } - } - - // - // lets write physical address of dummy control endpoint descriptor - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_HEAD_ED_OFFSET), m_ControlEndpointDescriptor->PhysicalAddress.LowPart); - - // - // lets write physical address of dummy bulk endpoint descriptor - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_BULK_HEAD_ED_OFFSET), m_BulkEndpointDescriptor->PhysicalAddress.LowPart); - - // - // read descriptor A - // - Descriptor = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_A_OFFSET)); - - // - // get port count (in a loop due to AMD errata) - // - do - { - KeStallExecutionProcessor(20); - m_NumberOfPorts = OHCI_RH_GET_PORT_COUNT(Descriptor); - } while (m_NumberOfPorts == 0); - - DPRINT("NumberOfPorts %lu\n", m_NumberOfPorts); - ASSERT(m_NumberOfPorts < OHCI_MAX_PORT_COUNT); - - // - // no over current protection - // - Descriptor |= OHCI_RH_NO_OVER_CURRENT_PROTECTION; - - // - // power switching on - // - Descriptor &= ~OHCI_RH_NO_POWER_SWITCHING; - - // - // control each port power independently - // - Descriptor |= OHCI_RH_POWER_SWITCHING_MODE; - - // - // write the configuration back - // - DPRINT("Descriptor A: %x\n", Descriptor); - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_A_OFFSET), Descriptor); - - // - // read descriptor B - // - Descriptor = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_B_OFFSET)); - - // - // set power power control for each port to use PPS - // - for (Port = 1; Port <= m_NumberOfPorts; Port++) - { - Descriptor |= (1 << (16 + Port)); - } - - // - // write the configuration back - // - DPRINT("Descriptor B: %x\n", Descriptor); - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_B_OFFSET), Descriptor); - - // - // HCCA alignment check - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_HCCA_OFFSET), 0xFFFFFFFF); - KeStallExecutionProcessor(10); - Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_HCCA_OFFSET)); - ASSERT((m_HCCAPhysicalAddress.LowPart & Control) == m_HCCAPhysicalAddress.LowPart); - DPRINT("HCCA: %x Alignment mask: %x\n", m_HCCAPhysicalAddress.LowPart, Control); - - // - // write address of HCCA - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_HCCA_OFFSET), m_HCCAPhysicalAddress.LowPart); - - // - // now enable the interrupts - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_NORMAL_INTERRUPTS | OHCI_MASTER_INTERRUPT_ENABLE); - - // - // enable all queues - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET), (NewControl & OHCI_REMOTE_WAKEUP_CONNECTED) | OHCI_ENABLE_LIST); - - // - // start the controller - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET), OHCI_ENABLE_LIST | - (NewControl & OHCI_REMOTE_WAKEUP_CONNECTED) | - OHCI_CONTROL_BULK_RATIO_1_4 | - OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL); - - // - // wait a bit - // - KeStallExecutionProcessor(100); - - // - // is the controller started - // - Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET)); - - // - // assert that the controller has been started - // - ASSERT((Control & OHCI_HC_FUNCTIONAL_STATE_MASK) == OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL); - ASSERT((Control & OHCI_ENABLE_LIST) == OHCI_ENABLE_LIST); - DPRINT("Control %x\n", Control); - - // - // done - // - DPRINT("OHCI controller is operational\n"); - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::AllocateEndpointDescriptor( - OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor) -{ - POHCI_ENDPOINT_DESCRIPTOR Descriptor; - PHYSICAL_ADDRESS DescriptorAddress; - NTSTATUS Status; - - // - // allocate descriptor - // - Status = m_MemoryManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR), (PVOID*)&Descriptor, &DescriptorAddress); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate descriptor - // - return Status; - } - - // - // initialize descriptor - // - Descriptor->Flags = OHCI_ENDPOINT_SKIP; - Descriptor->HeadPhysicalDescriptor = 0; - Descriptor->NextPhysicalEndpoint = 0; - Descriptor->TailPhysicalDescriptor = 0; - Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart; - - // - // store result - // - *OutDescriptor = Descriptor; - - // - // done - // - return STATUS_SUCCESS; -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::GetBulkHeadEndpointDescriptor( - struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) -{ - *OutDescriptor = m_BulkEndpointDescriptor; -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::GetInterruptEndpointDescriptors( - struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptor) -{ - *OutDescriptor = m_InterruptEndpoints; -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::GetIsochronousHeadEndpointDescriptor( - struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) -{ - *OutDescriptor = m_IsoEndpointDescriptor; -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::HeadEndpointDescriptorModified( - ULONG Type) -{ - if (Type == USB_ENDPOINT_TYPE_CONTROL) - { - // - // notify controller - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_CONTROL_LIST_FILLED); - } - else if (Type == USB_ENDPOINT_TYPE_BULK) - { - // - // notify controller - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_COMMAND_STATUS_OFFSET), OHCI_BULK_LIST_FILLED); - } -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::GetControlHeadEndpointDescriptor( - struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) -{ - *OutDescriptor = m_ControlEndpointDescriptor; -} - -NTSTATUS -CUSBHardwareDevice::InitializeController() -{ - NTSTATUS Status; - ULONG Index, Interval, IntervalIndex, InsertIndex; - POHCI_ENDPOINT_DESCRIPTOR Descriptor; - - // - // first allocate the hcca area - // - Status = m_MemoryManager->Allocate(sizeof(OHCIHCCA), (PVOID*)&m_HCCA, &m_HCCAPhysicalAddress); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - return Status; - } - - // - // now allocate an endpoint for control transfers - // this endpoint will never be removed - // - Status = AllocateEndpointDescriptor(&m_ControlEndpointDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - return Status; - } - - // - // now allocate an endpoint for bulk transfers - // this endpoint will never be removed - // - Status = AllocateEndpointDescriptor(&m_BulkEndpointDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - return Status; - } - - // - // now allocate an endpoint for iso transfers - // this endpoint will never be removed - // - Status = AllocateEndpointDescriptor(&m_IsoEndpointDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - return Status; - } - - // - // now allocate endpoint descriptors for iso / interrupt transfers interval is 1,2,4,8,16,32 - // - for(Index = 0; Index < OHCI_STATIC_ENDPOINT_COUNT; Index++) - { - // - // allocate endpoint descriptor - // - Status = AllocateEndpointDescriptor(&Descriptor); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - return Status; - } - - // - // save in array - // - m_InterruptEndpoints[Index] = Descriptor; - } - - - // - // now link the descriptors, taken from Haiku - // - Interval = OHCI_BIGGEST_INTERVAL; - IntervalIndex = OHCI_STATIC_ENDPOINT_COUNT - 1; - while (Interval > 1) - { - InsertIndex = Interval / 2; - while (InsertIndex < OHCI_BIGGEST_INTERVAL) - { - // - // assign endpoint address - // - m_HCCA->InterruptTable[InsertIndex] = m_InterruptEndpoints[IntervalIndex]->PhysicalAddress.LowPart; - InsertIndex += Interval; - } - - IntervalIndex--; - Interval /= 2; - } - - // - // link all endpoint descriptors to first descriptor in array - // - m_HCCA->InterruptTable[0] = m_InterruptEndpoints[0]->PhysicalAddress.LowPart; - for (Index = 1; Index < OHCI_STATIC_ENDPOINT_COUNT; Index++) - { - // - // link descriptor - // - m_InterruptEndpoints[Index]->NextPhysicalEndpoint = m_InterruptEndpoints[0]->PhysicalAddress.LowPart; - } - - // - // Now link the first endpoint to the isochronous endpoint - // - m_InterruptEndpoints[0]->NextPhysicalEndpoint = m_IsoEndpointDescriptor->PhysicalAddress.LowPart; - - // - // set iso endpoint type - // - m_IsoEndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT; - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::StopController(void) -{ - ASSERT(FALSE); - - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::ResetPort( - IN ULONG PortIndex) -{ - ASSERT(FALSE); - - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::GetPortStatus( - ULONG PortId, - OUT USHORT *PortStatus, - OUT USHORT *PortChange) -{ - ULONG Value; - - if (PortId > m_NumberOfPorts) - return STATUS_UNSUCCESSFUL; - - // init result variables - *PortStatus = 0; - *PortChange = 0; - - // - // read port status - // - Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId))); - DPRINT("GetPortStatus PortId %x Value %x\n", PortId, Value); - - // connected - if (Value & OHCI_RH_PORTSTATUS_CCS) - { - *PortStatus |= USB_PORT_STATUS_CONNECT; - - // low speed device - if (Value & OHCI_RH_PORTSTATUS_LSDA) - *PortStatus |= USB_PORT_STATUS_LOW_SPEED; - } - - // did a device connect? - if (Value & OHCI_RH_PORTSTATUS_CSC) - *PortChange |= USB_PORT_STATUS_CONNECT; - - // port enabled - if (Value & OHCI_RH_PORTSTATUS_PES) - *PortStatus |= USB_PORT_STATUS_ENABLE; - - // port disconnect or hardware error - if (Value & OHCI_RH_PORTSTATUS_PESC) - *PortChange |= USB_PORT_STATUS_CONNECT; - - // port suspend - if (Value & OHCI_RH_PORTSTATUS_PSS) - *PortStatus |= USB_PORT_STATUS_SUSPEND; - - // port suspend - if (Value & OHCI_RH_PORTSTATUS_PSSC) - *PortChange |= USB_PORT_STATUS_ENABLE; - - // port reset started - if (Value & OHCI_RH_PORTSTATUS_PRS) - *PortStatus |= USB_PORT_STATUS_RESET; - - // port reset ended - if (Value & OHCI_RH_PORTSTATUS_PRSC) - *PortChange |= USB_PORT_STATUS_RESET; - - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::ClearPortStatus( - ULONG PortId, - ULONG Status) -{ - ULONG Value; - - DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status); - - if (PortId > m_NumberOfPorts) - return STATUS_UNSUCCESSFUL; - - Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId))); - - if (Status == C_PORT_RESET) - { - // - // sanity checks - // - ASSERT((Value & OHCI_RH_PORTSTATUS_PRSC)); - - // - // clear reset bit complete - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRSC); - - // - // sanity check - // - ASSERT((Value & OHCI_RH_PORTSTATUS_PES)); - } - - if (Status == C_PORT_CONNECTION || Status == C_PORT_ENABLE) - { - // - // clear change bits - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), Value & (OHCI_RH_PORTSTATUS_CSC | OHCI_RH_PORTSTATUS_PESC)); - - // - // wait for port to stabilize - // - if (Status == C_PORT_CONNECTION && (Value & OHCI_RH_PORTSTATUS_CCS)) - { - LARGE_INTEGER Timeout; - - // - // delay is 100 ms - // - Timeout.QuadPart = 100; - DPRINT1("Waiting %lu milliseconds for port to stabilize after connection\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - } - } - - // - // re-enable root hub change - // - DPRINT("Enabling status change\n"); - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE); - - return STATUS_SUCCESS; -} - - -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::SetPortFeature( - ULONG PortId, - ULONG Feature) -{ - ULONG Value; - - DPRINT("CUSBHardwareDevice::SetPortFeature PortId %x Feature %x\n", PortId, Feature); - - // - // read port status - // - Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId))); - - - if (Feature == PORT_ENABLE) - { - // - // enable port - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PES); - return STATUS_SUCCESS; - } - else if (Feature == PORT_POWER) - { - LARGE_INTEGER Timeout; - - // - // enable power - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PPS); - - // - // read descriptor A for the delay data - // - Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_A_OFFSET)); - - // - // compute the delay - // - Timeout.QuadPart = OHCI_RH_GET_POWER_ON_TO_POWER_GOOD_TIME(Value); - - // - // delay is multiplied by 2 ms - // - Timeout.QuadPart *= 2; - DPRINT("Waiting %lu milliseconds for port power up\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - - return STATUS_SUCCESS; - } - else if (Feature == PORT_SUSPEND) - { - // - // enable port - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PSS); - return STATUS_SUCCESS; - } - else if (Feature == PORT_RESET) - { - // - // assert - // - ASSERT((Value & OHCI_RH_PORTSTATUS_CCS)); - - // - // reset port - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRS); - - // - // an interrupt signals the reset completion - // - return STATUS_SUCCESS; - } - return STATUS_SUCCESS; -} - - - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::SetStatusChangeEndpointCallBack( - PVOID CallBack, - PVOID Context) -{ - m_SCECallBack = (HD_INIT_CALLBACK*)CallBack; - m_SCEContext = Context; -} - -VOID -STDMETHODCALLTYPE -CUSBHardwareDevice::GetCurrentFrameNumber( - PULONG FrameNumber) -{ - ULONG Control; - ULONG Number; - - - Number = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_NUMBER_OFFSET)); - DPRINT("FrameNumberInterval %x Frame %x\n", Number, m_HCCA->CurrentFrameNumber); - - // - // remove reserved bits - // - Number &= 0xFFFF; - - // - // store frame number - // - *FrameNumber = Number; - - // - // is the controller started - // - Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET)); - ASSERT((Control & OHCI_ENABLE_LIST) == OHCI_ENABLE_LIST); - - -} - - -BOOLEAN -NTAPI -InterruptServiceRoutine( - IN PKINTERRUPT Interrupt, - IN PVOID ServiceContext) -{ - CUSBHardwareDevice *This; - ULONG DoneHead, Status, Acknowledge = 0; - - // - // get context - // - This = (CUSBHardwareDevice*) ServiceContext; - - DPRINT("InterruptServiceRoutine\n"); - - // - // get done head - // - DoneHead = This->m_HCCA->DoneHead; - - // - // check if zero - // - if (DoneHead == 0) - { - // - // the interrupt was not caused by DoneHead update - // check if something important happened - // - DPRINT("InterruptStatus %x InterruptEnable %x\n", READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)), - READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_ENABLE_OFFSET))); - Status = READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)) & READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_ENABLE_OFFSET)) & (~OHCI_WRITEBACK_DONE_HEAD); - if (Status == 0) - { - // - // nothing happened, appears to be shared interrupt - // - return FALSE; - } - } - else - { - // - // DoneHead update happened, check if there are other events too - // - Status = OHCI_WRITEBACK_DONE_HEAD; - - // - // since ed descriptors are 16 byte aligned, the controller sets the lower bits if there were other interrupt requests - // - if (DoneHead & OHCI_DONE_INTERRUPTS) - { - // - // get other events - // - Status |= READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET)) & READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_ENABLE_OFFSET)); - } - } - - // - // sanity check - // - ASSERT(Status != 0); - - if (Status & OHCI_WRITEBACK_DONE_HEAD) - { - // - // head completed - // - Acknowledge |= OHCI_WRITEBACK_DONE_HEAD; - This->m_HCCA->DoneHead = 0; - } - - if (Status & OHCI_RESUME_DETECTED) - { - // - // resume - // - DPRINT1("InterruptServiceRoutine> Resume\n"); - Acknowledge |= OHCI_RESUME_DETECTED; - } - - - if (Status & OHCI_UNRECOVERABLE_ERROR) - { - DPRINT1("InterruptServiceRoutine> Controller error\n"); - - // - // halt controller - // - ASSERT(FALSE); - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_CONTROL_OFFSET), OHCI_HC_FUNCTIONAL_STATE_RESET); - } - - if (Status & OHCI_ROOT_HUB_STATUS_CHANGE) - { - // - // disable interrupt as it will fire untill the port has been reset - // - DPRINT1("Disabling status change interrupt\n"); - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_DISABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE); - Acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE; - } - - // - // is there something to acknowledge - // - if (Acknowledge) - { - // - // ack change - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_INTERRUPT_STATUS_OFFSET), Acknowledge); - } - - // - // defer processing - // - DPRINT("Status %x Acknowledge %x FrameNumber %x\n", Status, Acknowledge, This->m_HCCA->CurrentFrameNumber); - KeInsertQueueDpc(&This->m_IntDpcObject, UlongToPtr(Status), UlongToPtr(DoneHead & ~1)); - - // - // interrupt handled - // - return TRUE; -} - -VOID -NTAPI -OhciDeferredRoutine( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2) -{ - CUSBHardwareDevice *This; - ULONG CStatus, Index, PortStatus; - ULONG DoneHead, QueueSCEWorkItem; - - // - // get parameters - // - This = (CUSBHardwareDevice*)DeferredContext; - CStatus = PtrToUlong(SystemArgument1); - DoneHead = PtrToUlong(SystemArgument2); - - DPRINT("OhciDeferredRoutine Status %x DoneHead %x\n", CStatus, DoneHead); - - if (CStatus & OHCI_WRITEBACK_DONE_HEAD) - { - // - // notify queue of event - // - This->m_UsbQueue->TransferDescriptorCompletionCallback(DoneHead); - } - if (CStatus & OHCI_ROOT_HUB_STATUS_CHANGE) - { - // - // device connected, lets check which port - // - QueueSCEWorkItem = FALSE; - for(Index = 0; Index < This->m_NumberOfPorts; Index++) - { - // - // read port status - // - PortStatus = READ_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_RH_PORT_STATUS(Index))); - - // - // check if there is a status change - // - if (PortStatus & OHCI_RH_PORTSTATUS_CSC) - { - // - // did a device connect - // - if (PortStatus & OHCI_RH_PORTSTATUS_CCS) - { - // - // device connected - // - DPRINT1("New device arrival at Port %lu LowSpeed %x\n", Index, (PortStatus & OHCI_RH_PORTSTATUS_LSDA)); - - // - // enable port - // - WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_RH_PORT_STATUS(Index)), OHCI_RH_PORTSTATUS_PES); - } - else - { - // - // device disconnected - // - DPRINT1("Device disconnected at Port %x\n", Index); - } - - // - // work to do - // - QueueSCEWorkItem = TRUE; - } - else if (PortStatus & OHCI_RH_PORTSTATUS_PESC) - { - // - // device disconnected or some error condition - // - ASSERT(!(PortStatus & OHCI_RH_PORTSTATUS_PES)); - - // - // work to do - // - QueueSCEWorkItem = TRUE; - } - else if (PortStatus & OHCI_RH_PORTSTATUS_PRSC) - { - // - // This is a port reset complete interrupt - // - DPRINT1("Port %lu completed reset\n", Index); - - // - // Queue a work item - // - QueueSCEWorkItem = TRUE; - } - } - - // - // is there a status change callback and a device connected / disconnected - // - if (QueueSCEWorkItem && This->m_SCECallBack != NULL) - { - if (InterlockedCompareExchange(&This->m_StatusChangeWorkItemStatus, 1, 0) == 0) - { - // - // queue work item for processing - // - ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue); - } - } - } -} - -VOID -NTAPI -StatusChangeWorkItemRoutine( - PVOID Context) -{ - // - // cast to hardware object - // - CUSBHardwareDevice * This = (CUSBHardwareDevice*)Context; - - // - // is there a callback - // - if (This->m_SCECallBack) - { - // - // issue callback - // - This->m_SCECallBack(This->m_SCEContext); - } - - // - // reset active status - // - InterlockedDecrement(&This->m_StatusChangeWorkItemStatus); -} - -NTSTATUS -NTAPI -CreateUSBHardware( - PUSBHARDWAREDEVICE *OutHardware) -{ - PUSBHARDWAREDEVICE This; - - This = new(NonPagedPool, TAG_USBOHCI) CUSBHardwareDevice(0); - - if (!This) - return STATUS_INSUFFICIENT_RESOURCES; - - This->AddRef(); - - // return result - *OutHardware = (PUSBHARDWAREDEVICE)This; - - return STATUS_SUCCESS; -} diff --git a/drivers/usb/usbohci/hardware.h b/drivers/usb/usbohci/hardware.h deleted file mode 100644 index 35e214c8a2b..00000000000 --- a/drivers/usb/usbohci/hardware.h +++ /dev/null @@ -1,347 +0,0 @@ -#pragma once - -// -// OHCI Operational Registers -// - -#define OHCI_REVISION_OFFSET (0x00) -#define OHCI_REVISION_LOW(rev) ((rev) & 0x0f) -#define OHCI_REVISION_HIGH(rev) (((rev) >> 4) & 0x03) - - -// -// OHCI Control Register -// -#define OHCI_CONTROL_OFFSET (0x004) -#define OHCI_CONTROL_BULK_SERVICE_RATIO_MASK (0x003) -#define OHCI_CONTROL_BULK_RATIO_1_1 (0x000) -#define OHCI_CONTROL_BULK_RATIO_1_2 (0x001) -#define OHCI_CONTROL_BULK_RATIO_1_3 (0x002) -#define OHCI_CONTROL_BULK_RATIO_1_4 (0x003) -#define OHCI_PERIODIC_LIST_ENABLE (0x004) -#define OHCI_ISOCHRONOUS_ENABLE (0x008) -#define OHCI_CONTROL_LIST_ENABLE (0x010) -#define OHCI_BULK_LIST_ENABLE (0x020) -#define OHCI_HC_FUNCTIONAL_STATE_MASK (0x0C0) -#define OHCI_HC_FUNCTIONAL_STATE_RESET (0x000) -#define OHCI_HC_FUNCTIONAL_STATE_RESUME (0x040) -#define OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL (0x080) -#define OHCI_HC_FUNCTIONAL_STATE_SUSPEND (0x0c0) -#define OHCI_INTERRUPT_ROUTING (0x100) -#define OHCI_REMOTE_WAKEUP_CONNECTED (0x200) -#define OHCI_REMORE_WAKEUP_ENABLED (0x400) - -// -// OHCI Command Status Register -// -#define OHCI_COMMAND_STATUS_OFFSET (0x08) -#define OHCI_HOST_CONTROLLER_RESET 0x00000001 -#define OHCI_CONTROL_LIST_FILLED 0x00000002 -#define OHCI_BULK_LIST_FILLED 0x00000004 -#define OHCI_OWNERSHIP_CHANGE_REQUEST 0x00000008 -#define OHCI_SCHEDULING_OVERRUN_COUNT_MASK 0x00030000 - - -// -// OHCI Interrupt Status Register -// -#define OHCI_INTERRUPT_STATUS_OFFSET 0x0c -#define OHCI_SCHEDULING_OVERRUN 0x00000001 -#define OHCI_WRITEBACK_DONE_HEAD 0x00000002 -#define OHCI_START_OF_FRAME 0x00000004 -#define OHCI_RESUME_DETECTED 0x00000008 -#define OHCI_UNRECOVERABLE_ERROR 0x00000010 -#define OHCI_FRAME_NUMBER_OVERFLOW 0x00000020 -#define OHCI_ROOT_HUB_STATUS_CHANGE 0x00000040 -#define OHCI_OWNERSHIP_CHANGE 0x40000000 -#define OHCI_MASTER_INTERRUPT_ENABLE 0x80000000 - - -// -// OHCI Interrupt Enable Register -// -#define OHCI_INTERRUPT_ENABLE_OFFSET 0x10 - -// -// OHCI Interrupt Enable Register -// -#define OHCI_INTERRUPT_DISABLE_OFFSET 0x14 - -// -// OHCI HCCA Register -// -#define OHCI_HCCA_OFFSET 0x18 -#define OHCI_PERIOD_CURRENT_ED_OFFSET 0x1c -#define OHCI_CONTROL_HEAD_ED_OFFSET 0x20 -#define OHCI_CONTROL_CURRENT_ED_OFFSET 0x24 -#define OHCI_BULK_HEAD_ED_OFFSET 0x28 - -// -// OHCI Root Hub Descriptor A register -// -#define OHCI_RH_DESCRIPTOR_A_OFFSET 0x48 -#define OHCI_RH_GET_PORT_COUNT(s) ((s) & 0xff) -#define OHCI_RH_POWER_SWITCHING_MODE 0x0100 -#define OHCI_RH_NO_POWER_SWITCHING 0x0200 -#define OHCI_RH_DEVICE_TYPE 0x0400 -#define OHCI_RH_OVER_CURRENT_PROTECTION_MODE 0x0800 -#define OHCI_RH_NO_OVER_CURRENT_PROTECTION 0x1000 -#define OHCI_RH_GET_POWER_ON_TO_POWER_GOOD_TIME(s) ((s) >> 24) - -// -// Frame interval register (section 7.3.1) -// -#define OHCI_FRAME_INTERVAL_OFFSET 0x34 -#define OHCI_GET_INTERVAL_VALUE(s) ((s) & 0x3fff) -#define OHCI_GET_FS_LARGEST_DATA_PACKET(s) (((s) >> 16) & 0x7fff) -#define OHCI_FRAME_INTERVAL_TOGGLE 0x80000000 - -// -// frame interval -// -#define OHCI_FRAME_INTERVAL_NUMBER_OFFSET 0x3C - -// -// periodic start register -// -#define OHCI_PERIODIC_START_OFFSET 0x40 -#define OHCI_PERIODIC(i) ((i) * 9 / 10) - -// -// Root Hub Descriptor B register (section 7.4.2) -// - -#define OHCI_RH_DESCRIPTOR_B_OFFSET 0x4c - -// -// Root Hub status register (section 7.4.3) -// -#define OHCI_RH_STATUS_OFFSET 0x50 -#define OHCI_RH_LOCAL_POWER_STATUS 0x00000001 -#define OHCI_RH_OVER_CURRENT_INDICATOR 0x00000002 -#define OHCI_RH_DEVICE_REMOTE_WAKEUP_ENABLE 0x00008000 -#define OHCI_RH_LOCAL_POWER_STATUS_CHANGE 0x00010000 -#define OHCI_RH_OVER_CURRENT_INDICATOR_CHANGE 0x00020000 -#define OHCI_RH_CLEAR_REMOTE_WAKEUP_ENABLE 0x80000000 - -// -// Root Hub port status (n) register (section 7.4.4) -// -#define OHCI_RH_PORT_STATUS(n) (0x54 + (n) * 4)// 0 based indexing -#define OHCI_RH_PORTSTATUS_CCS 0x00000001 -#define OHCI_RH_PORTSTATUS_PES 0x00000002 -#define OHCI_RH_PORTSTATUS_PSS 0x00000004 -#define OHCI_RH_PORTSTATUS_POCI 0x00000008 -#define OHCI_RH_PORTSTATUS_PRS 0x00000010 -#define OHCI_RH_PORTSTATUS_PPS 0x00000100 -#define OHCI_RH_PORTSTATUS_LSDA 0x00000200 -#define OHCI_RH_PORTSTATUS_CSC 0x00010000 -#define OHCI_RH_PORTSTATUS_PESC 0x00020000 -#define OHCI_RH_PORTSTATUS_PSSC 0x00040000 -#define OHCI_RH_PORTSTATUS_OCIC 0x00080000 -#define OHCI_RH_PORTSTATUS_PRSC 0x00100000 - -// -// Enable List -// - -#define OHCI_ENABLE_LIST (OHCI_PERIODIC_LIST_ENABLE \ - | OHCI_ISOCHRONOUS_ENABLE \ - | OHCI_CONTROL_LIST_ENABLE \ - | OHCI_BULK_LIST_ENABLE) - -// -// All interrupts -// -#define OHCI_ALL_INTERRUPTS (OHCI_SCHEDULING_OVERRUN \ - | OHCI_WRITEBACK_DONE_HEAD \ - | OHCI_START_OF_FRAME \ - | OHCI_RESUME_DETECTED \ - | OHCI_UNRECOVERABLE_ERROR \ - | OHCI_FRAME_NUMBER_OVERFLOW \ - | OHCI_ROOT_HUB_STATUS_CHANGE \ - | OHCI_OWNERSHIP_CHANGE) - -// -// All normal interrupts -// -#define OHCI_NORMAL_INTERRUPTS (OHCI_SCHEDULING_OVERRUN \ - | OHCI_WRITEBACK_DONE_HEAD \ - | OHCI_RESUME_DETECTED \ - | OHCI_UNRECOVERABLE_ERROR \ - | OHCI_ROOT_HUB_STATUS_CHANGE \ - | OHCI_OWNERSHIP_CHANGE) - -// -// FSMPS -// - -#define OHCI_FSMPS(i) (((i - 210) * 6 / 7) << 16) - -// -// Periodic -// - -#define OHCI_PERIODIC(i) ((i) * 9 / 10) - -// -------------------------------- -// HCCA structure (section 4.4) -// 256 bytes aligned -// -------------------------------- - -#define OHCI_NUMBER_OF_INTERRUPTS 32 -#define OHCI_STATIC_ENDPOINT_COUNT 6 -#define OHCI_BIGGEST_INTERVAL 32 - -typedef struct -{ - ULONG InterruptTable[OHCI_NUMBER_OF_INTERRUPTS]; - ULONG CurrentFrameNumber; - ULONG DoneHead; - UCHAR Reserved[120]; -}OHCIHCCA, *POHCIHCCA; - -#define OHCI_DONE_INTERRUPTS 1 -#define OHCI_HCCA_SIZE 256 -#define OHCI_HCCA_ALIGN 256 -#define OHCI_PAGE_SIZE 0x1000 -#define OHCI_PAGE(x) ((x) &~ 0xfff) -#define OHCI_PAGE_OFFSET(x) ((x) & 0xfff) - - -typedef struct _OHCI_ENDPOINT_DESCRIPTOR -{ - // Hardware part - ULONG Flags; - ULONG TailPhysicalDescriptor; - ULONG HeadPhysicalDescriptor; - ULONG NextPhysicalEndpoint; - - // Software part - PHYSICAL_ADDRESS PhysicalAddress; - PVOID HeadLogicalDescriptor; - PVOID NextDescriptor; - PVOID Request; - LIST_ENTRY DescriptorListEntry; -}OHCI_ENDPOINT_DESCRIPTOR, *POHCI_ENDPOINT_DESCRIPTOR; - - -#define OHCI_ENDPOINT_SKIP 0x00004000 -#define OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s) (s) -#define OHCI_ENDPOINT_GET_DEVICE_ADDRESS(s) ((s) & 0xFF) -#define OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(s) (((s) >> 7) & 0xf) -#define OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(s) ((s) << 7) -#define OHCI_ENDPOINT_GET_MAX_PACKET_SIZE(s) (((s) >> 16) & 0x07ff) -#define OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s) ((s) << 16) -#define OHCI_ENDPOINT_LOW_SPEED 0x00002000 -#define OHCI_ENDPOINT_FULL_SPEED 0x00000000 -#define OHCI_ENDPOINT_DIRECTION_OUT 0x00000800 -#define OHCI_ENDPOINT_DIRECTION_IN 0x00001000 -#define OHCI_ENDPOINT_GENERAL_FORMAT 0x00000000 -#define OHCI_ENDPOINT_ISOCHRONOUS_FORMAT 0x00008000 -#define OHCI_ENDPOINT_HEAD_MASK 0xfffffffc -#define OHCI_ENDPOINT_HALTED 0x00000001 -#define OHCI_ENDPOINT_TOGGLE_CARRY 0x00000002 -#define OHCI_ENDPOINT_DIRECTION_DESCRIPTOR 0x00000000 - -// -// Maximum port count set by OHCI -// -#define OHCI_MAX_PORT_COUNT 15 - - -typedef struct -{ - ULONG PortStatus; - ULONG PortChange; -}OHCI_PORT_STATUS; - - -typedef struct -{ - // Hardware part 16 bytes - ULONG Flags; // Flags field - ULONG BufferPhysical; // Physical buffer pointer - ULONG NextPhysicalDescriptor; // Physical pointer next descriptor - ULONG LastPhysicalByteAddress; // Physical pointer to buffer end - // Software part - PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor - PVOID NextLogicalDescriptor; - ULONG BufferSize; // Size of the buffer - PVOID BufferLogical; // Logical pointer to the buffer -}OHCI_GENERAL_TD, *POHCI_GENERAL_TD; - - -#define OHCI_TD_BUFFER_ROUNDING 0x00040000 -#define OHCI_TD_DIRECTION_PID_MASK 0x00180000 -#define OHCI_TD_DIRECTION_PID_SETUP 0x00000000 -#define OHCI_TD_DIRECTION_PID_OUT 0x00080000 -#define OHCI_TD_DIRECTION_PID_IN 0x00100000 -#define OHCI_TD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7) -#define OHCI_TD_SET_DELAY_INTERRUPT(x) ((x) << 21) -#define OHCI_TD_INTERRUPT_MASK 0x00e00000 -#define OHCI_TD_TOGGLE_CARRY 0x00000000 -#define OHCI_TD_TOGGLE_0 0x02000000 -#define OHCI_TD_TOGGLE_1 0x03000000 -#define OHCI_TD_TOGGLE_MASK 0x03000000 -#define OHCI_TD_GET_ERROR_COUNT(x) (((x) >> 26) & 3) -#define OHCI_TD_GET_CONDITION_CODE(x) ((x) >> 28) -#define OHCI_TD_SET_CONDITION_CODE(x) ((x) << 28) -#define OHCI_TD_CONDITION_CODE_MASK 0xf0000000 - -#define OHCI_TD_INTERRUPT_IMMEDIATE 0x00 -#define OHCI_TD_INTERRUPT_NONE 0x07 - -#define OHCI_TD_CONDITION_NO_ERROR 0x00 -#define OHCI_TD_CONDITION_CRC_ERROR 0x01 -#define OHCI_TD_CONDITION_BIT_STUFFING 0x02 -#define OHCI_TD_CONDITION_TOGGLE_MISMATCH 0x03 -#define OHCI_TD_CONDITION_STALL 0x04 -#define OHCI_TD_CONDITION_NO_RESPONSE 0x05 -#define OHCI_TD_CONDITION_PID_CHECK_FAILURE 0x06 -#define OHCI_TD_CONDITION_UNEXPECTED_PID 0x07 -#define OHCI_TD_CONDITION_DATA_OVERRUN 0x08 -#define OHCI_TD_CONDITION_DATA_UNDERRUN 0x09 -#define OHCI_TD_CONDITION_BUFFER_OVERRUN 0x0c -#define OHCI_TD_CONDITION_BUFFER_UNDERRUN 0x0d -#define OHCI_TD_CONDITION_NOT_ACCESSED 0x0f - -// -------------------------------- -// Isochronous transfer descriptor structure (section 4.3.2) -// -------------------------------- - -#define OHCI_ITD_NOFFSET 8 - -typedef struct _OHCI_ISO_TD_ -{ - - // Hardware part 32 byte - ULONG Flags; - ULONG BufferPhysical; // Physical page number of byte 0 - ULONG NextPhysicalDescriptor; // Next isochronous transfer descriptor - ULONG LastPhysicalByteAddress; // Physical buffer end - USHORT Offset[OHCI_ITD_NOFFSET]; // Buffer offsets - - // Software part - PHYSICAL_ADDRESS PhysicalAddress; // Physical address of this descriptor - struct _OHCI_ISO_TD_ * NextLogicalDescriptor; // Logical pointer next descriptor -}OHCI_ISO_TD, *POHCI_ISO_TD; - -C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, Flags) == 0); -C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, BufferPhysical) == 4); -C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, NextPhysicalDescriptor) == 8); -C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, LastPhysicalByteAddress) == 12); -C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, Offset) == 16); -C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, PhysicalAddress) == 32); -C_ASSERT(FIELD_OFFSET(OHCI_ISO_TD, NextLogicalDescriptor) == 40); -C_ASSERT(sizeof(OHCI_ISO_TD) == 48); - -#define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff) -#define OHCI_ITD_SET_STARTING_FRAME(x) ((x) & 0xffff) -#define OHCI_ITD_GET_DELAY_INTERRUPT(x) (((x) >> 21) & 7) -#define OHCI_ITD_SET_DELAY_INTERRUPT(x) ((x) << 21) -#define OHCI_ITD_NO_INTERRUPT 0x00e00000 -#define OHCI_ITD_GET_FRAME_COUNT(x) ((((x) >> 24) & 7) + 1) -#define OHCI_ITD_SET_FRAME_COUNT(x) (((x) - 1) << 24) -#define OHCI_ITD_GET_CONDITION_CODE(x) ((x) >> 28) -#define OHCI_ITD_NO_CONDITION_CODE 0xf0000000 diff --git a/drivers/usb/usbohci/interfaces.h b/drivers/usb/usbohci/interfaces.h deleted file mode 100644 index ac77ae4b8fb..00000000000 --- a/drivers/usb/usbohci/interfaces.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef INTERFACES_HPP -#define INTERFACES_HPP - -struct _OHCI_ENDPOINT_DESCRIPTOR; -struct IDMAMemoryManager; -struct IUSBQueue; - -//========================================================================================= -// -// class IUSBHardwareDevice -// -// Description: This class provides access to the usb hardware controller -// - - -#define DEFINE_ABSTRACT_USBOHCIHARDWARE() \ - STDMETHOD_(VOID, GetBulkHeadEndpointDescriptor)( THIS_ \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) PURE; \ - \ - STDMETHOD_(VOID, GetControlHeadEndpointDescriptor)( THIS_ \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) PURE; \ - \ - STDMETHOD_(VOID, GetIsochronousHeadEndpointDescriptor)( THIS_ \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) PURE; \ - \ - STDMETHOD_(VOID, GetInterruptEndpointDescriptors)( THIS_ \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptor) PURE; \ - \ - STDMETHOD_(VOID, HeadEndpointDescriptorModified)( THIS_ \ - IN ULONG Type) PURE; \ - \ - STDMETHOD_(VOID, GetCurrentFrameNumber)( THIS_ \ - IN PULONG FrameNumber) PURE; - -#define IMP_IUSBOHCIHARDWAREDEVICE \ - STDMETHODIMP_(VOID) GetBulkHeadEndpointDescriptor( \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor); \ - \ - STDMETHODIMP_(VOID) GetControlHeadEndpointDescriptor( \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor); \ - \ - STDMETHODIMP_(VOID) GetIsochronousHeadEndpointDescriptor( \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor); \ - \ - STDMETHODIMP_(VOID) GetInterruptEndpointDescriptors( \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR *** OutDescriptor); \ - \ - STDMETHODIMP_(VOID) HeadEndpointDescriptorModified( \ - IN ULONG Type); \ - \ - STDMETHODIMP_(VOID) GetCurrentFrameNumber( \ - OUT PULONG FrameNumber); - -DECLARE_INTERFACE_(IOHCIHardwareDevice, IUSBHardwareDevice) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBHARDWAREDEVICE() - DEFINE_ABSTRACT_USBOHCIHARDWARE() -}; - -typedef IOHCIHardwareDevice *POHCIHARDWAREDEVICE; - - -//========================================================================================= -// -// class IUSBRequest -// -// Description: This class is used to issue request to usb controller. The class is -// initialized using InitializeXXX methods. You also need to call SetEndpoint to define the endpoint -// In addition you can call SetCompletionDetails if you need to wait for the end of -// the request or want to complete an irp. You call AddUSBRequest to add the request to the queue. -// Once the request is completed the CompletionCallback is invoked. The CompletionCallback -// will take care of any completion details which have been set. If the request is cancelled, the -// CancelCallback routine is invoked. -// - - -#define DEFINE_ABSTRACT_USBOHCIREQUEST() \ - STDMETHOD_(NTSTATUS, GetEndpointDescriptor)( THIS_ \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) PURE; \ - \ - STDMETHOD_(VOID, CompletionCallback)( THIS) PURE; \ - \ - STDMETHOD_(VOID, FreeEndpointDescriptor)( THIS_ \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) PURE; \ - \ - STDMETHOD_(UCHAR, GetInterval)( THIS) PURE; - - -#define IMP_IOHCIREQUEST \ - STDMETHODIMP_(NTSTATUS) GetEndpointDescriptor( \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor); \ - \ - STDMETHODIMP_(VOID) CompletionCallback(); \ - \ - STDMETHODIMP_(VOID) FreeEndpointDescriptor( \ - IN struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor); \ - \ - STDMETHODIMP_(UCHAR) GetInterval(); - -DECLARE_INTERFACE_(IOHCIRequest, IUSBRequest) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBREQUEST() - DEFINE_ABSTRACT_USBOHCIREQUEST() -}; - -typedef IOHCIRequest *POHCIREQUEST; - -//========================================================================================= -// -// class IUSBQueue -// -// Description: This class manages pending requests -// - -#define DEFINE_ABSTRACT_USBOHCIQUEUE() \ - STDMETHOD_(VOID, TransferDescriptorCompletionCallback)( THIS_ \ - IN ULONG TransferDescriptorLogicalAddress) PURE; - -#define IMP_IUSBOHCIQUEUE \ - STDMETHODIMP_(VOID) TransferDescriptorCompletionCallback( \ - IN ULONG TransferDescriptorLogicalAddress); - -DECLARE_INTERFACE_(IOHCIQueue, IUSBQueue) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBQUEUE() - DEFINE_ABSTRACT_USBOHCIQUEUE() -}; - -typedef IOHCIQueue *POHCIQUEUE; - -#endif /* INTERFACES_HPP */ diff --git a/drivers/usb/usbohci/usb_queue.cpp b/drivers/usb/usbohci/usb_queue.cpp deleted file mode 100644 index 6a356f6e4ba..00000000000 --- a/drivers/usb/usbohci/usb_queue.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbohci/usb_queue.cpp - * PURPOSE: USB OHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbohci.h" - -#define NDEBUG -#include - -class CUSBQueue : public IOHCIQueue -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // com - IMP_IUSBQUEUE - IMP_IUSBOHCIQUEUE - - // local functions - BOOLEAN IsTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress); - BOOLEAN IsTransferDescriptorInIsoEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress); - NTSTATUS FindTransferDescriptorInEndpoint(IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor); - NTSTATUS FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor); - NTSTATUS FindTransferDescriptorInIsochronousHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor); - - VOID CleanupEndpointDescriptor(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor); - POHCI_ENDPOINT_DESCRIPTOR FindInterruptEndpointDescriptor(UCHAR InterruptInterval); - VOID PrintEndpointList(POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor); - VOID LinkEndpoint(POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor, POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor); - VOID AddEndpointDescriptor(IN POHCI_ENDPOINT_DESCRIPTOR Descriptor); - - - // constructor / destructor - CUSBQueue(IUnknown *OuterUnknown){} - virtual ~CUSBQueue(){} - -protected: - LONG m_Ref; // reference count - KSPIN_LOCK m_Lock; // list lock - POHCIHARDWAREDEVICE m_Hardware; // hardware - POHCI_ENDPOINT_DESCRIPTOR m_BulkHeadEndpointDescriptor; // bulk head descriptor - POHCI_ENDPOINT_DESCRIPTOR m_ControlHeadEndpointDescriptor; // control head descriptor - POHCI_ENDPOINT_DESCRIPTOR m_IsoHeadEndpointDescriptor; // isochronous head descriptor - POHCI_ENDPOINT_DESCRIPTOR * m_InterruptEndpoints; - LIST_ENTRY m_PendingRequestList; // pending request list -}; - -//================================================================================================= -// COM -// -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - if (IsEqualGUIDAligned(refiid, IID_IUnknown)) - { - *Output = PVOID(PUNKNOWN(this)); - PUNKNOWN(*Output)->AddRef(); - return STATUS_SUCCESS; - } - - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::Initialize( - IN PUSBHARDWAREDEVICE Hardware, - IN PDMA_ADAPTER AdapterObject, - IN PDMAMEMORYMANAGER MemManager, - IN OPTIONAL PKSPIN_LOCK Lock) -{ - if (!Hardware) - { - // WTF - DPRINT1("[USBOHCI] Failed to initialize queue\n"); - return STATUS_UNSUCCESSFUL; - } - - // - // store hardware - // - m_Hardware = POHCIHARDWAREDEVICE(Hardware); - ASSERT(m_Hardware); - - // - // get bulk endpoint descriptor - // - m_Hardware->GetBulkHeadEndpointDescriptor(&m_BulkHeadEndpointDescriptor); - - // - // get control endpoint descriptor - // - m_Hardware->GetControlHeadEndpointDescriptor(&m_ControlHeadEndpointDescriptor); - - // - // get isochronous endpoint - // - m_Hardware->GetIsochronousHeadEndpointDescriptor(&m_IsoHeadEndpointDescriptor); - - // - // get interrupt endpoints - // - m_Hardware->GetInterruptEndpointDescriptors(&m_InterruptEndpoints); - - // - // initialize spinlock - // - KeInitializeSpinLock(&m_Lock); - - // - // init list - // - InitializeListHead(&m_PendingRequestList); - - return STATUS_SUCCESS; -} - -VOID -CUSBQueue::LinkEndpoint( - POHCI_ENDPOINT_DESCRIPTOR HeadEndpointDescriptor, - POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor) -{ - POHCI_ENDPOINT_DESCRIPTOR CurrentEndpointDescriptor = HeadEndpointDescriptor; - - // - // get last descriptor in queue - // - while(CurrentEndpointDescriptor->NextDescriptor) - { - // - // move to last descriptor - // - CurrentEndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentEndpointDescriptor->NextDescriptor; - } - - // - // link endpoints - // - CurrentEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->PhysicalAddress.LowPart; - CurrentEndpointDescriptor->NextDescriptor = EndpointDescriptor; - -} - -VOID -CUSBQueue::AddEndpointDescriptor( - IN POHCI_ENDPOINT_DESCRIPTOR Descriptor) -{ - IOHCIRequest *Request; - ULONG Type; - POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor; - POHCI_ISO_TD CurrentDescriptor; - ULONG FrameNumber; - USHORT Frame; - - - // - // sanity check - // - ASSERT(Descriptor->Request); - Request = (IOHCIRequest*)Descriptor->Request; - - // - // get request type - // - Type = Request->GetTransferType(); - - // - // check type - // - if (Type == USB_ENDPOINT_TYPE_BULK) - { - // - // get head descriptor - // - HeadDescriptor = m_BulkHeadEndpointDescriptor; - } - else if (Type == USB_ENDPOINT_TYPE_CONTROL) - { - // - // get head descriptor - // - HeadDescriptor = m_ControlHeadEndpointDescriptor; - } - else if (Type == USB_ENDPOINT_TYPE_INTERRUPT) - { - // - // get head descriptor - // - HeadDescriptor = FindInterruptEndpointDescriptor(Request->GetInterval()); - ASSERT(HeadDescriptor); - } - else if (Type == USB_ENDPOINT_TYPE_ISOCHRONOUS) - { - // - // get head descriptor - // - HeadDescriptor = m_IsoHeadEndpointDescriptor; - - // - // get current frame number - // - m_Hardware->GetCurrentFrameNumber(&FrameNumber); - - // - // FIXME: increment frame number - // - FrameNumber += 300; - - // - // apply frame number to iso transfer descriptors - // - CurrentDescriptor = (POHCI_ISO_TD)Descriptor->HeadLogicalDescriptor; - - DPRINT("ISO: NextFrameNumber %x\n", FrameNumber); - Frame = (FrameNumber & 0xFFFF); - - while(CurrentDescriptor) - { - // - // set current frame number - // - CurrentDescriptor->Flags |= OHCI_ITD_SET_STARTING_FRAME(Frame); - - // - // move to next frame number - // - Frame += OHCI_ITD_GET_FRAME_COUNT(CurrentDescriptor->Flags); - - // - // move to next descriptor - // - CurrentDescriptor = CurrentDescriptor->NextLogicalDescriptor; - } - - // - // get current frame number - // - m_Hardware->GetCurrentFrameNumber(&FrameNumber); - - DPRINT("Hardware 1ms %p Iso %p\n",m_InterruptEndpoints[0], m_IsoHeadEndpointDescriptor); - ASSERT(m_InterruptEndpoints[0]->NextPhysicalEndpoint == m_IsoHeadEndpointDescriptor->PhysicalAddress.LowPart); - - PrintEndpointList(m_IsoHeadEndpointDescriptor); - } - else - { - // - // bad request type - // - ASSERT(FALSE); - return; - } - - // - // set descriptor active - // - Descriptor->Flags &= ~OHCI_ENDPOINT_SKIP; - - // - // insert endpoint at end - // - LinkEndpoint(HeadDescriptor, Descriptor); - - if (Type == USB_ENDPOINT_TYPE_CONTROL || Type == USB_ENDPOINT_TYPE_BULK) - { - // - // notify hardware of our request - // - m_Hardware->HeadEndpointDescriptorModified(Type); - } -} - - -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::AddUSBRequest( - IUSBRequest * Req) -{ - NTSTATUS Status; - IN POHCI_ENDPOINT_DESCRIPTOR Descriptor; - POHCIREQUEST Request; - - DPRINT("CUSBQueue::AddUSBRequest\n"); - - // get request - Request = POHCIREQUEST(Req); - - - // - // sanity check - // - ASSERT(Request != NULL); - - // - // add extra reference which is released when the request is completed - // - Request->AddRef(); - - // - // get transfer descriptors - // - Status = Request->GetEndpointDescriptor(&Descriptor); - if (!NT_SUCCESS(Status)) - { - // - // failed to get transfer descriptor - // - DPRINT1("CUSBQueue::AddUSBRequest GetEndpointDescriptor failed with %x\n", Status); - - // - // release reference - // - Request->Release(); - return Status; - } - - // - // add the request - // - AddEndpointDescriptor(Descriptor); - return STATUS_SUCCESS; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::CreateUSBRequest( - IUSBRequest **OutRequest) -{ - PUSBREQUEST UsbRequest; - NTSTATUS Status; - - *OutRequest = NULL; - Status = InternalCreateUSBRequest(&UsbRequest); - - if (NT_SUCCESS(Status)) - { - *OutRequest = UsbRequest; - } - - return Status; -} - -NTSTATUS -CUSBQueue::FindTransferDescriptorInEndpoint( - IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, - IN ULONG TransferDescriptorLogicalAddress, - OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, - OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor) -{ - POHCI_ENDPOINT_DESCRIPTOR LastDescriptor = EndpointDescriptor; - - - // - // skip first endpoint head - // - EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor; - - while(EndpointDescriptor) - { - // - // check if the transfer descriptor is inside the list - // - if ((EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HEAD_MASK) == EndpointDescriptor->TailPhysicalDescriptor || (EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED)) - { - // - // found endpoint - // - *OutEndpointDescriptor = EndpointDescriptor; - *OutPreviousEndpointDescriptor = LastDescriptor; - - // - // done - // - return STATUS_SUCCESS; - } - - // - // store last endpoint - // - LastDescriptor = EndpointDescriptor; - - // - // move to next - // - EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor; - } - - // - // failed to endpoint - // - return STATUS_NOT_FOUND; -} - -NTSTATUS -CUSBQueue::FindTransferDescriptorInInterruptHeadEndpoints(IN ULONG TransferDescriptorLogicalAddress, OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor) -{ - ULONG Index; - NTSTATUS Status; - - // - // search descriptor in endpoint list - // - for(Index = 0; Index < OHCI_STATIC_ENDPOINT_COUNT; Index++) - { - // - // is it in current endpoint - // - Status = FindTransferDescriptorInEndpoint(m_InterruptEndpoints[Index], TransferDescriptorLogicalAddress, OutEndpointDescriptor, OutPreviousEndpointDescriptor); - if (NT_SUCCESS(Status)) - { - // - // found transfer descriptor - // - return STATUS_SUCCESS; - } - } - - // - // not found - // - return STATUS_NOT_FOUND; -} - -NTSTATUS -CUSBQueue::FindTransferDescriptorInIsochronousHeadEndpoints( - IN ULONG TransferDescriptorLogicalAddress, - OUT POHCI_ENDPOINT_DESCRIPTOR *OutEndpointDescriptor, - OUT POHCI_ENDPOINT_DESCRIPTOR *OutPreviousEndpointDescriptor) -{ - POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor; - POHCI_ENDPOINT_DESCRIPTOR LastDescriptor = m_IsoHeadEndpointDescriptor; - - - // - // skip first endpoint head - // - EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)m_IsoHeadEndpointDescriptor->NextDescriptor; - - while(EndpointDescriptor) - { - // - // check if the transfer descriptor is inside the list - // - if (IsTransferDescriptorInIsoEndpoint(EndpointDescriptor, TransferDescriptorLogicalAddress)) - { - // - // found endpoint - // - *OutEndpointDescriptor = EndpointDescriptor; - *OutPreviousEndpointDescriptor = LastDescriptor; - - // - // done - // - return STATUS_SUCCESS; - } - - // - // store last endpoint - // - LastDescriptor = EndpointDescriptor; - - // - // move to next - // - EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor; - } - - // - // failed to endpoint - // - return STATUS_NOT_FOUND; -} - -BOOLEAN -CUSBQueue::IsTransferDescriptorInIsoEndpoint( - IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, - IN ULONG TransferDescriptorLogicalAddress) -{ - POHCI_ISO_TD Descriptor; - - // - // get first general transfer descriptor - // - Descriptor = (POHCI_ISO_TD)EndpointDescriptor->HeadLogicalDescriptor; - - // - // sanity check - // - ASSERT(Descriptor); - - do - { - if (Descriptor->PhysicalAddress.LowPart == TransferDescriptorLogicalAddress) - { - // - // found descriptor - // - return TRUE; - } - - // - // move to next - // - Descriptor = (POHCI_ISO_TD)Descriptor->NextLogicalDescriptor; - }while(Descriptor); - - // - // no descriptor found - // - return FALSE; -} - - -BOOLEAN -CUSBQueue::IsTransferDescriptorInEndpoint( - IN POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, - IN ULONG TransferDescriptorLogicalAddress) -{ - POHCI_GENERAL_TD Descriptor; - - // - // get first general transfer descriptor - // - Descriptor = (POHCI_GENERAL_TD)EndpointDescriptor->HeadLogicalDescriptor; - - // - // sanity check - // - ASSERT(Descriptor); - - do - { - if (Descriptor->PhysicalAddress.LowPart == TransferDescriptorLogicalAddress) - { - // - // found descriptor - // - return TRUE; - } - - // - // move to next - // - Descriptor = (POHCI_GENERAL_TD)Descriptor->NextLogicalDescriptor; - }while(Descriptor); - - - // - // no descriptor found - // - return FALSE; -} - -VOID -CUSBQueue::CleanupEndpointDescriptor( - POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, - POHCI_ENDPOINT_DESCRIPTOR PreviousEndpointDescriptor) -{ - POHCIREQUEST Request; - POHCI_ENDPOINT_DESCRIPTOR NewEndpointDescriptor; - USBD_STATUS UrbStatus; - KIRQL OldLevel; - - // - // FIXME: verify unlinking process - // - PreviousEndpointDescriptor->NextDescriptor = EndpointDescriptor->NextDescriptor; - PreviousEndpointDescriptor->NextPhysicalEndpoint = EndpointDescriptor->NextPhysicalEndpoint; - - // - // get corresponding request - // - Request = POHCIREQUEST(EndpointDescriptor->Request); - ASSERT(Request); - - // - // check for errors - // - if (EndpointDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED) - { - // - // the real error will processed by IUSBRequest - // - UrbStatus = USBD_STATUS_STALL_PID; - } - else - { - // - // well done ;) - // - UrbStatus = USBD_STATUS_SUCCESS; - } - - // - // Check if the transfer was completed and if UrbStatus is ok - // - if ((Request->IsRequestComplete() == FALSE) && (UrbStatus == USBD_STATUS_SUCCESS)) - { - // - // request is incomplete, get new queue head - // - if (Request->GetEndpointDescriptor(&NewEndpointDescriptor) == STATUS_SUCCESS) - { - // - // notify of completion - // - Request->FreeEndpointDescriptor(EndpointDescriptor); - - // - // first acquire request lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // add to pending list - // - InsertTailList(&m_PendingRequestList, &NewEndpointDescriptor->DescriptorListEntry); - - // - // release queue head - // - KeReleaseSpinLock(&m_Lock, OldLevel); - - // - // Done for now - // - return; - } - DPRINT1("Unable to create a new QueueHead\n"); - //ASSERT(FALSE); - - // - // Else there was a problem - // FIXME: Find better return - UrbStatus = USBD_STATUS_INSUFFICIENT_RESOURCES; - } - - if (UrbStatus != USBD_STATUS_SUCCESS) - { - DPRINT1("URB failed with status 0x%x\n", UrbStatus); - //PC_ASSERT(FALSE); - } - - // - // free endpoint descriptor - // - Request->FreeEndpointDescriptor(EndpointDescriptor); - - // - // notify of completion - // - Request->CompletionCallback(); - - - // - // release request - // - Request->Release(); -} - -VOID -CUSBQueue::PrintEndpointList( - POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor) -{ - DPRINT1("CUSBQueue::PrintEndpointList HeadEndpoint %p Logical %x\n", EndpointDescriptor, EndpointDescriptor->PhysicalAddress.LowPart); - - // - // get first general transfer descriptor - // - EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor; - - while(EndpointDescriptor) - { - DPRINT1(" CUSBQueue::PrintEndpointList Endpoint %p Logical %x\n", EndpointDescriptor, EndpointDescriptor->PhysicalAddress.LowPart); - - // - // move to next - // - EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)EndpointDescriptor->NextDescriptor; - } -} - -VOID -STDMETHODCALLTYPE -CUSBQueue::TransferDescriptorCompletionCallback( - ULONG TransferDescriptorLogicalAddress) -{ - POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor, PreviousEndpointDescriptor; - PLIST_ENTRY Entry; - NTSTATUS Status; - - DPRINT("CUSBQueue::TransferDescriptorCompletionCallback transfer descriptor %x\n", TransferDescriptorLogicalAddress); - - do - { - // - // find transfer descriptor in control list - // - Status = FindTransferDescriptorInEndpoint(m_ControlHeadEndpointDescriptor, TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor); - if (NT_SUCCESS(Status)) - { - // - // cleanup endpoint - // - CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor); - - // - // done - // - continue; - } - - // - // find transfer descriptor in bulk list - // - Status = FindTransferDescriptorInEndpoint(m_BulkHeadEndpointDescriptor, TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor); - if (NT_SUCCESS(Status)) - { - // - // cleanup endpoint - // - CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor); - - // - // done - // - continue; - } - - // - // find transfer descriptor in interrupt list - // - Status = FindTransferDescriptorInInterruptHeadEndpoints(TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor); - if (NT_SUCCESS(Status)) - { - // - // cleanup endpoint - // - CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor); - - // - // done - // - continue; - } - - // - // last try: find the descriptor in isochronous list - // - Status = FindTransferDescriptorInIsochronousHeadEndpoints(TransferDescriptorLogicalAddress, &EndpointDescriptor, &PreviousEndpointDescriptor); - if (NT_SUCCESS(Status)) - { - // - // cleanup endpoint - // - DPRINT("ISO endpoint complete\n"); - //ASSERT(FALSE); - CleanupEndpointDescriptor(EndpointDescriptor, PreviousEndpointDescriptor); - - // - // done - // - continue; - } - - // - // no more completed descriptors found - // - break; - - }while(TRUE); - - - // - // acquire spin lock - // - KeAcquireSpinLockAtDpcLevel(&m_Lock); - - // - // is there a pending list item - // - if (!IsListEmpty(&m_PendingRequestList)) - { - // - // get list entry - // - Entry = RemoveHeadList(&m_PendingRequestList); - - // - // get entry - // - EndpointDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CONTAINING_RECORD(Entry, OHCI_ENDPOINT_DESCRIPTOR, DescriptorListEntry); - - // - // add entry - // - AddEndpointDescriptor(EndpointDescriptor); - } - - // - // release lock - // - KeReleaseSpinLockFromDpcLevel(&m_Lock); -} - -POHCI_ENDPOINT_DESCRIPTOR -CUSBQueue::FindInterruptEndpointDescriptor( - UCHAR InterruptInterval) -{ - ULONG Index = 0; - ULONG Power = 1; - - // - // sanity check - // - ASSERT(InterruptInterval <= OHCI_BIGGEST_INTERVAL); - - // - // find interrupt index - // - while (Power <= OHCI_BIGGEST_INTERVAL / 2) - { - // - // is current interval greater - // - if (Power * 2 > InterruptInterval) - break; - - // - // increment power - // - Power *= 2; - - // - // move to next interrupt - // - Index++; - } - - DPRINT("InterruptInterval %lu Selected InterruptIndex %lu Chosen Interval %lu\n", InterruptInterval, Index, Power); - - // - // return endpoint - // - return m_InterruptEndpoints[Index]; -} - -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::AbortDevicePipe( - IN UCHAR DeviceAddress, - IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) -{ - POHCI_ENDPOINT_DESCRIPTOR HeadDescriptor, CurrentDescriptor, PreviousDescriptor, TempDescriptor; - ULONG Type; - POHCI_GENERAL_TD TransferDescriptor; - - // - // get type - // - Type = (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK); - - // - // check type - // - if (Type == USB_ENDPOINT_TYPE_BULK) - { - // - // get head descriptor - // - HeadDescriptor = m_BulkHeadEndpointDescriptor; - } - else if (Type == USB_ENDPOINT_TYPE_CONTROL) - { - // - // get head descriptor - // - HeadDescriptor = m_ControlHeadEndpointDescriptor; - } - else if (Type == USB_ENDPOINT_TYPE_INTERRUPT) - { - // - // get head descriptor - // - HeadDescriptor = FindInterruptEndpointDescriptor(EndpointDescriptor->bInterval); - ASSERT(HeadDescriptor); - } - else - { - // - // IMPLEMENT me - // - ASSERT(Type == USB_ENDPOINT_TYPE_ISOCHRONOUS); - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; - } - - // - // FIXME should disable list processing - // - - // - // now remove all endpoints - // - ASSERT(HeadDescriptor); - CurrentDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)HeadDescriptor->NextDescriptor; - PreviousDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)HeadDescriptor; - - while(CurrentDescriptor) - { - if ((CurrentDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HEAD_MASK) == CurrentDescriptor->TailPhysicalDescriptor || (CurrentDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_HALTED)) - { - // - // cleanup endpoint - // - TempDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor; - CleanupEndpointDescriptor(CurrentDescriptor, PreviousDescriptor); - - // - // use next descriptor - // - CurrentDescriptor = TempDescriptor; - } - - if (!CurrentDescriptor) - break; - - if (CurrentDescriptor->HeadPhysicalDescriptor) - { - TransferDescriptor = (POHCI_GENERAL_TD)CurrentDescriptor->HeadLogicalDescriptor; - ASSERT(TransferDescriptor); - - if ((OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(TransferDescriptor->Flags) == (EndpointDescriptor->bEndpointAddress & 0xF)) && - (OHCI_ENDPOINT_GET_DEVICE_ADDRESS(TransferDescriptor->Flags) == DeviceAddress)) - { - // - // cleanup endpoint - // - TempDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor; - CleanupEndpointDescriptor(CurrentDescriptor, PreviousDescriptor); - // - // use next descriptor - // - CurrentDescriptor = TempDescriptor; - } - } - - if (!CurrentDescriptor) - break; - - PreviousDescriptor = CurrentDescriptor; - CurrentDescriptor = (POHCI_ENDPOINT_DESCRIPTOR)CurrentDescriptor->NextDescriptor; - } - - // - // done - // - return STATUS_SUCCESS; -} - - -NTSTATUS -NTAPI -CreateUSBQueue( - PUSBQUEUE *OutUsbQueue) -{ - PUSBQUEUE This; - - // - // allocate controller - // - This = new(NonPagedPool, TAG_USBOHCI) CUSBQueue(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutUsbQueue = (PUSBQUEUE)This; - - // - // done - // - return STATUS_SUCCESS; -} diff --git a/drivers/usb/usbohci/usb_request.cpp b/drivers/usb/usbohci/usb_request.cpp deleted file mode 100644 index c56795731de..00000000000 --- a/drivers/usb/usbohci/usb_request.cpp +++ /dev/null @@ -1,2014 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbohci/usb_request.cpp - * PURPOSE: USB OHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbohci.h" - -#define NDEBUG -#include - -class CUSBRequest : public IOHCIRequest -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // IUSBRequest interface functions - IMP_IUSBREQUEST - IMP_IOHCIREQUEST - - // local functions - ULONG InternalGetTransferType(); - UCHAR InternalGetPidDirection(); - UCHAR STDMETHODCALLTYPE GetDeviceAddress(); - NTSTATUS BuildSetupPacket(); - NTSTATUS BuildSetupPacketFromURB(); - NTSTATUS BuildControlTransferDescriptor(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor); - NTSTATUS BuildBulkInterruptEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor); - NTSTATUS BuildIsochronousEndpoint(POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor); - NTSTATUS CreateGeneralTransferDescriptor(POHCI_GENERAL_TD* OutDescriptor, ULONG BufferSize); - VOID FreeDescriptor(POHCI_GENERAL_TD Descriptor); - NTSTATUS AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor); - NTSTATUS CreateIsochronousTransferDescriptor(OUT POHCI_ISO_TD *OutDescriptor, ULONG FrameCount); - UCHAR GetEndpointAddress(); - USHORT GetMaxPacketSize(); - VOID CheckError(struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor); - VOID DumpEndpointDescriptor(struct _OHCI_ENDPOINT_DESCRIPTOR *Descriptor); - NTSTATUS BuildTransferDescriptorChain(IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, OUT POHCI_GENERAL_TD * OutFirstDescriptor, OUT POHCI_GENERAL_TD * OutLastDescriptor, OUT PULONG OutTransferBufferOffset); - VOID InitDescriptor(IN POHCI_GENERAL_TD CurrentDescriptor, IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode); - - // constructor / destructor - CUSBRequest(IUnknown *OuterUnknown); - virtual ~CUSBRequest(); - -protected: - LONG m_Ref; - - // - // memory manager for allocating setup packet / queue head / transfer descriptors - // - PDMAMEMORYMANAGER m_DmaManager; - - // - // caller provided irp packet containing URB request - // - PIRP m_Irp; - - // - // transfer buffer length - // - ULONG m_TransferBufferLength; - - // - // current transfer length - // - ULONG m_TransferBufferLengthCompleted; - - // - // Total Transfer Length - // - ULONG m_TotalBytesTransferred; - - // - // transfer buffer MDL - // - PMDL m_TransferBufferMDL; - - // - // caller provided setup packet - // - PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket; - - // - // completion event for callers who initialized request with setup packet - // - PKEVENT m_CompletionEvent; - - // - // device address for callers who initialized it with device address - // - UCHAR m_DeviceAddress; - - // - // store endpoint descriptor - // - PUSB_ENDPOINT m_EndpointDescriptor; - - // - // allocated setup packet from the DMA pool - // - PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket; - PHYSICAL_ADDRESS m_DescriptorSetupPacket; - - // - // stores the result of the operation - // - NTSTATUS m_NtStatusCode; - ULONG m_UrbStatusCode; - - // - // device speed - // - USB_DEVICE_SPEED m_DeviceSpeed; - - // - // store urb - // - PURB m_Urb; - - // - // base buffer - // - PVOID m_Base; -}; - -//---------------------------------------------------------------------------------------- -CUSBRequest::CUSBRequest(IUnknown *OuterUnknown) : - m_CompletionEvent(NULL) -{ - UNREFERENCED_PARAMETER(OuterUnknown); -} - -//---------------------------------------------------------------------------------------- -CUSBRequest::~CUSBRequest() -{ - if (m_CompletionEvent != NULL) - { - ExFreePoolWithTag(m_CompletionEvent, TAG_USBOHCI); - } -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - return STATUS_UNSUCCESSFUL; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::InitializeWithSetupPacket( - IN PDMAMEMORYMANAGER DmaManager, - IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, - IN PUSBDEVICE Device, - IN OPTIONAL struct _USB_ENDPOINT* EndpointDescriptor, - IN OUT ULONG TransferBufferLength, - IN OUT PMDL TransferBuffer) -{ - // - // sanity checks - // - PC_ASSERT(DmaManager); - PC_ASSERT(SetupPacket); - - // - // initialize packet - // - m_DmaManager = DmaManager; - m_SetupPacket = SetupPacket; - m_TransferBufferLength = TransferBufferLength; - m_TransferBufferMDL = TransferBuffer; - m_DeviceAddress = Device->GetDeviceAddress(); - m_EndpointDescriptor = EndpointDescriptor; - m_TotalBytesTransferred = 0; - m_DeviceSpeed = Device->GetSpeed(); - - // - // Set Length Completed to 0 - // - m_TransferBufferLengthCompleted = 0; - - // - // allocate completion event - // - m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_USBOHCI); - if (!m_CompletionEvent) - { - // - // failed to allocate completion event - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize completion event - // - KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE); - - // - // done - // - return STATUS_SUCCESS; -} -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::InitializeWithIrp( - IN PDMAMEMORYMANAGER DmaManager, - IN struct IUSBDevice* Device, - IN OUT PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - - // - // sanity checks - // - PC_ASSERT(DmaManager); - PC_ASSERT(Irp); - - m_DmaManager = DmaManager; - m_TotalBytesTransferred = 0; - - // - // get current irp stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - - // - // sanity check - // - PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL); - PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB); - PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0); - - // - // get urb - // - m_Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // store irp - // - m_Irp = Irp; - - // - // store speed - // - m_DeviceSpeed = Device->GetSpeed(); - - // - // check function type - // - switch (m_Urb->UrbHeader.Function) - { - case URB_FUNCTION_ISOCH_TRANSFER: - { - // - // there must be at least one packet - // - ASSERT(m_Urb->UrbIsochronousTransfer.NumberOfPackets); - - // - // is there data to be transferred - // - if (m_Urb->UrbIsochronousTransfer.TransferBufferLength) - { - // - // Check if there is a MDL - // - if (!m_Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) - { - // - // sanity check - // - PC_ASSERT(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer); - - // - // Create one using TransferBuffer - // - DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer, m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - m_TransferBufferMDL = IoAllocateMdl(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer, - m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, - FALSE, - FALSE, - NULL); - - if (!m_TransferBufferMDL) - { - // - // failed to allocate mdl - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // build mdl for non paged pool - // FIXME: Does hub driver already do this when passing MDL? - // - MmBuildMdlForNonPagedPool(m_TransferBufferMDL); - } - else - { - // - // use provided mdl - // - m_TransferBufferMDL = m_Urb->UrbIsochronousTransfer.TransferBufferMDL; - } - } - - // - // save buffer length - // - m_TransferBufferLength = m_Urb->UrbIsochronousTransfer.TransferBufferLength; - - // - // Set Length Completed to 0 - // - m_TransferBufferLengthCompleted = 0; - - // - // get endpoint descriptor - // - m_EndpointDescriptor = (PUSB_ENDPOINT)m_Urb->UrbIsochronousTransfer.PipeHandle; - - // - // completed initialization - // - break; - } - // - // luckily those request have the same structure layout - // - case URB_FUNCTION_CLASS_INTERFACE: - case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: - case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: - { - // - // bulk interrupt transfer - // - if (m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength) - { - // - // Check if there is a MDL - // - if (!m_Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) - { - // - // sanity check - // - PC_ASSERT(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer); - - // - // Create one using TransferBuffer - // - DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer, m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - m_TransferBufferMDL = IoAllocateMdl(m_Urb->UrbBulkOrInterruptTransfer.TransferBuffer, - m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, - FALSE, - FALSE, - NULL); - - if (!m_TransferBufferMDL) - { - // - // failed to allocate mdl - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // build mdl for non paged pool - // FIXME: Does hub driver already do this when passing MDL? - // - MmBuildMdlForNonPagedPool(m_TransferBufferMDL); - - // - // Keep that ehci created the MDL and needs to free it. - // - } - else - { - m_TransferBufferMDL = m_Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL; - } - - // - // save buffer length - // - m_TransferBufferLength = m_Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; - - // - // Set Length Completed to 0 - // - m_TransferBufferLengthCompleted = 0; - - // - // get endpoint descriptor - // - m_EndpointDescriptor = (PUSB_ENDPOINT)m_Urb->UrbBulkOrInterruptTransfer.PipeHandle; - - } - break; - } - default: - DPRINT1("URB Function: not supported %x\n", m_Urb->UrbHeader.Function); - PC_ASSERT(FALSE); - } - - // - // done - // - return STATUS_SUCCESS; - -} - -//---------------------------------------------------------------------------------------- -BOOLEAN -STDMETHODCALLTYPE -CUSBRequest::IsRequestComplete() -{ - // - // FIXME: check if request was split - // - - // - // Check if the transfer was completed, only valid for Bulk Transfers - // - if ((m_TransferBufferLengthCompleted < m_TransferBufferLength) - && (GetTransferType() == USB_ENDPOINT_TYPE_BULK)) - { - // - // Transfer not completed - // - return FALSE; - } - return TRUE; -} -//---------------------------------------------------------------------------------------- -ULONG -STDMETHODCALLTYPE -CUSBRequest::GetTransferType() -{ - // - // call internal implementation - // - return InternalGetTransferType(); -} - -USHORT -CUSBRequest::GetMaxPacketSize() -{ - if (!m_EndpointDescriptor) - { - if (m_DeviceSpeed == UsbLowSpeed) - { - // - // control pipes use 8 bytes packets - // - return 8; - } - else - { - // - // must be full speed - // - ASSERT(m_DeviceSpeed == UsbFullSpeed); - return 64; - } - } - - ASSERT(m_Irp); - ASSERT(m_EndpointDescriptor); - - // - // return max packet size - // - return m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; -} - -UCHAR -STDMETHODCALLTYPE -CUSBRequest::GetInterval() -{ - ASSERT(m_EndpointDescriptor); - ASSERT((m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT); - - // - // return interrupt interval - // - return m_EndpointDescriptor->EndPointDescriptor.bInterval; -} - -UCHAR -CUSBRequest::GetEndpointAddress() -{ - if (!m_EndpointDescriptor) - { - // - // control request - // - return 0; - } - - ASSERT(m_Irp); - ASSERT(m_EndpointDescriptor); - - // - // endpoint number is between 1-15 - // - return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0xF); -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBRequest::InternalGetTransferType() -{ - ULONG TransferType; - - // - // check if an irp is provided - // - if (m_Irp) - { - ASSERT(m_EndpointDescriptor); - - // - // end point is defined in the low byte of bmAttributes - // - TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK); - } - else - { - // - // initialized with setup packet, must be a control transfer - // - TransferType = USB_ENDPOINT_TYPE_CONTROL; - } - - // - // done - // - return TransferType; -} - -UCHAR -CUSBRequest::InternalGetPidDirection() -{ - if (m_EndpointDescriptor) - { - // - // end point direction is highest bit in bEndpointAddress - // - return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7; - } - else - { - // - // request arrives on the control pipe, extract direction from setup packet - // - ASSERT(m_SetupPacket); - return (m_SetupPacket->bmRequestType.B >> 7); - } -} - -//---------------------------------------------------------------------------------------- -UCHAR -STDMETHODCALLTYPE -CUSBRequest::GetDeviceAddress() -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - PUSBDEVICE UsbDevice; - - // - // check if there is an irp provided - // - if (!m_Irp) - { - // - // used provided address - // - return m_DeviceAddress; - } - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // get contained urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // check if there is a pipe handle provided - // - if (Urb->UrbHeader.UsbdDeviceHandle) - { - // - // there is a device handle provided - // - UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle; - - // - // return device address - // - return UsbDevice->GetDeviceAddress(); - } - - // - // no device handle provided, it is the host root bus - // - return 0; -} - -VOID -CUSBRequest::FreeDescriptor( - POHCI_GENERAL_TD Descriptor) -{ - if (Descriptor->BufferSize) - { - // - // free buffer - // - m_DmaManager->Release(Descriptor->BufferLogical, Descriptor->BufferSize); - } - - // - // release descriptor - // - m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD)); - -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::CreateIsochronousTransferDescriptor( - POHCI_ISO_TD* OutDescriptor, - ULONG FrameCount) -{ - POHCI_ISO_TD Descriptor; - PHYSICAL_ADDRESS DescriptorAddress; - NTSTATUS Status; - - // - // allocate transfer descriptor - // - Status = m_DmaManager->Allocate(sizeof(OHCI_ISO_TD), (PVOID*)&Descriptor, &DescriptorAddress); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - return Status; - } - - // - // initialize descriptor, hardware part - // - Descriptor->Flags = OHCI_ITD_SET_FRAME_COUNT(FrameCount) | OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE);// | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED); - Descriptor->BufferPhysical = 0; - Descriptor->NextPhysicalDescriptor = 0; - Descriptor->LastPhysicalByteAddress = 0; - - // - // software part - // - Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart; - Descriptor->NextLogicalDescriptor = 0; - - // - // store result - // - *OutDescriptor = Descriptor; - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBRequest::BuildIsochronousEndpoint( - POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor) -{ - POHCI_ISO_TD FirstDescriptor = NULL, PreviousDescriptor = NULL, CurrentDescriptor = NULL; - POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor; - ULONG Index = 0, SubIndex, NumberOfPackets, PageOffset, Page; - NTSTATUS Status; - PVOID Buffer; - PIO_STACK_LOCATION IoStack; - PURB Urb; - PHYSICAL_ADDRESS Address; - - // - // get current irp stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // sanity check - // - PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL); - PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB); - PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0); - - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - ASSERT(Urb); - - // - // allocate endpoint descriptor - // - Status = AllocateEndpointDescriptor(&EndpointDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // failed to create setup descriptor - // - ASSERT(FALSE); - return Status; - } - - // - // get buffer - // - Buffer = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); - ASSERT(Buffer); - - // - // FIXME: support requests which spans several pages - // - ASSERT(ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(m_TransferBufferMDL), MmGetMdlByteCount(m_TransferBufferMDL)) <= 2); - - Status = m_DmaManager->Allocate(m_TransferBufferLength, &Buffer, &Address); - ASSERT(Status == STATUS_SUCCESS); - - - while(Index < Urb->UrbIsochronousTransfer.NumberOfPackets) - { - // - // get number of packets remaining - // - NumberOfPackets = min(Urb->UrbIsochronousTransfer.NumberOfPackets - Index, OHCI_ITD_NOFFSET); - // - // allocate iso descriptor - // - Status = CreateIsochronousTransferDescriptor(&CurrentDescriptor, NumberOfPackets); - if (!NT_SUCCESS(Status)) - { - // - // FIXME: cleanup - // failed to allocate descriptor - // - ASSERT(FALSE); - return Status; - } - - // - // get physical page (HACK) - // - *(volatile char *)Buffer; - Page = MmGetPhysicalAddress(Buffer).LowPart; - - // - // get page offset - // - PageOffset = BYTE_OFFSET(Page); - - // - // initialize descriptor - // - CurrentDescriptor->BufferPhysical = Page - PageOffset; - - for(SubIndex = 0; SubIndex < NumberOfPackets; SubIndex++) - { - // - // store buffer offset - // - CurrentDescriptor->Offset[SubIndex] = Urb->UrbIsochronousTransfer.IsoPacket[Index+SubIndex].Offset + PageOffset; - DPRINT("Index %lu PacketOffset %lu FinalOffset %lu\n", SubIndex+Index, Urb->UrbIsochronousTransfer.IsoPacket[Index+SubIndex].Offset, CurrentDescriptor->Offset[SubIndex]); - } - - // - // increment packet offset - // - Index += NumberOfPackets; - - // - // check if this is the last descriptor - // - if (Index == Urb->UrbIsochronousTransfer.NumberOfPackets) - { - // - // end of transfer - // - CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + m_TransferBufferLength - 1; - } - else - { - // - // use start address of next packet - 1 - // - CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + PageOffset + Urb->UrbIsochronousTransfer.IsoPacket[Index].Offset - 1; - } - - // - // is there a previous descriptor - // - if (PreviousDescriptor) - { - // - // link descriptors - // - PreviousDescriptor->NextLogicalDescriptor = CurrentDescriptor; - PreviousDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart; - } - else - { - // - // first descriptor - // - FirstDescriptor = CurrentDescriptor; - } - - // - // store as previous descriptor - // - PreviousDescriptor = CurrentDescriptor; - DPRINT("Current Descriptor %p Logical %lx StartAddress %x EndAddress %x\n", CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, CurrentDescriptor->BufferPhysical, CurrentDescriptor->LastPhysicalByteAddress); - - // - // fire interrupt as soon transfer is finished - // - CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE); - } - - // - // clear interrupt mask for last transfer descriptor - // - CurrentDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK; - - // - // fire interrupt as soon transfer is finished - // - CurrentDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE); - - // - // set isochronous type - // - EndpointDescriptor->Flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT; - - // - // now link descriptor to endpoint - // - EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart; - EndpointDescriptor->TailPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart; - EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor; - - // - // store result - // - *OutEndpointDescriptor = EndpointDescriptor; - - // - // done - // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::CreateGeneralTransferDescriptor( - POHCI_GENERAL_TD* OutDescriptor, - ULONG BufferSize) -{ - POHCI_GENERAL_TD Descriptor; - PHYSICAL_ADDRESS DescriptorAddress; - NTSTATUS Status; - - // - // allocate transfer descriptor - // - Status = m_DmaManager->Allocate(sizeof(OHCI_GENERAL_TD), (PVOID*)&Descriptor, &DescriptorAddress); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - return Status; - } - - // - // initialize descriptor, hardware part - // - Descriptor->Flags = 0; - Descriptor->BufferPhysical = 0; - Descriptor->NextPhysicalDescriptor = 0; - Descriptor->LastPhysicalByteAddress = 0; - - // - // software part - // - Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart; - Descriptor->BufferSize = BufferSize; - - if (BufferSize > 0) - { - // - // allocate buffer from dma - // - Status = m_DmaManager->Allocate(BufferSize, &Descriptor->BufferLogical, &DescriptorAddress); - if (!NT_SUCCESS(Status)) - { - // - // no memory - // - m_DmaManager->Release(Descriptor, sizeof(OHCI_GENERAL_TD)); - return Status; - } - - // - // set physical address of buffer - // - Descriptor->BufferPhysical = DescriptorAddress.LowPart; - Descriptor->LastPhysicalByteAddress = Descriptor->BufferPhysical + BufferSize - 1; - } - - // - // store result - // - *OutDescriptor = Descriptor; - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBRequest::AllocateEndpointDescriptor( - OUT POHCI_ENDPOINT_DESCRIPTOR *OutDescriptor) -{ - POHCI_ENDPOINT_DESCRIPTOR Descriptor; - PHYSICAL_ADDRESS DescriptorAddress; - NTSTATUS Status; - - // - // allocate descriptor - // - Status = m_DmaManager->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR), (PVOID*)&Descriptor, &DescriptorAddress); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate descriptor - // - return Status; - } - - // - // initialize descriptor - // - Descriptor->Flags = OHCI_ENDPOINT_SKIP; - - // - // append device address and endpoint number - // - Descriptor->Flags |= OHCI_ENDPOINT_SET_DEVICE_ADDRESS(GetDeviceAddress()); - Descriptor->Flags |= OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(GetEndpointAddress()); - Descriptor->Flags |= OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(GetMaxPacketSize()); - - DPRINT("Flags %x DeviceAddress %x EndpointAddress %x PacketSize %lu\n", Descriptor->Flags, GetDeviceAddress(), GetEndpointAddress(), GetMaxPacketSize()); - - // - // is there an endpoint descriptor - // - if (m_EndpointDescriptor) - { - // - // check direction - // - if (USB_ENDPOINT_DIRECTION_OUT(m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress)) - { - // - // direction out - // - Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_OUT; - } - else - { - // - // direction in - // - Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_IN; - } - } - else - { - // - // get it from transfer descriptor - // - Descriptor->Flags |= OHCI_ENDPOINT_DIRECTION_DESCRIPTOR; - } - - // - // set type - // - if (m_DeviceSpeed == UsbFullSpeed) - { - // - // device is full speed - // - Descriptor->Flags |= OHCI_ENDPOINT_FULL_SPEED; - } - else if (m_DeviceSpeed == UsbLowSpeed) - { - // - // device is full speed - // - Descriptor->Flags |= OHCI_ENDPOINT_LOW_SPEED; - } - else - { - // - // error - // - ASSERT(FALSE); - } - - Descriptor->HeadPhysicalDescriptor = 0; - Descriptor->NextPhysicalEndpoint = 0; - Descriptor->TailPhysicalDescriptor = 0; - Descriptor->PhysicalAddress.QuadPart = DescriptorAddress.QuadPart; - - // - // store result - // - *OutDescriptor = Descriptor; - - // - // done - // - return STATUS_SUCCESS; -} - -VOID -CUSBRequest::InitDescriptor( - IN POHCI_GENERAL_TD CurrentDescriptor, - IN PVOID TransferBuffer, - IN ULONG TransferBufferLength, - IN UCHAR PidDirection) -{ - ULONG Direction; - - if (PidDirection) - { - // - // input direction - // - Direction = OHCI_TD_DIRECTION_PID_IN; - } - else - { - // - // output direction - // - Direction = OHCI_TD_DIRECTION_PID_OUT; - } - - - // - // initialize descriptor - // - CurrentDescriptor->Flags = Direction | OHCI_TD_BUFFER_ROUNDING | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY; - - // - // store physical address of buffer - // - CurrentDescriptor->BufferPhysical = MmGetPhysicalAddress(TransferBuffer).LowPart; - CurrentDescriptor->LastPhysicalByteAddress = CurrentDescriptor->BufferPhysical + TransferBufferLength - 1; - - DPRINT("CurrentDescriptor %p Addr %x TransferBufferLength %lu\n", CurrentDescriptor, CurrentDescriptor->PhysicalAddress.LowPart, TransferBufferLength); -} - -NTSTATUS -CUSBRequest::BuildTransferDescriptorChain( - IN PVOID TransferBuffer, - IN ULONG TransferBufferLength, - IN UCHAR PidDirection, - OUT POHCI_GENERAL_TD * OutFirstDescriptor, - OUT POHCI_GENERAL_TD * OutLastDescriptor, - OUT PULONG OutTransferBufferOffset) -{ - POHCI_GENERAL_TD FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL; - NTSTATUS Status; - ULONG MaxLengthInPage, TransferBufferOffset = 0; - ULONG MaxPacketSize = 0, TransferSize, CurrentSize; - - // - // for now use one page as maximum size - // - MaxPacketSize = PAGE_SIZE; - - do - { - // - // allocate transfer descriptor - // - Status = CreateGeneralTransferDescriptor(&CurrentDescriptor, 0); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate transfer descriptor - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - if (MaxPacketSize) - { - // - // transfer size is minimum available buffer or endpoint size - // - TransferSize = min(TransferBufferLength - TransferBufferOffset, MaxPacketSize); - } - else - { - // - // use available buffer - // - TransferSize = TransferBufferLength - TransferBufferOffset; - } - - // - // get page offset - // - MaxLengthInPage = PAGE_SIZE - BYTE_OFFSET(TransferBuffer); - - // - // get minimum from current page size - // - CurrentSize = min(TransferSize, MaxLengthInPage); - ASSERT(CurrentSize); - - // - // now init the descriptor - // - InitDescriptor(CurrentDescriptor, - (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset), - CurrentSize, - PidDirection); - - // - // adjust offset - // - TransferBufferOffset += CurrentSize; - - // - // is there a previous descriptor - // - if (LastDescriptor) - { - // - // link descriptors - // - LastDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor; - LastDescriptor->NextPhysicalDescriptor = CurrentDescriptor->PhysicalAddress.LowPart; - } - else - { - // - // it is the first descriptor - // - FirstDescriptor = CurrentDescriptor; - } - - if(TransferBufferLength == TransferBufferOffset) - { - // - // end reached - // - break; - } - - }while(TRUE); - - if (OutFirstDescriptor) - { - // - // store first descriptor - // - *OutFirstDescriptor = FirstDescriptor; - } - - if (OutLastDescriptor) - { - // - // store last descriptor - // - *OutLastDescriptor = CurrentDescriptor; - } - - if (OutTransferBufferOffset) - { - // - // store offset - // - *OutTransferBufferOffset = TransferBufferOffset; - } - - // - // done - // - return STATUS_SUCCESS; -} - - -NTSTATUS -CUSBRequest::BuildBulkInterruptEndpoint( - POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor) -{ - POHCI_GENERAL_TD FirstDescriptor, LastDescriptor; - POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor; - NTSTATUS Status; - PVOID Base; - ULONG ChainDescriptorLength; - - // - // sanity check - // - ASSERT(m_EndpointDescriptor); - - // - // allocate endpoint descriptor - // - Status = AllocateEndpointDescriptor(&EndpointDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // failed to create setup descriptor - // - return Status; - } - - ASSERT(m_TransferBufferMDL); - - if (m_Base == NULL) - { - // - // get buffer - // - m_Base = MmGetSystemAddressForMdlSafe(m_TransferBufferMDL, NormalPagePriority); - } - - // - // Increase the size of last transfer, 0 in case this is the first - // - Base = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted); - - // - // sanity checks - // - ASSERT(m_EndpointDescriptor); - ASSERT(Base); - - // - // use 2 * PAGE_SIZE at max for each new request - // - ULONG MaxTransferLength = min(1 * PAGE_SIZE, m_TransferBufferLength - m_TransferBufferLengthCompleted); - DPRINT("m_TransferBufferLength %lu m_TransferBufferLengthCompleted %lu DataToggle %x\n", m_TransferBufferLength, m_TransferBufferLengthCompleted, m_EndpointDescriptor->DataToggle); - - // - // build bulk transfer descriptor chain - // - Status = BuildTransferDescriptorChain(Base, - MaxTransferLength, - InternalGetPidDirection(), - &FirstDescriptor, - &LastDescriptor, - &ChainDescriptorLength); - if (!NT_SUCCESS(Status)) - { - // - // failed to build transfer descriptor chain - // - m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); - return Status; - } - - // - // move to next offset - // - m_TransferBufferLengthCompleted += ChainDescriptorLength; - - // - // first descriptor has no carry bit - // - FirstDescriptor->Flags &= ~OHCI_TD_TOGGLE_CARRY; - - // - // apply data toggle - // - FirstDescriptor->Flags |= (m_EndpointDescriptor->DataToggle ? OHCI_TD_TOGGLE_1 : OHCI_TD_TOGGLE_0); - - // - // clear interrupt mask for last transfer descriptor - // - LastDescriptor->Flags &= ~OHCI_TD_INTERRUPT_MASK; - - - // - // fire interrupt as soon transfer is finished - // - LastDescriptor->Flags |= OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE); - - // - // now link descriptor to endpoint - // - EndpointDescriptor->HeadPhysicalDescriptor = FirstDescriptor->PhysicalAddress.LowPart; - EndpointDescriptor->TailPhysicalDescriptor = (FirstDescriptor == LastDescriptor ? 0 : LastDescriptor->PhysicalAddress.LowPart); - EndpointDescriptor->HeadLogicalDescriptor = FirstDescriptor; - - // - // dump descriptor list - // - //DumpEndpointDescriptor(EndpointDescriptor); - - // - // store result - // - *OutEndpointDescriptor = EndpointDescriptor; - - // - // done - // - return STATUS_SUCCESS; -} - -VOID -CUSBRequest::DumpEndpointDescriptor( - POHCI_ENDPOINT_DESCRIPTOR Descriptor) -{ - ULONG Count = 0; - POHCI_GENERAL_TD GeneralDescriptor; - - DPRINT1("EndpointDescriptor %p Addr %x\n", Descriptor, Descriptor->PhysicalAddress.LowPart); - DPRINT1("EndpointDescriptor HeadPhysicalDescriptor %x HeadLogicalDescriptor %p\n", Descriptor->HeadPhysicalDescriptor, Descriptor->HeadLogicalDescriptor); - DPRINT1("EndpointDescriptor TailPhysicalDescriptor %x\n", Descriptor->TailPhysicalDescriptor); - DPRINT1("EndpointDescriptor NextDescriptor %p\n", Descriptor->NextDescriptor); - DPRINT1("EndpointDescriptor NextPhysicalEndpoint %x\n", Descriptor->NextPhysicalEndpoint); - DPRINT1("EndpointDescriptor Flags %x\n", Descriptor->Flags); - - - GeneralDescriptor = (POHCI_GENERAL_TD)Descriptor->HeadLogicalDescriptor; - while(GeneralDescriptor) - { - DPRINT1("Descriptor %lu Address %p Addr %x\n", Count, GeneralDescriptor, GeneralDescriptor->PhysicalAddress); - DPRINT1("Descriptor %lu BufferLogical %p BufferPhysical %x\n", Count, GeneralDescriptor->BufferLogical, GeneralDescriptor->BufferPhysical); - DPRINT1("Descriptor %lu BufferSize %lu\n", Count, GeneralDescriptor->BufferSize); - DPRINT1("Descriptor %lu LastPhysicalByteAddress %x\n", Count, GeneralDescriptor->LastPhysicalByteAddress); - DPRINT1("Descriptor %lu Flags %x\n", Count, GeneralDescriptor->Flags); - DPRINT1("Descriptor %lu NextLogicalDescriptor %p NextPhysicalDescriptor %x\n", Count, GeneralDescriptor->NextLogicalDescriptor, GeneralDescriptor->NextPhysicalDescriptor); - - Count++; - GeneralDescriptor = (POHCI_GENERAL_TD)GeneralDescriptor->NextLogicalDescriptor; - } -} - -NTSTATUS -CUSBRequest::BuildControlTransferDescriptor( - POHCI_ENDPOINT_DESCRIPTOR * OutEndpointDescriptor) -{ - POHCI_GENERAL_TD SetupDescriptor, StatusDescriptor, DataDescriptor = NULL, LastDescriptor; - POHCI_ENDPOINT_DESCRIPTOR EndpointDescriptor; - NTSTATUS Status; - - // - // allocate endpoint descriptor - // - Status = AllocateEndpointDescriptor(&EndpointDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // failed to create setup descriptor - // - return Status; - } - - // - // first allocate setup descriptor - // - Status = CreateGeneralTransferDescriptor(&SetupDescriptor, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - if (!NT_SUCCESS(Status)) - { - // - // failed to create setup descriptor - // - m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); - return Status; - } - - // - // now create the status descriptor - // - Status = CreateGeneralTransferDescriptor(&StatusDescriptor, 0); - if (!NT_SUCCESS(Status)) - { - // - // failed to create status descriptor - // - FreeDescriptor(SetupDescriptor); - m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); - return Status; - } - - // - // finally create the last descriptor - // - Status = CreateGeneralTransferDescriptor(&LastDescriptor, 0); - if (!NT_SUCCESS(Status)) - { - // - // failed to create status descriptor - // - FreeDescriptor(SetupDescriptor); - FreeDescriptor(StatusDescriptor); - m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); - return Status; - } - - // - // initialize setup descriptor - // - SetupDescriptor->Flags = OHCI_TD_BUFFER_ROUNDING | OHCI_TD_DIRECTION_PID_SETUP | OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE); - - // - // initialize status descriptor - // - StatusDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_IMMEDIATE); - - if (m_SetupPacket) - { - // - // copy setup packet - // - RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - } - else - { - // - // generate setup packet from urb - // - ASSERT(FALSE); - } - - if (m_TransferBufferLength) - { - // - // FIXME: support more than one data descriptor - // - ASSERT(m_TransferBufferLength < 8192); - - // - // now create the data descriptor - // - Status = CreateGeneralTransferDescriptor(&DataDescriptor, 0); - if (!NT_SUCCESS(Status)) - { - // - // failed to create status descriptor - // - m_DmaManager->Release(EndpointDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); - FreeDescriptor(SetupDescriptor); - FreeDescriptor(StatusDescriptor); - return Status; - } - - // - // initialize data descriptor - // - DataDescriptor->Flags = OHCI_TD_SET_CONDITION_CODE(OHCI_TD_CONDITION_NOT_ACCESSED) | OHCI_TD_SET_DELAY_INTERRUPT(OHCI_TD_INTERRUPT_NONE) | OHCI_TD_TOGGLE_CARRY | OHCI_TD_TOGGLE_1; - - // - // setup pid direction - // - DataDescriptor->Flags |= (InternalGetPidDirection() != FALSE) ? OHCI_TD_DIRECTION_PID_IN : OHCI_TD_DIRECTION_PID_OUT; - - // - // use short packets - // - DataDescriptor->Flags |= OHCI_TD_BUFFER_ROUNDING; - - // - // store physical address of buffer - // - DataDescriptor->BufferPhysical = MmGetPhysicalAddress(MmGetMdlVirtualAddress(m_TransferBufferMDL)).LowPart; - DataDescriptor->LastPhysicalByteAddress = DataDescriptor->BufferPhysical + m_TransferBufferLength - 1; - - // - // flip status pid direction - // - StatusDescriptor->Flags |= (InternalGetPidDirection() != FALSE) ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN; - - // - // link setup descriptor to data descriptor - // - SetupDescriptor->NextPhysicalDescriptor = DataDescriptor->PhysicalAddress.LowPart; - SetupDescriptor->NextLogicalDescriptor = DataDescriptor; - - // - // link data descriptor to status descriptor - // FIXME: check if there are more data descriptors - // - DataDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart; - DataDescriptor->NextLogicalDescriptor = StatusDescriptor; - - // - // link status descriptor to last descriptor - // - StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart; - StatusDescriptor->NextLogicalDescriptor = LastDescriptor; - } - else - { - // - // status descriptor is always in - // - StatusDescriptor->Flags |= OHCI_TD_DIRECTION_PID_IN; - - // - // link setup descriptor to status descriptor - // - SetupDescriptor->NextPhysicalDescriptor = StatusDescriptor->PhysicalAddress.LowPart; - SetupDescriptor->NextLogicalDescriptor = StatusDescriptor; - // - // link status descriptor to last descriptor - // - StatusDescriptor->NextPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart; - StatusDescriptor->NextLogicalDescriptor = LastDescriptor; - } - - // - // now link descriptor to endpoint - // - EndpointDescriptor->HeadPhysicalDescriptor = SetupDescriptor->PhysicalAddress.LowPart; - EndpointDescriptor->TailPhysicalDescriptor = LastDescriptor->PhysicalAddress.LowPart; - EndpointDescriptor->HeadLogicalDescriptor = SetupDescriptor; - - // - // store result - // - *OutEndpointDescriptor = EndpointDescriptor; - - // - // dump descriptor - // - //DumpEndpointDescriptor(EndpointDescriptor); - - // - // done - // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::GetEndpointDescriptor( - struct _OHCI_ENDPOINT_DESCRIPTOR ** OutDescriptor) -{ - ULONG TransferType; - NTSTATUS Status; - - - // - // get transfer type - // - TransferType = InternalGetTransferType(); - - // - // build request depending on type - // - switch(TransferType) - { - case USB_ENDPOINT_TYPE_CONTROL: - Status = BuildControlTransferDescriptor((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor); - break; - case USB_ENDPOINT_TYPE_BULK: - case USB_ENDPOINT_TYPE_INTERRUPT: - Status = BuildBulkInterruptEndpoint(OutDescriptor); - break; - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - Status = BuildIsochronousEndpoint((POHCI_ENDPOINT_DESCRIPTOR*)OutDescriptor); - break; - default: - PC_ASSERT(FALSE); - Status = STATUS_NOT_IMPLEMENTED; - break; - } - - - - if (NT_SUCCESS(Status)) - { - // - // store queue head - // - //m_QueueHead = *OutDescriptor; - - // - // store request object - // - (*OutDescriptor)->Request = PVOID(this); - } - - // - // done - // - return Status; -} - -//---------------------------------------------------------------------------------------- -VOID -STDMETHODCALLTYPE -CUSBRequest::GetResultStatus( - OUT OPTIONAL NTSTATUS * NtStatusCode, - OUT OPTIONAL PULONG UrbStatusCode) -{ - // - // sanity check - // - PC_ASSERT(m_CompletionEvent); - - // - // wait for the operation to complete - // - KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL); - - // - // copy status - // - if (NtStatusCode) - { - *NtStatusCode = m_NtStatusCode; - } - - // - // copy urb status - // - if (UrbStatusCode) - { - *UrbStatusCode = m_UrbStatusCode; - } - -} - -VOID -STDMETHODCALLTYPE -CUSBRequest::FreeEndpointDescriptor( - struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) -{ - POHCI_GENERAL_TD TransferDescriptor, NextTransferDescriptor; - POHCI_ISO_TD IsoTransferDescriptor, IsoNextTransferDescriptor; - ULONG Index, PacketCount; - - DPRINT("CUSBRequest::FreeEndpointDescriptor EndpointDescriptor %p Logical %x\n", OutDescriptor, OutDescriptor->PhysicalAddress.LowPart); - - // - // check for errors - // - CheckError(OutDescriptor); - - - if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT) - { - // - // get first iso transfer descriptor - // - IsoTransferDescriptor = (POHCI_ISO_TD)OutDescriptor->HeadLogicalDescriptor; - - // - // release endpoint descriptor - // - m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); - - while(IsoTransferDescriptor) - { - // - // get next - // - IsoNextTransferDescriptor = IsoTransferDescriptor->NextLogicalDescriptor; - - // - // get packet count - // - PacketCount = OHCI_ITD_GET_FRAME_COUNT(IsoTransferDescriptor->Flags); - - DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x PacketCount %lu\n", IsoTransferDescriptor, IsoTransferDescriptor->PhysicalAddress.LowPart, IsoTransferDescriptor->BufferPhysical, IsoTransferDescriptor->LastPhysicalByteAddress, PacketCount); - - for(Index = 0; Index < PacketCount; Index++) - { - DPRINT("PSW Index %lu Value %x\n", Index, IsoTransferDescriptor->Offset[Index]); - } - - // - // release descriptor - // - m_DmaManager->Release(IsoTransferDescriptor, sizeof(OHCI_ISO_TD)); - - // - // move to next - // - IsoTransferDescriptor = IsoNextTransferDescriptor; - } - } - else - { - // - // get first general transfer descriptor - // - TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor; - - // - // release endpoint descriptor - // - m_DmaManager->Release(OutDescriptor, sizeof(OHCI_ENDPOINT_DESCRIPTOR)); - - while(TransferDescriptor) - { - // - // get next - // - NextTransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor; - - // - // is there a buffer associated - // - if (TransferDescriptor->BufferSize) - { - // - // release buffer - // - m_DmaManager->Release(TransferDescriptor->BufferLogical, TransferDescriptor->BufferSize); - } - - DPRINT("CUSBRequest::FreeEndpointDescriptor Descriptor %p Logical %x Buffer Physical %x EndAddress %x\n", TransferDescriptor, TransferDescriptor->PhysicalAddress.LowPart, TransferDescriptor->BufferPhysical, TransferDescriptor->LastPhysicalByteAddress); - - // - // release descriptor - // - m_DmaManager->Release(TransferDescriptor, sizeof(OHCI_GENERAL_TD)); - - // - // move to next - // - TransferDescriptor = NextTransferDescriptor; - } - } - -} - -VOID -CUSBRequest::CheckError( - struct _OHCI_ENDPOINT_DESCRIPTOR * OutDescriptor) -{ - POHCI_GENERAL_TD TransferDescriptor; - ULONG ConditionCode; - PURB Urb; - PIO_STACK_LOCATION IoStack; - - - // - // set status code - // - m_NtStatusCode = STATUS_SUCCESS; - m_UrbStatusCode = USBD_STATUS_SUCCESS; - - - if (OutDescriptor->Flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT) - { - // - // FIXME: handle isochronous support - // - ASSERT(FALSE); - } - else - { - // - // get first general transfer descriptor - // - TransferDescriptor = (POHCI_GENERAL_TD)OutDescriptor->HeadLogicalDescriptor; - - if (m_EndpointDescriptor != NULL) - { - // - // update data toggle - // - m_EndpointDescriptor->DataToggle = (OutDescriptor->HeadPhysicalDescriptor & OHCI_ENDPOINT_TOGGLE_CARRY); - } - - while(TransferDescriptor) - { - // - // get condition code - // - ConditionCode = OHCI_TD_GET_CONDITION_CODE(TransferDescriptor->Flags); - if (ConditionCode != OHCI_TD_CONDITION_NO_ERROR) - { - // - // FIXME status code - // - m_NtStatusCode = STATUS_UNSUCCESSFUL; - - switch(ConditionCode) - { - case OHCI_TD_CONDITION_CRC_ERROR: - DPRINT1("OHCI_TD_CONDITION_CRC_ERROR detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_CRC; - break; - case OHCI_TD_CONDITION_BIT_STUFFING: - DPRINT1("OHCI_TD_CONDITION_BIT_STUFFING detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_BTSTUFF; - break; - case OHCI_TD_CONDITION_TOGGLE_MISMATCH: - DPRINT1("OHCI_TD_CONDITION_TOGGLE_MISMATCH detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_DATA_TOGGLE_MISMATCH; - break; - case OHCI_TD_CONDITION_STALL: - DPRINT1("OHCI_TD_CONDITION_STALL detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_STALL_PID; - break; - case OHCI_TD_CONDITION_NO_RESPONSE: - DPRINT1("OHCI_TD_CONDITION_NO_RESPONSE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_DEV_NOT_RESPONDING; - break; - case OHCI_TD_CONDITION_PID_CHECK_FAILURE: - DPRINT1("OHCI_TD_CONDITION_PID_CHECK_FAILURE detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_PID_CHECK_FAILURE; - break; - case OHCI_TD_CONDITION_UNEXPECTED_PID: - DPRINT1("OHCI_TD_CONDITION_UNEXPECTED_PID detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_UNEXPECTED_PID; - break; - case OHCI_TD_CONDITION_DATA_OVERRUN: - DPRINT1("OHCI_TD_CONDITION_DATA_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_DATA_OVERRUN; - break; - case OHCI_TD_CONDITION_DATA_UNDERRUN: - if (m_Irp) - { - // - // get current irp stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - if(Urb->UrbBulkOrInterruptTransfer.TransferFlags & USBD_SHORT_TRANSFER_OK) - { - // - // short packets are ok - // - ASSERT(Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER); - m_NtStatusCode = STATUS_SUCCESS; - break; - } - } - DPRINT1("OHCI_TD_CONDITION_DATA_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_DATA_UNDERRUN; - break; - case OHCI_TD_CONDITION_BUFFER_OVERRUN: - DPRINT1("OHCI_TD_CONDITION_BUFFER_OVERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_BUFFER_OVERRUN; - break; - case OHCI_TD_CONDITION_BUFFER_UNDERRUN: - DPRINT1("OHCI_TD_CONDITION_BUFFER_UNDERRUN detected in TransferDescriptor TransferDescriptor %p\n", TransferDescriptor); - m_UrbStatusCode = USBD_STATUS_BUFFER_UNDERRUN; - break; - } - } - - // - // get next - // - TransferDescriptor = (POHCI_GENERAL_TD)TransferDescriptor->NextLogicalDescriptor; - } - } -} - -VOID -STDMETHODCALLTYPE -CUSBRequest::CompletionCallback() -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - - DPRINT("CUSBRequest::CompletionCallback\n"); - - if (m_Irp) - { - // - // set irp completion status - // - m_Irp->IoStatus.Status = m_NtStatusCode; - - // - // get current irp stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // store urb status - // - Urb->UrbHeader.Status = m_UrbStatusCode; - - // - // Check if the MDL was created - // - if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) - { - // - // Free Mdl - // - IoFreeMdl(m_TransferBufferMDL); - } - - // - // FIXME calculate length - // - - // - // complete request - // - IoCompleteRequest(m_Irp, IO_NO_INCREMENT); - } - else - { - // - // signal completion event - // - PC_ASSERT(m_CompletionEvent); - KeSetEvent(m_CompletionEvent, 0, FALSE); - } -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -NTAPI -InternalCreateUSBRequest( - PUSBREQUEST *OutRequest) -{ - PUSBREQUEST This; - - // - // allocate requests - // - This = new(NonPagedPool, TAG_USBOHCI) CUSBRequest(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutRequest = (PUSBREQUEST)This; - - // - // done - // - return STATUS_SUCCESS; -} diff --git a/drivers/usb/usbohci/usbohci.cpp b/drivers/usb/usbohci/usbohci.cpp deleted file mode 100644 index d51d609d729..00000000000 --- a/drivers/usb/usbohci/usbohci.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbohci/usbohci.cpp - * PURPOSE: USB OHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbohci.h" - -#define NDEBUG -#include - -extern -"C" -NTSTATUS -NTAPI -DriverEntry( - PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath) -{ - - /* initialize driver object */ - DriverObject->DriverExtension->AddDevice = USBLIB_AddDevice; - - DriverObject->MajorFunction[IRP_MJ_CREATE] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_POWER] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_PNP] = USBLIB_Dispatch; - return STATUS_SUCCESS; -} - - -extern "C" { - void free(void * ptr) - { - ExFreePool(ptr); - } -} diff --git a/drivers/usb/usbohci/usbohci.h b/drivers/usb/usbohci/usbohci.h deleted file mode 100644 index fcc3a80586b..00000000000 --- a/drivers/usb/usbohci/usbohci.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef USBOHCI_H__ -#define USBOHCI_H__ - -#include - -#include "hardware.h" -#include "interfaces.h" - -// -// flags for handling USB_REQUEST_SET_FEATURE / USB_REQUEST_GET_FEATURE -// -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVER_CURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#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 - -// -// tag for allocations -// -#define TAG_USBOHCI 'ICHO' - -// -// assert for c++ - taken from portcls -// -#define PC_ASSERT(exp) \ - (VOID)((!(exp)) ? \ - RtlAssert((PVOID) #exp, (PVOID)__FILE__, __LINE__, NULL ), FALSE : TRUE) - -extern "C" -{ - -// -// hardware.cpp -// -NTSTATUS NTAPI CreateUSBHardware(PUSBHARDWAREDEVICE *OutHardware); - -// -// usb_queue.cpp -// -NTSTATUS NTAPI CreateUSBQueue(PUSBQUEUE *OutUsbQueue); - -// -// usb_request.cpp -// -NTSTATUS NTAPI InternalCreateUSBRequest(PUSBREQUEST *OutRequest); -} - -#endif /* USBOHCI_H__ */ diff --git a/drivers/usb/usbohci/usbohci.rc b/drivers/usb/usbohci/usbohci.rc deleted file mode 100644 index 98b4d6e3685..00000000000 --- a/drivers/usb/usbohci/usbohci.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "USBOHCI Driver API" -#define REACTOS_STR_INTERNAL_NAME "usbohci" -#define REACTOS_STR_ORIGINAL_FILENAME "usbohci.sys" -#include diff --git a/drivers/usb/usbuhci/CMakeLists.txt b/drivers/usb/usbuhci/CMakeLists.txt deleted file mode 100644 index c288a0138ab..00000000000 --- a/drivers/usb/usbuhci/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ - -set_cpp() - -remove_definitions(-D_WIN32_WINNT=0x502) -add_definitions(-D_WIN32_WINNT=0x600) - -include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/drivers/libusb) - -list(APPEND SOURCE - usbuhci.cpp - usb_request.cpp - usb_queue.cpp - hardware.cpp - usbuhci.h) - -add_library(usbuhci MODULE - ${SOURCE} - guid.cpp - usbuhci.rc) - -target_link_libraries(usbuhci uuid libusb libcntpr ${PSEH_LIB}) -set_module_type(usbuhci kernelmodedriver) -add_importlibs(usbuhci ntoskrnl hal usbd) -add_pch(usbuhci usbuhci.h SOURCE) -add_cd_file(TARGET usbuhci DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/drivers/usb/usbuhci/guid.cpp b/drivers/usb/usbuhci/guid.cpp deleted file mode 100644 index 50a60369ff3..00000000000 --- a/drivers/usb/usbuhci/guid.cpp +++ /dev/null @@ -1,9 +0,0 @@ -/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */ - -#include -#include -#include -#include -#include - -/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */ diff --git a/drivers/usb/usbuhci/hardware.cpp b/drivers/usb/usbuhci/hardware.cpp deleted file mode 100644 index 44605a9dbe7..00000000000 --- a/drivers/usb/usbuhci/hardware.cpp +++ /dev/null @@ -1,1516 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbuhci/hcd_controller.cpp - * PURPOSE: USB UHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbuhci.h" - -#define NDEBUG -#include - -typedef VOID __stdcall HD_INIT_CALLBACK(IN PVOID CallBackContext); - -BOOLEAN -NTAPI -InterruptServiceRoutine( - IN PKINTERRUPT Interrupt, - IN PVOID ServiceContext); - -VOID -NTAPI -UhciDeferredRoutine( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2); - -VOID -NTAPI -TimerDpcRoutine( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2); - - -VOID -NTAPI -StatusChangeWorkItemRoutine(PVOID Context); - - - -class CUSBHardwareDevice : public IUHCIHardwareDevice -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - // com - IMP_IUSBHARDWAREDEVICE - IMP_IUHCIHARDWAREDEVICE - - // local - NTSTATUS StartController(); - NTSTATUS StopController(); - NTSTATUS ResetController(); - VOID GlobalReset(); - BOOLEAN InterruptService(); - NTSTATUS InitializeController(); - - // friend function - friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext); - friend VOID NTAPI UhciDeferredRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); - friend VOID NTAPI TimerDpcRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); - friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context); - VOID WriteRegister8(IN ULONG Register, IN UCHAR value); - VOID WriteRegister16(ULONG Register, USHORT Value); - VOID WriteRegister32(ULONG Register, ULONG Value); - UCHAR ReadRegister8(ULONG Register); - USHORT ReadRegister16(ULONG Register); - ULONG ReadRegister32(ULONG Register); - - // constructor / destructor - CUSBHardwareDevice(IUnknown *OuterUnknown){} - virtual ~CUSBHardwareDevice(){} - -protected: - LONG m_Ref; // reference count - PDRIVER_OBJECT m_DriverObject; // driver object - PDEVICE_OBJECT m_PhysicalDeviceObject; // pdo - PDEVICE_OBJECT m_FunctionalDeviceObject; // fdo (hcd controller) - PDEVICE_OBJECT m_NextDeviceObject; // lower device object - KSPIN_LOCK m_Lock; // hardware lock - PKINTERRUPT m_Interrupt; // interrupt object - KDPC m_IntDpcObject; // dpc object for deferred isr processing - PVOID VirtualBase; // virtual base for memory manager - PHYSICAL_ADDRESS PhysicalAddress; // physical base for memory manager - PULONG m_Base; // UHCI operational port base registers - PDMA_ADAPTER m_Adapter; // dma adapter object - ULONG m_MapRegisters; // map registers count - USHORT m_VendorID; // vendor id - USHORT m_DeviceID; // device id - PUHCIQUEUE m_UsbQueue; // usb request queue - ULONG m_NumberOfPorts; // number of ports - PDMAMEMORYMANAGER m_MemoryManager; // memory manager - HD_INIT_CALLBACK* m_SCECallBack; // status change callback routine - PVOID m_SCEContext; // status change callback routine context - //WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback - ULONG m_InterruptMask; // interrupt enabled mask - ULONG m_PortResetChange; // port reset status - PULONG m_FrameList; // frame list - PHYSICAL_ADDRESS m_FrameListPhysicalAddress; // frame list physical address - PUSHORT m_FrameBandwidth; // frame bandwidth - PUHCI_QUEUE_HEAD m_QueueHead[5]; // queue heads - PHYSICAL_ADDRESS m_StrayDescriptorPhysicalAddress; // physical address stray descriptor - PUHCI_TRANSFER_DESCRIPTOR m_StrayDescriptor; // stray descriptor - KTIMER m_SCETimer; // SCE timer - KDPC m_SCETimerDpc; // timer dpc -}; - -//================================================================================================= -// COM -// -NTSTATUS -STDMETHODCALLTYPE -CUSBHardwareDevice::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - if (IsEqualGUIDAligned(refiid, IID_IUnknown)) - { - *Output = PVOID(PUNKNOWN(this)); - PUNKNOWN(*Output)->AddRef(); - return STATUS_SUCCESS; - } - - return STATUS_UNSUCCESSFUL; -} - -LPCSTR -STDMETHODCALLTYPE -CUSBHardwareDevice::GetUSBType() -{ - return "USBUHCI"; -} - - -NTSTATUS -CUSBHardwareDevice::Initialize( - PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT FunctionalDeviceObject, - PDEVICE_OBJECT PhysicalDeviceObject, - PDEVICE_OBJECT LowerDeviceObject) -{ - BUS_INTERFACE_STANDARD BusInterface; - PCI_COMMON_CONFIG PciConfig; - NTSTATUS Status; - ULONG BytesRead; - - DPRINT("CUSBHardwareDevice::Initialize\n"); - - // - // Create DMAMemoryManager for use with QueueHeads and Transfer Descriptors. - // - Status = CreateDMAMemoryManager(&m_MemoryManager); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create DMAMemoryManager Object\n"); - return Status; - } - - // - // Create the UsbQueue class that will handle the Asynchronous and Periodic Schedules - // - Status = CreateUSBQueue((PUSBQUEUE*)&m_UsbQueue); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create UsbQueue!\n"); - return Status; - } - - // - // store device objects - // - m_DriverObject = DriverObject; - m_FunctionalDeviceObject = FunctionalDeviceObject; - m_PhysicalDeviceObject = PhysicalDeviceObject; - m_NextDeviceObject = LowerDeviceObject; - - // - // initialize device lock - // - KeInitializeSpinLock(&m_Lock); - - // - // initialize status change work item - // - //ExInitializeWorkItem(&m_StatusChangeWorkItem, StatusChangeWorkItemRoutine, PVOID(this)); - - - // initialize timer - KeInitializeTimer(&m_SCETimer); - - // initialize timer dpc - KeInitializeDpc(&m_SCETimerDpc, TimerDpcRoutine, PVOID(this)); - - - m_VendorID = 0; - m_DeviceID = 0; - - Status = GetBusInterface(PhysicalDeviceObject, &BusInterface); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get BusInterface!\n"); - return Status; - } - - BytesRead = (*BusInterface.GetBusData)(BusInterface.Context, - PCI_WHICHSPACE_CONFIG, - &PciConfig, - 0, - PCI_COMMON_HDR_LENGTH); - - if (BytesRead != PCI_COMMON_HDR_LENGTH) - { - DPRINT1("Failed to get pci config information!\n"); - return STATUS_SUCCESS; - } - - m_VendorID = PciConfig.VendorID; - m_DeviceID = PciConfig.DeviceID; - - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::PnpStart( - PCM_RESOURCE_LIST RawResources, - PCM_RESOURCE_LIST TranslatedResources) -{ - ULONG Index; - PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor; - DEVICE_DESCRIPTION DeviceDescription; - NTSTATUS Status; - - DPRINT("CUSBHardwareDevice::PnpStart\n"); - for(Index = 0; Index < TranslatedResources->List[0].PartialResourceList.Count; Index++) - { - // - // get resource descriptor - // - ResourceDescriptor = &TranslatedResources->List[0].PartialResourceList.PartialDescriptors[Index]; - - switch(ResourceDescriptor->Type) - { - case CmResourceTypeInterrupt: - { - KeInitializeDpc(&m_IntDpcObject, - UhciDeferredRoutine, - this); - - Status = IoConnectInterrupt(&m_Interrupt, - InterruptServiceRoutine, - (PVOID)this, - NULL, - ResourceDescriptor->u.Interrupt.Vector, - (KIRQL)ResourceDescriptor->u.Interrupt.Level, - (KIRQL)ResourceDescriptor->u.Interrupt.Level, - (KINTERRUPT_MODE)(ResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED), - (ResourceDescriptor->ShareDisposition != CmResourceShareDeviceExclusive), - ResourceDescriptor->u.Interrupt.Affinity, - FALSE); - - if (!NT_SUCCESS(Status)) - { - // - // failed to register interrupt - // - DPRINT1("IoConnect Interrupt failed with %x\n", Status); - return Status; - } - break; - } - case CmResourceTypePort: - { - // - // Store Resource base - // - m_Base = (PULONG)(ULONG_PTR)ResourceDescriptor->u.Port.Start.QuadPart; //FIXME - DPRINT("UHCI Base %p Length %x\n", m_Base, ResourceDescriptor->u.Port.Length); - break; - } - } - } - - ASSERT(m_Base); - - // - // zero device description - // - RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION)); - - // - // initialize device description - // - DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; - DeviceDescription.Master = TRUE; - DeviceDescription.ScatterGather = TRUE; - DeviceDescription.Dma32BitAddresses = TRUE; - DeviceDescription.DmaWidth = Width32Bits; - DeviceDescription.InterfaceType = PCIBus; - DeviceDescription.MaximumLength = MAXULONG; - - // - // get dma adapter - // - m_Adapter = IoGetDmaAdapter(m_PhysicalDeviceObject, &DeviceDescription, &m_MapRegisters); - if (!m_Adapter) - { - // - // failed to get dma adapter - // - DPRINT1("Failed to acquire dma adapter\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Create Common Buffer - // - VirtualBase = m_Adapter->DmaOperations->AllocateCommonBuffer(m_Adapter, - PAGE_SIZE * 4, - &PhysicalAddress, - FALSE); - if (!VirtualBase) - { - DPRINT1("Failed to allocate a common buffer\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Initialize the DMAMemoryManager - // - Status = m_MemoryManager->Initialize(this, &m_Lock, PAGE_SIZE * 4, VirtualBase, PhysicalAddress, 32); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to initialize the DMAMemoryManager\n"); - return Status; - } - - // - // initializes the controller - // - Status = InitializeController(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to Initialize the controller \n"); - ASSERT(FALSE); - return Status; - } - - // - // Initialize the UsbQueue now that we have an AdapterObject. - // - Status = m_UsbQueue->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter, m_MemoryManager, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to Initialize the UsbQueue\n"); - return Status; - } - - // - // Start the controller - // - DPRINT("Starting Controller\n"); - Status = StartController(); - - - // - // done - // - return Status; -} - -NTSTATUS -CUSBHardwareDevice::PnpStop(void) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -CUSBHardwareDevice::GetDeviceDetails( - OUT OPTIONAL PUSHORT VendorId, - OUT OPTIONAL PUSHORT DeviceId, - OUT OPTIONAL PULONG NumberOfPorts, - OUT OPTIONAL PULONG Speed) -{ - if (VendorId) - { - // - // get vendor - // - *VendorId = m_VendorID; - } - - if (DeviceId) - { - // - // get device id - // - *DeviceId = m_DeviceID; - } - - if (NumberOfPorts) - { - // - // get number of ports - // - *NumberOfPorts = m_NumberOfPorts; - } - - if (Speed) - { - // - // speed is 0x100 - // - *Speed = 0x100; - } - - return STATUS_SUCCESS; -} - -NTSTATUS CUSBHardwareDevice::GetDMA( - OUT struct IDMAMemoryManager **OutDMAMemoryManager) -{ - if (!m_MemoryManager) - return STATUS_UNSUCCESSFUL; - *OutDMAMemoryManager = m_MemoryManager; - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::GetUSBQueue( - OUT struct IUSBQueue **OutUsbQueue) -{ - if (!m_UsbQueue) - return STATUS_UNSUCCESSFUL; - *OutUsbQueue = m_UsbQueue; - return STATUS_SUCCESS; -} - - -NTSTATUS -CUSBHardwareDevice::StartController(void) -{ - ULONG Index; - USHORT Status; - - - // - // debug info - // - DPRINT("[USBUHCI] USBCMD: %x USBSTS %x\n", ReadRegister16(UHCI_USBCMD), ReadRegister16(UHCI_USBSTS)); - - // - // Set the run bit in the command register - // - WriteRegister16(UHCI_USBCMD, ReadRegister16(UHCI_USBCMD) | UHCI_USBCMD_RS); - - for(Index = 0; Index < 100; Index++) - { - // - // wait a bit - // - KeStallExecutionProcessor(100); - - // - // get controller status - // - Status = ReadRegister16(UHCI_USBSTS); - DPRINT("[USBUHCI] Status %x\n", Status); - - if (!(Status & UHCI_USBSTS_HCHALT)) - { - // - // controller started - // - break; - } - } - - DPRINT("[USBUHCI] USBCMD: %x USBSTS %x\n", ReadRegister16(UHCI_USBCMD), ReadRegister16(UHCI_USBSTS)); - - - if ((Status & UHCI_USBSTS_HCHALT)) - { - // - // failed to start controller - // - DPRINT1("[USBUHCI] Failed to start controller Status %x\n", Status); - ASSERT(FALSE); - return STATUS_UNSUCCESSFUL; - } - - // - // Set the configure bit - // - WriteRegister16(UHCI_USBCMD, ReadRegister16(UHCI_USBCMD) | UHCI_USBCMD_CF); - - for(Index = 0; Index < 2; Index++) - { - // - // get port status - // - Status = ReadRegister16(UHCI_PORTSC1 + Index * 2); - - // - // clear connection change and port suspend - // - WriteRegister16(UHCI_PORTSC1 + Index * 2, Status & ~(UHCI_PORTSC_STATCHA | UHCI_PORTSC_SUSPEND)); - } - - DPRINT("[USBUHCI] Controller Started\n"); - DPRINT("[USBUHCI] Controller Status %x\n", ReadRegister16(UHCI_USBSTS)); - DPRINT("[USBUHCI] Controller Cmd Status %x\n", ReadRegister16(UHCI_USBCMD)); - DPRINT("[USBUHCI] Controller Interrupt Status %x\n", ReadRegister16(UHCI_USBINTR)); - DPRINT("[USBUHCI] Controller Frame %x\n", ReadRegister16(UHCI_FRNUM)); - DPRINT("[USBUHCI] Controller Port Status 0 %x\n", ReadRegister16(UHCI_PORTSC1)); - DPRINT("[USBUHCI] Controller Port Status 1 %x\n", ReadRegister16(UHCI_PORTSC1 + 2)); - - - // queue timer - LARGE_INTEGER Expires; - Expires.QuadPart = -10 * 10000; - - KeSetTimerEx(&m_SCETimer, Expires, 1000, &m_SCETimerDpc); - - // - // done - // - return STATUS_SUCCESS; -} - -VOID -CUSBHardwareDevice::GlobalReset() -{ - LARGE_INTEGER Timeout; - - // - // back up start of modify register - // - ASSERT(m_Base); - UCHAR sofValue = READ_PORT_UCHAR((PUCHAR)m_Base + UHCI_SOFMOD); - - // - // perform global reset - // - WriteRegister16(UHCI_USBCMD, ReadRegister16(UHCI_USBCMD) | UHCI_USBCMD_GRESET); - - // - // delay is 10 ms - // - Timeout.QuadPart = 10; - DPRINT("Waiting %lu milliseconds for global reset\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - - // - // clear command register - // - WriteRegister16(UHCI_USBCMD, ReadRegister16(UHCI_USBCMD) & ~UHCI_USBCMD_GRESET); - KeStallExecutionProcessor(10); - - - // - // restore start of modify register - // - WRITE_PORT_UCHAR((PUCHAR)m_Base + UHCI_SOFMOD, sofValue); -} - -NTSTATUS -CUSBHardwareDevice::InitializeController() -{ - NTSTATUS Status; - ULONG Index; - BUS_INTERFACE_STANDARD BusInterface; - USHORT Value; - PHYSICAL_ADDRESS Address; - - DPRINT("[USBUHCI] InitializeController\n"); - - // - // now disable all interrupts - // - WriteRegister16(UHCI_USBINTR, 0); - - - // - // UHCI has two ports - // - m_NumberOfPorts = 2; - - // - // get bus interface - // - Status = GetBusInterface(m_PhysicalDeviceObject, &BusInterface); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get BusInterface!\n"); - return Status; - } - - // - // reclaim ownership from BIOS - // - Value = 0; - BusInterface.GetBusData(BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Value, PCI_LEGSUP, sizeof(USHORT)); - DPRINT("[USBUHCI] LEGSUP %x\n", Value); - - Value = PCI_LEGSUP_USBPIRQDEN; - BusInterface.SetBusData(BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Value, PCI_LEGSUP, sizeof(USHORT)); - - DPRINT("[USBUHCI] Acquired ownership\n"); - Value = 0; - BusInterface.GetBusData(BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Value, 0x60, sizeof(UCHAR)); - DPRINT("[USBUHCI] SBRN %x\n", Value); - - // - // perform global reset - // - GlobalReset(); - - // - // reset controller - // - Status = ResetController(); - if (!NT_SUCCESS(Status)) - { - // - // failed to reset controller - // - DPRINT1("[USBUHCI] Failed to reset controller\n"); - return Status; - } - - // - // allocate frame list - // - Status = m_MemoryManager->Allocate(NUMBER_OF_FRAMES * sizeof(ULONG), (PVOID*)&m_FrameList, &m_FrameListPhysicalAddress); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate frame list - // - DPRINT1("[USBUHCI] Failed to allocate frame list with %x\n", Status); - return Status; - } - - // - // Set base pointer and reset frame number - // - WriteRegister32(UHCI_FRBASEADD, m_FrameListPhysicalAddress.LowPart); - WriteRegister16(UHCI_FRNUM, 0); - - // - // Set the max packet size for bandwidth reclamation to 64 bytes - // - WriteRegister16(UHCI_USBCMD, ReadRegister16(UHCI_USBCMD) | UHCI_USBCMD_MAXP); - - // - // now create queues - // 0: interrupt transfers - // 1: low speed control transfers - // 2: full speed control transfers - // 3: bulk transfers - // 4: debug queue - // - for(Index = 0; Index < 5; Index++) - { - // - // create queue head - // - Status = m_MemoryManager->Allocate(sizeof(UHCI_QUEUE_HEAD), (PVOID*)&m_QueueHead[Index], &Address); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate queue head - // - DPRINT1("[USBUHCI] Failed to allocate queue head %x Index %x\n", Status, Index); - return Status; - } - - // - // store queue head - // - m_QueueHead[Index]->PhysicalAddress = Address.LowPart; - m_QueueHead[Index]->ElementPhysical = QH_TERMINATE; - m_QueueHead[Index]->LinkPhysical = QH_TERMINATE; - - if (Index > 0) - { - // - // link queue heads - // - m_QueueHead[Index-1]->LinkPhysical = m_QueueHead[Index]->PhysicalAddress | QH_NEXT_IS_QH; - m_QueueHead[Index-1]->NextLogicalDescriptor = m_QueueHead[Index]; - } - } - - DPRINT("Index %d QueueHead %p LinkPhysical %x ElementPhysical %x PhysicalAddress %x Request %p NextElementDescriptor %p\n", - 0, - m_QueueHead[0], - m_QueueHead[0]->LinkPhysical, - m_QueueHead[0]->ElementPhysical, - m_QueueHead[0]->PhysicalAddress, - m_QueueHead[0]->Request, - m_QueueHead[0]->NextElementDescriptor); - DPRINT("Index %d QueueHead %p LinkPhysical %x ElementPhysical %x PhysicalAddress %x Request %p NextElementDescriptor %p\n", - 1, - m_QueueHead[1], - m_QueueHead[1]->LinkPhysical, - m_QueueHead[1]->ElementPhysical, - m_QueueHead[1]->PhysicalAddress, - m_QueueHead[1]->Request, - m_QueueHead[1]->NextElementDescriptor); - - DPRINT("Index %d QueueHead %p LinkPhysical %x ElementPhysical %x PhysicalAddress %x Request %p NextElementDescriptor %p\n", - 2, - m_QueueHead[2], - m_QueueHead[2]->LinkPhysical, - m_QueueHead[2]->ElementPhysical, - m_QueueHead[2]->PhysicalAddress, - m_QueueHead[2]->Request, - m_QueueHead[2]->NextElementDescriptor); - DPRINT("Index %d QueueHead %p LinkPhysical %x ElementPhysical %x PhysicalAddress %x Request %p NextElementDescriptor %p\n", - 3, - m_QueueHead[3], - m_QueueHead[3]->LinkPhysical, - m_QueueHead[3]->ElementPhysical, - m_QueueHead[3]->PhysicalAddress, - m_QueueHead[3]->Request, - m_QueueHead[3]->NextElementDescriptor); - DPRINT("Index %d QueueHead %p LinkPhysical %x ElementPhysical %x PhysicalAddress %x Request %p NextElementDescriptor %p\n", - 4, - m_QueueHead[4], - m_QueueHead[4]->LinkPhysical, - m_QueueHead[4]->ElementPhysical, - m_QueueHead[4]->PhysicalAddress, - m_QueueHead[4]->Request, - m_QueueHead[4]->NextElementDescriptor); - - // - // terminate last queue head with stray descriptor - // - Status = m_MemoryManager->Allocate(sizeof(UHCI_TRANSFER_DESCRIPTOR), (PVOID*)&m_StrayDescriptor, &m_StrayDescriptorPhysicalAddress); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate queue head - // - DPRINT1("[USBUHCI] Failed to allocate queue head %x Index %x\n", Status, Index); - return Status; - } -#if 0 - // - // init stray descriptor - // - m_StrayDescriptor->PhysicalAddress = m_StrayDescriptorPhysicalAddress.LowPart; - m_StrayDescriptor->LinkPhysical = TD_TERMINATE; - m_StrayDescriptor->Token = TD_TOKEN_NULL_DATA | (0x7f << TD_TOKEN_DEVADDR_SHIFT) | TD_TOKEN_IN; - - - // - // link to last queue head - // - m_QueueHead[4]->LinkPhysical = m_StrayDescriptor->PhysicalAddress; - m_QueueHead[4]->NextLogicalDescriptor = m_StrayDescriptor; -#endif - - // - // allocate frame bandwidth array - // - m_FrameBandwidth = (PUSHORT)ExAllocatePool(NonPagedPool, sizeof(USHORT) * NUMBER_OF_FRAMES); - if (!m_FrameBandwidth) - { - // - // no memory - // - DPRINT1("[USBUHCI] Failed to allocate memory\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // init frame list - // - for (Index = 0; Index < NUMBER_OF_FRAMES; Index++) - { - // - // store frame list interrupt queue - // - m_FrameList[Index] = m_QueueHead[UHCI_INTERRUPT_QUEUE]->PhysicalAddress | FRAMELIST_NEXT_IS_QH; - m_FrameBandwidth[Index] = MAX_AVAILABLE_BANDWIDTH; - - - } - - // - // set enabled interrupt mask - // - m_InterruptMask = UHCI_USBSTS_USBINT | UHCI_USBSTS_ERRINT | UHCI_USBSTS_HOSTERR | UHCI_USBSTS_HCPRERR | UHCI_USBSTS_HCHALT; - - // - // now enable interrupts - // - WriteRegister16(UHCI_USBINTR, UHCI_USBINTR_CRC | UHCI_USBINTR_IOC| UHCI_USBINTR_SHORT); - - DPRINT("[USBUHCI] Controller initialized\n"); - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::StopController(void) -{ - ASSERT(FALSE); - // - // failed to reset controller - // - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS -CUSBHardwareDevice::ResetController(void) -{ - ULONG Count = 0; - USHORT Status; - - // clear run bit - WriteRegister16(UHCI_USBCMD, ReadRegister16(UHCI_USBCMD) & ~UHCI_USBCMD_RS); - - // wait for the controller to stop - while((ReadRegister16(UHCI_USBSTS) & UHCI_USBSTS_HCHALT) == 0) - { - DPRINT("[UHCI] Waiting for the controller to halt\n"); - KeStallExecutionProcessor(10); - } - - // clear configure bit - WriteRegister16(UHCI_USBCMD, ReadRegister16(UHCI_USBCMD) & ~UHCI_USBCMD_CF); - - // - // reset controller - // - WriteRegister16(UHCI_USBCMD, UHCI_USBCMD_HCRESET); - - do - { - // - // wait a bit - // - KeStallExecutionProcessor(100); - - // - // get status - // - Status = ReadRegister16(UHCI_USBCMD); - if (!(Status & UHCI_USBCMD_HCRESET)) - { - // - // controller reset completed - // - return STATUS_SUCCESS; - } - }while(Count++ < 100); - - DPRINT1("[USBUHCI] Failed to reset controller Status %x\n", Status); - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS -CUSBHardwareDevice::ResetPort( - IN ULONG PortIndex) -{ - ULONG Port; - USHORT Status; - ULONG Index; - LARGE_INTEGER Timeout; - - DPRINT("[UHCI] ResetPort Id %lu\n", PortIndex); - - // - // sanity check - // - ASSERT(PortIndex <= 1); - - // - // get register offset - // - Port = UHCI_PORTSC1 + PortIndex * 2; - - // - // read port status - // - Status = ReadRegister16(Port); - - - - // - // remove unwanted bits - // - Status &= UHCI_PORTSC_DATAMASK; - - // - // now reset the port - // - WriteRegister16(Port, Status | UHCI_PORTSC_RESET); - - // - // delay is 20 ms for port reset - // - Timeout.QuadPart = 20; - DPRINT("Waiting %lu milliseconds for port reset\n", Timeout.LowPart); - - // - // convert to 100 ns units (absolute) - // - Timeout.QuadPart *= -10000; - - // - // perform the wait - // - KeDelayExecutionThread(KernelMode, FALSE, &Timeout); - - // - // re-read status - // - Status = ReadRegister16(Port); - - // - // remove unwanted bits - // - Status &= UHCI_PORTSC_DATAMASK; - - // - // clear reset port - // - WriteRegister16(Port, (Status & ~UHCI_PORTSC_RESET)); - - - // - // now wait a bit - // - KeStallExecutionProcessor(10); - - for (Index = 0; Index < 100; Index++) - { - // read port status - Status = ReadRegister16(Port); - - // remove unwanted bits - Status &= UHCI_PORTSC_DATAMASK; - - // enable port - WriteRegister16(Port, Status | UHCI_PORTSC_ENABLED); - - // - // wait a bit - // - KeStallExecutionProcessor(50); - - // - // re-read port - // - Status = ReadRegister16(Port); - - if ((Status & UHCI_PORTSC_CURSTAT) == 0) - { - // no device connected. since we waited long enough we can assume - // that the port was reset and no device is connected. - break; - } - - if (Status & (UHCI_PORTSC_STATCHA | UHCI_PORTSC_ENABCHA)) - { - // port enabled changed or connection status were set. - // acknowledge either / both and wait again. - WriteRegister16(Port, Status); - continue; - } - - if (Status & UHCI_PORTSC_ENABLED) - { - // the port is enabled - break; - } - } - - m_PortResetChange |= (1 << PortIndex); - DPRINT("[USBUHCI] Port Index %x Status after reset %x\n", PortIndex, ReadRegister16(Port)); - - // - // is there a callback - // - if (m_SCECallBack) - { - // - // issue callback - // - m_SCECallBack(m_SCEContext); - } - - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::GetPortStatus( - ULONG PortId, - OUT USHORT *PortStatus, - OUT USHORT *PortChange) -{ - USHORT Status; - - // - // sanity check - // - if (PortId > 1) - { - // - // invalid index - // - DPRINT1("[UHCI] Invalid PortIndex %lu\n", PortId); - return STATUS_INVALID_PARAMETER; - } - - // - // init status - // - *PortStatus = 0; - *PortChange = 0; - - // - // read port status - // - Status = ReadRegister16(UHCI_PORTSC1 + PortId * 2); - DPRINT("[USBUHCI] PortId %x Status %x\n", PortId, Status); - - // build the status - if (Status & UHCI_PORTSC_CURSTAT) - { - *PortStatus |= USB_PORT_STATUS_CONNECT; - } - - if (Status & UHCI_PORTSC_ENABLED) - { - *PortStatus |= USB_PORT_STATUS_ENABLE; - } - - if (Status & UHCI_PORTSC_RESET) - { - *PortStatus |= USB_PORT_STATUS_RESET; - } - - if (Status & UHCI_PORTSC_LOWSPEED) - { - *PortStatus |= USB_PORT_STATUS_LOW_SPEED; - } - - if (Status & UHCI_PORTSC_STATCHA) - { - *PortChange |= USB_PORT_STATUS_CONNECT; - } - - if (Status & UHCI_PORTSC_ENABCHA) - { - *PortChange |= USB_PORT_STATUS_ENABLE; - } - - if (m_PortResetChange & (1 << PortId)) - { - *PortChange |= USB_PORT_STATUS_RESET; - } - - // - // port always has power - // - *PortStatus |= USB_PORT_STATUS_POWER; - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBHardwareDevice::ClearPortStatus( - ULONG PortId, - ULONG Feature) -{ - ULONG PortRegister; - USHORT PortStatus; - - DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Feature); - - // - // sanity check - // - if (PortId > 1) - { - // - // invalid index - // - DPRINT1("[UHCI] Invalid PortIndex %lu\n", PortId); - return STATUS_INVALID_PARAMETER; - } - - // - // read current status - // - PortRegister = UHCI_PORTSC1 + PortId * 2; - PortStatus = ReadRegister16(PortRegister); - DPRINT("[UHCI] PortStatus %x\n", PortStatus); - - if (Feature == C_PORT_RESET) - { - // - // UHCI is not supporting port reset register bit - // - m_PortResetChange &= ~(1 << PortId); - } - else if (Feature == C_PORT_CONNECTION || Feature == C_PORT_ENABLE) - { - // - // clear port status changes - // - WriteRegister16(PortRegister, PortStatus); - } - - return STATUS_SUCCESS; -} - - -NTSTATUS -CUSBHardwareDevice::SetPortFeature( - ULONG PortId, - ULONG Feature) -{ - ULONG PortRegister; - - DPRINT("[UHCI] SetPortFeature PortId %x Feature %x\n", PortId, Feature); - - // - // sanity check - // - if (PortId > 1) - { - // - // invalid index - // - DPRINT1("[UHCI] Invalid PortIndex %lu\n", PortId); - return STATUS_INVALID_PARAMETER; - } - - PortRegister = UHCI_PORTSC1 + PortId * 2; - - if (Feature == PORT_RESET) - { - // - // reset port - // - return ResetPort(PortId); - } - else if (Feature == PORT_ENABLE) - { - // - // reset port - // - WriteRegister16(PortRegister, ReadRegister16(PortRegister) | UHCI_PORTSC_ENABLED); - } - else if (Feature == PORT_POWER) - { - // - // port power is no op, it is always enabled - // - } - - return STATUS_SUCCESS; -} - - - -VOID -CUSBHardwareDevice::SetStatusChangeEndpointCallBack( - PVOID CallBack, - PVOID Context) -{ - m_SCECallBack = (HD_INIT_CALLBACK*)CallBack; - m_SCEContext = Context; -} - -BOOLEAN -NTAPI -InterruptServiceRoutine( - IN PKINTERRUPT Interrupt, - IN PVOID ServiceContext) -{ - CUSBHardwareDevice *This; - USHORT Status, Acknowledge; - - // - // get context - // - This = (CUSBHardwareDevice*) ServiceContext; - - // - // read register - // - Status = This->ReadRegister16(UHCI_USBSTS); - DPRINT("InterruptServiceRoutine %x\n", Status); - - // - // check if the interrupt signaled are from us - // - if ((Status & This->m_InterruptMask) == 0) - { - if (Status != 0) - { - // - // FIXME: received unexpected interrupt - // - DPRINT1("[USBUHCI] Unexpected interrupt %x\n", Status); - This->WriteRegister16(UHCI_USBSTS, Status); - } - - // - // shared interrupt - // - return FALSE; - } - - // - // check for the interrupt cause - // - Acknowledge = 0; - - if (Status & UHCI_USBSTS_USBINT) - { - // - // transfer finished - // - Acknowledge |= UHCI_USBSTS_USBINT; - } - - if (Status & UHCI_USBSTS_ERRINT) - { - // - // error interrupt - // - Acknowledge |= UHCI_USBSTS_ERRINT; - DPRINT("[UHCI] Error interrupt\n"); - } - - if (Status & UHCI_USBSTS_RESDET) - { - // - // resume detected - // - DPRINT("[UHCI] Resume detected\n"); - Acknowledge |= UHCI_USBSTS_RESDET; - } - - if (Status & UHCI_USBSTS_HOSTERR) - { - // - // host system error - // - DPRINT("[UHCI] Host System Error\n"); - Acknowledge |= UHCI_USBSTS_HOSTERR; - } - - if (Status & UHCI_USBSTS_HCPRERR) - { - // - // processing error - // - DPRINT("[UHCI] Process Error\n"); - Acknowledge |= UHCI_USBSTS_HCPRERR; - } - - if (Status & UHCI_USBSTS_HCHALT) - { - // - // controller halted - // - DPRINT("[UHCI] Host controller halted\n"); - - // - // disable interrupts - // - This->WriteRegister16(UHCI_USBINTR, 0); - This->m_InterruptMask = 0; - } - - // - // do we have something to acknowledge - // - if (Acknowledge) - { - // - // acknowledge interrupt - // - This->WriteRegister16(UHCI_USBSTS, Acknowledge); - - // - // queue dpc - // - KeInsertQueueDpc(&This->m_IntDpcObject, UlongToPtr(Status), NULL); - } - - // - // interrupt handled - // - return TRUE; -} - - -VOID -CUSBHardwareDevice::WriteRegister8( - IN ULONG Register, - IN UCHAR Value) -{ - WRITE_PORT_UCHAR((PUCHAR)((PUCHAR)m_Base + Register), Value); -} - - -VOID -CUSBHardwareDevice::WriteRegister16( - ULONG Register, - USHORT Value) -{ - WRITE_PORT_USHORT((PUSHORT)((PUCHAR)m_Base + Register), Value); -} - - -VOID -CUSBHardwareDevice::WriteRegister32( - ULONG Register, - ULONG Value) -{ - WRITE_PORT_ULONG((PULONG)((PUCHAR)m_Base + Register), Value); -} - - -UCHAR -CUSBHardwareDevice::ReadRegister8( - ULONG Register) -{ - return READ_PORT_UCHAR((PUCHAR)((PUCHAR)m_Base + Register)); -} - - -USHORT -CUSBHardwareDevice::ReadRegister16( - ULONG Register) -{ - return READ_PORT_USHORT((PUSHORT)((PUCHAR)m_Base + Register)); -} - - -ULONG -CUSBHardwareDevice::ReadRegister32( - ULONG Register) -{ - return READ_PORT_ULONG((PULONG)((PUCHAR)m_Base + Register)); -} - -VOID -CUSBHardwareDevice::GetQueueHead( - IN ULONG QueueHeadIndex, - OUT PUHCI_QUEUE_HEAD *OutQueueHead) -{ - // - // sanity check - // - ASSERT(QueueHeadIndex < 5); - - // - // store queue head - // - *OutQueueHead = m_QueueHead[QueueHeadIndex]; -} - -VOID -NTAPI -UhciDeferredRoutine( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2) -{ - CUSBHardwareDevice *This; - ULONG Status; - - // - // get parameters - // - This = (CUSBHardwareDevice*)DeferredContext; - - DPRINT("UhciDeferredRoutine\n"); - - // - // get status - // - Status = PtrToUlong(SystemArgument1); - if (Status & (UHCI_USBSTS_USBINT | UHCI_USBSTS_ERRINT)) - { - // - // a transfer finished, inform the queue - // - This->m_UsbQueue->TransferInterrupt(Status & UHCI_USBSTS_USBINT); - return; - } - - // - // other event - // - DPRINT1("[USBUHCI] Status %x not handled\n", Status); -} - -VOID -NTAPI -TimerDpcRoutine( - IN PKDPC Dpc, - IN PVOID DeferredContext, - IN PVOID SystemArgument1, - IN PVOID SystemArgument2) -{ - CUSBHardwareDevice *This; - USHORT PortStatus = 0; - USHORT PortChange = 0; - - // get parameters - This = (CUSBHardwareDevice*)DeferredContext; - - // check port 0 - This->GetPortStatus(0, &PortStatus, &PortChange); - if (PortChange) - { - // invoke status change work item routine - StatusChangeWorkItemRoutine(DeferredContext); - return; - } - - // check port 1 - This->GetPortStatus(1, &PortStatus, &PortChange); - if (PortChange) - { - // invoke status change work item routine - StatusChangeWorkItemRoutine(DeferredContext); - } -} - - -VOID -NTAPI -StatusChangeWorkItemRoutine( - PVOID Context) -{ - // - // cast to hardware object - // - CUSBHardwareDevice * This = (CUSBHardwareDevice*)Context; - - // - // is there a callback - // - if (This->m_SCECallBack) - { - // - // issue callback - // - This->m_SCECallBack(This->m_SCEContext); - } - -} - -NTSTATUS -NTAPI -CreateUSBHardware( - PUSBHARDWAREDEVICE *OutHardware) -{ - PUSBHARDWAREDEVICE This; - - This = new(NonPagedPool, TAG_USBUHCI) CUSBHardwareDevice(0); - - if (!This) - return STATUS_INSUFFICIENT_RESOURCES; - - This->AddRef(); - - // return result - *OutHardware = (PUSBHARDWAREDEVICE)This; - - return STATUS_SUCCESS; -} diff --git a/drivers/usb/usbuhci/hardware.h b/drivers/usb/usbuhci/hardware.h deleted file mode 100644 index 75f43250665..00000000000 --- a/drivers/usb/usbuhci/hardware.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2004-2006, Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Michael Lotz - * Niels S. Reedijk - */ - -#ifndef UHCI_HARDWARE_H -#define UHCI_HARDWARE_H - -/************************************************************ - * The Registers * - ************************************************************/ - -// R/W -- Read/Write -// R/WC -- Read/Write Clear -// ** -- Only writable with words! - -// PCI register -#define PCI_LEGSUP 0xC0 -#define PCI_LEGSUP_USBPIRQDEN 0x2000 -#define PCI_LEGSUP_CLEAR_SMI 0x8f00 - -// Registers -#define UHCI_USBCMD 0x00 // USB Command - word - R/W -#define UHCI_USBSTS 0x02 // USB Status - word - R/WC -#define UHCI_USBINTR 0x04 // USB Interrupt Enable - word - R/W -#define UHCI_FRNUM 0x06 // Frame number - word - R/W** -#define UHCI_FRBASEADD 0x08 // Frame List BAse Address - dword - R/W -#define UHCI_SOFMOD 0x0c // Start of Frame Modify - byte - R/W -#define UHCI_PORTSC1 0x10 // Port 1 Status/Control - word - R/WC** -#define UHCI_PORTSC2 0x12 // Port 2 Status/Control - word - R/WC** - -// USBCMD -#define UHCI_USBCMD_RS 0x01 // Run/Stop -#define UHCI_USBCMD_HCRESET 0x02 // Host Controller Reset -#define UHCI_USBCMD_GRESET 0x04 // Global Reset -#define UHCI_USBCMD_EGSM 0x08 // Enter Global Suspend mode -#define UHCI_USBCMD_FGR 0x10 // Force Global resume -#define UHCI_USBCMD_SWDBG 0x20 // Software Debug -#define UHCI_USBCMD_CF 0x40 // Configure Flag -#define UHCI_USBCMD_MAXP 0x80 // Max packet - -//USBSTS -#define UHCI_USBSTS_USBINT 0x01 // USB interrupt -#define UHCI_USBSTS_ERRINT 0x02 // USB error interrupt -#define UHCI_USBSTS_RESDET 0x04 // Resume Detect -#define UHCI_USBSTS_HOSTERR 0x08 // Host System Error -#define UHCI_USBSTS_HCPRERR 0x10 // Host Controller Process error -#define UHCI_USBSTS_HCHALT 0x20 // HCHalted - -//USBINTR -#define UHCI_USBINTR_CRC 0x01 // Timeout/ CRC interrupt enable -#define UHCI_USBINTR_RESUME 0x02 // Resume interrupt enable -#define UHCI_USBINTR_IOC 0x04 // Interrupt on complete enable -#define UHCI_USBINTR_SHORT 0x08 // Short packet interrupt enable - -//PORTSC -#define UHCI_PORTSC_CURSTAT 0x0001 // Current connect status -#define UHCI_PORTSC_STATCHA 0x0002 // Current connect status change -#define UHCI_PORTSC_ENABLED 0x0004 // Port enabled/disabled -#define UHCI_PORTSC_ENABCHA 0x0008 // Change in enabled/disabled -#define UHCI_PORTSC_LINE_0 0x0010 // The status of D+ -#define UHCI_PORTSC_LINE_1 0x0020 // The status of D- -#define UHCI_PORTSC_RESUME 0x0040 // Something with the suspend state ??? -#define UHCI_PORTSC_LOWSPEED 0x0100 // Low speed device attached? -#define UHCI_PORTSC_RESET 0x0200 // Port is in reset -#define UHCI_PORTSC_SUSPEND 0x1000 // Set port in suspend state - -#define UHCI_PORTSC_DATAMASK 0x13f5 // Mask that excludes the change bits - -/************************************************************ - * Hardware structs * - ************************************************************/ - -// Framelist flags -#define FRAMELIST_TERMINATE 0x1 -#define FRAMELIST_NEXT_IS_QH 0x2 - -// Number of frames -#define NUMBER_OF_FRAMES 1024 -#define MAX_AVAILABLE_BANDWIDTH 900 // Microseconds - -// Represents a Transfer Descriptor (TD) -typedef struct _UHCI_TRANSFER_DESCRIPTOR -{ - ULONG LinkPhysical; // Link to next transfer descriptor / queue head - ULONG Status; // status - ULONG Token; // packet header - ULONG BufferPhysical; // pointer to the buffer - - // Software part - ULONG PhysicalAddress; // Physical address of this descriptor - PVOID NextLogicalDescriptor; - ULONG BufferSize; // Size of the buffer - PVOID BufferLogical; // Logical pointer to the buffer - PVOID UserBuffer; -}UHCI_TRANSFER_DESCRIPTOR, *PUHCI_TRANSFER_DESCRIPTOR; - -#define TD_NEXT_IS_QH 0x02 - -// Control and Status -#define TD_CONTROL_SPD (1 << 29) -#define TD_CONTROL_3_ERRORS (3 << 27) -#define TD_CONTROL_LOWSPEED (1 << 26) -#define TD_CONTROL_ISOCHRONOUS (1 << 25) -#define TD_CONTROL_IOC (1 << 24) - -#define TD_STATUS_ACTIVE (1 << 23) -#define TD_STATUS_ERROR_STALLED (1 << 22) -#define TD_STATUS_ERROR_BUFFER (1 << 21) -#define TD_STATUS_ERROR_BABBLE (1 << 20) -#define TD_STATUS_ERROR_NAK (1 << 19) -#define TD_STATUS_ERROR_CRC (1 << 18) -#define TD_STATUS_ERROR_TIMEOUT (1 << 18) -#define TD_STATUS_ERROR_BITSTUFF (1 << 17) - -#define TD_STATUS_ACTLEN_MASK 0x07ff -#define TD_STATUS_ACTLEN_NULL 0x07ff - -// Token -#define TD_TOKEN_MAXLEN_SHIFT 21 -#define TD_TOKEN_NULL_DATA (0x07ff << TD_TOKEN_MAXLEN_SHIFT) -#define TD_TOKEN_DATA_TOGGLE_SHIFT 19 -#define TD_TOKEN_DATA1 (1 << TD_TOKEN_DATA_TOGGLE_SHIFT) - -#define TD_TOKEN_SETUP 0x2d -#define TD_TOKEN_IN 0x69 -#define TD_TOKEN_OUT 0xe1 - -#define TD_TOKEN_ENDPTADDR_SHIFT 15 -#define TD_TOKEN_DEVADDR_SHIFT 8 - -#define TD_DEPTH_FIRST 0x04 -#define TD_TERMINATE 0x01 -#define TD_ERROR_MASK 0x440000 -#define TD_ERROR_COUNT_SHIFT 27 -#define TD_ERROR_COUNT_MASK 0x03 -#define TD_LINK_MASK 0xfffffff0 - - -static -inline -ULONG -UHCI_TRANSFER_DESCRIPTOR_MAXIMUM_LENGTH(PUHCI_TRANSFER_DESCRIPTOR Descriptor) -{ - ULONG Length = (Descriptor->Token >> TD_TOKEN_MAXLEN_SHIFT) + 1; - if (Length == TD_STATUS_ACTLEN_NULL + 1) - return 0; - return Length; -} - -static -inline -ULONG -UHCI_TRANSFER_DESCRIPTOR_LENGTH(PUHCI_TRANSFER_DESCRIPTOR Descriptor) -{ - ULONG Length = (Descriptor->Status & TD_STATUS_ACTLEN_MASK) + 1; - if (Length == TD_STATUS_ACTLEN_NULL + 1) - return 0; - return Length; -} - -// Represents a Queue Head (QH) -typedef struct _UHCI_QUEUE_HEAD -{ - // hardware part - ULONG LinkPhysical; // address - ULONG ElementPhysical; // next descriptor - - // Software part - ULONG PhysicalAddress; - PVOID NextLogicalDescriptor; - PVOID Request; - PVOID NextElementDescriptor; -}UHCI_QUEUE_HEAD, *PUHCI_QUEUE_HEAD; - -#define QH_TERMINATE 0x01 -#define QH_NEXT_IS_QH 0x02 -#define QH_LINK_MASK 0xfffffff0 - - -#define UHCI_INTERRUPT_QUEUE 0 -#define UHCI_LOW_SPEED_CONTROL_QUEUE 1 -#define UHCI_FULL_SPEED_CONTROL_QUEUE 2 -#define UHCI_BULK_QUEUE 3 -#define UHCI_DEBUG_QUEUE 4 - -#endif /* UHCI_HARDWARE_H */ diff --git a/drivers/usb/usbuhci/interfaces.h b/drivers/usb/usbuhci/interfaces.h deleted file mode 100644 index ff6ebe082a1..00000000000 --- a/drivers/usb/usbuhci/interfaces.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef INTERFACES_HPP -#define INTERFACES_HPP - -//--------------------------------------------------------------------------- -// -// Object Hierarchy -// -------------------------------------------------------------------- -// | IRootHCDController | -// | IHCDController Intel USB Universal Host Controller - 3A37 | -// | IHCDController - Intel USB Universal HostController - 3A38 | -// | IHCDController - Intel USB Universal HostController - 3A38 | -// |------------------------------------------------------------------| -// -// -// IHCDController Intel USB Universal Host Controller - 3A37 -// IHubController -// IUSBHardwareDevice -// IDMAMemoryManager -// IUSBQueue <- interacts with -> IUSBRequest -// -// -// Each IHCDController creates an IUSBHardwareDevice class upon initialization. The -// IUSBHardwareDevice class is used to abstract usb controller specifics. The IHubController -// manages all attached devices and handles hub control ioctl requests. -// -// Each IUSBHardwareDevice has one IDMAMemoryManager and one IUSBQueue. The IDMAMemoryManager -// is used to handle dma memory allocations. The IUSBQueue manages requests which are send to the -// usb hardware. See IUSBRequest class for details. -// - - -struct _UHCI_QUEUE_HEAD; -struct IDMAMemoryManager; -struct IUSBQueue; - -//========================================================================================= -// -// class IUSBHardwareDevice -// -// Description: This class provides access to the usb hardware controller -// - -#define DEFINE_ABSTRACT_USBUHCIHARDWAREDEVICE() \ - STDMETHOD_(VOID, GetQueueHead)( THIS_ \ - IN ULONG QueueHeadIndex, \ - IN struct _UHCI_QUEUE_HEAD **OutQueueHead) PURE; - -#define IMP_IUHCIHARDWAREDEVICE \ - STDMETHODIMP_(VOID) GetQueueHead( \ - IN ULONG QueueHeadIndex, \ - IN struct _UHCI_QUEUE_HEAD **OutQueueHead); - -DECLARE_INTERFACE_(IUHCIHardwareDevice, IUSBHardwareDevice) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBHARDWAREDEVICE() - DEFINE_ABSTRACT_USBUHCIHARDWAREDEVICE() -}; - -typedef IUHCIHardwareDevice *PUHCIHARDWAREDEVICE; - -//========================================================================================= -// -// class IUSBRequest -// -// Description: This class is used to issue request to usb controller. The class is -// initialized using InitializeXXX methods. You also need to call SetEndpoint to define the endpoint -// In addition you can call SetCompletionDetails if you need to wait for the end of -// the request or want to complete an irp. You call AddUSBRequest to add the request to the queue. -// Once the request is completed the CompletionCallback is invoked. The CompletionCallback -// will take care of any completion details which have been set. If the request is cancelled, the -// CancelCallback routine is invoked. -// - - - -#define DEFINE_ABSTRACT_USBUHCIREQUEST() \ - STDMETHOD_(NTSTATUS, GetEndpointDescriptor)( THIS_ \ - IN struct _UHCI_QUEUE_HEAD**OutDescriptor) PURE; \ - \ - STDMETHOD_(UCHAR, GetInterval)( THIS) PURE; \ - \ - STDMETHOD_(USB_DEVICE_SPEED, GetDeviceSpeed)( THIS) PURE; \ - \ - STDMETHOD_(VOID, CompletionCallback)( THIS) PURE; \ - \ - STDMETHOD_(VOID, FreeEndpointDescriptor)( THIS_ \ - IN struct _UHCI_QUEUE_HEAD *OutDescriptor) PURE; - - -#define IMP_IUHCIREQUEST \ - STDMETHODIMP_(NTSTATUS) GetEndpointDescriptor(THIS_ \ - IN struct _UHCI_QUEUE_HEAD**OutDescriptor); \ - \ - STDMETHODIMP_(UCHAR) GetInterval(THIS); \ - \ - STDMETHODIMP_(USB_DEVICE_SPEED) GetDeviceSpeed(THIS); \ - \ - STDMETHODIMP_(VOID) CompletionCallback(THIS); \ - \ - STDMETHODIMP_(VOID) FreeEndpointDescriptor(THIS_ \ - IN struct _UHCI_QUEUE_HEAD * OutDescriptor); - -DECLARE_INTERFACE_(IUHCIRequest, IUSBRequest) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBREQUEST() - DEFINE_ABSTRACT_USBUHCIREQUEST() -}; - - -typedef IUHCIRequest *PUHCIREQUEST; - -//========================================================================================= -// -// class IUSBQueue -// -// Description: This class manages pending requests -// - -#define DEFINE_ABSTRACT_USBUHCIQUEUE() \ - STDMETHOD_(VOID, TransferInterrupt)( \ - IN UCHAR ErrorInterrupt) PURE; - -#define IMP_IUHCIQUEUE \ - STDMETHODIMP_(VOID) TransferInterrupt( \ - IN UCHAR ErrorInterrupt); - -DECLARE_INTERFACE_(IUHCIQueue, IUSBQueue) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBQUEUE() - DEFINE_ABSTRACT_USBUHCIQUEUE() -}; - -typedef IUHCIQueue *PUHCIQUEUE; - -#endif /* INTERFACES_HPP */ diff --git a/drivers/usb/usbuhci/usb_queue.cpp b/drivers/usb/usbuhci/usb_queue.cpp deleted file mode 100644 index 30f68a1721e..00000000000 --- a/drivers/usb/usbuhci/usb_queue.cpp +++ /dev/null @@ -1,548 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbuhci/usb_queue.cpp - * PURPOSE: USB UHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbuhci.h" - -#define NDEBUG -#include - -class CUSBQueue : public IUHCIQueue -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // com - IMP_IUSBQUEUE - IMP_IUHCIQUEUE - - // local - VOID LinkQueueHead(PUHCI_QUEUE_HEAD QueueHead, PUHCI_QUEUE_HEAD NextQueueHead); - VOID UnLinkQueueHead(PUHCI_QUEUE_HEAD PreviousQueueHead, PUHCI_QUEUE_HEAD NextQueueHead); - BOOLEAN IsQueueHeadComplete(PUHCI_QUEUE_HEAD QueueHead); - NTSTATUS AddQueueHead(PUHCI_QUEUE_HEAD NewQueueHead); - VOID QueueHeadCleanup(IN PUHCI_QUEUE_HEAD QueueHead, IN PUHCI_QUEUE_HEAD PreviousQueueHead, OUT PUHCI_QUEUE_HEAD *NextQueueHead); - - - // constructor / destructor - CUSBQueue(IUnknown *OuterUnknown){} - virtual ~CUSBQueue(){} - -protected: - LONG m_Ref; // reference count - KSPIN_LOCK m_Lock; // list lock - PUHCIHARDWAREDEVICE m_Hardware; // hardware - -}; - -//================================================================================================= -// COM -// -NTSTATUS -STDMETHODCALLTYPE -CUSBQueue::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - if (IsEqualGUIDAligned(refiid, IID_IUnknown)) - { - *Output = PVOID(PUNKNOWN(this)); - PUNKNOWN(*Output)->AddRef(); - return STATUS_SUCCESS; - } - - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS -CUSBQueue::Initialize( - IN PUSBHARDWAREDEVICE Hardware, - IN PDMA_ADAPTER AdapterObject, - IN PDMAMEMORYMANAGER MemManager, - IN OPTIONAL PKSPIN_LOCK Lock) -{ - - // - // store hardware - // - m_Hardware = PUHCIHARDWAREDEVICE(Hardware); - - // - // initialize spinlock - // - KeInitializeSpinLock(&m_Lock); - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBQueue::AddQueueHead( - PUHCI_QUEUE_HEAD NewQueueHead) -{ - PUHCIREQUEST Request; - PUHCI_QUEUE_HEAD QueueHead = NULL; - - - // - // get request - // - Request = (PUHCIREQUEST)NewQueueHead->Request; - if (!Request) - { - // - // no request - // - return STATUS_INVALID_PARAMETER; - } - - if (Request->GetTransferType() == USB_ENDPOINT_TYPE_CONTROL) - { - // - // get device speed - // - if (Request->GetDeviceSpeed() == UsbLowSpeed) - { - // - // use low speed queue - // - m_Hardware->GetQueueHead(UHCI_LOW_SPEED_CONTROL_QUEUE, &QueueHead); - } - else - { - // - // use full speed queue - // - m_Hardware->GetQueueHead(UHCI_FULL_SPEED_CONTROL_QUEUE, &QueueHead); - } - } - else if (Request->GetTransferType() == USB_ENDPOINT_TYPE_BULK) - { - // - // use full speed queue - // - m_Hardware->GetQueueHead(UHCI_BULK_QUEUE, &QueueHead); - } - else if (Request->GetTransferType() == USB_ENDPOINT_TYPE_INTERRUPT) - { - // - // use full speed queue - // - m_Hardware->GetQueueHead(UHCI_INTERRUPT_QUEUE, &QueueHead); - } - - // - // FIXME support isochronous - // - ASSERT(QueueHead); - - // - // add reference - // - Request->AddRef(); - - // - // now link the new queue head - // - LinkQueueHead(QueueHead, NewQueueHead); - return STATUS_SUCCESS; - -} - -NTSTATUS -CUSBQueue::AddUSBRequest( - IUSBRequest * Req) -{ - PUHCI_QUEUE_HEAD NewQueueHead; - NTSTATUS Status; - PUHCIREQUEST Request; - - // get request - Request = (PUHCIREQUEST)Req; - - // - // get queue head - // - Status = Request->GetEndpointDescriptor(&NewQueueHead); - if (!NT_SUCCESS(Status)) - { - // - // failed to create queue head - // - DPRINT1("[USBUHCI] Failed to create queue head %x\n", Status); - return Status; - } - - // - // sanity check - // - ASSERT(PVOID(Request) == NewQueueHead->Request); - - // - // add queue head - // - DPRINT("AddUSBRequest Request %p\n", Request); - DPRINT("NewQueueHead %p\n", NewQueueHead); - return AddQueueHead(NewQueueHead); -} - -VOID -CUSBQueue::LinkQueueHead( - IN PUHCI_QUEUE_HEAD QueueHead, - IN PUHCI_QUEUE_HEAD NextQueueHead) -{ - NextQueueHead->LinkPhysical = QueueHead->LinkPhysical; - NextQueueHead->NextLogicalDescriptor = QueueHead->NextLogicalDescriptor; - - QueueHead->LinkPhysical = NextQueueHead->PhysicalAddress | QH_NEXT_IS_QH; - QueueHead->NextLogicalDescriptor = (PVOID)NextQueueHead; -} - - -VOID -CUSBQueue::UnLinkQueueHead( - PUHCI_QUEUE_HEAD QueueHeadToRemove, - PUHCI_QUEUE_HEAD PreviousQueueHead) -{ - PreviousQueueHead->LinkPhysical = QueueHeadToRemove->LinkPhysical; - PreviousQueueHead->NextLogicalDescriptor = QueueHeadToRemove->NextLogicalDescriptor; -} - -NTSTATUS -CUSBQueue::AbortDevicePipe( - IN UCHAR DeviceAddress, - IN PUSB_ENDPOINT_DESCRIPTOR EndDescriptor) -{ - KIRQL OldLevel; - PUHCI_TRANSFER_DESCRIPTOR Descriptor; - PUHCI_QUEUE_HEAD QueueHead, PreviousQueueHead = NULL; - UCHAR EndpointAddress, EndpointDeviceAddress; - PUSB_ENDPOINT EndpointDescriptor; - - // get descriptor - EndpointDescriptor = (PUSB_ENDPOINT)EndDescriptor; - - // acquire lock - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // get queue head - m_Hardware->GetQueueHead(UHCI_INTERRUPT_QUEUE, &QueueHead); - - while(QueueHead) - { - // get descriptor - Descriptor = (PUHCI_TRANSFER_DESCRIPTOR)QueueHead->NextElementDescriptor; - - if (Descriptor) - { - // extract endpoint address - EndpointAddress = (Descriptor->Token >> TD_TOKEN_ENDPTADDR_SHIFT) & 0x0F; - - // extract device address - EndpointDeviceAddress = (Descriptor->Token >> TD_TOKEN_DEVADDR_SHIFT) & 0x7F; - - // check if they match - if (EndpointAddress == (EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0x0F) && - DeviceAddress == EndpointDeviceAddress) - { - // cleanup queue head - QueueHeadCleanup(QueueHead, PreviousQueueHead, &QueueHead); - continue; - } - } - - // move to next queue head - PreviousQueueHead = QueueHead; - QueueHead = (PUHCI_QUEUE_HEAD)QueueHead->NextLogicalDescriptor; - } - - // release lock - KeReleaseSpinLock(&m_Lock, OldLevel); - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBQueue::CreateUSBRequest( - IUSBRequest **OutRequest) -{ - PUSBREQUEST UsbRequest; - NTSTATUS Status; - - *OutRequest = NULL; - Status = InternalCreateUSBRequest(&UsbRequest); - - if (NT_SUCCESS(Status)) - { - *OutRequest = UsbRequest; - } - - return Status; -} - -BOOLEAN -CUSBQueue::IsQueueHeadComplete( - IN PUHCI_QUEUE_HEAD QueueHead) -{ - PUHCI_TRANSFER_DESCRIPTOR Descriptor; - ULONG ErrorCount; - - if (QueueHead->NextElementDescriptor == NULL) - { - // - // empty queue head - // - DPRINT("QueueHead %p empty element physical\n", QueueHead); - return FALSE; - } - - // - // check all descriptors - // - Descriptor = (PUHCI_TRANSFER_DESCRIPTOR)QueueHead->NextElementDescriptor; - while(Descriptor) - { - if (Descriptor->Status & TD_STATUS_ACTIVE) - { - // - // descriptor is still active - // - DPRINT("Descriptor %p is active Status %x BufferSize %lu\n", Descriptor, Descriptor->Status, Descriptor->BufferSize); - return FALSE; - } - - if (Descriptor->Status & TD_ERROR_MASK) - { - // - // error happened - // - DPRINT1("[USBUHCI] Error detected at descriptor %p Physical %x\n", Descriptor, Descriptor->PhysicalAddress); - - // - // get error count - // - ErrorCount = (Descriptor->Status >> TD_ERROR_COUNT_SHIFT) & TD_ERROR_COUNT_MASK; - if (ErrorCount == 0) - { - // - // error retry count elapsed - // - DPRINT1("[USBUHCI] ErrorBuffer %x TimeOut %x Nak %x BitStuff %x\n", - Descriptor->Status & TD_STATUS_ERROR_BUFFER, - Descriptor->Status & TD_STATUS_ERROR_TIMEOUT, - Descriptor->Status & TD_STATUS_ERROR_NAK, - Descriptor->Status & TD_STATUS_ERROR_BITSTUFF); - return TRUE; - } - else if (Descriptor->Status & TD_STATUS_ERROR_BABBLE) - { - // - // babble error - // - DPRINT1("[USBUHCI] Babble detected\n"); - return TRUE; - } - else - { - // - // stall detected - // - DPRINT1("[USBUHCI] Stall detected\n"); - } - } - - // - // move to next descriptor - // - Descriptor = (PUHCI_TRANSFER_DESCRIPTOR)Descriptor->NextLogicalDescriptor; - } - - // - // request is complete - // - return TRUE; -} - -VOID -CUSBQueue::QueueHeadCleanup( - IN PUHCI_QUEUE_HEAD QueueHead, - IN PUHCI_QUEUE_HEAD PreviousQueueHead, - OUT PUHCI_QUEUE_HEAD *NextQueueHead) -{ - PUHCIREQUEST Request; - PUHCI_QUEUE_HEAD NewQueueHead; - NTSTATUS Status; - - // - // unlink queue head - // - UnLinkQueueHead(QueueHead, PreviousQueueHead); - - // - // get next queue head - // - *NextQueueHead = (PUHCI_QUEUE_HEAD)PreviousQueueHead->NextLogicalDescriptor; - ASSERT(*NextQueueHead != QueueHead); - - // - // the queue head is complete, is the transfer now completed? - // - Request = (PUHCIREQUEST)QueueHead->Request; - ASSERT(Request); - - // - // free queue head - // - DPRINT("Request %p\n", Request); - Request->FreeEndpointDescriptor(QueueHead); - - // - // check if transfer is complete - // - if (Request->IsRequestComplete()) - { - // - // the transfer is complete - // - Request->CompletionCallback(); - Request->Release(); - return; - } - - // - // grab new queue head - // - Status = Request->GetEndpointDescriptor(&NewQueueHead); - if (!NT_SUCCESS(Status)) - { - // - // failed to get new queue head - // - DPRINT1("[USBUHCI] Failed to get new queue head with %x\n", Status); - Request->CompletionCallback(); - Request->Release(); - return; - } - - // - // Link queue head - // - Status = AddQueueHead(NewQueueHead); - if (!NT_SUCCESS(Status)) - { - // - // failed to get new queue head - // - DPRINT1("[USBUHCI] Failed to add queue head with %x\n", Status); - Request->CompletionCallback(); - Request->Release(); - return; - } - -} - -VOID -CUSBQueue::TransferInterrupt( - UCHAR ErrorInterrupt) -{ - KIRQL OldLevel; - PUHCI_QUEUE_HEAD QueueHead, PreviousQueueHead = NULL; - BOOLEAN IsComplete; - - // - // acquire lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // get queue head - // - m_Hardware->GetQueueHead(UHCI_INTERRUPT_QUEUE, &QueueHead); - - while(QueueHead) - { - // - // is queue head complete - // - DPRINT("QueueHead %p\n", QueueHead); - IsComplete = IsQueueHeadComplete(QueueHead); - if (IsComplete) - { - // - // cleanup queue head - // - QueueHeadCleanup(QueueHead, PreviousQueueHead, &QueueHead); - continue; - } - - // - // backup previous queue head - // - PreviousQueueHead = QueueHead; - - // - // get next queue head - // - QueueHead = (PUHCI_QUEUE_HEAD)QueueHead->NextLogicalDescriptor; - } - - // - // release lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); -} - -NTSTATUS -NTAPI -CreateUSBQueue( - PUSBQUEUE *OutUsbQueue) -{ - PUSBQUEUE This; - - // - // allocate controller - // - This = new(NonPagedPool, TAG_USBUHCI) CUSBQueue(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutUsbQueue = (PUSBQUEUE)This; - - // - // done - // - return STATUS_SUCCESS; -} diff --git a/drivers/usb/usbuhci/usb_request.cpp b/drivers/usb/usbuhci/usb_request.cpp deleted file mode 100644 index 0b667b6e293..00000000000 --- a/drivers/usb/usbuhci/usb_request.cpp +++ /dev/null @@ -1,1446 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbuhci/usb_request.cpp - * PURPOSE: USB UHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbuhci.h" - -#define NDEBUG -#include - -class CUSBRequest : public IUHCIRequest -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // com - IMP_IUSBREQUEST - IMP_IUHCIREQUEST - - // local functions - ULONG InternalGetTransferType(); - UCHAR InternalGetPidDirection(); - UCHAR GetDeviceAddress(); - NTSTATUS BuildSetupPacket(); - NTSTATUS BuildSetupPacketFromURB(); - UCHAR GetEndpointAddress(); - USHORT GetMaxPacketSize(); - NTSTATUS CreateDescriptor(PUHCI_TRANSFER_DESCRIPTOR *OutDescriptor, IN UCHAR PidCode, ULONG BufferLength); - NTSTATUS BuildControlTransferDescriptor(IN PUHCI_QUEUE_HEAD * OutQueueHead); - NTSTATUS BuildBulkInterruptTransferDescriptor(IN PUHCI_QUEUE_HEAD * OutQueueHead); - NTSTATUS BuildQueueHead(OUT PUHCI_QUEUE_HEAD *OutQueueHead); - VOID FreeDescriptor(IN PUHCI_TRANSFER_DESCRIPTOR Descriptor); - NTSTATUS BuildTransferDescriptorChain(IN PVOID TransferBuffer, IN ULONG TransferBufferLength, IN UCHAR PidCode, IN UCHAR InitialDataToggle, OUT PUHCI_TRANSFER_DESCRIPTOR * OutFirstDescriptor, OUT PUHCI_TRANSFER_DESCRIPTOR * OutLastDescriptor, OUT PULONG OutTransferBufferOffset, OUT PUCHAR OutDataToggle); - - // constructor / destructor - CUSBRequest(IUnknown *OuterUnknown); - virtual ~CUSBRequest(); - -protected: - LONG m_Ref; - - // - // memory manager for allocating setup packet / queue head / transfer descriptors - // - PDMAMEMORYMANAGER m_DmaManager; - - // - // caller provided irp packet containing URB request - // - PIRP m_Irp; - - // - // transfer buffer length - // - ULONG m_TransferBufferLength; - - // - // current transfer length - // - ULONG m_TransferBufferLengthCompleted; - - // - // Total Transfer Length - // - ULONG m_TotalBytesTransferred; - - // - // transfer buffer MDL - // - PMDL m_TransferBufferMDL; - - // - // caller provided setup packet - // - PUSB_DEFAULT_PIPE_SETUP_PACKET m_SetupPacket; - - // - // completion event for callers who initialized request with setup packet - // - PKEVENT m_CompletionEvent; - - // - // device address for callers who initialized it with device address - // - UCHAR m_DeviceAddress; - - // - // store end point address - // - PUSB_ENDPOINT m_EndpointDescriptor; - - // - // allocated setup packet from the DMA pool - // - PUSB_DEFAULT_PIPE_SETUP_PACKET m_DescriptorPacket; - PHYSICAL_ADDRESS m_DescriptorSetupPacket; - - // - // stores the result of the operation - // - NTSTATUS m_NtStatusCode; - ULONG m_UrbStatusCode; - - // - // store device speed - // - USB_DEVICE_SPEED m_DeviceSpeed; - - // base - PVOID m_Base; - -}; - -//---------------------------------------------------------------------------------------- -CUSBRequest::CUSBRequest(IUnknown *OuterUnknown) : - m_CompletionEvent(NULL) -{ - UNREFERENCED_PARAMETER(OuterUnknown); -} - -//---------------------------------------------------------------------------------------- -CUSBRequest::~CUSBRequest() -{ - if (m_CompletionEvent != NULL) - { - ExFreePoolWithTag(m_CompletionEvent, TAG_USBUHCI); - } -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBRequest::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - return STATUS_UNSUCCESSFUL; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::InitializeWithSetupPacket( - IN PDMAMEMORYMANAGER DmaManager, - IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, - IN PUSBDEVICE Device, - IN OPTIONAL struct _USB_ENDPOINT * EndpointDescriptor, - IN OUT ULONG TransferBufferLength, - IN OUT PMDL TransferBuffer) -{ - // - // sanity checks - // - PC_ASSERT(DmaManager); - PC_ASSERT(SetupPacket); - - // - // initialize packet - // - m_DmaManager = DmaManager; - m_SetupPacket = SetupPacket; - m_TransferBufferLength = TransferBufferLength; - m_TransferBufferMDL = TransferBuffer; - m_DeviceAddress = Device->GetDeviceAddress(); - m_EndpointDescriptor = EndpointDescriptor; - m_TotalBytesTransferred = 0; - m_DeviceSpeed = Device->GetSpeed(); - - // - // Set Length Completed to 0 - // - m_TransferBufferLengthCompleted = 0; - - // - // allocate completion event - // - m_CompletionEvent = (PKEVENT)ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_USBUHCI); - if (!m_CompletionEvent) - { - // - // failed to allocate completion event - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize completion event - // - KeInitializeEvent(m_CompletionEvent, NotificationEvent, FALSE); - - // - // done - // - return STATUS_SUCCESS; -} -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::InitializeWithIrp( - IN PDMAMEMORYMANAGER DmaManager, - IN PUSBDEVICE Device, - IN OUT PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - - // - // sanity checks - // - PC_ASSERT(DmaManager); - PC_ASSERT(Irp); - - m_DmaManager = DmaManager; - m_TotalBytesTransferred = 0; - m_DeviceSpeed = Device->GetSpeed(); - - // - // get current irp stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - - // - // sanity check - // - PC_ASSERT(IoStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL); - PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB); - PC_ASSERT(IoStack->Parameters.Others.Argument1 != 0); - - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // store irp - // - m_Irp = Irp; - - // - // check function type - // - switch (Urb->UrbHeader.Function) - { - case URB_FUNCTION_ISOCH_TRANSFER: - { - // - // there must be at least one packet - // - ASSERT(Urb->UrbIsochronousTransfer.NumberOfPackets); - - // - // is there data to be transferred - // - if (Urb->UrbIsochronousTransfer.TransferBufferLength) - { - // - // Check if there is a MDL - // - if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) - { - // - // sanity check - // - PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer); - - // - // Create one using TransferBuffer - // - DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, - Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, - FALSE, - FALSE, - NULL); - - if (!m_TransferBufferMDL) - { - // - // failed to allocate mdl - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // build mdl for non paged pool - // FIXME: Does hub driver already do this when passing MDL? - // - MmBuildMdlForNonPagedPool(m_TransferBufferMDL); - } - else - { - // - // use provided mdl - // - m_TransferBufferMDL = Urb->UrbIsochronousTransfer.TransferBufferMDL; - } - } - - // - // save buffer length - // - m_TransferBufferLength = Urb->UrbIsochronousTransfer.TransferBufferLength; - - // - // Set Length Completed to 0 - // - m_TransferBufferLengthCompleted = 0; - - // - // get endpoint descriptor - // - m_EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbIsochronousTransfer.PipeHandle; - - // - // completed initialization - // - break; - } - // - // luckily those request have the same structure layout - // - case URB_FUNCTION_CLASS_INTERFACE: - case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: - case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: - { - // - // bulk interrupt transfer - // - if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength) - { - // - // Check if there is a MDL - // - if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) - { - // - // sanity check - // - PC_ASSERT(Urb->UrbBulkOrInterruptTransfer.TransferBuffer); - - // - // Create one using TransferBuffer - // - DPRINT("Creating Mdl from Urb Buffer %p Length %lu\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - m_TransferBufferMDL = IoAllocateMdl(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, - Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, - FALSE, - FALSE, - NULL); - - if (!m_TransferBufferMDL) - { - // - // failed to allocate mdl - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // build mdl for non paged pool - // FIXME: Does hub driver already do this when passing MDL? - // - MmBuildMdlForNonPagedPool(m_TransferBufferMDL); - - // - // Keep that ehci created the MDL and needs to free it. - // - } - else - { - m_TransferBufferMDL = Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL; - } - - // - // save buffer length - // - m_TransferBufferLength = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; - - // - // Set Length Completed to 0 - // - m_TransferBufferLengthCompleted = 0; - - // - // get endpoint descriptor - // - m_EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle; - - } - break; - } - default: - DPRINT1("URB Function: not supported %x\n", Urb->UrbHeader.Function); - PC_ASSERT(FALSE); - } - - // - // done - // - return STATUS_SUCCESS; - -} - -//---------------------------------------------------------------------------------------- -BOOLEAN -CUSBRequest::IsRequestComplete() -{ - // - // FIXME: check if request was split - // - - // - // Check if the transfer was completed, only valid for Bulk Transfers - // - if ((m_TransferBufferLengthCompleted < m_TransferBufferLength) - && (GetTransferType() == USB_ENDPOINT_TYPE_BULK)) - { - // - // Transfer not completed - // - return FALSE; - } - return TRUE; -} -//---------------------------------------------------------------------------------------- -ULONG -CUSBRequest::GetTransferType() -{ - // - // call internal implementation - // - return InternalGetTransferType(); -} - -USHORT -CUSBRequest::GetMaxPacketSize() -{ - if (!m_EndpointDescriptor) - { - // - // control request - // - return 0; - } - - ASSERT(m_Irp); - ASSERT(m_EndpointDescriptor); - - // - // return max packet size - // - return m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; -} - -UCHAR -CUSBRequest::GetInterval() -{ - ASSERT(m_EndpointDescriptor); - ASSERT((m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT); - - // - // return interrupt interval - // - return m_EndpointDescriptor->EndPointDescriptor.bInterval; -} - -UCHAR -CUSBRequest::GetEndpointAddress() -{ - if (!m_EndpointDescriptor) - { - // - // control request - // - return 0; - } - - ASSERT(m_Irp); - ASSERT(m_EndpointDescriptor); - - // - // endpoint number is between 1-15 - // - return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & 0xF); -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBRequest::InternalGetTransferType() -{ - ULONG TransferType; - - // - // check if an irp is provided - // - if (m_Irp) - { - ASSERT(m_EndpointDescriptor); - - // - // end point is defined in the low byte of bmAttributes - // - TransferType = (m_EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK); - } - else - { - // - // initialized with setup packet, must be a control transfer - // - TransferType = USB_ENDPOINT_TYPE_CONTROL; - } - - // - // done - // - return TransferType; -} - -UCHAR -CUSBRequest::InternalGetPidDirection() -{ - if (m_EndpointDescriptor) - { - // - // end point direction is highest bit in bEndpointAddress - // - return (m_EndpointDescriptor->EndPointDescriptor.bEndpointAddress & USB_ENDPOINT_DIRECTION_MASK) >> 7; - } - else - { - // - // request arrives on the control pipe, extract direction from setup packet - // - ASSERT(m_SetupPacket); - return (m_SetupPacket->bmRequestType.B >> 7); - } -} - - -//---------------------------------------------------------------------------------------- -UCHAR -CUSBRequest::GetDeviceAddress() -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - PUSBDEVICE UsbDevice; - - // - // check if there is an irp provided - // - if (!m_Irp) - { - // - // used provided address - // - return m_DeviceAddress; - } - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // get contained urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // check if there is a pipe handle provided - // - if (Urb->UrbHeader.UsbdDeviceHandle) - { - // - // there is a device handle provided - // - UsbDevice = (PUSBDEVICE)Urb->UrbHeader.UsbdDeviceHandle; - - // - // return device address - // - return UsbDevice->GetDeviceAddress(); - } - - // - // no device handle provided, it is the host root bus - // - return 0; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::GetEndpointDescriptor( - struct _UHCI_QUEUE_HEAD ** OutQueueHead) -{ - NTSTATUS Status = STATUS_UNSUCCESSFUL; - ULONG TransferType; - - // get transfer type - TransferType = InternalGetTransferType(); - - if (TransferType == USB_ENDPOINT_TYPE_CONTROL) - { - // - // build queue head - // - Status = BuildControlTransferDescriptor(OutQueueHead); - } - else if (TransferType == USB_ENDPOINT_TYPE_INTERRUPT || TransferType == USB_ENDPOINT_TYPE_BULK) - { - // - // build queue head - // - Status = BuildBulkInterruptTransferDescriptor(OutQueueHead); - } - - if (!NT_SUCCESS(Status)) - { - // - // failed - // - return Status; - } - - // - // store result - // - (*OutQueueHead)->Request = PVOID(this); - - // - // done - // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -VOID -CUSBRequest::GetResultStatus( - OUT OPTIONAL NTSTATUS * NtStatusCode, - OUT OPTIONAL PULONG UrbStatusCode) -{ - // - // sanity check - // - PC_ASSERT(m_CompletionEvent); - - // - // wait for the operation to complete - // - KeWaitForSingleObject(m_CompletionEvent, Executive, KernelMode, FALSE, NULL); - - // - // copy status - // - if (NtStatusCode) - { - *NtStatusCode = m_NtStatusCode; - } - - // - // copy urb status - // - if (UrbStatusCode) - { - *UrbStatusCode = m_UrbStatusCode; - } - -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CUSBRequest::CreateDescriptor( - OUT PUHCI_TRANSFER_DESCRIPTOR *OutDescriptor, - IN UCHAR PidCode, - ULONG BufferLength) -{ - PUHCI_TRANSFER_DESCRIPTOR Descriptor; - PHYSICAL_ADDRESS Address; - NTSTATUS Status; - - // - // allocate descriptor - // - Status = m_DmaManager->Allocate(sizeof(UHCI_TRANSFER_DESCRIPTOR), (PVOID*)&Descriptor, &Address); - if (!NT_SUCCESS(Status)) - { - DPRINT1("[USBUHCI] Failed to allocate descriptor\n"); - return Status; - } - - // - // init descriptor - // - Descriptor->PhysicalAddress = Address.LowPart; - Descriptor->Status = TD_STATUS_ACTIVE; - - if (InternalGetTransferType() == USB_ENDPOINT_TYPE_ISOCHRONOUS) - { - // - // isochronous transfer descriptor - // - Descriptor->Status |= TD_CONTROL_ISOCHRONOUS; - } - else - { - // - // error count - // - Descriptor->Status |= TD_CONTROL_3_ERRORS; - - if (PidCode == TD_TOKEN_IN && (InternalGetTransferType() != USB_ENDPOINT_TYPE_CONTROL)) - { - // - // enable short packet detect for bulk & interrupt - // - Descriptor->Status |= TD_CONTROL_SPD; - } - } - - // - // is it low speed device - // - if (m_DeviceSpeed == UsbLowSpeed) - { - // - // low speed device - // - Descriptor->Status |= TD_CONTROL_LOWSPEED; - } - - // - // store buffer size - // - Descriptor->BufferSize = BufferLength; - - // - // is there a buffer - // - if(BufferLength) - { - // - // store buffer length - // - Descriptor->Token = (BufferLength - 1) << TD_TOKEN_MAXLEN_SHIFT; - } - else - { - // - // no buffer magic constant - // - Descriptor->Token = TD_TOKEN_NULL_DATA; - } - - // - // store address & endpoint number - // - Descriptor->Token |= GetEndpointAddress() << TD_TOKEN_ENDPTADDR_SHIFT; - Descriptor->Token |= GetDeviceAddress() << TD_TOKEN_DEVADDR_SHIFT | PidCode; - - if (BufferLength) - { - // - // allocate buffer for descriptor - // - Status = m_DmaManager->Allocate(BufferLength, (PVOID*)&Descriptor->BufferLogical, &Address); - if (!NT_SUCCESS(Status)) - { - DPRINT1("[USBUHCI] Failed to allocate descriptor buffer length %lu\n", BufferLength); - m_DmaManager->Release(Descriptor, sizeof(UHCI_TRANSFER_DESCRIPTOR)); - return Status; - } - - // - // store address - // - Descriptor->BufferPhysical = Address.LowPart; - } - - // - // done - // - *OutDescriptor = Descriptor; - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBRequest::BuildTransferDescriptorChain( - IN PVOID TransferBuffer, - IN ULONG TransferBufferLength, - IN UCHAR PidCode, - IN UCHAR InitialDataToggle, - OUT PUHCI_TRANSFER_DESCRIPTOR * OutFirstDescriptor, - OUT PUHCI_TRANSFER_DESCRIPTOR * OutLastDescriptor, - OUT PULONG OutTransferBufferOffset, - OUT PUCHAR OutDataToggle) -{ - PUHCI_TRANSFER_DESCRIPTOR FirstDescriptor = NULL, CurrentDescriptor, LastDescriptor = NULL; - ULONG TransferBufferOffset = 0; - NTSTATUS Status; - ULONG MaxPacketSize, CurrentBufferSize; - - // - // FIXME FIXME FIXME FIXME FIXME - // - if (GetDeviceSpeed() == UsbLowSpeed) - { - // - // low speed use max 8 bytes - // - MaxPacketSize = 8; - } - else - { - if (m_EndpointDescriptor) - { - // - // use endpoint size - // - MaxPacketSize = m_EndpointDescriptor->EndPointDescriptor.wMaxPacketSize; - } - else - { - // - // use max 64 bytes - // - MaxPacketSize = 64; - } - } - - do - { - // - // determine current packet size - // - CurrentBufferSize = min(MaxPacketSize, TransferBufferLength - TransferBufferOffset); - - // - // allocate descriptor - // - Status = CreateDescriptor(&CurrentDescriptor, PidCode, CurrentBufferSize); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate queue head - // - DPRINT1("[UHCI] Failed to create descriptor\n"); - ASSERT(FALSE); - return Status; - } - - if (PidCode == TD_TOKEN_OUT) - { - // - // copy buffer - // - RtlCopyMemory(CurrentDescriptor->BufferLogical, (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset), CurrentBufferSize); - } - else - { - // - // store user buffer - // - CurrentDescriptor->UserBuffer = (PVOID)((ULONG_PTR)TransferBuffer + TransferBufferOffset); - } - - if (!FirstDescriptor) - { - // - // first descriptor - // - FirstDescriptor = CurrentDescriptor; - } - else - { - // - // link descriptor - // - LastDescriptor->LinkPhysical = CurrentDescriptor->PhysicalAddress | TD_DEPTH_FIRST; - LastDescriptor->NextLogicalDescriptor = (PVOID)CurrentDescriptor; - } - - if (InitialDataToggle) - { - // - // apply data toggle - // - CurrentDescriptor->Token |= TD_TOKEN_DATA1; - } - - // - // re-run - // - LastDescriptor = CurrentDescriptor; - TransferBufferOffset += CurrentBufferSize; - InitialDataToggle = !InitialDataToggle; - - }while(TransferBufferOffset < TransferBufferLength); - - if (OutTransferBufferOffset) - { - // - // store transfer buffer length - // - *OutTransferBufferOffset = TransferBufferOffset; - } - - if (OutFirstDescriptor) - { - // - // store first descriptor - // - *OutFirstDescriptor = FirstDescriptor; - } - - if (OutLastDescriptor) - { - // - // store last descriptor - // - *OutLastDescriptor = CurrentDescriptor; - } - - if (OutDataToggle) - { - // - // store data toggle - // - *OutDataToggle = InitialDataToggle; - } - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -CUSBRequest::BuildQueueHead( - OUT PUHCI_QUEUE_HEAD *OutQueueHead) -{ - PUHCI_QUEUE_HEAD QueueHead; - NTSTATUS Status; - PHYSICAL_ADDRESS Address; - - // - // allocate queue head - // - Status = m_DmaManager->Allocate(sizeof(UHCI_QUEUE_HEAD), (PVOID*)&QueueHead, &Address); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate queue head - // - DPRINT1("[UHCI] Failed to create queue head\n"); - return Status; - } - - // - // store address - // - QueueHead->PhysicalAddress = Address.LowPart; - QueueHead->ElementPhysical = Address.LowPart; - - // - // store result - // - *OutQueueHead = QueueHead; - return STATUS_SUCCESS; -} - -VOID -CUSBRequest::FreeDescriptor( - IN PUHCI_TRANSFER_DESCRIPTOR Descriptor) -{ - if (Descriptor->BufferLogical) - { - // - // free buffer - // - m_DmaManager->Release(Descriptor->BufferLogical, Descriptor->BufferSize); - } - - // - // free descriptors - // - m_DmaManager->Release(Descriptor, sizeof(UHCI_TRANSFER_DESCRIPTOR)); -} - -NTSTATUS -CUSBRequest::BuildBulkInterruptTransferDescriptor( - IN PUHCI_QUEUE_HEAD * OutQueueHead) -{ - NTSTATUS Status; - PUHCI_QUEUE_HEAD QueueHead; - PUHCI_TRANSFER_DESCRIPTOR FirstDescriptor, LastDescriptor; - ULONG ChainDescriptorLength; - BOOLEAN Direction; - PVOID Buffer; - ULONG BufferSize; - - // create queue head - Status = BuildQueueHead(&QueueHead); - if (!NT_SUCCESS(Status)) - { - // failed to allocate queue head - DPRINT1("[UHCI] Failed to create queue head\n"); - return Status; - } - - // get direction - Direction = InternalGetPidDirection(); - - if (!m_Base) - { - // get buffer base - m_Base = MmGetMdlVirtualAddress(m_TransferBufferMDL); - - // sanity check - ASSERT(m_Base != NULL); - } - - // get new buffer offset - Buffer = (PVOID)((ULONG_PTR)m_Base + m_TransferBufferLengthCompleted); - - // FIXME determine buffer limit - BufferSize = min(m_TransferBufferLength - m_TransferBufferLengthCompleted, PAGE_SIZE); - - // create descriptor chain - Status = BuildTransferDescriptorChain(Buffer, - BufferSize, - Direction ? TD_TOKEN_IN : TD_TOKEN_OUT, - m_EndpointDescriptor->DataToggle, - &FirstDescriptor, - &LastDescriptor, - &ChainDescriptorLength, - NULL); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate descriptor - // - DPRINT1("[UHCI] Failed to create descriptor chain\n"); - m_DmaManager->Release(QueueHead, sizeof(UHCI_QUEUE_HEAD)); - return Status; - } - - // adjust buffer offset - m_TransferBufferLengthCompleted += ChainDescriptorLength; - - // fire interrupt when the last descriptor is complete - LastDescriptor->Status |= TD_CONTROL_IOC; - LastDescriptor->LinkPhysical = TD_TERMINATE; - LastDescriptor->NextLogicalDescriptor = NULL; - - // link queue head with first data descriptor descriptor - QueueHead->NextElementDescriptor = (PVOID)FirstDescriptor; - QueueHead->ElementPhysical = FirstDescriptor->PhysicalAddress; - - // store result - *OutQueueHead = QueueHead; - return STATUS_SUCCESS; -} - - -NTSTATUS -CUSBRequest::BuildControlTransferDescriptor( - IN PUHCI_QUEUE_HEAD * OutQueueHead) -{ - PUHCI_TRANSFER_DESCRIPTOR SetupDescriptor, StatusDescriptor, FirstDescriptor, LastDescriptor; - PUHCI_QUEUE_HEAD QueueHead; - BOOLEAN Direction; - NTSTATUS Status; - ULONG ChainDescriptorLength; - - // - // create queue head - // - Status = BuildQueueHead(&QueueHead); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate queue head - // - DPRINT1("[UHCI] Failed to create queue head\n"); - return Status; - } - - // - // get direction - // - Direction = InternalGetPidDirection(); - - // - // build setup descriptor - // - Status = CreateDescriptor(&SetupDescriptor, - TD_TOKEN_SETUP, - sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate descriptor - // - DPRINT1("[UHCI] Failed to create setup descriptor\n"); - m_DmaManager->Release(QueueHead, sizeof(UHCI_QUEUE_HEAD)); - return Status; - } - - // - // build status descriptor - // - Status = CreateDescriptor(&StatusDescriptor, - Direction ? TD_TOKEN_OUT : TD_TOKEN_IN, - 0); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate descriptor - // - DPRINT1("[UHCI] Failed to create status descriptor\n"); - FreeDescriptor(SetupDescriptor); - m_DmaManager->Release(QueueHead, sizeof(UHCI_QUEUE_HEAD)); - return Status; - } - - if (m_SetupPacket) - { - // - // copy setup packet - // - RtlCopyMemory(SetupDescriptor->BufferLogical, m_SetupPacket, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - } - else - { - // - // generate setup packet from urb - // - ASSERT(FALSE); - } - - // - // init status descriptor - // - StatusDescriptor->Status |= TD_CONTROL_IOC; - StatusDescriptor->Token |= TD_TOKEN_DATA1; - StatusDescriptor->LinkPhysical = TD_TERMINATE; - StatusDescriptor->NextLogicalDescriptor = NULL; - - if (m_TransferBufferLength) - { - // - // create descriptor chain - // - Status = BuildTransferDescriptorChain(MmGetMdlVirtualAddress(m_TransferBufferMDL), - m_TransferBufferLength, - Direction ? TD_TOKEN_IN : TD_TOKEN_OUT, - TRUE, - &FirstDescriptor, - &LastDescriptor, - &ChainDescriptorLength, - NULL); - if (!NT_SUCCESS(Status)) - { - // - // failed to allocate descriptor - // - DPRINT1("[UHCI] Failed to create descriptor chain\n"); - FreeDescriptor(SetupDescriptor); - FreeDescriptor(StatusDescriptor); - m_DmaManager->Release(QueueHead, sizeof(UHCI_QUEUE_HEAD)); - return Status; - } - - // - // link setup descriptor to first data descriptor - // - SetupDescriptor->LinkPhysical = FirstDescriptor->PhysicalAddress | TD_DEPTH_FIRST; - SetupDescriptor->NextLogicalDescriptor = (PVOID)FirstDescriptor; - - // - // link last data descriptor to status descriptor - // - LastDescriptor->LinkPhysical = StatusDescriptor->PhysicalAddress | TD_DEPTH_FIRST; - LastDescriptor->NextLogicalDescriptor = (PVOID)StatusDescriptor; - } - else - { - // - // directly link setup to status descriptor - // - SetupDescriptor->LinkPhysical = StatusDescriptor->PhysicalAddress | TD_DEPTH_FIRST; - SetupDescriptor->NextLogicalDescriptor = (PVOID)StatusDescriptor; - } - - // - // link queue head with setup descriptor - // - QueueHead->NextElementDescriptor = (PVOID)SetupDescriptor; - QueueHead->ElementPhysical = SetupDescriptor->PhysicalAddress; - - // - // store result - // - *OutQueueHead = QueueHead; - return STATUS_SUCCESS; -} -USB_DEVICE_SPEED -CUSBRequest::GetDeviceSpeed() -{ - return m_DeviceSpeed; -} - -VOID -CUSBRequest::FreeEndpointDescriptor( - struct _UHCI_QUEUE_HEAD * OutDescriptor) -{ - PUHCI_TRANSFER_DESCRIPTOR Descriptor, NextDescriptor; - ULONG ErrorCount; - UCHAR DataToggle = 0; - ULONG Index = 0; - - // - // grab first transfer descriptor - // - Descriptor = (PUHCI_TRANSFER_DESCRIPTOR)OutDescriptor->NextElementDescriptor; - while(Descriptor) - { - // get data toggle - DataToggle = (Descriptor->Token >> TD_TOKEN_DATA_TOGGLE_SHIFT) & 0x01; - - if (Descriptor->Status & TD_ERROR_MASK) - { - // - // error happened - // - DPRINT1("[USBUHCI] Error detected at descriptor %p Physical %x\n", Descriptor, Descriptor->PhysicalAddress); - - // - // get error count - // - ErrorCount = (Descriptor->Status >> TD_ERROR_COUNT_SHIFT) & TD_ERROR_COUNT_MASK; - if (ErrorCount == 0) - { - // - // error retry count elapsed - // - m_NtStatusCode = STATUS_UNSUCCESSFUL; - - if (Descriptor->Status & TD_STATUS_ERROR_BUFFER) - { - DPRINT1("[USBUHCI] Buffer Error detected in descriptor %p Index %lu\n", Descriptor, Index); - m_UrbStatusCode = USBD_STATUS_DATA_BUFFER_ERROR; - } - else if (Descriptor->Status & TD_STATUS_ERROR_TIMEOUT) - { - DPRINT1("[USBUHCI] Timeout detected in descriptor %p Index %lu\n", Descriptor, Index); - m_UrbStatusCode = USBD_STATUS_TIMEOUT; - } - else if (Descriptor->Status & TD_STATUS_ERROR_NAK) - { - DPRINT1("[USBUHCI] Unexpected pid detected in descriptor %p Index %lu\n", Descriptor, Index); - m_UrbStatusCode = USBD_STATUS_UNEXPECTED_PID; - } - else if (Descriptor->Status & TD_STATUS_ERROR_BITSTUFF) - { - DPRINT1("[USBUHCI] BitStuff detected in descriptor %p Index %lu\n", Descriptor, Index); - m_UrbStatusCode = USBD_STATUS_BTSTUFF; - } - } - else if (Descriptor->Status & TD_STATUS_ERROR_BABBLE) - { - // - // babble error - // - DPRINT1("[USBUHCI] Babble detected in descriptor %p Index %lu\n", Descriptor, Index); - m_UrbStatusCode = USBD_STATUS_BABBLE_DETECTED; - } - else - { - // - // stall detected - // - DPRINT1("[USBUHCI] Stall detected Descriptor %p Index %lu\n", Descriptor, Index); - m_UrbStatusCode = USBD_STATUS_STALL_PID; - } - } - else - { - // - // FIXME detect actual length - // - if (Descriptor->UserBuffer) - { - // - // copy contents back - // - RtlCopyMemory(Descriptor->UserBuffer, Descriptor->BufferLogical, Descriptor->BufferSize); - } - } - // - // move to next descriptor - // - NextDescriptor = (PUHCI_TRANSFER_DESCRIPTOR)Descriptor->NextLogicalDescriptor; - - // - // free endpoint descriptor - // - FreeDescriptor(Descriptor); - - // - // move to next - // - Descriptor = NextDescriptor; - Index++; - } - - // - // now free queue head - // - m_DmaManager->Release(OutDescriptor, sizeof(UHCI_QUEUE_HEAD)); - - // is there an endpoint descriptor - if (m_EndpointDescriptor) - { - // invert last data toggle - m_EndpointDescriptor->DataToggle = (DataToggle == 0); - } -} - -VOID -CUSBRequest::CompletionCallback() -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - - DPRINT("CUSBRequest::CompletionCallback\n"); - - if (m_Irp) - { - // - // set irp completion status - // - m_Irp->IoStatus.Status = m_NtStatusCode; - - // - // get current irp stack location - // - IoStack = IoGetCurrentIrpStackLocation(m_Irp); - - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - - // - // store urb status - // - Urb->UrbHeader.Status = m_UrbStatusCode; - - // - // Check if the MDL was created - // - if (!Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL) - { - // - // Free Mdl - // - IoFreeMdl(m_TransferBufferMDL); - } - - // - // FIXME calculate length - // - - // - // complete request - // - IoCompleteRequest(m_Irp, IO_NO_INCREMENT); - } - else - { - // - // signal completion event - // - PC_ASSERT(m_CompletionEvent); - KeSetEvent(m_CompletionEvent, 0, FALSE); - } - -} - - -//----------------------------------------------------------------------------------------- -NTSTATUS -NTAPI -InternalCreateUSBRequest( - PUSBREQUEST *OutRequest) -{ - PUSBREQUEST This; - - // - // allocate requests - // - This = new(NonPagedPool, TAG_USBUHCI) CUSBRequest(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutRequest = (PUSBREQUEST)This; - - // - // done - // - return STATUS_SUCCESS; -} diff --git a/drivers/usb/usbuhci/usbuhci.cpp b/drivers/usb/usbuhci/usbuhci.cpp deleted file mode 100644 index 54b54360872..00000000000 --- a/drivers/usb/usbuhci/usbuhci.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Host Controller Interface - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/usb/usbuhci/usbohci.cpp - * PURPOSE: USB UHCI device driver. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "usbuhci.h" - -#define NDEBUG -#include - -extern -"C" -NTSTATUS -NTAPI -DriverEntry( - PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath) -{ - - /* initialize driver object */ - DriverObject->DriverExtension->AddDevice = USBLIB_AddDevice; - - DriverObject->MajorFunction[IRP_MJ_CREATE] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_POWER] = USBLIB_Dispatch; - DriverObject->MajorFunction[IRP_MJ_PNP] = USBLIB_Dispatch; - return STATUS_SUCCESS; -} - -extern "C" { - void free(void * ptr) - { - ExFreePool(ptr); - } -} diff --git a/drivers/usb/usbuhci/usbuhci.h b/drivers/usb/usbuhci/usbuhci.h deleted file mode 100644 index 4d8cfb20137..00000000000 --- a/drivers/usb/usbuhci/usbuhci.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef USBUHCI_H__ -#define USBUHCI_H__ - -#include - -#include "hardware.h" -#include "interfaces.h" - -// -// flags for handling USB_REQUEST_SET_FEATURE / USB_REQUEST_GET_FEATURE -// -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVER_CURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#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 - -// -// tag for allocations -// -#define TAG_USBUHCI 'ICHU' - -// -// assert for c++ - taken from portcls -// -#define PC_ASSERT(exp) \ - (VOID)((!(exp)) ? \ - RtlAssert((PVOID) #exp, (PVOID)__FILE__, __LINE__, NULL ), FALSE : TRUE) - -// -// hardware.cpp -// -NTSTATUS NTAPI CreateUSBHardware(PUSBHARDWAREDEVICE *OutHardware); - -// -// usb_queue.cpp -// -NTSTATUS NTAPI CreateUSBQueue(PUSBQUEUE *OutUsbQueue); - -// -// usb_request.cpp -// -NTSTATUS NTAPI InternalCreateUSBRequest(PUSBREQUEST *OutRequest); - -#endif /* USBUHCI_H__ */ diff --git a/drivers/usb/usbuhci/usbuhci.rc b/drivers/usb/usbuhci/usbuhci.rc deleted file mode 100644 index 7b4777d9412..00000000000 --- a/drivers/usb/usbuhci/usbuhci.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "USBUHCI Driver API" -#define REACTOS_STR_INTERNAL_NAME "usbuhci" -#define REACTOS_STR_ORIGINAL_FILENAME "usbuhci.sys" -#include diff --git a/sdk/lib/drivers/CMakeLists.txt b/sdk/lib/drivers/CMakeLists.txt index 141db7db5b7..ec8f9317d1c 100644 --- a/sdk/lib/drivers/CMakeLists.txt +++ b/sdk/lib/drivers/CMakeLists.txt @@ -4,7 +4,6 @@ add_subdirectory(copysup) add_subdirectory(csq) add_subdirectory(hidparser) add_subdirectory(ip) -add_subdirectory(libusb) add_subdirectory(lwip) add_subdirectory(ntoskrnl_vista) add_subdirectory(rdbsslib) diff --git a/sdk/lib/drivers/libusb/CMakeLists.txt b/sdk/lib/drivers/libusb/CMakeLists.txt deleted file mode 100644 index f155267c3a2..00000000000 --- a/sdk/lib/drivers/libusb/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -set_cpp() - -remove_definitions(-D_WIN32_WINNT=0x502) -add_definitions(-D_WIN32_WINNT=0x600) - -add_definitions(-DUNICODE -D_UNICODE) - -list(APPEND SOURCE - hcd_controller.cpp - hub_controller.cpp - memory_manager.cpp - misc.cpp - usb_device.cpp - purecall.cpp - libusb.cpp - libusb.h) - -add_library(libusb ${SOURCE}) -add_dependencies(libusb bugcodes xdk) -add_pch(libusb libusb.h SOURCE) diff --git a/sdk/lib/drivers/libusb/common_interfaces.h b/sdk/lib/drivers/libusb/common_interfaces.h deleted file mode 100644 index 5cf12e5c35f..00000000000 --- a/sdk/lib/drivers/libusb/common_interfaces.h +++ /dev/null @@ -1,691 +0,0 @@ - -#ifndef COMMON_INTERFACES_HPP -#define COMMON_INTERFACES_HPP - -typedef struct _USB_ENDPOINT -{ - USB_ENDPOINT_DESCRIPTOR EndPointDescriptor; - UCHAR HubAddress; - UCHAR HubPort; - UCHAR DataToggle; -} USB_ENDPOINT, *PUSB_ENDPOINT; - -typedef struct _USB_INTERFACE -{ - LIST_ENTRY ListEntry; - PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - USB_ENDPOINT EndPoints[1]; -} USB_INTERFACE, *PUSB_INTERFACE; - -typedef struct -{ - PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; - LIST_ENTRY InterfaceList; -}USB_CONFIGURATION, *PUSB_CONFIGURATION; - -//--------------------------------------------------------------------------- -// -// Object Hierarchy -// -------------------------------------------------------------------- -// | IRootHCDController | -// | IHCDController Intel USB Universal Host Controller - 3A37 | -// | IHCDController - Intel USB Universal HostController - 3A38 | -// | IHCDController - Intel USB Universal HostController - 3A38 | -// |------------------------------------------------------------------| -// -// -// IHCDController Intel USB Universal Host Controller - 3A37 -// IHubController -// IUSBHardwareDevice -// IDMAMemoryManager -// IUSBQueue <- interacts with -> IUSBRequest -// -// -// Each IHCDController creates an IUSBHardwareDevice class upon initialization. The -// IUSBHardwardeDevice class is used to abstract usb controller specifics. The IHubController -// manages all attached devices and handles hub control ioctl requests. -// -// Each IUSBHardwareDevice has one IDMAMemoryManager and one IUSBQueue. The IDMAMemoryManager -// is used to handle dma memory allocations. The IUSBQueue manages requests which are send to the -// usb hardware. See IUSBRequest class for details. -// - - -//========================================================================================= -// -// class IRootHCDController -// -// Description: This class serves as the root host controller. The host controller mantains -// a list of registered controllers and provides support functions for the host controllers - -struct IHCDController; - -DECLARE_INTERFACE_(IRootHCDController, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - -//----------------------------------------------------------------------------------------- -// -// Initialize -// -// Description: This function initializes the root host controller. It allocates the resources -// required to manage the registered controllers - - virtual NTSTATUS Initialize() = 0; - -//----------------------------------------------------------------------------------------- -// -// RegisterHCD -// -// Description: this function registers a host controller with the root host controller - - virtual NTSTATUS RegisterHCD(struct IHCDController * Controller) = 0; - -//----------------------------------------------------------------------------------------- -// -// UnregisterHCD -// -// Description: this function unregistes a host controller - - virtual NTSTATUS UnregisterHCD(struct IHCDController * Controller) = 0; - -//----------------------------------------------------------------------------------------- -// -// GetControllerCount -// -// Description: returns the number of host controllers registered - - virtual ULONG GetControllerCount() = 0; - -}; - -typedef IRootHCDController *PROOTHDCCONTROLLER; - -//========================================================================================= -// -// class IHCDController -// -// Description: This class is used to manage a single USB host controller -// - -DECLARE_INTERFACE_(IHCDController, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - -//----------------------------------------------------------------------------------------- -// -// Initialize -// -// Description: This function initializes the IHCDController implementation. -// It creates an IUSBHardwareDevice object and initializes it. It also registeres itself with -// the IRootHCDController -// - virtual NTSTATUS Initialize(IN PROOTHDCCONTROLLER RootHCDController, - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT PhysicalDeviceObject) = 0; - -}; - -typedef IHCDController *PHCDCONTROLLER; - - -//========================================================================================= -// -// class IUSBHardwareDevice -// -// Description: This class provides access to the usb hardware controller -// - -struct IDMAMemoryManager; -struct IUSBQueue; - -#define DEFINE_ABSTRACT_USBHARDWAREDEVICE() \ - STDMETHOD_(NTSTATUS, Initialize)( THIS_ \ - IN PDRIVER_OBJECT DriverObject, \ - IN PDEVICE_OBJECT FunctionalDeviceObject, \ - IN PDEVICE_OBJECT PhysicalDeviceObject, \ - IN PDEVICE_OBJECT LowerDeviceObject) PURE; \ - \ - STDMETHOD_(NTSTATUS, PnpStart)( THIS_ \ - IN PCM_RESOURCE_LIST RawResources, \ - IN PCM_RESOURCE_LIST TranslatedResources) PURE; \ - \ - STDMETHOD_(NTSTATUS, PnpStop)( THIS) PURE; \ - \ - STDMETHOD_(NTSTATUS, GetDeviceDetails)( THIS_ \ - OUT OPTIONAL PUSHORT VendorId, \ - OUT OPTIONAL PUSHORT DeviceId, \ - OUT OPTIONAL PULONG NumberOfPorts, \ - OUT OPTIONAL PULONG Speed) PURE; \ - \ - STDMETHOD_(NTSTATUS, GetUSBQueue)( THIS_ \ - OUT struct IUSBQueue **OutUsbQueue) PURE; \ - \ - STDMETHOD_(NTSTATUS, GetDMA)( THIS_ \ - OUT struct IDMAMemoryManager **OutDMA) PURE; \ - \ - STDMETHOD_(NTSTATUS, ResetPort)( THIS_ \ - IN ULONG PortNumber) PURE; \ - \ - STDMETHOD_(NTSTATUS, GetPortStatus)( THIS_ \ - IN ULONG PortId, \ - OUT USHORT *PortStatus, \ - OUT USHORT *PortChange) PURE; \ - \ - STDMETHOD_(NTSTATUS, ClearPortStatus)( THIS_ \ - IN ULONG PortId, \ - IN ULONG Status) PURE; \ - \ - STDMETHOD_(NTSTATUS, SetPortFeature)( THIS_ \ - IN ULONG PortId, \ - IN ULONG Feature) PURE; \ - \ - STDMETHOD_(VOID, SetStatusChangeEndpointCallBack)( THIS_ \ - IN PVOID CallBack, \ - IN PVOID Context) PURE; \ - \ - STDMETHOD_(LPCSTR, GetUSBType)(THIS) PURE; - - -#define IMP_IUSBHARDWAREDEVICE \ - STDMETHODIMP_(NTSTATUS) Initialize( \ - IN PDRIVER_OBJECT DriverObject, \ - IN PDEVICE_OBJECT FunctionalDeviceObject, \ - IN PDEVICE_OBJECT PhysicalDeviceObject, \ - IN PDEVICE_OBJECT LowerDeviceObject); \ - \ - STDMETHODIMP_(NTSTATUS) PnpStart( \ - IN PCM_RESOURCE_LIST RawResources, \ - IN PCM_RESOURCE_LIST TranslatedResources); \ - \ - STDMETHODIMP_(NTSTATUS) PnpStop(VOID); \ - \ - STDMETHODIMP_(NTSTATUS) GetDeviceDetails( \ - OUT OPTIONAL PUSHORT VendorId, \ - OUT OPTIONAL PUSHORT DeviceId, \ - OUT OPTIONAL PULONG NumberOfPorts, \ - OUT OPTIONAL PULONG Speed); \ - \ - STDMETHODIMP_(NTSTATUS) GetUSBQueue( \ - OUT struct IUSBQueue **OutUsbQueue); \ - \ - STDMETHODIMP_(NTSTATUS) GetDMA( \ - OUT struct IDMAMemoryManager **OutDMA); \ - \ - STDMETHODIMP_(NTSTATUS) ResetPort( \ - IN ULONG PortNumber); \ - \ - STDMETHODIMP_(NTSTATUS) GetPortStatus( \ - IN ULONG PortId, \ - OUT USHORT *PortStatus, \ - OUT USHORT *PortChange); \ - \ - STDMETHODIMP_(NTSTATUS) ClearPortStatus( \ - IN ULONG PortId, \ - IN ULONG Status); \ - \ - STDMETHODIMP_(NTSTATUS) SetPortFeature( \ - IN ULONG PortId, \ - IN ULONG Feature); \ - \ - STDMETHODIMP_(VOID) SetStatusChangeEndpointCallBack( \ - IN PVOID CallBack, \ - IN PVOID Context); \ - \ - STDMETHODIMP_(LPCSTR) GetUSBType(); - -DECLARE_INTERFACE_(IUSBHardwareDevice, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBHARDWAREDEVICE() -}; - -typedef IUSBHardwareDevice *PUSBHARDWAREDEVICE; - - -//========================================================================================= -// -// class IDMAMemoryManager -// -// Description: This class provides access to the dma buffer. It provides methods to -// allocate and free from the dma buffer -// - -DECLARE_INTERFACE_(IDMAMemoryManager, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - -//----------------------------------------------------------------------------------------- -// -// Initialize -// -// Description: initializes the memory manager - - virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Device, - IN PKSPIN_LOCK Lock, - IN ULONG DmaBufferSize, - IN PVOID VirtualBase, - IN PHYSICAL_ADDRESS PhysicalAddress, - IN ULONG DefaultBlockSize) = 0; - -//----------------------------------------------------------------------------------------- -// -// Allocate -// -// Description: allocates block of memory from allocator - - virtual NTSTATUS Allocate(IN ULONG Size, - OUT PVOID *OutVirtualBase, - OUT PPHYSICAL_ADDRESS OutPhysicalAddress) = 0; - - -//----------------------------------------------------------------------------------------- -// -// Free -// -// Description: releases memory block - - virtual NTSTATUS Release(IN PVOID VirtualBase, - IN ULONG Size) = 0; - -}; - -typedef IDMAMemoryManager *PDMAMEMORYMANAGER; - - -//========================================================================================= -// -// class IUSBRequest -// -// Description: This class is used to issue request to usb controller. The class is -// initialized using InitializeXXX methods. You also need to call SetEndpoint to define the endpoint -// In addition you can call SetCompletionDetails if you need to wait for the end of -// the request or want to complete an irp. You call AddUSBRequest to add the request to the queue. -// Once the request is completed the CompletionCallback is invoked. The CompletionCallback -// will take care of any completion details which have been set. If the request is cancelled, the -// CancelCallback routine is invoked. -// - -struct IUSBDevice; - -#define DEFINE_ABSTRACT_USBREQUEST() \ - STDMETHOD_(NTSTATUS, InitializeWithSetupPacket)( THIS_ \ - IN PDMAMEMORYMANAGER DmaManager, \ - IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, \ - IN struct IUSBDevice *Device, \ - IN OPTIONAL struct _USB_ENDPOINT *EndpointDescriptor, \ - IN OUT ULONG TransferBufferLength, \ - IN OUT PMDL TransferBuffer) PURE; \ - \ - STDMETHOD_(NTSTATUS, InitializeWithIrp)( THIS_ \ - IN PDMAMEMORYMANAGER DmaManager, \ - IN struct IUSBDevice *Device, \ - IN OUT PIRP Irp) PURE; \ - \ - STDMETHOD_(BOOLEAN, IsRequestComplete)( THIS) PURE; \ - \ - STDMETHOD_(ULONG, GetTransferType)( THIS) PURE; \ - \ - STDMETHOD_(VOID, GetResultStatus)( THIS_ \ - OUT OPTIONAL NTSTATUS * NtStatusCode, \ - OUT OPTIONAL PULONG UrbStatusCode) PURE; - -#define IMP_IUSBREQUEST \ - STDMETHODIMP_(NTSTATUS) InitializeWithSetupPacket( \ - IN PDMAMEMORYMANAGER DmaManager, \ - IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, \ - IN struct IUSBDevice *Device, \ - IN OPTIONAL struct _USB_ENDPOINT *EndpointDescriptor, \ - IN OUT ULONG TransferBufferLength, \ - IN OUT PMDL TransferBuffer); \ - \ - STDMETHODIMP_(NTSTATUS) InitializeWithIrp( \ - IN PDMAMEMORYMANAGER DmaManager, \ - IN struct IUSBDevice *Device, \ - IN OUT PIRP Irp); \ - \ - STDMETHODIMP_(BOOLEAN) IsRequestComplete(VOID); \ - \ - STDMETHODIMP_(ULONG) GetTransferType(VOID); \ - \ - STDMETHODIMP_(VOID) GetResultStatus( \ - OUT OPTIONAL NTSTATUS * NtStatusCode, \ - OUT OPTIONAL PULONG UrbStatusCode); - -DECLARE_INTERFACE_(IUSBRequest, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBREQUEST() -}; - - -typedef IUSBRequest *PUSBREQUEST; - -//========================================================================================= -// -// class IUSBQueue -// -// Description: This class manages pending requests -// - -#define DEFINE_ABSTRACT_USBQUEUE() \ - STDMETHOD_(NTSTATUS, Initialize)( THIS_ \ - IN PUSBHARDWAREDEVICE Hardware, \ - IN PDMA_ADAPTER AdapterObject, \ - IN PDMAMEMORYMANAGER MemManager, \ - IN OPTIONAL PKSPIN_LOCK Lock) PURE; \ - \ - STDMETHOD_(NTSTATUS, AddUSBRequest)( THIS_ \ - IN IUSBRequest * Request) PURE; \ - \ - STDMETHOD_(NTSTATUS, CreateUSBRequest)( THIS_ \ - IN IUSBRequest **OutRequest) PURE; \ - \ - STDMETHOD_(NTSTATUS, AbortDevicePipe)( THIS_ \ - IN UCHAR DeviceAddress, \ - IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) PURE; - -#define IMP_IUSBQUEUE \ - STDMETHODIMP_(NTSTATUS) Initialize( \ - IN PUSBHARDWAREDEVICE Hardware, \ - IN PDMA_ADAPTER AdapterObject, \ - IN PDMAMEMORYMANAGER MemManager, \ - IN OPTIONAL PKSPIN_LOCK Lock); \ - \ - STDMETHODIMP_(NTSTATUS) AddUSBRequest( \ - IN IUSBRequest * Request); \ - \ - STDMETHODIMP_(NTSTATUS) CreateUSBRequest( \ - OUT IUSBRequest **OutRequest); \ - \ - STDMETHODIMP_(NTSTATUS) AbortDevicePipe( \ - IN UCHAR DeviceAddress, \ - IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor); - -DECLARE_INTERFACE_(IUSBQueue, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - DEFINE_ABSTRACT_USBQUEUE() -}; - -typedef IUSBQueue *PUSBQUEUE; - -//========================================================================================= -// -// class IHubController -// -// Description: This class implements a hub controller -// - -DECLARE_INTERFACE_(IHubController, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - -//---------------------------------------------------------------------------------------- -// -// Initialize -// -// Description: Initializes the hub controller - - virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject, - IN PHCDCONTROLLER Controller, - IN PUSBHARDWAREDEVICE Device, - IN BOOLEAN IsRootHubDevice, - IN ULONG DeviceAddress) = 0; - -//---------------------------------------------------------------------------------------- -// -// GetHubControllerDeviceObject -// -// Description: Returns the hub controller device object - - virtual NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject) = 0; - -//---------------------------------------------------------------------------------------- -// -// GetHubControllerSymbolicLink -// -// Description: Returns the symbolic link of the root hub - - virtual NTSTATUS GetHubControllerSymbolicLink(ULONG BufferLength, PVOID Buffer, PULONG RequiredLength) = 0; - - -}; - -typedef IHubController *PHUBCONTROLLER; - -//========================================================================================= -// -// class IDispatchIrp -// -// Description: This class is used to handle irp dispatch requests -// - -DECLARE_INTERFACE_(IDispatchIrp, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - -//----------------------------------------------------------------------------------------- -// -// HandlePnp -// -// Description: This function handles all pnp requests - - virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) = 0; - -//----------------------------------------------------------------------------------------- -// -// HandlePower -// -// Description: This function handles all power pnp requests -// - virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) = 0; - -//----------------------------------------------------------------------------------------- -// -// HandleDeviceControl -// -// Description: handles device io control requests - - virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) = 0; - -//----------------------------------------------------------------------------------------- -// -// HandleSystemControl -// -// Description: handles WMI system control requests - - virtual NTSTATUS HandleSystemControl(IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) = 0; -}; - -typedef IDispatchIrp *PDISPATCHIRP; - -//========================================================================================= -// -// class IUSBDevice -// -// Description: This class is used to abstract details of a usb device -// - -DECLARE_INTERFACE_(IUSBDevice, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - -//---------------------------------------------------------------------------------------- -// -// Initialize -// -// Description: Initializes the usb device - - virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, - IN PUSBHARDWAREDEVICE Device, - IN PVOID Parent, - IN ULONG Port, - IN ULONG PortStatus) = 0; - -//----------------------------------------------------------------------------------------- -// -// IsHub -// -// Description: returns true when device is a hub - - virtual BOOLEAN IsHub() = 0; - -//----------------------------------------------------------------------------------------- -// -// GetParent -// -// Description: gets the parent device of the this device - - virtual NTSTATUS GetParent(PVOID * Parent) = 0; - -//----------------------------------------------------------------------------------------- -// -// GetDeviceAddress -// -// Description: gets the device address of the this device - - virtual UCHAR GetDeviceAddress() = 0; - - -//----------------------------------------------------------------------------------------- -// -// GetPort -// -// Description: gets the port to which this device is connected - - virtual ULONG GetPort() = 0; - -//----------------------------------------------------------------------------------------- -// -// GetSpeed -// -// Description: gets the speed of the device - - virtual USB_DEVICE_SPEED GetSpeed() = 0; - -//----------------------------------------------------------------------------------------- -// -// GetType -// -// Description: gets the type of the device, either 1.1 or 2.0 device - - virtual USB_DEVICE_TYPE GetType() = 0; - -//----------------------------------------------------------------------------------------- -// -// GetState -// -// Description: gets the device state - - virtual ULONG GetState() = 0; - -//----------------------------------------------------------------------------------------- -// -// SetDeviceHandleData -// -// Description: sets device handle data - - virtual void SetDeviceHandleData(PVOID Data) = 0; - -//----------------------------------------------------------------------------------------- -// -// SetDeviceAddress -// -// Description: sets device handle data - - virtual NTSTATUS SetDeviceAddress(UCHAR DeviceAddress) = 0; - -//----------------------------------------------------------------------------------------- -// -// GetDeviceDescriptor -// -// Description: sets device handle data - - virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) = 0; - -//----------------------------------------------------------------------------------------- -// -// GetConfigurationValue -// -// Description: gets current selected configuration index - - virtual UCHAR GetConfigurationValue() = 0; - -//----------------------------------------------------------------------------------------- -// -// SubmitIrp -// -// Description: submits an irp containing an urb - - virtual NTSTATUS SubmitIrp(PIRP Irp) = 0; - -//----------------------------------------------------------------------------------------- -// -// GetConfigurationDescriptors -// -// Description: returns one or more configuration descriptors - - virtual VOID GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer, - IN ULONG BufferLength, - OUT PULONG OutBufferLength) = 0; - -//----------------------------------------------------------------------------------------- -// -// Description: returns length of configuration descriptors -// - virtual ULONG GetConfigurationDescriptorsLength() = 0; - -//----------------------------------------------------------------------------------------- -// -// SubmitSetupPacket -// -// Description: submits an setup packet. The usb device will then create an usb request from it and submit it to the queue - - virtual NTSTATUS SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, - IN OUT ULONG BufferLength, - OUT PVOID Buffer) = 0; - -//----------------------------------------------------------------------------------------- -// -// SelectConfiguration -// -// Description: selects a configuration - - virtual NTSTATUS SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, - IN PUSBD_INTERFACE_INFORMATION Interface, - OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle) = 0; - -//----------------------------------------------------------------------------------------- -// -// SelectConfiguration -// -// Description: selects a interface of an configuration - - virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, - IN OUT PUSBD_INTERFACE_INFORMATION Interface) = 0; - -//----------------------------------------------------------------------------------------- -// -// AbortPipe -// -// Description: aborts all pending requests - - virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) = 0; - -//----------------------------------------------------------------------------------------- -// -// GetMaxPacketSize -// -// Description: aborts all pending requests - - virtual UCHAR GetMaxPacketSize() = 0; -}; - -typedef IUSBDevice *PUSBDEVICE; - -#endif diff --git a/sdk/lib/drivers/libusb/hcd_controller.cpp b/sdk/lib/drivers/libusb/hcd_controller.cpp deleted file mode 100644 index a12f3991453..00000000000 --- a/sdk/lib/drivers/libusb/hcd_controller.cpp +++ /dev/null @@ -1,791 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library - * LICENSE: GPL - See COPYING in the top level directory - * FILE: lib/drivers/libusb/hcd_controller.cpp - * PURPOSE: USB Common Driver Library. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "libusb.h" - -#define NDEBUG -#include - -class CHCDController : public IHCDController, - public IDispatchIrp -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // IHCDController interface functions - NTSTATUS Initialize(IN PROOTHDCCONTROLLER RootHCDController, IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject); - - // IDispatchIrp interface functions - NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp); - NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp); - NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp); - NTSTATUS HandleSystemControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp); - - // local functions - NTSTATUS CreateFDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject); - NTSTATUS SetSymbolicLink(BOOLEAN Enable); - - // constructor / destructor - CHCDController(IUnknown *OuterUnknown){} - virtual ~CHCDController(){} - -protected: - LONG m_Ref; - PROOTHDCCONTROLLER m_RootController; - PDRIVER_OBJECT m_DriverObject; - PDEVICE_OBJECT m_PhysicalDeviceObject; - PDEVICE_OBJECT m_FunctionalDeviceObject; - PDEVICE_OBJECT m_NextDeviceObject; - PUSBHARDWAREDEVICE m_Hardware; - PHUBCONTROLLER m_HubController; - ULONG m_FDODeviceNumber; - LPCSTR m_USBType; -}; - -//================================================================================================= -// COM -// -NTSTATUS -STDMETHODCALLTYPE -CHCDController::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - return STATUS_UNSUCCESSFUL; -} - -//------------------------------------------------------------------------------------------------- -NTSTATUS -CHCDController::Initialize( - IN PROOTHDCCONTROLLER RootHCDController, - IN PDRIVER_OBJECT DriverObject, - IN PDEVICE_OBJECT PhysicalDeviceObject) -{ - NTSTATUS Status; - PCOMMON_DEVICE_EXTENSION DeviceExtension; - - // - // create usb hardware - // - Status = CreateUSBHardware(&m_Hardware); - if (!NT_SUCCESS(Status)) - { - // - // failed to create hardware object - // - DPRINT1("Failed to create hardware object\n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize members - // - m_DriverObject = DriverObject; - m_PhysicalDeviceObject = PhysicalDeviceObject; - m_RootController = RootHCDController; - - // - // create FDO - // - Status = CreateFDO(m_DriverObject, &m_FunctionalDeviceObject); - if (!NT_SUCCESS(Status)) - { - // - // failed to create PDO - // - return Status; - } - - // - // now attach to device stack - // - m_NextDeviceObject = IoAttachDeviceToDeviceStack(m_FunctionalDeviceObject, m_PhysicalDeviceObject); - if (!m_NextDeviceObject) - { - // - // failed to attach to device stack - // - IoDeleteDevice(m_FunctionalDeviceObject); - m_FunctionalDeviceObject = 0; - - return STATUS_NO_SUCH_DEVICE; - } - - // - // initialize hardware object - // - Status = m_Hardware->Initialize(m_DriverObject, m_FunctionalDeviceObject, m_PhysicalDeviceObject, m_NextDeviceObject); - if (!NT_SUCCESS(Status)) - { - DPRINT1("[%s] Failed to initialize hardware object %x\n", m_Hardware->GetUSBType(), Status); - - // - // failed to initialize hardware object, detach from device stack - // - IoDetachDevice(m_NextDeviceObject); - - // - // now delete the device - // - IoDeleteDevice(m_FunctionalDeviceObject); - - // - // nullify pointers :) - // - m_FunctionalDeviceObject = 0; - m_NextDeviceObject = 0; - - return Status; - } - - // - // get usb controller type - // - m_USBType = m_Hardware->GetUSBType(); - - - // - // set device flags - // - m_FunctionalDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; - - - // - // get device extension - // - DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_FunctionalDeviceObject->DeviceExtension; - PC_ASSERT(DeviceExtension); - - // - // initialize device extension - // - DeviceExtension->IsFDO = TRUE; - DeviceExtension->IsHub = FALSE; - DeviceExtension->Dispatcher = PDISPATCHIRP(this); - - // - // device is initialized - // - m_FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - - // - // is there a root controller - // - if (m_RootController) - { - // - // add reference - // - m_RootController->AddRef(); - - // - // register with controller - // - m_RootController->RegisterHCD(this); - } - - - // - // done - // - return STATUS_SUCCESS; -} - -//------------------------------------------------------------------------------------------------- -NTSTATUS -CHCDController::HandleDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PCOMMON_DEVICE_EXTENSION DeviceExtension; - NTSTATUS Status = STATUS_NOT_IMPLEMENTED; - PUSB_HCD_DRIVERKEY_NAME DriverKey; - ULONG ResultLength; - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - - // - // get device extension - // - DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - // - // sanity check - // - PC_ASSERT(DeviceExtension->IsFDO); - - DPRINT1("[%s] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu\n", m_USBType, - IoStack->Parameters.DeviceIoControl.IoControlCode, - IoStack->Parameters.DeviceIoControl.InputBufferLength, - IoStack->Parameters.DeviceIoControl.OutputBufferLength); - - // - // perform ioctl for FDO - // - if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_HCD_DRIVERKEY_NAME) - { - // - // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME - // - if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME)) - { - // - // get device property size - // - Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, 0, NULL, &ResultLength); - - // - // get input buffer - // - DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer; - - // - // check result - // - if (Status == STATUS_BUFFER_TOO_SMALL) - { - // - // does the caller provide enough buffer space - // - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= ResultLength) - { - // - // it does - // - Status = IoGetDeviceProperty(m_PhysicalDeviceObject, DevicePropertyDriverKeyName, IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength); - } - - // - // store result - // - DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR); - Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength; - Status = STATUS_SUCCESS; - } - } - else - { - // - // buffer is certainly too small - // - Status = STATUS_BUFFER_OVERFLOW; - Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME); - } - } - else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_USB_GET_ROOT_HUB_NAME) - { - // - // check if sizee is at least >= USB_HCD_DRIVERKEY_NAME - // - if(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USB_HCD_DRIVERKEY_NAME)) - { - // - // sanity check - // - PC_ASSERT(m_HubController); - - // - // get input buffer - // - DriverKey = (PUSB_HCD_DRIVERKEY_NAME)Irp->AssociatedIrp.SystemBuffer; - - // - // get symbolic link - // - Status = m_HubController->GetHubControllerSymbolicLink(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG), DriverKey->DriverKeyName, &ResultLength); - - - if (NT_SUCCESS(Status)) - { - // - // null terminate it - // - PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(ULONG) - sizeof(WCHAR) >= ResultLength); - - DriverKey->DriverKeyName[ResultLength / sizeof(WCHAR)] = L'\0'; - } - - // - // store result - // - DriverKey->ActualLength = ResultLength + FIELD_OFFSET(USB_HCD_DRIVERKEY_NAME, DriverKeyName) + sizeof(WCHAR); - Irp->IoStatus.Information = IoStack->Parameters.DeviceIoControl.OutputBufferLength; - Status = STATUS_SUCCESS; - } - else - { - // - // buffer is certainly too small - // - Status = STATUS_BUFFER_OVERFLOW; - Irp->IoStatus.Information = sizeof(USB_HCD_DRIVERKEY_NAME); - } - } - - // - // complete the request - // - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - // - // done - // - return Status; -} - -NTSTATUS -CHCDController::HandlePnp( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PCOMMON_DEVICE_EXTENSION DeviceExtension; - PCM_RESOURCE_LIST RawResourceList; - PCM_RESOURCE_LIST TranslatedResourceList; - PDEVICE_RELATIONS DeviceRelations; - NTSTATUS Status; - - // - // get device extension - // - DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - // - // sanity check - // - PC_ASSERT(DeviceExtension->IsFDO); - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - - switch(IoStack->MinorFunction) - { - case IRP_MN_START_DEVICE: - { - DPRINT("[%s] HandlePnp IRP_MN_START FDO\n", m_USBType); - - // - // first start lower device object - // - Status = SyncForwardIrp(m_NextDeviceObject, Irp); - - if (NT_SUCCESS(Status)) - { - // - // operation succeeded, lets start the device - // - RawResourceList = IoStack->Parameters.StartDevice.AllocatedResources; - TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated; - - if (m_Hardware) - { - // - // start the hardware - // - Status = m_Hardware->PnpStart(RawResourceList, TranslatedResourceList); - } - - if (NT_SUCCESS(Status)) - { - // - // enable symbolic link - // - Status = SetSymbolicLink(TRUE); - } - } - - DPRINT("[%s] HandlePnp IRP_MN_START FDO: Status %x\n", m_USBType ,Status); - break; - } - case IRP_MN_QUERY_DEVICE_RELATIONS: - { - DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %lx\n", m_USBType, IoStack->Parameters.QueryDeviceRelations.Type); - - if (m_HubController == NULL) - { - // - // create hub controller - // - Status = CreateHubController(&m_HubController); - if (!NT_SUCCESS(Status)) - { - // - // failed to create hub controller - // - break; - } - - // - // initialize hub controller - // - Status = m_HubController->Initialize(m_DriverObject, PHCDCONTROLLER(this), m_Hardware, TRUE, 0 /* FIXME*/); - if (!NT_SUCCESS(Status)) - { - // - // failed to initialize hub controller - // - break; - } - - // - // add reference to prevent it from getting deleting while hub driver adds / removes references - // - m_HubController->AddRef(); - } - - if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations) - { - // - // allocate device relations - // - DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS)); - - if (!DeviceRelations) - { - // - // no memory - // - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // init device relations - // - DeviceRelations->Count = 1; - Status = m_HubController->GetHubControllerDeviceObject(&DeviceRelations->Objects [0]); - - // - // sanity check - // - PC_ASSERT(Status == STATUS_SUCCESS); - - ObReferenceObject(DeviceRelations->Objects [0]); - - // - // store result - // - Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; - Status = STATUS_SUCCESS; - } - else - { - // - // not supported - // - Status = STATUS_NOT_SUPPORTED; - } - break; - } - case IRP_MN_STOP_DEVICE: - { - DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType); - - if (m_Hardware) - { - // - // stop the hardware - // - Status = m_Hardware->PnpStop(); - } - else - { - // - // fake success - // - Status = STATUS_SUCCESS; - } - - if (NT_SUCCESS(Status)) - { - // - // stop lower device - // - Status = SyncForwardIrp(m_NextDeviceObject, Irp); - } - break; - } - case IRP_MN_QUERY_REMOVE_DEVICE: - case IRP_MN_QUERY_STOP_DEVICE: - { -#if 0 - // - // sure - // - Irp->IoStatus.Status = STATUS_SUCCESS; - - // - // forward irp to next device object - // - IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(m_NextDeviceObject, Irp); -#else - DPRINT1("[%s] Denying controller removal due to reinitialization bugs\n", m_USBType); - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_UNSUCCESSFUL; -#endif - } - case IRP_MN_REMOVE_DEVICE: - { - DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE FDO\n", m_USBType); - - // - // delete the symbolic link - // - SetSymbolicLink(FALSE); - - // - // forward irp to next device object - // - IoSkipCurrentIrpStackLocation(Irp); - IoCallDriver(m_NextDeviceObject, Irp); - - // - // detach device from device stack - // - IoDetachDevice(m_NextDeviceObject); - - // - // delete device - // - IoDeleteDevice(m_FunctionalDeviceObject); - - return STATUS_SUCCESS; - } - default: - { - // - // forward irp to next device object - // - IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(m_NextDeviceObject, Irp); - } - } - - // - // store result and complete request - // - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; -} - -NTSTATUS -CHCDController::HandlePower( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PoStartNextPowerIrp(Irp); - IoSkipCurrentIrpStackLocation(Irp); - return PoCallDriver(m_NextDeviceObject, Irp); -} - -NTSTATUS -CHCDController::HandleSystemControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - IoSkipCurrentIrpStackLocation(Irp); - return IoCallDriver(m_NextDeviceObject, Irp); -} - -NTSTATUS -CHCDController::CreateFDO( - PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT * OutDeviceObject) -{ - WCHAR CharDeviceName[64]; - NTSTATUS Status; - ULONG UsbDeviceNumber = 0; - UNICODE_STRING DeviceName; - - while (TRUE) - { - // - // construct device name - // - swprintf(CharDeviceName, L"\\Device\\USBFDO-%d", UsbDeviceNumber); - - // - // initialize device name - // - RtlInitUnicodeString(&DeviceName, CharDeviceName); - - // - // create device - // - Status = IoCreateDevice(DriverObject, - sizeof(COMMON_DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_CONTROLLER, - 0, - FALSE, - OutDeviceObject); - - // - // check for success - // - if (NT_SUCCESS(Status)) - break; - - // - // is there a device object with that same name - // - if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION)) - { - // - // Try the next name - // - UsbDeviceNumber++; - continue; - } - - // - // bail out on other errors - // - if (!NT_SUCCESS(Status)) - { - DPRINT1("[%s] CreateFDO: Failed to create %wZ, Status %x\n", m_USBType, &DeviceName, Status); - return Status; - } - } - - // - // store FDO number - // - m_FDODeviceNumber = UsbDeviceNumber; - - DPRINT("[%s] CreateFDO: DeviceName %wZ\n", m_USBType, &DeviceName); - - /* done */ - return Status; -} - -NTSTATUS -CHCDController::SetSymbolicLink( - BOOLEAN Enable) -{ - NTSTATUS Status; - WCHAR LinkName[32]; - WCHAR FDOName[32]; - UNICODE_STRING Link, FDO; - - if (Enable) - { - // - // create legacy link - // - swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber); - swprintf(FDOName, L"\\Device\\USBFDO-%d", m_FDODeviceNumber); - RtlInitUnicodeString(&Link, LinkName); - RtlInitUnicodeString(&FDO, FDOName); - - // - // create symbolic link - // - Status = IoCreateSymbolicLink(&Link, &FDO); - - if (!NT_SUCCESS(Status)) - { - // - // FIXME: handle me - // - ASSERT(0); - } - } - else - { - // - // create legacy link - // - swprintf(LinkName, L"\\DosDevices\\HCD%d", m_FDODeviceNumber); - RtlInitUnicodeString(&Link, LinkName); - - // - // now delete the symbolic link - // - Status = IoDeleteSymbolicLink(&Link); - - if (!NT_SUCCESS(Status)) - { - // - // FIXME: handle me - // - ASSERT(0); - } - } - - // - // done - // - return Status; -} - -NTSTATUS -NTAPI -CreateHCDController( - PHCDCONTROLLER *OutHcdController) -{ - PHCDCONTROLLER This; - - // - // allocate controller - // - This = new(NonPagedPool, TAG_USBLIB) CHCDController(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutHcdController = (PHCDCONTROLLER)This; - - // - // done - // - return STATUS_SUCCESS; -} diff --git a/sdk/lib/drivers/libusb/hub_controller.cpp b/sdk/lib/drivers/libusb/hub_controller.cpp deleted file mode 100644 index 4d0d30d2596..00000000000 --- a/sdk/lib/drivers/libusb/hub_controller.cpp +++ /dev/null @@ -1,4014 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library - * LICENSE: GPL - See COPYING in the top level directory - * FILE: lib/drivers/libusb/hub_controller.cpp - * PURPOSE: USB Common Driver Library. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "libusb.h" - -#define NDEBUG -#include - -VOID NTAPI StatusChangeEndpointCallBack( - PVOID Context); - -class CHubController : public IHubController, - public IDispatchIrp -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // IHubController interface functions - virtual NTSTATUS Initialize(IN PDRIVER_OBJECT DriverObject, IN PHCDCONTROLLER Controller, IN PUSBHARDWAREDEVICE Device, IN BOOLEAN IsRootHubDevice, IN ULONG DeviceAddress); - virtual NTSTATUS GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject); - virtual NTSTATUS GetHubControllerSymbolicLink(ULONG BufferLength, PVOID Buffer, PULONG RequiredLength); - - // IDispatchIrp interface functions - virtual NTSTATUS HandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp); - virtual NTSTATUS HandlePower(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp); - virtual NTSTATUS HandleDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp); - virtual NTSTATUS HandleSystemControl(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp); - - // local functions - NTSTATUS HandleQueryInterface(PIO_STACK_LOCATION IoStack); - NTSTATUS SetDeviceInterface(BOOLEAN bEnable); - NTSTATUS CreatePDO(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * OutDeviceObject); - PUSBHARDWAREDEVICE GetUsbHardware(); - ULONG AcquireDeviceAddress(); - VOID ReleaseDeviceAddress(ULONG DeviceAddress); - BOOLEAN ValidateUsbDevice(PUSBDEVICE UsbDevice); - NTSTATUS AddUsbDevice(PUSBDEVICE UsbDevice); - NTSTATUS RemoveUsbDevice(PUSBDEVICE UsbDevice); - VOID SetNotification(PVOID CallbackContext, PRH_INIT_CALLBACK CallbackRoutine); - // internal ioctl routines - NTSTATUS HandleGetDescriptor(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleGetDescriptorFromInterface(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleClassDevice(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleGetStatusFromDevice(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleSelectConfiguration(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleSelectInterface(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleClassOther(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleClassInterface(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleClassEndpoint(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleVendorDevice(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleBulkOrInterruptTransfer(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleIsochronousTransfer(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleClearStall(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleSyncResetAndClearStall(IN OUT PIRP Irp, PURB Urb); - NTSTATUS HandleAbortPipe(IN OUT PIRP Irp, PURB Urb); - - friend VOID NTAPI StatusChangeEndpointCallBack(PVOID Context); - - // constructor / destructor - CHubController(IUnknown *OuterUnknown){} - virtual ~CHubController(){} - -protected: - LONG m_Ref; - PHCDCONTROLLER m_Controller; - PUSBHARDWAREDEVICE m_Hardware; - BOOLEAN m_IsRootHubDevice; - ULONG m_DeviceAddress; - - BOOLEAN m_InterfaceEnabled; - UNICODE_STRING m_HubDeviceInterfaceString; - - PDEVICE_OBJECT m_HubControllerDeviceObject; - PDRIVER_OBJECT m_DriverObject; - - PVOID m_HubCallbackContext; - PRH_INIT_CALLBACK m_HubCallbackRoutine; - - USB_DEVICE_DESCRIPTOR m_DeviceDescriptor; - - KSPIN_LOCK m_Lock; - RTL_BITMAP m_DeviceAddressBitmap; - PULONG m_DeviceAddressBitmapBuffer; - LIST_ENTRY m_UsbDeviceList; - PIRP m_PendingSCEIrp; - LPCSTR m_USBType; - - - //Internal Functions - BOOLEAN QueryStatusChangeEndpoint(PIRP Irp); -}; - -typedef struct -{ - LIST_ENTRY Entry; - PUSBDEVICE Device; -}USBDEVICE_ENTRY, *PUSBDEVICE_ENTRY; - -/* Lifted from Linux with slight changes */ -const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] = -{ - 0x12, /* bLength; */ - USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType; Device */ - 0x00, 0x20, /* bcdUSB; v1.1 */ - USB_DEVICE_CLASS_HUB, /* bDeviceClass; HUB_CLASSCODE */ - 0x01, /* bDeviceSubClass; */ - 0x00, /* bDeviceProtocol; [ low/full speeds only ] */ - 0x08, /* bMaxPacketSize0; 8 Bytes */ - /* Fill Vendor and Product in when init root hub */ - 0x00, 0x00, /* idVendor; */ - 0x00, 0x00, /* idProduct; */ - 0x00, 0x00, /* bcdDevice */ - 0x00, /* iManufacturer; */ - 0x00, /* iProduct; */ - 0x00, /* iSerialNumber; */ - 0x01 /* bNumConfigurations; */ - -}; - -const USB_CONFIGURATION_DESCRIPTOR ROOTHUB2_CONFIGURATION_DESCRIPTOR = -{ - sizeof(USB_CONFIGURATION_DESCRIPTOR), - USB_CONFIGURATION_DESCRIPTOR_TYPE, - sizeof(USB_CONFIGURATION_DESCRIPTOR) + sizeof(USB_INTERFACE_DESCRIPTOR) + sizeof(USB_ENDPOINT_DESCRIPTOR), - 1, - 1, - 0, - 0x40, /* self powered */ - 0x0 -}; - -const USB_INTERFACE_DESCRIPTOR ROOTHUB2_INTERFACE_DESCRIPTOR = -{ - sizeof(USB_INTERFACE_DESCRIPTOR), /* bLength */ - USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType; Interface */ - 0, /* bInterfaceNumber; */ - 0, /* bAlternateSetting; */ - 0x1, /* bNumEndpoints; */ - 0x09, /* bInterfaceClass; HUB_CLASSCODE */ - 0x01, /* bInterfaceSubClass; */ - 0x00, /* bInterfaceProtocol: */ - 0x00, /* iInterface; */ -}; - -const USB_ENDPOINT_DESCRIPTOR ROOTHUB2_ENDPOINT_DESCRIPTOR = -{ - sizeof(USB_ENDPOINT_DESCRIPTOR), /* bLength */ - USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ - 0x81, /* bEndPointAddress */ - USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ - 0x01, /* wMaxPacketSize */ - 0xC /* bInterval */ -}; - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CHubController::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - return STATUS_UNSUCCESSFUL; -} -//---------------------------------------------------------------------------------------- -NTSTATUS -CHubController::Initialize( - IN PDRIVER_OBJECT DriverObject, - IN PHCDCONTROLLER Controller, - IN PUSBHARDWAREDEVICE Device, - IN BOOLEAN IsRootHubDevice, - IN ULONG DeviceAddress) -{ - NTSTATUS Status; - PCOMMON_DEVICE_EXTENSION DeviceExtension; - USHORT VendorID, DeviceID; - ULONG Dummy1; - - // - // initialize members - // - m_Controller = Controller; - m_Hardware = Device; - m_IsRootHubDevice = IsRootHubDevice; - m_DeviceAddress = DeviceAddress; - m_DriverObject = DriverObject; - m_USBType = m_Hardware->GetUSBType(); - KeInitializeSpinLock(&m_Lock); - InitializeListHead(&m_UsbDeviceList); - - // - // allocate device address bitmap buffer - // - m_DeviceAddressBitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, 16, TAG_USBLIB); - if (!m_DeviceAddressBitmapBuffer) - { - // - // no memory - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize device address bitmap - // - RtlInitializeBitMap(&m_DeviceAddressBitmap, m_DeviceAddressBitmapBuffer, 128); - RtlClearAllBits(&m_DeviceAddressBitmap); - - // - // create PDO - // - Status = CreatePDO(m_DriverObject, &m_HubControllerDeviceObject); - if (!NT_SUCCESS(Status)) - { - // - // failed to create hub device object - // - return Status; - } - - // - // get device extension - // - DeviceExtension = (PCOMMON_DEVICE_EXTENSION)m_HubControllerDeviceObject->DeviceExtension; - - // - // initialize device extension - // - DeviceExtension->IsFDO = FALSE; - DeviceExtension->IsHub = TRUE; //FIXME - DeviceExtension->Dispatcher = PDISPATCHIRP(this); - - // - // intialize device descriptor - // - C_ASSERT(sizeof(USB_DEVICE_DESCRIPTOR) == sizeof(ROOTHUB2_DEVICE_DESCRIPTOR)); - RtlMoveMemory(&m_DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR)); - - if (NT_SUCCESS(m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &Dummy1, &Dummy1))) - { - // - // update device descriptor - // - m_DeviceDescriptor.idVendor = VendorID; - m_DeviceDescriptor.idProduct = DeviceID; - m_DeviceDescriptor.bcdUSB = 0x200; //FIXME - } - - // - // Set the SCE Callback that the Hardware Device will call on port status change - // - Device->SetStatusChangeEndpointCallBack((PVOID)StatusChangeEndpointCallBack, this); - - // - // clear init flag - // - m_HubControllerDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - return STATUS_SUCCESS; -} - -// -// Queries the ports to see if there has been a device connected or removed. -// -BOOLEAN -CHubController::QueryStatusChangeEndpoint( - PIRP Irp) -{ - ULONG PortCount, PortId; - PIO_STACK_LOCATION IoStack; - USHORT PortStatus, PortChange; - PURB Urb; - PUCHAR TransferBuffer; - UCHAR Changed = FALSE; - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - ASSERT(IoStack); - - // - // Get the Urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - ASSERT(Urb); - - // - // Get the number of ports and check each one for device connected - // - m_Hardware->GetDeviceDetails(NULL, NULL, &PortCount, NULL); - DPRINT("[%s] SCE Request %p TransferBufferLength %lu Flags %x MDL %p\n", m_USBType, Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength, Urb->UrbBulkOrInterruptTransfer.TransferFlags, Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL); - - TransferBuffer = (PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer; - - // - // Loop the ports - // - for (PortId = 0; PortId < PortCount; PortId++) - { - m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange); - - DPRINT("[%s] Port %d: Status %x, Change %x\n", m_USBType, PortId, PortStatus, PortChange); - - - // - // If there's a flag in PortChange return TRUE so the SCE Irp will be completed - // - if (PortChange != 0) - { - DPRINT1("[%s] Change state on port %d\n", m_USBType, PortId); - // Set the value for the port number - *TransferBuffer = 1 << ((PortId + 1) & 7); - Changed = TRUE; - } - } - - return Changed; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::GetHubControllerDeviceObject(PDEVICE_OBJECT * HubDeviceObject) -{ - // - // store controller object - // - *HubDeviceObject = m_HubControllerDeviceObject; - - return STATUS_SUCCESS; -} -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::GetHubControllerSymbolicLink( - ULONG BufferLength, - PVOID Buffer, - PULONG RequiredLength) -{ - if (!m_InterfaceEnabled) - { - // - // device interface not yet enabled - // - return STATUS_UNSUCCESSFUL; - } - - if (BufferLength < (ULONG)m_HubDeviceInterfaceString.Length - 8) - { - // - // buffer too small - // length is without '\??\' - // - *RequiredLength = m_HubDeviceInterfaceString.Length- 8; - - // - // done - // - return STATUS_BUFFER_OVERFLOW; - } - - // - // copy symbolic link - // - RtlCopyMemory(Buffer, &m_HubDeviceInterfaceString.Buffer[4], m_HubDeviceInterfaceString.Length - 8); - - // - // store length, length is without '\??\' - // - *RequiredLength = m_HubDeviceInterfaceString.Length - 8; - - // - // done - // - return STATUS_SUCCESS; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandlePnp( - IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PDEVICE_CAPABILITIES DeviceCapabilities; - PPNP_BUS_INFORMATION BusInformation; - PDEVICE_RELATIONS DeviceRelations; - NTSTATUS Status; - ULONG Index = 0; - SIZE_T Length; - USHORT VendorID, DeviceID; - ULONG HiSpeed, NumPorts; - WCHAR Buffer[300]; - LPWSTR DeviceName; - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - - switch(IoStack->MinorFunction) - { - case IRP_MN_START_DEVICE: - { - DPRINT("[%s] HandlePnp IRP_MN_START_DEVICE\n", m_USBType); - // - // register device interface - // - Status = SetDeviceInterface(TRUE); - break; - } - case IRP_MN_QUERY_STOP_DEVICE: - case IRP_MN_QUERY_REMOVE_DEVICE: - { - // - // sure - // - Status = STATUS_SUCCESS; - break; - } - case IRP_MN_QUERY_ID: - { - DPRINT("[%s] HandlePnp IRP_MN_QUERY_ID Type %x\n", m_USBType, IoStack->Parameters.QueryId.IdType); - - if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID) - { - if (m_Hardware) - { - // - // query device id - // - Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed); - - if (HiSpeed == 0x200) - { - // - // USB 2.0 hub - // - swprintf(Buffer, L"USB\\ROOT_HUB20"); - } - else - { - // - // USB 1.1 hub - // - swprintf(Buffer, L"USB\\ROOT_HUB"); - } - - // - // calculate length - // - Length = (wcslen(Buffer) + 1); - - // - // allocate buffer - // - DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_USBLIB); - - if (!DeviceName) - { - // - // no memory - // - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // copy device name - // - wcscpy(DeviceName, Buffer); - - // - // store result - // - Irp->IoStatus.Information = (ULONG_PTR)DeviceName; - Status = STATUS_SUCCESS; - break; - } - Status = STATUS_UNSUCCESSFUL; - PC_ASSERT(0); - break; - } - - if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) - { - if (m_Hardware) - { - // - // query device id - // - Status = m_Hardware->GetDeviceDetails(&VendorID, &DeviceID, &NumPorts, &HiSpeed); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("[%s] HandlePnp> failed to get hardware id %x\n", m_USBType, Status); - VendorID = 0x8086; - DeviceID = 0x3A37; - } - - if (HiSpeed == 0x200) - { - // - // USB 2.0 hub - // - Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1; - Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID%04x&PID%04x", VendorID, DeviceID) + 1; - Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1; - } - else - { - // - // USB 1.1 hub - // - Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x&REV0000", VendorID, DeviceID) + 1; - Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB&VID%04x&PID%04x", VendorID, DeviceID) + 1; - Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB") + 1; - } - - Buffer[Index] = UNICODE_NULL; - Index++; - - // - // allocate buffer - // - DeviceName = (LPWSTR)ExAllocatePoolWithTag(PagedPool, Index * sizeof(WCHAR), TAG_USBLIB); - - if (!DeviceName) - { - // - // no memory - // - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // copy device name - // - RtlMoveMemory(DeviceName, Buffer, Index * sizeof(WCHAR)); - - // - // store result - // - Irp->IoStatus.Information = (ULONG_PTR)DeviceName; - Status = STATUS_SUCCESS; - break; - } - } - // Here we should leave Status as is. - Status = Irp->IoStatus.Status; - break; - } - case IRP_MN_QUERY_CAPABILITIES: - { - DPRINT("[%s] HandlePnp IRP_MN_QUERY_CAPABILITIES\n", m_USBType); - - DeviceCapabilities = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities; - - DeviceCapabilities->LockSupported = FALSE; - DeviceCapabilities->EjectSupported = FALSE; - DeviceCapabilities->Removable = FALSE; - DeviceCapabilities->DockDevice = FALSE; - DeviceCapabilities->UniqueID = FALSE; - DeviceCapabilities->SilentInstall = FALSE; - DeviceCapabilities->RawDeviceOK = FALSE; - DeviceCapabilities->SurpriseRemovalOK = FALSE; - DeviceCapabilities->Address = 0; - DeviceCapabilities->UINumber = 0; - DeviceCapabilities->DeviceD2 = 1; - - /* FIXME */ - DeviceCapabilities->HardwareDisabled = FALSE; - DeviceCapabilities->NoDisplayInUI = FALSE; - DeviceCapabilities->DeviceState[0] = PowerDeviceD0; - for (Index = 1; Index < PowerSystemMaximum; Index++) - DeviceCapabilities->DeviceState[Index] = PowerDeviceD3; - DeviceCapabilities->DeviceWake = PowerDeviceUnspecified; - DeviceCapabilities->D1Latency = 0; - DeviceCapabilities->D2Latency = 0; - DeviceCapabilities->D3Latency = 0; - - Status = STATUS_SUCCESS; - break; - } - case IRP_MN_QUERY_INTERFACE: - { - DPRINT("[%s] HandlePnp IRP_MN_QUERY_INTERFACE\n", m_USBType); - - // - // handle device interface requests - // - Status = HandleQueryInterface(IoStack); - - // - // If a bus driver does not export the requested interface, it - // should leave Status as is. - // - if (Status == STATUS_NOT_SUPPORTED) - Status = Irp->IoStatus.Status; - - break; - } - case IRP_MN_REMOVE_DEVICE: - { - DPRINT("[%s] HandlePnp IRP_MN_REMOVE_DEVICE\n", m_USBType); - - // - // deactivate device interface for BUS PDO - // - SetDeviceInterface(FALSE); - - // - // complete the request first - // - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - // - // now delete device - // - IoDeleteDevice(m_HubControllerDeviceObject); - - // - // nullify pointer - // - m_HubControllerDeviceObject = 0; - - // - // done - // - return STATUS_SUCCESS; - } - case IRP_MN_QUERY_DEVICE_RELATIONS: - { - DPRINT("[%s] HandlePnp IRP_MN_QUERY_DEVICE_RELATIONS Type %x\n", m_USBType, IoStack->Parameters.QueryDeviceRelations.Type); - - if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) - { - // - // allocate device relations - // - DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_USBLIB); - if (!DeviceRelations) - { - // - // no memory - // - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - // - // initialize device relations - // - DeviceRelations->Count = 1; - DeviceRelations->Objects[0] = DeviceObject; - ObReferenceObject(DeviceObject); - - // - // done - // - Status = STATUS_SUCCESS; - Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; - } - else - { - // - // not handled - // - Status = Irp->IoStatus.Status; - } - break; - } - case IRP_MN_QUERY_BUS_INFORMATION: - { - DPRINT("[%s] HandlePnp IRP_MN_QUERY_BUS_INFORMATION\n", m_USBType); - - // - // allocate buffer for bus information - // - BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION)); - if (BusInformation) - { - // - // copy BUS guid - // - RtlMoveMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_USB, sizeof(GUID)); - - // - // set bus type - // - BusInformation->LegacyBusType = PNPBus; - BusInformation->BusNumber = 0; - - Status = STATUS_SUCCESS; - Irp->IoStatus.Information = (ULONG_PTR)BusInformation; - } - else - { - // - // no memory - // - Status = STATUS_INSUFFICIENT_RESOURCES; - } - break; - } - case IRP_MN_STOP_DEVICE: - { - DPRINT("[%s] HandlePnp IRP_MN_STOP_DEVICE\n", m_USBType); - // - // stop device - // - Status = STATUS_SUCCESS; - break; - } - case IRP_MN_SURPRISE_REMOVAL: - { - DPRINT("[%s] HandlePnp IRP_MN_SURPRISE_REMOVAL\n", m_USBType); - Status = STATUS_SUCCESS; - break; - } - default: - { - // - // ignore request with default status - // - Status = Irp->IoStatus.Status; - break; - } - } - - // - // complete request - // - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - // - // done - // - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandlePower( - IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) -{ - NTSTATUS Status; - Status = Irp->IoStatus.Status; - PoStartNextPowerIrp(Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleSystemControl( - IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) -{ - NTSTATUS Status; - Status = Irp->IoStatus.Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleIsochronousTransfer( - IN OUT PIRP Irp, - PURB Urb) -{ - PUSBDEVICE UsbDevice; - PUSB_ENDPOINT_DESCRIPTOR EndPointDesc = NULL; - - // - // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request - // - EndPointDesc = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbIsochronousTransfer.PipeHandle; - - if (!EndPointDesc) - { - DPRINT1("[%s] Error No EndpointDesc\n", m_USBType); - Urb->UrbIsochronousTransfer.Hdr.Status = USBD_STATUS_INVALID_PIPE_HANDLE; - return STATUS_INVALID_PARAMETER; - } - - // - // sanity checks - // - ASSERT(EndPointDesc); - DPRINT("[%s] HandleIsochronousTransfer EndPointDesc %p Address %x bmAttributes %x\n", m_USBType, EndPointDesc, EndPointDesc->bEndpointAddress, EndPointDesc->bmAttributes); - ASSERT((EndPointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleIsochronousTransfer invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - return UsbDevice->SubmitIrp(Irp); -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleBulkOrInterruptTransfer( - IN OUT PIRP Irp, - PURB Urb) -{ - PUSBDEVICE UsbDevice; - PUSB_ENDPOINT EndPointDesc = NULL; - // - // First check if the request is for the Status Change Endpoint - // - - // - // Is the Request for the root hub - // - if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this) || Urb->UrbHeader.UsbdDeviceHandle == NULL) - { - ASSERT(m_PendingSCEIrp == NULL); - if (QueryStatusChangeEndpoint(Irp)) - { - // - // We've seen a change already, so return immediately - // - return STATUS_SUCCESS; - } - - // - // Else pend the IRP, to be completed when a device connects or disconnects. - // - DPRINT("[%s] Pending SCE Irp\n", m_USBType); - m_PendingSCEIrp = Irp; - IoMarkIrpPending(Irp); - return STATUS_PENDING; - } - - // - // Check PipeHandle to determine if this is a Bulk or Interrupt Transfer Request - // - EndPointDesc = (PUSB_ENDPOINT)Urb->UrbBulkOrInterruptTransfer.PipeHandle; - - // - // sanity checks - // - ASSERT(EndPointDesc); - ASSERT((EndPointDesc->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_BULK || (EndPointDesc->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleBulkOrInterruptTransfer invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - return UsbDevice->SubmitIrp(Irp); -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleClassOther( - IN OUT PIRP Irp, - PURB Urb) -{ - NTSTATUS Status = STATUS_NOT_IMPLEMENTED; - USHORT PortStatus = 0, PortChange = 0; - PUSHORT Buffer; - ULONG NumPort; - ULONG PortId; - - DPRINT("[%s] HandleClassOther> Request %x Value %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value); - - // - // get number of ports available - // - Status = m_Hardware->GetDeviceDetails(NULL, NULL, &NumPort, NULL); - PC_ASSERT(Status == STATUS_SUCCESS); - - // - // sanity check - // - PC_ASSERT(Urb->UrbControlVendorClassRequest.Index - 1 < (USHORT)NumPort); - - // - // port range reported start from 1 -n - // convert back port id so it matches the hardware - // - PortId = Urb->UrbControlVendorClassRequest.Index - 1; - - // - // check request code - // - switch(Urb->UrbControlVendorClassRequest.Request) - { - case USB_REQUEST_GET_STATUS: - { - // - // sanity check - // - PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength == sizeof(USHORT) * 2); - PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer); - - // - // get port status - // - Status = m_Hardware->GetPortStatus(PortId, &PortStatus, &PortChange); - - if (NT_SUCCESS(Status)) - { - // - // request contains buffer of 2 ushort which are used from submitting port status and port change status - // - DPRINT("[%s] PortId %x PortStatus %x PortChange %x\n", m_USBType, PortId, PortStatus, PortChange); - Buffer = (PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer; - - // - // store status, then port change - // - *Buffer = PortStatus; - Buffer++; - *Buffer = PortChange; - } - - // - // done - // - break; - } - case USB_REQUEST_CLEAR_FEATURE: - { - switch (Urb->UrbControlVendorClassRequest.Value) - { - case C_PORT_CONNECTION: - Status = m_Hardware->ClearPortStatus(PortId, C_PORT_CONNECTION); - break; - case C_PORT_RESET: - Status = m_Hardware->ClearPortStatus(PortId, C_PORT_RESET); - break; - default: - DPRINT("[%s] Unknown Value for Clear Feature %x \n", m_USBType, Urb->UrbControlVendorClassRequest.Value); - break; - } - - break; - } - case USB_REQUEST_SET_FEATURE: - { - // - // request set feature - // - switch(Urb->UrbControlVendorClassRequest.Value) - { - case PORT_ENABLE: - { - // - // port enable is a no-op for EHCI - // - Status = STATUS_SUCCESS; - break; - } - - case PORT_SUSPEND: - { - // - // set suspend port feature - // - Status = m_Hardware->SetPortFeature(PortId, PORT_SUSPEND); - break; - } - case PORT_POWER: - { - // - // set power feature on port - // - Status = m_Hardware->SetPortFeature(PortId, PORT_POWER); - break; - } - - case PORT_RESET: - { - // - // reset port feature - // - Status = m_Hardware->SetPortFeature(PortId, PORT_RESET); - PC_ASSERT(Status == STATUS_SUCCESS); - break; - } - default: - DPRINT1("[%s] Unsupported request id %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Value); - PC_ASSERT(FALSE); - } - break; - } - default: - DPRINT1("[%s] HandleClassOther Unknown request code %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request); - PC_ASSERT(0); - Status = STATUS_INVALID_DEVICE_REQUEST; - } - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleSelectConfiguration( - IN OUT PIRP Irp, - PURB Urb) -{ - PUSBDEVICE UsbDevice; - PUSBD_INTERFACE_INFORMATION InterfaceInfo; - NTSTATUS Status; - - // - // is the request for the Root Hub - // - if (Urb->UrbHeader.UsbdDeviceHandle == NULL) - { - // - // FIXME: support setting device to unconfigured state - // - PC_ASSERT(Urb->UrbSelectConfiguration.ConfigurationDescriptor); - - // - // set device handle - // - Urb->UrbSelectConfiguration.ConfigurationHandle = (PVOID)&ROOTHUB2_CONFIGURATION_DESCRIPTOR; - - // - // copy interface info - // - InterfaceInfo = &Urb->UrbSelectConfiguration.Interface; - - InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)&ROOTHUB2_INTERFACE_DESCRIPTOR; - InterfaceInfo->Class = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceClass; - InterfaceInfo->SubClass = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceSubClass; - InterfaceInfo->Protocol = ROOTHUB2_INTERFACE_DESCRIPTOR.bInterfaceProtocol; - InterfaceInfo->Reserved = 0; - - // - // sanity check - // - PC_ASSERT(InterfaceInfo->NumberOfPipes == 1); - - // - // copy pipe info - // - InterfaceInfo->Pipes[0].MaximumPacketSize = ROOTHUB2_ENDPOINT_DESCRIPTOR.wMaxPacketSize; - InterfaceInfo->Pipes[0].EndpointAddress = ROOTHUB2_ENDPOINT_DESCRIPTOR.bEndpointAddress; - InterfaceInfo->Pipes[0].Interval = ROOTHUB2_ENDPOINT_DESCRIPTOR.bInterval; - InterfaceInfo->Pipes[0].PipeType = (USBD_PIPE_TYPE)(ROOTHUB2_ENDPOINT_DESCRIPTOR.bmAttributes & USB_ENDPOINT_TYPE_MASK); - InterfaceInfo->Pipes[0].PipeHandle = (PVOID)&ROOTHUB2_ENDPOINT_DESCRIPTOR; - - return STATUS_SUCCESS; - } - else - { - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleSelectConfiguration invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - // - // select configuration - // - Status = UsbDevice->SelectConfiguration(Urb->UrbSelectConfiguration.ConfigurationDescriptor, &Urb->UrbSelectConfiguration.Interface, &Urb->UrbSelectConfiguration.ConfigurationHandle); - if (NT_SUCCESS(Status)) - { - // successfully configured device - Urb->UrbSelectConfiguration.Hdr.Status = USBD_STATUS_SUCCESS; - } - return Status; - } -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleSelectInterface( - IN OUT PIRP Irp, - PURB Urb) -{ - PUSBDEVICE UsbDevice; - - // - // sanity check - // - PC_ASSERT(Urb->UrbSelectInterface.ConfigurationHandle); - - // - // is the request for the Root Hub - // - if (Urb->UrbHeader.UsbdDeviceHandle == NULL) - { - // - // no op for root hub - // - return STATUS_SUCCESS; - } - else - { - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleSelectInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - // - // select interface - // - return UsbDevice->SelectInterface(Urb->UrbSelectInterface.ConfigurationHandle, &Urb->UrbSelectInterface.Interface); - } -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleGetStatusFromDevice( - IN OUT PIRP Irp, - PURB Urb) -{ - PUSHORT DeviceStatus; - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - PUSBDEVICE UsbDevice; - - // - // sanity checks - // - PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBufferLength >= sizeof(USHORT)); - PC_ASSERT(Urb->UrbControlGetStatusRequest.TransferBuffer); - - // - // get status buffer - // - DeviceStatus = (PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer; - - - if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this) || Urb->UrbHeader.UsbdDeviceHandle == NULL) - { - // - // FIXME need more flags ? - // - *DeviceStatus = USB_PORT_STATUS_CONNECT; - return STATUS_SUCCESS; - } - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleGetStatusFromDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - - // - // generate setup packet - // - CtrlSetup.bRequest = USB_REQUEST_GET_STATUS; - CtrlSetup.wValue.LowByte = 0; - CtrlSetup.wValue.HiByte = 0; - CtrlSetup.wIndex.W = Urb->UrbControlGetStatusRequest.Index; - CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength; - CtrlSetup.bmRequestType.B = 0x80; - - if (Urb->UrbHeader.Function == URB_FUNCTION_GET_STATUS_FROM_INTERFACE) - { - // - // add interface type - // - CtrlSetup.bmRequestType.B |= 0x01; - } - else if (Urb->UrbHeader.Function == URB_FUNCTION_GET_STATUS_FROM_ENDPOINT) - { - // - // add interface type - // - CtrlSetup.bmRequestType.B |= 0x02; - } - - // - // submit setup packet - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer); - ASSERT(Status == STATUS_SUCCESS); - DPRINT1("[%s] HandleGetStatusFromDevice Status %x Length %lu DeviceStatus %x\n", m_USBType, Status, Urb->UrbControlDescriptorRequest.TransferBufferLength, *DeviceStatus); - - // - // done - // - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleClassDevice( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - NTSTATUS Status = STATUS_NOT_IMPLEMENTED; - PUSB_HUB_DESCRIPTOR UsbHubDescriptor; - ULONG PortCount, Dummy2; - USHORT Dummy1; - PUSBDEVICE UsbDevice; - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - - DPRINT("[%s] HandleClassDevice Request %x Class %x\n", m_USBType, Urb->UrbControlVendorClassRequest.Request, Urb->UrbControlVendorClassRequest.Value >> 8); - - // - // check class request type - // - switch(Urb->UrbControlVendorClassRequest.Request) - { - case USB_REQUEST_GET_STATUS: - { - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - - // - // generate setup packet - // - CtrlSetup.bRequest = USB_REQUEST_GET_STATUS; - CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; - CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; - CtrlSetup.wLength = (USHORT)Urb->UrbControlGetStatusRequest.TransferBufferLength; - CtrlSetup.bmRequestType.B = 0xA0; - - // - // submit setup packet - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer); - ASSERT(Status == STATUS_SUCCESS); - break; - } - case USB_REQUEST_GET_DESCRIPTOR: - { - switch (Urb->UrbControlVendorClassRequest.Value >> 8) - { - case USB_DEVICE_CLASS_RESERVED: // FALL THROUGH - case USB_DEVICE_CLASS_HUB: - { - if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this) || Urb->UrbHeader.UsbdDeviceHandle == NULL) - { - // - // sanity checks - // - PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer); - PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength >= sizeof(USB_HUB_DESCRIPTOR)); - - // - // get hub descriptor - // - UsbHubDescriptor = (PUSB_HUB_DESCRIPTOR)Urb->UrbControlVendorClassRequest.TransferBuffer; - - // - // one hub is handled - // - UsbHubDescriptor->bDescriptorLength = sizeof(USB_HUB_DESCRIPTOR); - Urb->UrbControlVendorClassRequest.TransferBufferLength = sizeof(USB_HUB_DESCRIPTOR); - - // - // type should 0x29 according to msdn - // - UsbHubDescriptor->bDescriptorType = 0x29; - - // - // get port count - // - Status = m_Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &PortCount, &Dummy2); - PC_ASSERT(Status == STATUS_SUCCESS); - - // - // FIXME: retrieve values - // - UsbHubDescriptor->bNumberOfPorts = (UCHAR)PortCount; - UsbHubDescriptor->wHubCharacteristics = 0x00; - UsbHubDescriptor->bPowerOnToPowerGood = 0x01; - UsbHubDescriptor->bHubControlCurrent = 0x00; - - // - // done - // - Status = STATUS_SUCCESS; - } - else - { - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // FIXME: implement support for real hubs - // - UNIMPLEMENTED; - Status = STATUS_NOT_IMPLEMENTED; - } - break; - } - default: - DPRINT1("[%s] HandleClassDevice Class %x not implemented\n", m_USBType, Urb->UrbControlVendorClassRequest.Value >> 8); - break; - } - break; - } - default: - { - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleClassDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - // - // generate setup packet - // - CtrlSetup.bmRequestType.B = 0; - CtrlSetup.bmRequestType.Recipient = BMREQUEST_TO_DEVICE; - CtrlSetup.bmRequestType.Type = BMREQUEST_CLASS; - CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request; - CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; - CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; - CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength; - - if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN) - { - // - // data direction is device to host - // - CtrlSetup.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST; - } - - // - // submit setup packet - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer); - ASSERT(Status == STATUS_SUCCESS); - - break; - } - } - - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleGetDescriptorFromInterface( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - PUSBDEVICE UsbDevice; - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - - // - // sanity check - // - ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength); - ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleGetDescriptorFromInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - // - // generate setup packet - // - CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR; - CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index; - CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType; - CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId; - CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength; - CtrlSetup.bmRequestType.B = 0x81; - - // - // submit setup packet - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer); - if (!NT_SUCCESS(Status)) - { - DPRINT1("[%s] HandleGetDescriptorFromInterface failed with %x\n", m_USBType, Status); - } - - // - // done - // - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleGetDescriptor( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - NTSTATUS Status = STATUS_NOT_IMPLEMENTED; - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - PUCHAR Buffer; - PUSBDEVICE UsbDevice; - ULONG Length, BufferLength; - - DPRINT("[%s] HandleGetDescriptor Type %x\n", m_USBType, Urb->UrbControlDescriptorRequest.DescriptorType); - - // - // check descriptor type - // - switch(Urb->UrbControlDescriptorRequest.DescriptorType) - { - case USB_DEVICE_DESCRIPTOR_TYPE: - { - // - // sanity check - // - PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR)); - PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); - - if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this) || Urb->UrbHeader.UsbdDeviceHandle == NULL) - { - // - // copy root hub device descriptor - // - RtlCopyMemory((PUCHAR)Urb->UrbControlDescriptorRequest.TransferBuffer, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); - Irp->IoStatus.Information = sizeof(USB_DEVICE_DESCRIPTOR); - Urb->UrbControlDescriptorRequest.Hdr.Status = USBD_STATUS_SUCCESS; - Status = STATUS_SUCCESS; - } - else - { - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleGetDescriptor invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - // - // retrieve device descriptor from device - // - UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)Urb->UrbControlDescriptorRequest.TransferBuffer); - Irp->IoStatus.Information = sizeof(USB_DEVICE_DESCRIPTOR); - Urb->UrbControlDescriptorRequest.Hdr.Status = USBD_STATUS_SUCCESS; - Status = STATUS_SUCCESS; - } - break; - } - case USB_CONFIGURATION_DESCRIPTOR_TYPE: - { - // - // sanity checks - // - PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); - // - // From MSDN - // The caller must allocate a buffer large enough to hold all of this information or the data is truncated without error. - // - BufferLength = Urb->UrbControlDescriptorRequest.TransferBufferLength; - Buffer = (PUCHAR) Urb->UrbControlDescriptorRequest.TransferBuffer; - - if (Urb->UrbHeader.UsbdDeviceHandle == PVOID(this) || Urb->UrbHeader.UsbdDeviceHandle == NULL) - { - // - // request is for the root bus controller - // - Length = BufferLength > sizeof(USB_CONFIGURATION_DESCRIPTOR) ? - sizeof(USB_CONFIGURATION_DESCRIPTOR) : BufferLength; - RtlCopyMemory(Buffer, &ROOTHUB2_CONFIGURATION_DESCRIPTOR, Length); - - // - // Check if we still have some space left - // - if(Length == BufferLength) - { - // - // We copied all we could - // - Status = STATUS_SUCCESS; - break; - } - // - // Go further - // - Buffer += Length; - BufferLength -= Length; - - // - // copy interface descriptor template - // - Length = BufferLength > sizeof(USB_INTERFACE_DESCRIPTOR) ? - sizeof(USB_INTERFACE_DESCRIPTOR) : BufferLength; - RtlCopyMemory(Buffer, &ROOTHUB2_INTERFACE_DESCRIPTOR, Length); - - // - // Check if we still have some space left - // - if(Length == BufferLength) - { - // - // We copied all we could - // - Status = STATUS_SUCCESS; - break; - } - // - // Go further - // - Buffer += Length; - BufferLength -= Length; - - - // - // copy end point descriptor template - // - Length = BufferLength > sizeof(USB_ENDPOINT_DESCRIPTOR) ? - sizeof(USB_ENDPOINT_DESCRIPTOR) : BufferLength; - RtlCopyMemory(Buffer, &ROOTHUB2_ENDPOINT_DESCRIPTOR, Length); - - // - // done - // - Status = STATUS_SUCCESS; - - } - else - { - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] USB_CONFIGURATION_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - // - // Allocate temporary buffer - // - BufferLength = UsbDevice->GetConfigurationDescriptorsLength(); - Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, BufferLength, TAG_USBLIB); - if(!Buffer) - { - Status = STATUS_NO_MEMORY; - break; - } - - // - // perform work in IUSBDevice - // - UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)Buffer, BufferLength, &Length); - - // - // Copy what we can - // - Length = Urb->UrbControlDescriptorRequest.TransferBufferLength > Length ? - Length : Urb->UrbControlDescriptorRequest.TransferBufferLength; - RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, Buffer, Length); - - // - // Free temporary buffer - // - ExFreePoolWithTag(Buffer, TAG_USBLIB); - - // - // store result size - // - Irp->IoStatus.Information = Length; - Urb->UrbControlDescriptorRequest.TransferBufferLength = Length; - Urb->UrbControlDescriptorRequest.Hdr.Status = USBD_STATUS_SUCCESS; - Status = STATUS_SUCCESS; - } - break; - } - case USB_STRING_DESCRIPTOR_TYPE: - { - // - // sanity check - // - PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBuffer); - PC_ASSERT(Urb->UrbControlDescriptorRequest.TransferBufferLength); - - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] USB_STRING_DESCRIPTOR_TYPE invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - // - // generate setup packet - // - CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR; - CtrlSetup.wValue.LowByte = Urb->UrbControlDescriptorRequest.Index; - CtrlSetup.wValue.HiByte = Urb->UrbControlDescriptorRequest.DescriptorType; - CtrlSetup.wIndex.W = Urb->UrbControlDescriptorRequest.LanguageId; - CtrlSetup.wLength = (USHORT)Urb->UrbControlDescriptorRequest.TransferBufferLength; - CtrlSetup.bmRequestType.B = 0x80; - - // - // submit setup packet - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlDescriptorRequest.TransferBufferLength, Urb->UrbControlDescriptorRequest.TransferBuffer); - break; - } - default: - DPRINT1("[%s] CHubController::HandleGetDescriptor DescriptorType %x unimplemented\n", m_USBType, Urb->UrbControlDescriptorRequest.DescriptorType); - break; - } - - // - // done - // - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleClassEndpoint( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - PUSBDEVICE UsbDevice; - - // - // sanity check - // - PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer); - PC_ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength); - PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleClassEndpoint invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - - DPRINT1("URB_FUNCTION_CLASS_ENDPOINT\n"); - DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags); - DPRINT1("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength); - DPRINT1("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer); - DPRINT1("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL); - DPRINT1("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits); - DPRINT1("Request %x\n", Urb->UrbControlVendorClassRequest.Request); - DPRINT1("Value %x\n", Urb->UrbControlVendorClassRequest.Value); - DPRINT1("Index %x\n", Urb->UrbControlVendorClassRequest.Index); - - // - // initialize setup packet - // - CtrlSetup.bmRequestType.B = 0x22; //FIXME: Const. - CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request; - CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; - CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; - CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength; - - if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN) - { - // - // data direction is device to host - // - CtrlSetup.bmRequestType.B |= 0x80; - } - - - // - // issue request - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer); - - // - // assert on failure - // - PC_ASSERT(NT_SUCCESS(Status)); - - - // - // done - // - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleVendorDevice( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - NTSTATUS Status = STATUS_NOT_IMPLEMENTED; - PUSBDEVICE UsbDevice; - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - - //DPRINT("CHubController::HandleVendorDevice Request %x\n", Urb->UrbControlVendorClassRequest.Request); - - // - // sanity check - // - PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleVendorDevice invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - // - // initialize setup packet - // - CtrlSetup.bmRequestType.B = 0; - CtrlSetup.bmRequestType.Recipient = BMREQUEST_TO_DEVICE; - CtrlSetup.bmRequestType.Type = BMREQUEST_VENDOR; - CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request; - CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; - CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; - CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength; - - if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN) - { - // - // data direction is device to host - // - CtrlSetup.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST; - } - - // - // issue request - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer); - if (NT_SUCCESS(Status)) - { - // success - Urb->UrbControlVendorClassRequest.Hdr.Status = USBD_STATUS_SUCCESS; - Irp->IoStatus.Information = Urb->UrbControlVendorClassRequest.TransferBufferLength; - } - - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleSyncResetAndClearStall( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - NTSTATUS Status = STATUS_SUCCESS; - PUSB_ENDPOINT EndpointDescriptor; - ULONG Type; - - // - // sanity check - // - PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); - PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST)); - PC_ASSERT(Urb->UrbPipeRequest.PipeHandle); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleSyncResetAndClearStall invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // abort pipe - // - Status = HandleAbortPipe(Irp, Urb); - if (!NT_SUCCESS(Status)) - { - // - // failed - // - DPRINT1("[%s] failed to reset pipe %x\n", m_USBType, Status); - } - - - // - // get endpoint descriptor - // - EndpointDescriptor = (PUSB_ENDPOINT)Urb->UrbPipeRequest.PipeHandle; - - // - // get type - // - Type = (EndpointDescriptor->EndPointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK); - if (Type != USB_ENDPOINT_TYPE_ISOCHRONOUS) - { - // - // clear stall - // - Status = HandleClearStall(Irp, Urb); - } - DPRINT1("[%s] URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL Status %x\n", m_USBType, Status); - - // - // reset data toggle - // - if (NT_SUCCESS(Status)) - EndpointDescriptor->DataToggle = 0x0; - - // - // done - // - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleAbortPipe( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - NTSTATUS Status; - PUSBDEVICE UsbDevice; - PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - - // - // sanity check - // - PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); - PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST)); - PC_ASSERT(Urb->UrbPipeRequest.PipeHandle); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleAbortPipe invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get endpoint descriptor - // - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle; - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - - // - // issue request - // - Status = UsbDevice->AbortPipe(EndpointDescriptor); - DPRINT1("[%s] URB_FUNCTION_ABORT_PIPE Status %x\n", m_USBType, Status); - - // - // done - // - return Status; -} - - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleClearStall( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - PUSBDEVICE UsbDevice; - PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - - - // - // sanity check - // - PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); - PC_ASSERT(Urb->UrbHeader.Length == sizeof(struct _URB_PIPE_REQUEST)); - PC_ASSERT(Urb->UrbPipeRequest.PipeHandle); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleClearStall invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get endpoint descriptor - // - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Urb->UrbPipeRequest.PipeHandle; - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - DPRINT1("[%s] URB_FUNCTION_SYNC_CLEAR_STALL\n", m_USBType); - - // - // initialize setup packet - // - CtrlSetup.bmRequestType.B = 0x02; - CtrlSetup.bRequest = USB_REQUEST_CLEAR_FEATURE; - CtrlSetup.wValue.W = USB_FEATURE_ENDPOINT_STALL; - CtrlSetup.wIndex.W = EndpointDescriptor->bEndpointAddress; - CtrlSetup.wLength = 0; - CtrlSetup.wValue.W = 0; - - // - // issue request - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, 0, 0); - - DPRINT1("[%s] URB_FUNCTION_CLEAR_STALL Status %x\n", m_USBType, Status); - - // - // done - // - return Status; -} - - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleClassInterface( - IN OUT PIRP Irp, - IN OUT PURB Urb) -{ - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - PUSBDEVICE UsbDevice; - - // - // sanity check - // - //ASSERT(Urb->UrbControlVendorClassRequest.TransferBuffer || Urb->UrbControlVendorClassRequest.TransferBufferMDL); - //ASSERT(Urb->UrbControlVendorClassRequest.TransferBufferLength); - PC_ASSERT(Urb->UrbHeader.UsbdDeviceHandle); - - // - // check if this is a valid usb device handle - // - if (!ValidateUsbDevice(PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle))) - { - DPRINT1("[%s] HandleClassInterface invalid device handle %p\n", m_USBType, Urb->UrbHeader.UsbdDeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device - // - UsbDevice = PUSBDEVICE(Urb->UrbHeader.UsbdDeviceHandle); - - - DPRINT("URB_FUNCTION_CLASS_INTERFACE\n"); - DPRINT("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags); - DPRINT("TransferBufferLength %x\n", Urb->UrbControlVendorClassRequest.TransferBufferLength); - DPRINT("TransferBuffer %x\n", Urb->UrbControlVendorClassRequest.TransferBuffer); - DPRINT("TransferBufferMDL %x\n", Urb->UrbControlVendorClassRequest.TransferBufferMDL); - DPRINT("RequestTypeReservedBits %x\n", Urb->UrbControlVendorClassRequest.RequestTypeReservedBits); - DPRINT("Request %x\n", Urb->UrbControlVendorClassRequest.Request); - DPRINT("Value %x\n", Urb->UrbControlVendorClassRequest.Value); - DPRINT("Index %x\n", Urb->UrbControlVendorClassRequest.Index); - - // - // initialize setup packet - // - CtrlSetup.bmRequestType.B = 0x21; - CtrlSetup.bRequest = Urb->UrbControlVendorClassRequest.Request; - CtrlSetup.wValue.W = Urb->UrbControlVendorClassRequest.Value; - CtrlSetup.wIndex.W = Urb->UrbControlVendorClassRequest.Index; - CtrlSetup.wLength = (USHORT)Urb->UrbControlVendorClassRequest.TransferBufferLength; - - if (Urb->UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN) - { - // - // data direction is device to host - // - CtrlSetup.bmRequestType.B |= 0x80; - } - - // - // issue request - // - Status = UsbDevice->SubmitSetupPacket(&CtrlSetup, Urb->UrbControlVendorClassRequest.TransferBufferLength, Urb->UrbControlVendorClassRequest.TransferBuffer); - - // - // assert on failure - // - if (!NT_SUCCESS(Status)) - { - // - // display error - // - DPRINT1("[%s] URB_FUNCTION_CLASS_INTERFACE failed with Urb Status %x\n", m_USBType, Urb->UrbHeader.Status); - } - - // - // done - // - return Status; -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::HandleDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN OUT PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PURB Urb; - NTSTATUS Status = STATUS_NOT_IMPLEMENTED; - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - - // - // determine which request should be performed - // - switch(IoStack->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_INTERNAL_USB_SUBMIT_URB: - { - // - // get urb - // - Urb = (PURB)IoStack->Parameters.Others.Argument1; - PC_ASSERT(Urb); - - switch (Urb->UrbHeader.Function) - { - case URB_FUNCTION_SYNC_RESET_PIPE: - case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: - Status = HandleSyncResetAndClearStall(Irp, Urb); - break; - case URB_FUNCTION_ABORT_PIPE: - Status = HandleAbortPipe(Irp, Urb); - break; - case URB_FUNCTION_SYNC_CLEAR_STALL: - Status = HandleClearStall(Irp, Urb); - break; - case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE: - Status = HandleGetDescriptorFromInterface(Irp, Urb); - break; - case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: - Status = HandleGetDescriptor(Irp, Urb); - break; - case URB_FUNCTION_CLASS_DEVICE: - Status = HandleClassDevice(Irp, Urb); - break; - case URB_FUNCTION_GET_STATUS_FROM_DEVICE: - case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: - case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: - Status = HandleGetStatusFromDevice(Irp, Urb); - break; - case URB_FUNCTION_SELECT_CONFIGURATION: - Status = HandleSelectConfiguration(Irp, Urb); - break; - case URB_FUNCTION_SELECT_INTERFACE: - Status = HandleSelectInterface(Irp, Urb); - break; - case URB_FUNCTION_CLASS_OTHER: - Status = HandleClassOther(Irp, Urb); - break; - case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: - Status = HandleBulkOrInterruptTransfer(Irp, Urb); - break; - case URB_FUNCTION_ISOCH_TRANSFER: - Status = HandleIsochronousTransfer(Irp, Urb); - break; - case URB_FUNCTION_CLASS_INTERFACE: - Status = HandleClassInterface(Irp, Urb); - break; - case URB_FUNCTION_CLASS_ENDPOINT: - Status = HandleClassEndpoint(Irp, Urb); - break; - case URB_FUNCTION_VENDOR_DEVICE: - Status = HandleVendorDevice(Irp, Urb); - break; - default: - DPRINT1("[%s] IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", m_USBType, Urb->UrbHeader.Function); - break; - } - // - // request completed - // - break; - } - case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: - { - DPRINT("[%s] IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %p\n", m_USBType, this); - - if (IoStack->Parameters.Others.Argument1) - { - // - // store object as device handle - // - *(PVOID *)IoStack->Parameters.Others.Argument1 = (PVOID)this; - Status = STATUS_SUCCESS; - } - else - { - // - // mis-behaving hub driver - // - Status = STATUS_INVALID_DEVICE_REQUEST; - } - - // - // request completed - // - break; - } - case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO: - { - DPRINT("[%s] IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n", m_USBType); - - // - // this is the first request send, it delivers the PDO to the caller - // - if (IoStack->Parameters.Others.Argument1) - { - // - // store root hub pdo object - // - *(PVOID *)IoStack->Parameters.Others.Argument1 = DeviceObject; - } - - if (IoStack->Parameters.Others.Argument2) - { - // - // documentation claims to deliver the hcd controller object, although it is wrong - // - *(PVOID *)IoStack->Parameters.Others.Argument2 = DeviceObject; - } - - // - // request completed - // - Status = STATUS_SUCCESS; - break; - } - case IOCTL_INTERNAL_USB_GET_HUB_COUNT: - { - DPRINT("[%s] IOCTL_INTERNAL_USB_GET_HUB_COUNT\n", m_USBType); - - // - // after IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO is delivered, the usbhub driver - // requests this ioctl to deliver the number of presents. - - if (IoStack->Parameters.Others.Argument1) - { - // - // FIXME / verify: there is only one hub - // - *(PULONG)IoStack->Parameters.Others.Argument1 = 1; - } - - // - // request completed - // - Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof(ULONG); - break; - } - case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: - { - DPRINT1("[%s] IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION UNIMPLEMENTED\n", m_USBType); - Status = STATUS_SUCCESS; - break; - } - default: - { - DPRINT1("[%s] HandleDeviceControl>Type: IoCtl %x InputBufferLength %lu OutputBufferLength %lu NOT IMPLEMENTED\n", m_USBType, - IoStack->Parameters.DeviceIoControl.IoControlCode, - IoStack->Parameters.DeviceIoControl.InputBufferLength, - IoStack->Parameters.DeviceIoControl.OutputBufferLength); - break; - } - } - if (Status != STATUS_PENDING) - { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - - return Status; -} - -//----------------------------------------------------------------------------------------- -PUSBHARDWAREDEVICE -CHubController::GetUsbHardware() -{ - return m_Hardware; -} - -//----------------------------------------------------------------------------------------- -ULONG -CHubController::AcquireDeviceAddress() -{ - KIRQL OldLevel; - ULONG DeviceAddress; - - // - // acquire device lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // find address - // - DeviceAddress = RtlFindClearBits(&m_DeviceAddressBitmap, 1, 0); - if (DeviceAddress != MAXULONG) - { - // - // reserve address - // - RtlSetBits(&m_DeviceAddressBitmap, DeviceAddress, 1); - - // - // device addresses start from 0x1 - 0xFF - // - DeviceAddress++; - } - - // - // release spin lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); - - // - // return device address - // - return DeviceAddress; -} -//----------------------------------------------------------------------------------------- -VOID -CHubController::ReleaseDeviceAddress( - ULONG DeviceAddress) -{ - KIRQL OldLevel; - - // - // acquire device lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // sanity check - // - PC_ASSERT(DeviceAddress != 0); - - // - // convert back to bit number - // - DeviceAddress--; - - // - // clear bit - // - RtlClearBits(&m_DeviceAddressBitmap, DeviceAddress, 1); - - // - // release lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); -} -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::RemoveUsbDevice( - PUSBDEVICE UsbDevice) -{ - PUSBDEVICE_ENTRY DeviceEntry; - PLIST_ENTRY Entry; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - KIRQL OldLevel; - - // - // acquire lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // point to first entry - // - Entry = m_UsbDeviceList.Flink; - - // - // find matching entry - // - while(Entry != &m_UsbDeviceList) - { - // - // get entry - // - DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry); - - // - // is it current entry - // - if (DeviceEntry->Device == UsbDevice) - { - // - // remove entry - // - RemoveEntryList(Entry); - - // - // free entry - // - ExFreePoolWithTag(DeviceEntry, TAG_USBLIB); - - // - // done - // - Status = STATUS_SUCCESS; - break; - } - - // - // goto next device - // - Entry = Entry->Flink; - } - - // - // release lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); - - // - // return result - // - return Status; -} -//----------------------------------------------------------------------------------------- -BOOLEAN -CHubController::ValidateUsbDevice(PUSBDEVICE UsbDevice) -{ - PUSBDEVICE_ENTRY DeviceEntry; - PLIST_ENTRY Entry; - KIRQL OldLevel; - BOOLEAN Result = FALSE; - - // - // acquire lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // point to first entry - // - Entry = m_UsbDeviceList.Flink; - - // - // find matching entry - // - while(Entry != &m_UsbDeviceList) - { - // - // get entry - // - DeviceEntry = (PUSBDEVICE_ENTRY)CONTAINING_RECORD(Entry, USBDEVICE_ENTRY, Entry); - - // - // is it current entry - // - if (DeviceEntry->Device == UsbDevice) - { - // - // device is valid - // - Result = TRUE; - break; - } - - // - // goto next device - // - Entry = Entry->Flink; - } - - // - // release lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); - - // - // return result - // - return Result; - -} - -//----------------------------------------------------------------------------------------- -NTSTATUS -CHubController::AddUsbDevice( - PUSBDEVICE UsbDevice) -{ - PUSBDEVICE_ENTRY DeviceEntry; - KIRQL OldLevel; - - // - // allocate device entry - // - DeviceEntry = (PUSBDEVICE_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(USBDEVICE_ENTRY), TAG_USBLIB); - if (!DeviceEntry) - { - // - // no memory - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize entry - // - DeviceEntry->Device = UsbDevice; - - // - // acquire lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // insert entry - // - InsertTailList(&m_UsbDeviceList, &DeviceEntry->Entry); - - // - // release spin lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); - - // - // done - // - return STATUS_SUCCESS; -} - -//----------------------------------------------------------------------------------------- -VOID -CHubController::SetNotification( - PVOID CallbackContext, - PRH_INIT_CALLBACK CallbackRoutine) -{ - KIRQL OldLevel; - - // - // acquire hub controller lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // now set the callback routine and context of the hub - // - m_HubCallbackContext = CallbackContext; - m_HubCallbackRoutine = CallbackRoutine; - - // - // release hub controller lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); -} - -//================================================================================================= -// -// Generic Interface functions -// -VOID -USB_BUSIFFN -USBI_InterfaceReference( - PVOID BusContext) -{ - CHubController * Controller = (CHubController*)BusContext; - - DPRINT("USBI_InterfaceReference\n"); - - // - // add reference - // - Controller->AddRef(); -} - -VOID -USB_BUSIFFN -USBI_InterfaceDereference( - PVOID BusContext) -{ - CHubController * Controller = (CHubController*)BusContext; - - DPRINT("USBI_InterfaceDereference\n"); - - // - // release - // - Controller->Release(); -} -//================================================================================================= -// -// USB Hub Interface functions -// -NTSTATUS -USB_BUSIFFN -USBHI_CreateUsbDevice( - PVOID BusContext, - PUSB_DEVICE_HANDLE *NewDevice, - PUSB_DEVICE_HANDLE HubDeviceHandle, - USHORT PortStatus, - USHORT PortNumber) -{ - PUSBDEVICE NewUsbDevice; - CHubController * Controller; - NTSTATUS Status; - - DPRINT1("USBHI_CreateUsbDevice\n"); - - // - // first get hub controller - // - Controller = (CHubController *)BusContext; - - // - // sanity check - // - PC_ASSERT(Controller); - PC_ASSERT(BusContext == HubDeviceHandle); - - // - // now allocate usb device - // - Status = CreateUSBDevice(&NewUsbDevice); - - // - // check for success - // - if (!NT_SUCCESS(Status)) - { - // - // release controller - // - Controller->Release(); - DPRINT1("USBHI_CreateUsbDevice: failed to create usb device %x\n", Status); - return Status; - } - - // - // now initialize device - // - Status = NewUsbDevice->Initialize(PHUBCONTROLLER(Controller), Controller->GetUsbHardware(), HubDeviceHandle, PortNumber, PortStatus); - - // - // check for success - // - if (!NT_SUCCESS(Status)) - { - // - // release usb device - // - NewUsbDevice->Release(); - DPRINT1("USBHI_CreateUsbDevice: failed to initialize usb device %x\n", Status); - return Status; - } - - // - // insert into list - // - Status = Controller->AddUsbDevice(NewUsbDevice); - // - // check for success - // - if (!NT_SUCCESS(Status)) - { - // - // release usb device - // - NewUsbDevice->Release(); - - DPRINT1("USBHI_CreateUsbDevice: failed to add usb device %x\n", Status); - return Status; - } - - // - // store the handle - // - *NewDevice = NewUsbDevice; - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -USB_BUSIFFN -USBHI_InitializeUsbDevice( - PVOID BusContext, - PUSB_DEVICE_HANDLE DeviceHandle) -{ - PUSBDEVICE UsbDevice; - CHubController * Controller; - ULONG DeviceAddress; - NTSTATUS Status; - ULONG Index = 0; - - DPRINT("USBHI_InitializeUsbDevice\n"); - - // - // first get controller - // - Controller = (CHubController *)BusContext; - PC_ASSERT(Controller); - - // - // get device object - // - UsbDevice = (PUSBDEVICE)DeviceHandle; - PC_ASSERT(UsbDevice); - - // - // validate device handle - // - if (!Controller->ValidateUsbDevice(UsbDevice)) - { - DPRINT1("USBHI_InitializeUsbDevice invalid device handle %p\n", DeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // now reserve an address - // - DeviceAddress = Controller->AcquireDeviceAddress(); - - // - // is the device address valid - // - if (DeviceAddress == MAXULONG) - { - // - // failed to get an device address from the device address pool - // - DPRINT1("USBHI_InitializeUsbDevice failed to get device address\n"); - return STATUS_DEVICE_DATA_ERROR; - } - - do - { - // - // now set the device address - // - Status = UsbDevice->SetDeviceAddress((UCHAR)DeviceAddress); - - if (NT_SUCCESS(Status)) - break; - - }while(Index++ < 3 ); - - // - // check for failure - // - if (!NT_SUCCESS(Status)) - { - // - // failed to set device address - // - DPRINT1("USBHI_InitializeUsbDevice failed to set address with %x\n", Status); - - // - // release address - // - Controller->ReleaseDeviceAddress(DeviceAddress); - - // - // return error - // - return STATUS_DEVICE_DATA_ERROR; - } - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -USB_BUSIFFN -USBHI_GetUsbDescriptors( - PVOID BusContext, - PUSB_DEVICE_HANDLE DeviceHandle, - PUCHAR DeviceDescriptorBuffer, - PULONG DeviceDescriptorBufferLength, - PUCHAR ConfigDescriptorBuffer, - PULONG ConfigDescriptorBufferLength) -{ - PUSBDEVICE UsbDevice; - CHubController * Controller; - - DPRINT("USBHI_GetUsbDescriptors\n"); - - // - // sanity check - // - PC_ASSERT(DeviceDescriptorBuffer); - PC_ASSERT(DeviceDescriptorBufferLength); - PC_ASSERT(*DeviceDescriptorBufferLength >= sizeof(USB_DEVICE_DESCRIPTOR)); - PC_ASSERT(ConfigDescriptorBufferLength); - PC_ASSERT(*ConfigDescriptorBufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR)); - - // - // first get controller - // - Controller = (CHubController *)BusContext; - PC_ASSERT(Controller); - - - // - // get device object - // - UsbDevice = (PUSBDEVICE)DeviceHandle; - PC_ASSERT(UsbDevice); - - // - // validate device handle - // - if (!Controller->ValidateUsbDevice(UsbDevice)) - { - DPRINT1("USBHI_GetUsbDescriptors invalid device handle %p\n", DeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // get device descriptor - // - UsbDevice->GetDeviceDescriptor((PUSB_DEVICE_DESCRIPTOR)DeviceDescriptorBuffer); - - // - // store result length - // - *DeviceDescriptorBufferLength = sizeof(USB_DEVICE_DESCRIPTOR); - - // - // get configuration descriptor - // - UsbDevice->GetConfigurationDescriptors((PUSB_CONFIGURATION_DESCRIPTOR)ConfigDescriptorBuffer, *ConfigDescriptorBufferLength, ConfigDescriptorBufferLength); - - // - // complete the request - // - return STATUS_SUCCESS; -} - -NTSTATUS -USB_BUSIFFN -USBHI_RemoveUsbDevice( - PVOID BusContext, - PUSB_DEVICE_HANDLE DeviceHandle, - ULONG Flags) -{ - PUSBDEVICE UsbDevice; - CHubController * Controller; - NTSTATUS Status; - - DPRINT("USBHI_RemoveUsbDevice\n"); - - // - // first get controller - // - Controller = (CHubController *)BusContext; - PC_ASSERT(Controller); - - // - // get device object - // - UsbDevice = (PUSBDEVICE)DeviceHandle; - PC_ASSERT(UsbDevice); - - // - // validate device handle - // - if (!Controller->ValidateUsbDevice(UsbDevice)) - { - DPRINT1("USBHI_RemoveUsbDevice invalid device handle %p\n", DeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // check if there were flags passed - // - if (Flags & USBD_KEEP_DEVICE_DATA || Flags & USBD_MARK_DEVICE_BUSY) - { - // - // ignore flags for now - // - return STATUS_SUCCESS; - } - - // - // remove device - // - Status = Controller->RemoveUsbDevice(UsbDevice); - if (!NT_SUCCESS(Status)) - { - // - // invalid device handle - // - DPRINT1("USBHI_RemoveUsbDevice Invalid device handle %p\n", UsbDevice); - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // release usb device - // - UsbDevice->Release(); - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -USB_BUSIFFN -USBHI_RestoreUsbDevice( - PVOID BusContext, - PUSB_DEVICE_HANDLE OldDeviceHandle, - PUSB_DEVICE_HANDLE NewDeviceHandle) -{ - PUSBDEVICE OldUsbDevice, NewUsbDevice; - CHubController * Controller; - - DPRINT("USBHI_RestoreUsbDevice\n"); - - // - // first get controller - // - Controller = (CHubController *)BusContext; - PC_ASSERT(Controller); - - // - // get device object - // - OldUsbDevice = (PUSBDEVICE)OldDeviceHandle; - NewUsbDevice = (PUSBDEVICE)NewDeviceHandle; - PC_ASSERT(OldUsbDevice); - PC_ASSERT(NewDeviceHandle); - - // - // validate device handle - // - PC_ASSERT(Controller->ValidateUsbDevice(NewUsbDevice)); - PC_ASSERT(Controller->ValidateUsbDevice(OldUsbDevice)); - - DPRINT1("NewUsbDevice: DeviceAddress %x\n", NewUsbDevice->GetDeviceAddress()); - DPRINT1("OldUsbDevice: DeviceAddress %x\n", OldUsbDevice->GetDeviceAddress()); - - // - // remove old device handle - // - USBHI_RemoveUsbDevice(BusContext, OldDeviceHandle, 0); - - return STATUS_SUCCESS; -} - -NTSTATUS -USB_BUSIFFN -USBHI_QueryDeviceInformation( - PVOID BusContext, - PUSB_DEVICE_HANDLE DeviceHandle, - PVOID DeviceInformationBuffer, - ULONG DeviceInformationBufferLength, - PULONG LengthReturned) -{ - PUSB_DEVICE_INFORMATION_0 DeviceInfo; - PUSBDEVICE UsbDevice; - CHubController * Controller; - - DPRINT("USBHI_QueryDeviceInformation %p\n", BusContext); - - // - // sanity check - // - PC_ASSERT(DeviceInformationBufferLength >= sizeof(USB_DEVICE_INFORMATION_0)); - PC_ASSERT(DeviceInformationBuffer); - PC_ASSERT(LengthReturned); - - // - // get controller object - // - Controller = (CHubController*)BusContext; - PC_ASSERT(Controller); - - // - // get device object - // - UsbDevice = (PUSBDEVICE)DeviceHandle; - PC_ASSERT(UsbDevice); - - if (BusContext != DeviceHandle) - { - // - // validate device handle - // - if (!Controller->ValidateUsbDevice(UsbDevice)) - { - DPRINT1("USBHI_QueryDeviceInformation invalid device handle %p\n", DeviceHandle); - - // - // invalid device handle - // - return STATUS_DEVICE_NOT_CONNECTED; - } - - // - // access information buffer - // - DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer; - - // - // initialize with default values - // - DeviceInfo->InformationLevel = 0; - DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0); - DeviceInfo->PortNumber = UsbDevice->GetPort(); - DeviceInfo->CurrentConfigurationValue = UsbDevice->GetConfigurationValue(); - DeviceInfo->DeviceAddress = UsbDevice->GetDeviceAddress(); - DeviceInfo->HubAddress = 0; //FIXME - DeviceInfo->DeviceSpeed = UsbDevice->GetSpeed(); - DeviceInfo->DeviceType = UsbDevice->GetType(); - DeviceInfo->NumberOfOpenPipes = 0; //FIXME - - // - // get device descriptor - // - UsbDevice->GetDeviceDescriptor(&DeviceInfo->DeviceDescriptor); - - // - // FIXME return pipe information - // - - // - // store result length - // - *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0); - - return STATUS_SUCCESS; - } - - // - // access information buffer - // - DeviceInfo = (PUSB_DEVICE_INFORMATION_0)DeviceInformationBuffer; - - // - // initialize with default values - // - DeviceInfo->InformationLevel = 0; - DeviceInfo->ActualLength = sizeof(USB_DEVICE_INFORMATION_0); - DeviceInfo->PortNumber = 0; - DeviceInfo->CurrentConfigurationValue = 0; //FIXME; - DeviceInfo->DeviceAddress = 0; - DeviceInfo->HubAddress = 0; //FIXME - DeviceInfo->DeviceSpeed = UsbHighSpeed; //FIXME - DeviceInfo->DeviceType = Usb20Device; //FIXME - DeviceInfo->NumberOfOpenPipes = 0; //FIXME - - // - // get device descriptor - // - RtlMoveMemory(&DeviceInfo->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(USB_DEVICE_DESCRIPTOR)); - - // - // FIXME return pipe information - // - - // - // store result length - // -#ifdef _MSC_VER - *LengthReturned = FIELD_OFFSET(USB_DEVICE_INFORMATION_0, PipeList[DeviceInfo->NumberOfOpenPipes]); -#else - *LengthReturned = sizeof(USB_DEVICE_INFORMATION_0) + (DeviceInfo->NumberOfOpenPipes > 1 ? (DeviceInfo->NumberOfOpenPipes - 1) * sizeof(USB_PIPE_INFORMATION_0) : 0); -#endif - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -USB_BUSIFFN -USBHI_GetControllerInformation( - PVOID BusContext, - PVOID ControllerInformationBuffer, - ULONG ControllerInformationBufferLength, - PULONG LengthReturned) -{ - PUSB_CONTROLLER_INFORMATION_0 ControllerInfo; - - DPRINT("USBHI_GetControllerInformation\n"); - - // - // sanity checks - // - PC_ASSERT(ControllerInformationBuffer); - PC_ASSERT(ControllerInformationBufferLength >= sizeof(USB_CONTROLLER_INFORMATION_0)); - - // - // get controller info buffer - // - ControllerInfo = (PUSB_CONTROLLER_INFORMATION_0)ControllerInformationBuffer; - - // - // FIXME only version 0 is supported for now - // - PC_ASSERT(ControllerInfo->InformationLevel == 0); - - // - // fill in information - // - ControllerInfo->ActualLength = sizeof(USB_CONTROLLER_INFORMATION_0); - ControllerInfo->SelectiveSuspendEnabled = FALSE; //FIXME - ControllerInfo->IsHighSpeedController = TRUE; - - // - // set length returned - // - *LengthReturned = ControllerInfo->ActualLength; - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -USB_BUSIFFN -USBHI_ControllerSelectiveSuspend( - PVOID BusContext, - BOOLEAN Enable) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -USB_BUSIFFN -USBHI_GetExtendedHubInformation( - PVOID BusContext, - PDEVICE_OBJECT HubPhysicalDeviceObject, - PVOID HubInformationBuffer, - ULONG HubInformationBufferLength, - PULONG LengthReturned) -{ - PUSB_EXTHUB_INFORMATION_0 HubInfo; - CHubController * Controller; - PUSBHARDWAREDEVICE Hardware; - ULONG Index; - ULONG NumPort, Dummy2; - USHORT Dummy1; - NTSTATUS Status; - - DPRINT("USBHI_GetExtendedHubInformation\n"); - - // - // sanity checks - // - PC_ASSERT(HubInformationBuffer); - PC_ASSERT(HubInformationBufferLength == sizeof(USB_EXTHUB_INFORMATION_0)); - PC_ASSERT(LengthReturned); - - // - // get hub controller - // - Controller = (CHubController *)BusContext; - PC_ASSERT(Controller); - - // - // get usb hardware device - // - Hardware = Controller->GetUsbHardware(); - - // - // retrieve number of ports - // - Status = Hardware->GetDeviceDetails(&Dummy1, &Dummy1, &NumPort, &Dummy2); - if (!NT_SUCCESS(Status)) - { - // - // failed to get hardware details, ouch ;) - // - DPRINT1("USBHI_GetExtendedHubInformation failed to get hardware details with %x\n", Status); - return Status; - } - - // - // get hub information buffer - // - HubInfo = (PUSB_EXTHUB_INFORMATION_0)HubInformationBuffer; - - // - // initialize hub information - // - HubInfo->InformationLevel = 0; - - // - // store port count - // - HubInfo->NumberOfPorts = NumPort; - - // - // initialize port information - // - for(Index = 0; Index < NumPort; Index++) - { - HubInfo->Port[Index].PhysicalPortNumber = Index + 1; - HubInfo->Port[Index].PortLabelNumber = Index + 1; - HubInfo->Port[Index].VidOverride = 0; - HubInfo->Port[Index].PidOverride = 0; - HubInfo->Port[Index].PortAttributes = USB_PORTATTR_SHARED_USB2; //FIXME - } - - // - // store result length - // -#ifdef _MSC_VER - *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port[HubInfo->NumberOfPorts]); -#else - *LengthReturned = FIELD_OFFSET(USB_EXTHUB_INFORMATION_0, Port) + sizeof(USB_EXTPORT_INFORMATION_0) * HubInfo->NumberOfPorts; -#endif - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -USB_BUSIFFN -USBHI_GetRootHubSymbolicName( - PVOID BusContext, - PVOID HubSymNameBuffer, - ULONG HubSymNameBufferLength, - PULONG HubSymNameActualLength) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -PVOID -USB_BUSIFFN -USBHI_GetDeviceBusContext( - PVOID HubBusContext, - PVOID DeviceHandle) -{ - UNIMPLEMENTED; - return NULL; -} - -NTSTATUS -USB_BUSIFFN -USBHI_Initialize20Hub( - PVOID BusContext, - PUSB_DEVICE_HANDLE HubDeviceHandle, - ULONG TtCount) -{ - DPRINT("USBHI_Initialize20Hub HubDeviceHandle %p UNIMPLEMENTED TtCount %lu\n", HubDeviceHandle, TtCount); - return STATUS_SUCCESS; -} - - -WORKER_THREAD_ROUTINE InitRootHub; - -VOID -NTAPI -InitRootHub(IN PVOID Context) -{ - PINIT_ROOT_HUB_CONTEXT WorkItem; - - // - // get context - // - WorkItem = (PINIT_ROOT_HUB_CONTEXT)Context; - - // - // perform callback - // - WorkItem->CallbackRoutine(WorkItem->CallbackContext); - - // - // free contextg - // - ExFreePoolWithTag(Context, TAG_USBLIB); -} - -NTSTATUS -USB_BUSIFFN -USBHI_RootHubInitNotification( - PVOID BusContext, - PVOID CallbackContext, - PRH_INIT_CALLBACK CallbackRoutine) -{ - CHubController * Controller; - PINIT_ROOT_HUB_CONTEXT WorkItem; - - DPRINT("USBHI_RootHubInitNotification %p \n", CallbackContext); - - // - // get controller object - // - Controller = (CHubController*)BusContext; - PC_ASSERT(Controller); - - // - // set notification routine - // - Controller->SetNotification(CallbackContext, CallbackRoutine); - - // - // Create and initialize work item data - // - WorkItem = (PINIT_ROOT_HUB_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, sizeof(INIT_ROOT_HUB_CONTEXT), TAG_USBLIB); - if (!WorkItem) - { - DPRINT1("Failed to allocate memory!n"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // init context - // - WorkItem->CallbackRoutine = CallbackRoutine; - WorkItem->CallbackContext = CallbackContext; - - // - // Queue the work item to handle initializing the device - // - ExInitializeWorkItem(&WorkItem->WorkItem, InitRootHub, (PVOID)WorkItem); - ExQueueWorkItem(&WorkItem->WorkItem, DelayedWorkQueue); - - // - // done - // - return STATUS_SUCCESS; -} - -VOID -USB_BUSIFFN -USBHI_FlushTransfers( - PVOID BusContext, - PVOID DeviceHandle) -{ - UNIMPLEMENTED; -} - -VOID -USB_BUSIFFN -USBHI_SetDeviceHandleData( - PVOID BusContext, - PVOID DeviceHandle, - PDEVICE_OBJECT UsbDevicePdo) -{ - PUSBDEVICE UsbDevice; - CHubController * Controller; - - // - // get controller - // - Controller = (CHubController *)BusContext; - PC_ASSERT(Controller); - - // - // get device handle - // - UsbDevice = (PUSBDEVICE)DeviceHandle; - - // - // validate device handle - // - if (!Controller->ValidateUsbDevice(UsbDevice)) - { - DPRINT1("USBHI_SetDeviceHandleData DeviceHandle %p is invalid\n", DeviceHandle); - - // - // invalid handle - // - return; - } - else - { - // - // usbhub sends this request as a part of the Pnp startup sequence - // looks like we need apply a dragon voodoo to fixup the device stack - // otherwise usbhub will cause a bugcheck - // - DPRINT1("USBHI_SetDeviceHandleData %p\n", UsbDevicePdo); - - // - // sanity check - // - PC_ASSERT(UsbDevicePdo->AttachedDevice); - - // - // should be usbstor - // fixup device stack voodoo part #2 - // - UsbDevicePdo->AttachedDevice->StackSize++; - - // - // set device handle data - // - UsbDevice->SetDeviceHandleData(UsbDevicePdo); - } -} - -//================================================================================================= -// -// USB Device Interface functions -// - -VOID -USB_BUSIFFN -USBDI_GetUSBDIVersion( - PVOID BusContext, - PUSBD_VERSION_INFORMATION VersionInformation, - PULONG HcdCapabilites) -{ - CHubController * Controller; - PUSBHARDWAREDEVICE Device; - ULONG Speed, Dummy2; - USHORT Dummy1; - - DPRINT("USBDI_GetUSBDIVersion\n"); - - // - // get controller - // - Controller = (CHubController*)BusContext; - - // - // get usb hardware - // - Device = Controller->GetUsbHardware(); - PC_ASSERT(Device); - - if (VersionInformation) - { - // - // windows xp supported - // - VersionInformation->USBDI_Version = 0x00000500; - - // - // get device speed - // - Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed); - - // - // store speed details - // - VersionInformation->Supported_USB_Version = Speed; - } - - // - // no flags supported - // - *HcdCapabilites = 0; -} - -NTSTATUS -USB_BUSIFFN -USBDI_QueryBusTime( - PVOID BusContext, - PULONG CurrentFrame) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -USB_BUSIFFN -USBDI_SubmitIsoOutUrb( - PVOID BusContext, - PURB Urb) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -USB_BUSIFFN -USBDI_QueryBusInformation( - PVOID BusContext, - ULONG Level, - PVOID BusInformationBuffer, - PULONG BusInformationBufferLength, - PULONG BusInformationActualLength) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -BOOLEAN -USB_BUSIFFN -USBDI_IsDeviceHighSpeed( - PVOID BusContext) -{ - CHubController * Controller; - PUSBHARDWAREDEVICE Device; - ULONG Speed, Dummy2; - USHORT Dummy1; - - DPRINT("USBDI_IsDeviceHighSpeed\n"); - - // - // get controller - // - Controller = (CHubController*)BusContext; - - // - // get usb hardware - // - Device = Controller->GetUsbHardware(); - PC_ASSERT(Device); - - // - // get device speed - // - Device->GetDeviceDetails(&Dummy1, &Dummy1, &Dummy2, &Speed); - - // - // USB 2.0 equals 0x200 - // - return (Speed == 0x200); -} - -NTSTATUS -USB_BUSIFFN -USBDI_EnumLogEntry( - PVOID BusContext, - ULONG DriverTag, - ULONG EnumTag, - ULONG P1, - ULONG P2) -{ - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS -CHubController::HandleQueryInterface( - PIO_STACK_LOCATION IoStack) -{ - PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub; - PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI; - UNICODE_STRING GuidBuffer; - NTSTATUS Status; - - if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_HUB_GUID)) - { - // - // get request parameters - // - InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)IoStack->Parameters.QueryInterface.Interface; - InterfaceHub->Version = IoStack->Parameters.QueryInterface.Version; - - // - // check version - // - if (IoStack->Parameters.QueryInterface.Version >= 6) - { - DPRINT1("USB_BUS_INTERFACE_HUB_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version); - - // - // version not supported - // - return STATUS_NOT_SUPPORTED; - } - - // - // Interface version 0 - // - InterfaceHub->Size = IoStack->Parameters.QueryInterface.Size; - InterfaceHub->BusContext = PVOID(this); - InterfaceHub->InterfaceReference = USBI_InterfaceReference; - InterfaceHub->InterfaceDereference = USBI_InterfaceDereference; - - // - // Interface version 1 - // - if (IoStack->Parameters.QueryInterface.Version >= 1) - { - InterfaceHub->CreateUsbDevice = USBHI_CreateUsbDevice; - InterfaceHub->InitializeUsbDevice = USBHI_InitializeUsbDevice; - InterfaceHub->GetUsbDescriptors = USBHI_GetUsbDescriptors; - InterfaceHub->RemoveUsbDevice = USBHI_RemoveUsbDevice; - InterfaceHub->RestoreUsbDevice = USBHI_RestoreUsbDevice; - InterfaceHub->QueryDeviceInformation = USBHI_QueryDeviceInformation; - } - - // - // Interface version 2 - // - if (IoStack->Parameters.QueryInterface.Version >= 2) - { - InterfaceHub->GetControllerInformation = USBHI_GetControllerInformation; - InterfaceHub->ControllerSelectiveSuspend = USBHI_ControllerSelectiveSuspend; - InterfaceHub->GetExtendedHubInformation = USBHI_GetExtendedHubInformation; - InterfaceHub->GetRootHubSymbolicName = USBHI_GetRootHubSymbolicName; - InterfaceHub->GetDeviceBusContext = USBHI_GetDeviceBusContext; - InterfaceHub->Initialize20Hub = USBHI_Initialize20Hub; - - } - - // - // Interface version 3 - // - if (IoStack->Parameters.QueryInterface.Version >= 3) - { - InterfaceHub->RootHubInitNotification = USBHI_RootHubInitNotification; - } - - // - // Interface version 4 - // - if (IoStack->Parameters.QueryInterface.Version >= 4) - { - InterfaceHub->FlushTransfers = USBHI_FlushTransfers; - } - - // - // Interface version 5 - // - if (IoStack->Parameters.QueryInterface.Version >= 5) - { - InterfaceHub->SetDeviceHandleData = USBHI_SetDeviceHandleData; - } - - InterfaceHub->InterfaceReference(InterfaceHub->BusContext); - // - // request completed - // - return STATUS_SUCCESS; - } - else if (IsEqualGUIDAligned(*IoStack->Parameters.QueryInterface.InterfaceType, USB_BUS_INTERFACE_USBDI_GUID)) - { - // - // get request parameters - // - InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) IoStack->Parameters.QueryInterface.Interface; - InterfaceDI->Version = IoStack->Parameters.QueryInterface.Version; - - // - // check version - // - if (IoStack->Parameters.QueryInterface.Version >= 3) - { - DPRINT1("USB_BUS_INTERFACE_USBDI_GUID version %x not supported!\n", IoStack->Parameters.QueryInterface.Version); - - // - // version not supported - // - return STATUS_NOT_SUPPORTED; - } - - // - // interface version 0 - // - InterfaceDI->Size = IoStack->Parameters.QueryInterface.Size; - InterfaceDI->BusContext = PVOID(this); - InterfaceDI->InterfaceReference = USBI_InterfaceReference; - InterfaceDI->InterfaceDereference = USBI_InterfaceDereference; - InterfaceDI->GetUSBDIVersion = USBDI_GetUSBDIVersion; - InterfaceDI->QueryBusTime = USBDI_QueryBusTime; - InterfaceDI->SubmitIsoOutUrb = USBDI_SubmitIsoOutUrb; - InterfaceDI->QueryBusInformation = USBDI_QueryBusInformation; - - // - // interface version 1 - // - if (IoStack->Parameters.QueryInterface.Version >= 1) - { - InterfaceDI->IsDeviceHighSpeed = USBDI_IsDeviceHighSpeed; - } - - // - // interface version 2 - // - if (IoStack->Parameters.QueryInterface.Version >= 2) - { - InterfaceDI->EnumLogEntry = USBDI_EnumLogEntry; - } - - InterfaceDI->InterfaceReference(InterfaceDI->BusContext); - // - // request completed - // - return STATUS_SUCCESS; - } - else - { - // - // convert guid to string - // - Status = RtlStringFromGUID(*IoStack->Parameters.QueryInterface.InterfaceType, &GuidBuffer); - if (NT_SUCCESS(Status)) - { - // - // print interface - // - DPRINT1("HandleQueryInterface UNKNOWN INTERFACE GUID: %wZ Version %x\n", &GuidBuffer, IoStack->Parameters.QueryInterface.Version); - - // - // free guid buffer - // - RtlFreeUnicodeString(&GuidBuffer); - } - } - return STATUS_NOT_SUPPORTED; -} - -NTSTATUS -CHubController::SetDeviceInterface( - BOOLEAN Enable) -{ - NTSTATUS Status = STATUS_SUCCESS; - - if (Enable) - { - // - // register device interface - // - Status = IoRegisterDeviceInterface(m_HubControllerDeviceObject, &GUID_DEVINTERFACE_USB_HUB, NULL, &m_HubDeviceInterfaceString); - - if (NT_SUCCESS(Status)) - { - // - // now enable the device interface - // - Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, TRUE); - - // - // enable interface - // - m_InterfaceEnabled = TRUE; - } - } - else if (m_InterfaceEnabled) - { - // - // disable device interface - // - Status = IoSetDeviceInterfaceState(&m_HubDeviceInterfaceString, FALSE); - - if (NT_SUCCESS(Status)) - { - // - // now delete interface string - // - RtlFreeUnicodeString(&m_HubDeviceInterfaceString); - } - - // - // disable interface - // - m_InterfaceEnabled = FALSE; - } - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -CHubController::CreatePDO( - PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT * OutDeviceObject) -{ - WCHAR CharDeviceName[64]; - NTSTATUS Status; - ULONG UsbDeviceNumber = 0; - UNICODE_STRING DeviceName; - - while (TRUE) - { - // - // construct device name - // - swprintf(CharDeviceName, L"\\Device\\USBPDO-%d", UsbDeviceNumber); - - // - // initialize device name - // - RtlInitUnicodeString(&DeviceName, CharDeviceName); - - // - // create device - // - Status = IoCreateDevice(DriverObject, - sizeof(COMMON_DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_CONTROLLER, - 0, - FALSE, - OutDeviceObject); - - /* check for success */ - if (NT_SUCCESS(Status)) - break; - - // - // is there a device object with that same name - // - if ((Status == STATUS_OBJECT_NAME_EXISTS) || (Status == STATUS_OBJECT_NAME_COLLISION)) - { - // - // Try the next name - // - UsbDeviceNumber++; - continue; - } - - // - // bail out on other errors - // - if (!NT_SUCCESS(Status)) - { - DPRINT1("CreatePDO: Failed to create %wZ, Status %x\n", &DeviceName, Status); - return Status; - } - } - - DPRINT("CHubController::CreatePDO: DeviceName %wZ\n", &DeviceName); - - // - // fixup device stack voodoo part #1 - // - (*OutDeviceObject)->StackSize++; - - /* done */ - return Status; -} - - - -NTSTATUS -NTAPI -CreateHubController( - PHUBCONTROLLER *OutHcdController) -{ - PHUBCONTROLLER This; - - // - // allocate controller - // - This = new(NonPagedPool, TAG_USBLIB) CHubController(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutHcdController = (PHUBCONTROLLER)This; - - // - // done - // - return STATUS_SUCCESS; -} - -VOID NTAPI StatusChangeEndpointCallBack(PVOID Context) -{ - CHubController* This; - PIRP Irp; - This = (CHubController*)Context; - - ASSERT(This); - - Irp = This->m_PendingSCEIrp; - if (!Irp) - { - DPRINT1("There was no pending IRP for SCE. Did the usb hub 2.0 driver (usbhub2) load?\n"); - return; - } - - This->m_PendingSCEIrp = NULL; - This->QueryStatusChangeEndpoint(Irp); - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); -} diff --git a/sdk/lib/drivers/libusb/libusb.cpp b/sdk/lib/drivers/libusb/libusb.cpp deleted file mode 100644 index 632614803d3..00000000000 --- a/sdk/lib/drivers/libusb/libusb.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library - * LICENSE: GPL - See COPYING in the top level directory - * FILE: lib/drivers/libusb/libusb.cpp - * PURPOSE: USB Common Driver Library. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "libusb.h" - -#define NDEBUG -#include - -// -// driver verifier -// -DRIVER_ADD_DEVICE USBLIB_AddDevice; - -PVOID -__cdecl -operator new( - size_t iSize, - POOL_TYPE poolType, - ULONG tag) -{ - PVOID result = ExAllocatePoolWithTag(poolType, iSize, tag); - if (result) { - RtlZeroMemory(result, iSize); - } - return result; -} - -void -__cdecl -operator delete( - PVOID pVoid) -{ - if (pVoid) ExFreePool(pVoid); -} - -void -__cdecl -operator delete( - PVOID pVoid, UINT_PTR) -{ - if (pVoid) ExFreePool(pVoid); -} - -extern -"C" -{ -NTSTATUS -NTAPI -USBLIB_AddDevice( - PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT PhysicalDeviceObject) -{ - NTSTATUS Status; - PHCDCONTROLLER HcdController; - - DPRINT("USBLIB_AddDevice\n"); - - /* first create the controller object */ - Status = CreateHCDController(&HcdController); - if (!NT_SUCCESS(Status)) - { - /* failed to create hcd */ - DPRINT1("AddDevice: Failed to create hcd with %x\n", Status); - return Status; - } - - /* initialize the hcd */ - Status = HcdController->Initialize(NULL, // FIXME - DriverObject, - PhysicalDeviceObject); - - /* check for success */ - if (!NT_SUCCESS(Status)) - { - /* failed to initialize device */ - DPRINT1("AddDevice: failed to initialize\n"); - - /* release object */ - HcdController->Release(); - } - - return Status; - -} -} - -extern -"C" -{ -NTSTATUS -NTAPI -USBLIB_Dispatch( - PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PCOMMON_DEVICE_EXTENSION DeviceExtension; - PIO_STACK_LOCATION IoStack; - NTSTATUS Status; - - // - // get common device extension - // - DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - // - // get current stack location - // - IoStack = IoGetCurrentIrpStackLocation(Irp); - - // - // sanity checks - // - PC_ASSERT(DeviceExtension->Dispatcher); - - switch(IoStack->MajorFunction) - { - case IRP_MJ_PNP: - { - // - // dispatch pnp - // - return DeviceExtension->Dispatcher->HandlePnp(DeviceObject, Irp); - } - - case IRP_MJ_POWER: - { - // - // dispatch power - // - return DeviceExtension->Dispatcher->HandlePower(DeviceObject, Irp); - } - case IRP_MJ_INTERNAL_DEVICE_CONTROL: - case IRP_MJ_DEVICE_CONTROL: - { - // - // dispatch io control - // - return DeviceExtension->Dispatcher->HandleDeviceControl(DeviceObject, Irp); - } - case IRP_MJ_SYSTEM_CONTROL: - { - // - // dispatch system control - // - return DeviceExtension->Dispatcher->HandleSystemControl(DeviceObject, Irp); - } - default: - { - DPRINT1("USBLIB_Dispatch> Major %lu Minor %lu unhandeled\n", IoStack->MajorFunction, IoStack->MinorFunction); - Status = STATUS_SUCCESS; - } - } - - // - // complete request - // - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; -} -} diff --git a/sdk/lib/drivers/libusb/libusb.h b/sdk/lib/drivers/libusb/libusb.h deleted file mode 100644 index ee0bf584d55..00000000000 --- a/sdk/lib/drivers/libusb/libusb.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef LIBUSB_H__ -#define LIBUSB_H__ - -#include -#include -#include - -extern "C" -{ - #include -} - -// -// FIXME: -// #include -// -#include -#include - -// -// FIXME: -// the following includes are required to get kcom to compile -// -#include -#include - -PVOID -__cdecl -operator new( - size_t iSize, - POOL_TYPE poolType, - ULONG tag); - - -#include "common_interfaces.h" - -// -// flags for handling USB_REQUEST_SET_FEATURE / USB_REQUEST_GET_FEATURE -// -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVER_CURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#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 - -typedef struct -{ - BOOLEAN IsFDO; // is device a FDO or PDO - BOOLEAN IsHub; // is device a hub / child - not yet used - PDISPATCHIRP Dispatcher; // dispatches the code -}COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; - - -typedef struct _WORK_ITEM_DATA -{ - WORK_QUEUE_ITEM WorkItem; // work item - PVOID CallbackContext; // callback context - PRH_INIT_CALLBACK CallbackRoutine; // callback routine -} INIT_ROOT_HUB_CONTEXT, *PINIT_ROOT_HUB_CONTEXT; - -// -// tag for allocations -// -#define TAG_USBLIB 'LBSU' - -// -// assert for c++ - taken from portcls -// -#define PC_ASSERT(exp) \ - (VOID)((!(exp)) ? \ - RtlAssert((PVOID) #exp, (PVOID)__FILE__, __LINE__, NULL ), FALSE : TRUE) - -// hcd_controller.cpp -extern "C" -{ -NTSTATUS NTAPI CreateHCDController(PHCDCONTROLLER *HcdController); - -// hardware.cpp -NTSTATUS NTAPI CreateUSBHardware(PUSBHARDWAREDEVICE *OutHardware); - -// misc.cpp -NTSTATUS NTAPI SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp); -NTSTATUS NTAPI GetBusInterface(PDEVICE_OBJECT DeviceObject, PBUS_INTERFACE_STANDARD busInterface); - -// root_hub_controller.cpp -NTSTATUS NTAPI CreateHubController(PHUBCONTROLLER * OutHubController); - -// memory_manager.cpp -NTSTATUS NTAPI CreateDMAMemoryManager(PDMAMEMORYMANAGER *OutMemoryManager); - -// usb_device.cpp -NTSTATUS NTAPI CreateUSBDevice(PUSBDEVICE *OutDevice); - -// libusb.cpp -NTSTATUS NTAPI USBLIB_AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject); -NTSTATUS NTAPI USBLIB_Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -} - -#endif /* LIBUSB_H__ */ diff --git a/sdk/lib/drivers/libusb/memory_manager.cpp b/sdk/lib/drivers/libusb/memory_manager.cpp deleted file mode 100644 index bd1a40573c2..00000000000 --- a/sdk/lib/drivers/libusb/memory_manager.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library - * LICENSE: GPL - See COPYING in the top level directory - * FILE: lib/drivers/libusb/memory_manager.cpp - * PURPOSE: USB Common Driver Library. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "libusb.h" - -#define NDEBUG -#include - -class CDMAMemoryManager : public IDMAMemoryManager -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // IDMAMemoryManager interface functions - virtual NTSTATUS Initialize(IN PUSBHARDWAREDEVICE Device, IN PKSPIN_LOCK Lock, IN ULONG DmaBufferSize, IN PVOID VirtualBase, IN PHYSICAL_ADDRESS PhysicalAddress, IN ULONG DefaultBlockSize); - virtual NTSTATUS Allocate(IN ULONG Size, OUT PVOID *OutVirtualBase, OUT PPHYSICAL_ADDRESS OutPhysicalAddress); - virtual NTSTATUS Release(IN PVOID VirtualBase, IN ULONG Size); - - // constructor / destructor - CDMAMemoryManager(IUnknown *OuterUnknown){} - virtual ~CDMAMemoryManager(){} - -protected: - LONG m_Ref; - PUSBHARDWAREDEVICE m_Device; - PKSPIN_LOCK m_Lock; - LONG m_DmaBufferSize; - PVOID m_VirtualBase; - PHYSICAL_ADDRESS m_PhysicalAddress; - ULONG m_BlockSize; - - PULONG m_BitmapBuffer; - RTL_BITMAP m_Bitmap; -}; - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CDMAMemoryManager::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - return STATUS_UNSUCCESSFUL; -} - -NTSTATUS -CDMAMemoryManager::Initialize( - IN PUSBHARDWAREDEVICE Device, - IN PKSPIN_LOCK Lock, - IN ULONG DmaBufferSize, - IN PVOID VirtualBase, - IN PHYSICAL_ADDRESS PhysicalAddress, - IN ULONG DefaultBlockSize) -{ - ULONG BitmapLength; - - // - // sanity checks - // - PC_ASSERT(DmaBufferSize >= PAGE_SIZE); - PC_ASSERT(DmaBufferSize % PAGE_SIZE == 0); - PC_ASSERT(DefaultBlockSize == 32 || DefaultBlockSize == 64 || DefaultBlockSize == 128); - - // - // calculate bitmap length - // - BitmapLength = (DmaBufferSize / DefaultBlockSize) / 8; - - // - // allocate bitmap buffer - // - m_BitmapBuffer = (PULONG)ExAllocatePoolWithTag(NonPagedPool, BitmapLength, TAG_USBLIB); - if (!m_BitmapBuffer) - { - // - // no memory - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // initialize bitmap - // - RtlInitializeBitMap(&m_Bitmap, m_BitmapBuffer, BitmapLength * 8); - - // - // clear all bits - // - RtlClearAllBits(&m_Bitmap); - - // - // initialize rest of memory allocator - // - m_PhysicalAddress = PhysicalAddress; - m_VirtualBase = VirtualBase; - m_DmaBufferSize = DmaBufferSize; - m_Lock = Lock; - m_BlockSize = DefaultBlockSize; - - /* done */ - return STATUS_SUCCESS; -} - -NTSTATUS -CDMAMemoryManager::Allocate( - IN ULONG Size, - OUT PVOID *OutVirtualAddress, - OUT PPHYSICAL_ADDRESS OutPhysicalAddress) -{ - ULONG Length, BlockCount, FreeIndex, StartPage, EndPage; - KIRQL OldLevel; - ULONG BlocksPerPage; - - // - // sanity checks - // - ASSERT(Size <= PAGE_SIZE); - //ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); - - // - // align request - // - Length = (Size + m_BlockSize -1) & ~(m_BlockSize -1); - - // - // sanity check - // - ASSERT(Length); - - // - // convert to block count - // - BlockCount = Length / m_BlockSize; - - // - // acquire lock - // - KeAcquireSpinLock(m_Lock, &OldLevel); - - // - // helper variable - // - BlocksPerPage = PAGE_SIZE / m_BlockSize; - - // - // start search - // - FreeIndex = 0; - do - { - // - // search for an free index - // - FreeIndex = RtlFindClearBits(&m_Bitmap, BlockCount, FreeIndex); - - // - // check if there was a block found - // - if (FreeIndex == MAXULONG) - { - // - // no free block found - // - break; - } - - // - // check that the allocation does not spawn over page boundaries - // - StartPage = (FreeIndex * m_BlockSize); - StartPage = (StartPage != 0 ? StartPage / PAGE_SIZE : 0); - EndPage = ((FreeIndex + BlockCount) * m_BlockSize) / PAGE_SIZE; - - // - // does the request start and end on the same page - // - if (StartPage == EndPage) - { - // - // reserve block - // - RtlSetBits(&m_Bitmap, FreeIndex, BlockCount); - - // - // reserve block - // - break; - } - else if ((BlockCount == BlocksPerPage) && (FreeIndex % BlocksPerPage == 0)) - { - // - // the request equals PAGE_SIZE and is aligned at page boundary - // reserve block - // - RtlSetBits(&m_Bitmap, FreeIndex, BlockCount); - - // - // reserve block - // - break; - } - else - { - // - // request spawned over page boundary - // restart search on next page - // - FreeIndex = (EndPage * PAGE_SIZE) / m_BlockSize; - } - } - while(TRUE); - - // - // release lock - // - KeReleaseSpinLock(m_Lock, OldLevel); - - // - // did allocation succeed - // - if (FreeIndex == MAXULONG) - { - // - // failed to allocate block, requestor must retry - // - return STATUS_UNSUCCESSFUL; - } - - // - // return result - // - *OutVirtualAddress = (PVOID)((ULONG_PTR)m_VirtualBase + FreeIndex * m_BlockSize); - OutPhysicalAddress->QuadPart = m_PhysicalAddress.QuadPart + FreeIndex * m_BlockSize; - - // - // clear block - // - RtlZeroMemory(*OutVirtualAddress, Length); - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -CDMAMemoryManager::Release( - IN PVOID VirtualAddress, - IN ULONG Size) -{ - KIRQL OldLevel; - ULONG BlockOffset = 0, BlockLength, BlockCount; - - // - // sanity checks - // - PC_ASSERT(VirtualAddress); - PC_ASSERT((ULONG_PTR)VirtualAddress >= (ULONG_PTR)m_VirtualBase); - PC_ASSERT((ULONG_PTR)m_VirtualBase + m_DmaBufferSize > (ULONG_PTR)m_VirtualBase); - - // - // calculate block length - // - BlockLength = ((ULONG_PTR)VirtualAddress - (ULONG_PTR)m_VirtualBase); - - // - // check if its the first block - // - if (BlockLength) - { - // - // divide by base block size - // - BlockOffset = BlockLength / m_BlockSize; - } - - // - // align length to block size - // - Size = (Size + m_BlockSize - 1) & ~(m_BlockSize - 1); - - // - // convert to blocks - // - BlockCount = Size / m_BlockSize; - ASSERT(BlockCount); - - // - // acquire lock - // - KeAcquireSpinLock(m_Lock, &OldLevel); - - // - // sanity check - // - ASSERT(RtlAreBitsSet(&m_Bitmap, BlockOffset, BlockCount)); - - // - // release buffer - // - RtlClearBits(&m_Bitmap, BlockOffset, BlockCount); - - // - // release lock - // - KeReleaseSpinLock(m_Lock, OldLevel); - - // - // done - // - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -CreateDMAMemoryManager( - PDMAMEMORYMANAGER *OutMemoryManager) -{ - CDMAMemoryManager* This; - - // - // allocate controller - // - This = new(NonPagedPool, TAG_USBLIB) CDMAMemoryManager(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutMemoryManager = (PDMAMEMORYMANAGER)This; - - // - // done - // - return STATUS_SUCCESS; -} - diff --git a/sdk/lib/drivers/libusb/misc.cpp b/sdk/lib/drivers/libusb/misc.cpp deleted file mode 100644 index d1622f6b19c..00000000000 --- a/sdk/lib/drivers/libusb/misc.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library - * LICENSE: GPL - See COPYING in the top level directory - * FILE: lib/drivers/libusb/misc.cpp - * PURPOSE: USB Common Driver Library. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "libusb.h" - -#define NDEBUG -#include - -// -// driver verifier -// -IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine; - -NTSTATUS -NTAPI -SyncForwardIrpCompletionRoutine( - PDEVICE_OBJECT DeviceObject, - PIRP Irp, - PVOID Context) -{ - if (Irp->PendingReturned) - { - KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); - } - return STATUS_MORE_PROCESSING_REQUIRED; -} - -NTSTATUS -NTAPI -SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - KEVENT Event; - NTSTATUS Status; - - // - // initialize event - // - KeInitializeEvent(&Event, NotificationEvent, FALSE); - - // - // copy irp stack location - // - IoCopyCurrentIrpStackLocationToNext(Irp); - - // - // set completion routine - // - IoSetCompletionRoutine(Irp, SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE); - - - // - // call driver - // - Status = IoCallDriver(DeviceObject, Irp); - - - // - // check if pending - // - if (Status == STATUS_PENDING) - { - // - // wait for the request to finish - // - KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - - // - // copy status code - // - Status = Irp->IoStatus.Status; - } - - // - // done - // - return Status; -} - -NTSTATUS -NTAPI -GetBusInterface( - PDEVICE_OBJECT DeviceObject, - PBUS_INTERFACE_STANDARD busInterface) -{ - KEVENT Event; - NTSTATUS Status; - PIRP Irp; - IO_STATUS_BLOCK IoStatus; - PIO_STACK_LOCATION Stack; - - if ((!DeviceObject) || (!busInterface)) - return STATUS_UNSUCCESSFUL; - - KeInitializeEvent(&Event, NotificationEvent, FALSE); - - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, - DeviceObject, - NULL, - 0, - NULL, - &Event, - &IoStatus); - - if (Irp == NULL) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - Stack=IoGetNextIrpStackLocation(Irp); - Stack->MajorFunction = IRP_MJ_PNP; - Stack->MinorFunction = IRP_MN_QUERY_INTERFACE; - Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD); - Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_BUS_INTERFACE_STANDARD; - Stack->Parameters.QueryInterface.Version = 1; - Stack->Parameters.QueryInterface.Interface = (PINTERFACE)busInterface; - Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL; - Irp->IoStatus.Status=STATUS_NOT_SUPPORTED ; - - Status=IoCallDriver(DeviceObject, Irp); - - if (Status == STATUS_PENDING) - { - KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); - - Status=IoStatus.Status; - } - - return Status; -} - diff --git a/sdk/lib/drivers/libusb/purecall.cpp b/sdk/lib/drivers/libusb/purecall.cpp deleted file mode 100644 index 9fa4eb8b7e5..00000000000 --- a/sdk/lib/drivers/libusb/purecall.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library - * LICENSE: GPL - See COPYING in the top level directory - * FILE: lib/drivers/libusb/purecall.cpp - * PURPOSE: USB Common Driver Library. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "libusb.h" - -#define NDEBUG -#include - -extern "C" { - void - __cxa_pure_virtual() - { - // put error handling here - - DbgBreakPoint(); - - } -} diff --git a/sdk/lib/drivers/libusb/usb_device.cpp b/sdk/lib/drivers/libusb/usb_device.cpp deleted file mode 100644 index edc1896e1bf..00000000000 --- a/sdk/lib/drivers/libusb/usb_device.cpp +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * PROJECT: ReactOS Universal Serial Bus Bulk Driver Library - * LICENSE: GPL - See COPYING in the top level directory - * FILE: lib/drivers/libusb/usb_device.cpp - * PURPOSE: USB Common Driver Library. - * PROGRAMMERS: - * Michael Martin (michael.martin@reactos.org) - * Johannes Anderwald (johannes.anderwald@reactos.org) - */ - -#include "libusb.h" - -#define NDEBUG -#include - -class CUSBDevice : public IUSBDevice -{ -public: - STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); - - STDMETHODIMP_(ULONG) AddRef() - { - InterlockedIncrement(&m_Ref); - return m_Ref; - } - STDMETHODIMP_(ULONG) Release() - { - InterlockedDecrement(&m_Ref); - - if (!m_Ref) - { - delete this; - return 0; - } - return m_Ref; - } - - // IUSBDevice interface functions - virtual NTSTATUS Initialize(IN PHUBCONTROLLER HubController, IN PUSBHARDWAREDEVICE Device, IN PVOID Parent, IN ULONG Port, IN ULONG PortStatus); - virtual BOOLEAN IsHub(); - virtual NTSTATUS GetParent(PVOID * Parent); - virtual UCHAR GetDeviceAddress(); - virtual ULONG GetPort(); - virtual USB_DEVICE_SPEED GetSpeed(); - virtual USB_DEVICE_TYPE GetType(); - virtual ULONG GetState(); - virtual void SetDeviceHandleData(PVOID Data); - virtual NTSTATUS SetDeviceAddress(UCHAR DeviceAddress); - virtual void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor); - virtual UCHAR GetConfigurationValue(); - virtual NTSTATUS SubmitIrp(PIRP Irp); - virtual VOID GetConfigurationDescriptors(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer, IN ULONG BufferLength, OUT PULONG OutBufferLength); - virtual ULONG GetConfigurationDescriptorsLength(); - virtual NTSTATUS SubmitSetupPacket(IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, OUT ULONG BufferLength, OUT PVOID Buffer); - virtual NTSTATUS SelectConfiguration(IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, IN PUSBD_INTERFACE_INFORMATION Interface, OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle); - virtual NTSTATUS SelectInterface(IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, IN OUT PUSBD_INTERFACE_INFORMATION Interface); - virtual NTSTATUS AbortPipe(IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor); - virtual UCHAR GetMaxPacketSize(); - - - // local function - virtual NTSTATUS CommitIrp(PIRP Irp); - virtual NTSTATUS CommitSetupPacket(PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, IN ULONG BufferLength, IN OUT PMDL Mdl); - virtual NTSTATUS CreateConfigurationDescriptor(UCHAR ConfigurationIndex); - virtual NTSTATUS CreateDeviceDescriptor(); - virtual VOID DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor); - virtual VOID DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor); - virtual NTSTATUS GetConfigurationDescriptor(UCHAR ConfigurationIndex, USHORT BufferSize, PVOID Buffer); - virtual NTSTATUS BuildInterfaceDescriptor(IN ULONG ConfigurationIndex, IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo, OUT PUSB_INTERFACE *OutUsbInterface); - - - // constructor / destructor - CUSBDevice(IUnknown *OuterUnknown){} - virtual ~CUSBDevice(){} - -protected: - LONG m_Ref; - PHUBCONTROLLER m_HubController; - PUSBHARDWAREDEVICE m_Device; - PVOID m_Parent; - ULONG m_Port; - UCHAR m_DeviceAddress; - PVOID m_Data; - UCHAR m_ConfigurationIndex; - KSPIN_LOCK m_Lock; - USB_DEVICE_DESCRIPTOR m_DeviceDescriptor; - ULONG m_PortStatus; - PUSBQUEUE m_Queue; - PDMAMEMORYMANAGER m_DmaManager; - LPCSTR m_USBType; - - PUSB_CONFIGURATION m_ConfigurationDescriptors; -}; - -//---------------------------------------------------------------------------------------- -NTSTATUS -STDMETHODCALLTYPE -CUSBDevice::QueryInterface( - IN REFIID refiid, - OUT PVOID* Output) -{ - return STATUS_UNSUCCESSFUL; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::Initialize( - IN PHUBCONTROLLER HubController, - IN PUSBHARDWAREDEVICE Device, - IN PVOID Parent, - IN ULONG Port, - IN ULONG PortStatus) -{ - NTSTATUS Status; - - // - // initialize members - // - m_HubController = HubController; - m_Device = Device; - m_Parent = Parent; - m_Port = Port; - m_PortStatus = PortStatus; - m_USBType = m_Device->GetUSBType(); - - // - // initialize device lock - // - KeInitializeSpinLock(&m_Lock); - - // - // no device address has been set yet - // - m_DeviceAddress = 0; - - // - // get usb request queue - // - Status = m_Device->GetUSBQueue(&m_Queue); - if (!NT_SUCCESS(Status)) - { - // - // failed to get usb queue - // - DPRINT1("[%s] GetUsbQueue failed with %x\n", m_USBType, Status); - return Status; - } - - // - // get dma manager - // - Status = m_Device->GetDMA(&m_DmaManager); - if (!NT_SUCCESS(Status)) - { - // - // failed to get dma manager - // - DPRINT1("[%s] GetDMA failed with %x\n", m_USBType, Status); - return Status; - } - - // - // sanity check - // - PC_ASSERT(m_DmaManager); - - // - // get device descriptor - // - Status = CreateDeviceDescriptor(); - if (!NT_SUCCESS(Status)) - { - // - // failed to get device descriptor - // - DPRINT1("[%s] Failed to get device descriptor with %x\n", m_USBType, Status); - return Status; - } - - // - // done - // - return Status; -} - -//---------------------------------------------------------------------------------------- -BOOLEAN -CUSBDevice::IsHub() -{ - // - // USB Standard Device Class see http://www.usb.org/developers/defined_class/#BaseClass09h - // for details - // - return (m_DeviceDescriptor.bDeviceClass == 0x09 && m_DeviceDescriptor.bDeviceSubClass == 0x00); -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::GetParent( - PVOID * Parent) -{ - // - // returns parent - // - *Parent = m_Parent; - - // - // done - // - return STATUS_SUCCESS; -} - -//---------------------------------------------------------------------------------------- -UCHAR -CUSBDevice::GetDeviceAddress() -{ - // - // get device address - // - return m_DeviceAddress; -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBDevice::GetPort() -{ - // - // get port to which this device is connected to - // - return m_Port; -} - -//---------------------------------------------------------------------------------------- -USB_DEVICE_SPEED -CUSBDevice::GetSpeed() -{ - if (m_PortStatus & USB_PORT_STATUS_LOW_SPEED) - { - // - // low speed device - // - return UsbLowSpeed; - } - else if (m_PortStatus & USB_PORT_STATUS_HIGH_SPEED) - { - // - // high speed device - // - return UsbHighSpeed; - } - - // - // default to full speed - // - return UsbFullSpeed; -} - -//---------------------------------------------------------------------------------------- -USB_DEVICE_TYPE -CUSBDevice::GetType() -{ - // - // device is encoded into bcdUSB - // - if (m_DeviceDescriptor.bcdUSB == 0x110) - { - // - // USB 1.1 device - // - return Usb11Device; - } - else if (m_DeviceDescriptor.bcdUSB == 0x200) - { - // - // USB 2.0 device - // - return Usb20Device; - } - - DPRINT1("[%s] GetType Unknown bcdUSB Type %x\n", m_USBType, m_DeviceDescriptor.bcdUSB); - //PC_ASSERT(FALSE); - - return Usb11Device; -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBDevice::GetState() -{ - UNIMPLEMENTED; - return FALSE; -} - -//---------------------------------------------------------------------------------------- -void -CUSBDevice::SetDeviceHandleData( - PVOID Data) -{ - // - // set device data, for debugging issues - // - m_Data = Data; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::SetDeviceAddress( - UCHAR DeviceAddress) -{ - PUSB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - UCHAR Index; - - DPRINT1("[%s] SetDeviceAddress> Address %x\n", m_USBType, DeviceAddress); - - CtrlSetup = (PUSB_DEFAULT_PIPE_SETUP_PACKET)ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET), TAG_USBLIB); - if (!CtrlSetup) - return STATUS_INSUFFICIENT_RESOURCES; - - // zero request - RtlZeroMemory(CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - - // initialize request - CtrlSetup->bRequest = USB_REQUEST_SET_ADDRESS; - CtrlSetup->wValue.W = DeviceAddress; - - // set device address - Status = CommitSetupPacket(CtrlSetup, NULL, 0, NULL); - - // free setup packet - ExFreePoolWithTag(CtrlSetup, TAG_USBLIB); - - // check for success - if (!NT_SUCCESS(Status)) - { - // failed to set device address - DPRINT1("[%s] SetDeviceAddress> failed to set device address with %lx Address %x\n", m_USBType, Status, DeviceAddress); - return Status; - } - - // lets have a short nap - KeStallExecutionProcessor(300); - - // store new device address - m_DeviceAddress = DeviceAddress; - - // fetch device descriptor - Status = CreateDeviceDescriptor(); - if (!NT_SUCCESS(Status)) - { - DPRINT1("[%s] SetDeviceAddress failed to retrieve device descriptor with device address set Error %lx\n", m_USBType, Status); - // return error status - return Status; - } - - // check for invalid device descriptor - if (m_DeviceDescriptor.bLength != sizeof(USB_DEVICE_DESCRIPTOR) || - m_DeviceDescriptor.bDescriptorType != USB_DEVICE_DESCRIPTOR_TYPE || - m_DeviceDescriptor.bNumConfigurations == 0) - { - // failed to retrieve device descriptor - DPRINT1("[%s] SetDeviceAddress> device returned bogus device descriptor\n", m_USBType); - DumpDeviceDescriptor(&m_DeviceDescriptor); - - // return error status - return STATUS_UNSUCCESSFUL; - } - - // dump device descriptor - DumpDeviceDescriptor(&m_DeviceDescriptor); - - // sanity checks - PC_ASSERT(m_DeviceDescriptor.bNumConfigurations); - - // allocate configuration descriptor - m_ConfigurationDescriptors = (PUSB_CONFIGURATION) ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations, TAG_USBLIB); - - // zero configuration descriptor - RtlZeroMemory(m_ConfigurationDescriptors, sizeof(USB_CONFIGURATION) * m_DeviceDescriptor.bNumConfigurations); - - // retrieve the configuration descriptors - for (Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++) - { - // retrieve configuration descriptors from device - Status = CreateConfigurationDescriptor(Index); - if (!NT_SUCCESS(Status)) - { - DPRINT1("[%s] SetDeviceAddress> failed to retrieve configuration %lu\n", m_USBType, Index); - break; - } - } - - // - // done - // - return Status; - -} - -//---------------------------------------------------------------------------------------- -void -CUSBDevice::GetDeviceDescriptor( - PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) -{ - RtlMoveMemory(DeviceDescriptor, &m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); -} - -//---------------------------------------------------------------------------------------- -UCHAR -CUSBDevice::GetConfigurationValue() -{ - // - // return configuration index - // - return m_ConfigurationIndex; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::CommitIrp( - PIRP Irp) -{ - NTSTATUS Status; - PUSBREQUEST Request; - - if (!m_Queue || !m_DmaManager) - { - // - // no queue, wtf? - // - DPRINT1("[%s] CommitIrp> no queue / dma !!!\n", m_USBType); - return STATUS_UNSUCCESSFUL; - } - - // - // build usb request - // - Status = m_Queue->CreateUSBRequest(&Request); - if (!NT_SUCCESS(Status)) - { - // - // failed to build request - // - DPRINT1("[%s] CommitIrp> CreateUSBRequest failed with %lx\n", m_USBType, Status); - return Status; - } - - // - // initialize request - // - Status = Request->InitializeWithIrp(m_DmaManager, PUSBDEVICE(this), Irp); - - // - // mark irp as pending - // - IoMarkIrpPending(Irp); - - // - // now add the request - // - Status = m_Queue->AddUSBRequest(Request); - if (!NT_SUCCESS(Status)) - { - // - // failed to add request - // - DPRINT1("[%s] failed add request to queue with %lx\n", m_USBType, Status); - Request->Release(); - return Status; - } - - // - // done - // - return STATUS_PENDING; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::SubmitIrp( - PIRP Irp) -{ - KIRQL OldLevel; - NTSTATUS Status; - - // - // acquire device lock - // - KeAcquireSpinLock(&m_Lock, &OldLevel); - - // - // commit urb - // - Status = CommitIrp(Irp); - - // - // release lock - // - KeReleaseSpinLock(&m_Lock, OldLevel); - - return Status; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::CommitSetupPacket( - IN PUSB_DEFAULT_PIPE_SETUP_PACKET Packet, - IN OPTIONAL PUSB_ENDPOINT EndpointDescriptor, - IN ULONG BufferLength, - IN OUT PMDL Mdl) -{ - NTSTATUS Status; - PUSBREQUEST Request; - - if (!m_Queue) - { - // - // no queue, wtf? - // - DPRINT1("[%s] CommitSetupPacket> no queue!!!\n", m_USBType); - return STATUS_UNSUCCESSFUL; - } - - // - // build usb request - // - Status = m_Queue->CreateUSBRequest(&Request); - if (!NT_SUCCESS(Status)) - { - // - // failed to build request - // - DPRINT1("[%s] CommitSetupPacket> CreateUSBRequest failed with %x\n", m_USBType, Status); - return Status; - } - - // - // initialize request - // - Status = Request->InitializeWithSetupPacket(m_DmaManager, Packet, PUSBDEVICE(this), EndpointDescriptor, BufferLength, Mdl); - if (!NT_SUCCESS(Status)) - { - // - // failed to initialize request - // - DPRINT1("[%s] CommitSetupPacket failed to initialize usb request with %x\n", m_USBType, Status); - Request->Release(); - return Status; - } - - // - // now add the request - // - Status = m_Queue->AddUSBRequest(Request); - if (!NT_SUCCESS(Status)) - { - // - // failed to add request - // - DPRINT1("[%s] CommitSetupPacket> failed add request to queue with %x\n", m_USBType, Status); - Request->Release(); - return Status; - } - - // - // get the result code when the operation has been finished - // - Request->GetResultStatus(&Status, NULL); - - // - // release request - // - Request->Release(); - - // - // done - // - return Status; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::CreateDeviceDescriptor() -{ - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - PMDL Mdl; - NTSTATUS Status; - PVOID Buffer; - - // - // zero descriptor - // - RtlZeroMemory(&m_DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); - RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - - // - // setup request - // - CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR; - CtrlSetup.wValue.HiByte = USB_DEVICE_DESCRIPTOR_TYPE; - CtrlSetup.wLength = sizeof(USB_DEVICE_DESCRIPTOR); - CtrlSetup.bmRequestType.B = 0x80; - - // - // allocate buffer - // - Buffer = ExAllocatePool(NonPagedPool, PAGE_SIZE); - if (!Buffer) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // zero buffer - // - RtlZeroMemory(Buffer, PAGE_SIZE); - - // - // allocate mdl describing the device descriptor - // - Mdl = IoAllocateMdl(Buffer, sizeof(USB_DEVICE_DESCRIPTOR), FALSE, FALSE, 0); - if (!Mdl) - { - // - // failed to allocate mdl - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // build mdl for non paged pool - // - MmBuildMdlForNonPagedPool(Mdl); - - // - // commit setup packet - // - Status = CommitSetupPacket(&CtrlSetup, NULL, sizeof(USB_DEVICE_DESCRIPTOR), Mdl); - - // - // now free the mdl - // - IoFreeMdl(Mdl); - - if (NT_SUCCESS(Status)) - { - // - // copy device descriptor - // - RtlCopyMemory(&m_DeviceDescriptor, Buffer, sizeof(USB_DEVICE_DESCRIPTOR)); - } - - // - // free buffer - // - ExFreePool(Buffer); - - // - // done - // - return Status; - -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::GetConfigurationDescriptor( - IN UCHAR ConfigurationIndex, - IN USHORT BufferSize, - IN PVOID Buffer) -{ - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - PMDL Mdl; - - - // - // now build MDL describing the buffer - // - Mdl = IoAllocateMdl(Buffer, BufferSize, FALSE, FALSE, 0); - if (!Mdl) - { - // - // failed to allocate mdl - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // build mdl for non paged pool - // - MmBuildMdlForNonPagedPool(Mdl); - - - // - // build setup packet - // - CtrlSetup.bmRequestType.Recipient = BMREQUEST_TO_DEVICE; - CtrlSetup.bmRequestType.Type = BMREQUEST_STANDARD; - CtrlSetup.bmRequestType.Reserved = 0; - CtrlSetup.bmRequestType.Dir = BMREQUEST_DEVICE_TO_HOST; - CtrlSetup.bRequest = USB_REQUEST_GET_DESCRIPTOR; - CtrlSetup.wValue.LowByte = ConfigurationIndex; - CtrlSetup.wValue.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE; - CtrlSetup.wIndex.W = 0; - CtrlSetup.wLength = BufferSize; - - // - // commit packet - // - Status = CommitSetupPacket(&CtrlSetup, NULL, BufferSize, Mdl); - - // - // free mdl - // - IoFreeMdl(Mdl); - - // - // done - // - return Status; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::CreateConfigurationDescriptor( - UCHAR Index) -{ - NTSTATUS Status; - PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; - - // - // sanity checks - // - PC_ASSERT(m_ConfigurationDescriptors); - - // - // first allocate a buffer which should be enough to store all different interfaces and endpoints - // - ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_USBLIB); - if (!ConfigurationDescriptor) - { - // - // failed to allocate buffer - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // get partial configuration descriptor - // - Status = GetConfigurationDescriptor(Index, sizeof(USB_CONFIGURATION_DESCRIPTOR), ConfigurationDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // failed to get partial configuration descriptor - // - DPRINT1("[%s] Failed to get partial configuration descriptor Status %x Index %x\n", m_USBType, Status, Index); - ExFreePoolWithTag(ConfigurationDescriptor, TAG_USBLIB); - return Status; - } - - // - // now get full descriptor - // - Status = GetConfigurationDescriptor(Index, ConfigurationDescriptor->wTotalLength, ConfigurationDescriptor); - if (!NT_SUCCESS(Status)) - { - // - // failed to get full configuration descriptor - // - DPRINT1("[%s] Failed to get full configuration descriptor Status %x Index %x\n", m_USBType, Status, Index); - ExFreePoolWithTag(ConfigurationDescriptor, TAG_USBLIB); - return Status; - } - - // - // informal debug print - // - DumpConfigurationDescriptor(ConfigurationDescriptor); - - // - // sanity check - // - PC_ASSERT(ConfigurationDescriptor->bLength == sizeof(USB_CONFIGURATION_DESCRIPTOR)); - PC_ASSERT(ConfigurationDescriptor->wTotalLength <= PAGE_SIZE); - PC_ASSERT(ConfigurationDescriptor->bNumInterfaces); - - // - // request is complete, initialize configuration descriptor - // - m_ConfigurationDescriptors[Index].ConfigurationDescriptor = ConfigurationDescriptor; - InitializeListHead(&m_ConfigurationDescriptors[Index].InterfaceList); - - // - // done - // - return Status; -} -//---------------------------------------------------------------------------------------- -VOID -CUSBDevice::GetConfigurationDescriptors( - IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptorBuffer, - IN ULONG BufferLength, - OUT PULONG OutBufferLength) -{ - ULONG Length; - - // sanity check - ASSERT(BufferLength >= sizeof(USB_CONFIGURATION_DESCRIPTOR)); - ASSERT(ConfigDescriptorBuffer); - ASSERT(OutBufferLength); - - // reset copied length - *OutBufferLength = 0; - - // FIXME: support multiple configurations - PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1); - - // copy configuration descriptor - Length = min(m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength, BufferLength); - RtlCopyMemory(ConfigDescriptorBuffer, m_ConfigurationDescriptors[0].ConfigurationDescriptor, Length); - *OutBufferLength = Length; -} - -//---------------------------------------------------------------------------------------- -ULONG -CUSBDevice::GetConfigurationDescriptorsLength() -{ - // - // FIXME: support multiple configurations - // - PC_ASSERT(m_DeviceDescriptor.bNumConfigurations == 1); - - return m_ConfigurationDescriptors[0].ConfigurationDescriptor->wTotalLength; -} -//---------------------------------------------------------------------------------------- -VOID -CUSBDevice::DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor) -{ - DPRINT1("Dumping Device Descriptor %p\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 -CUSBDevice::DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor) -{ - DPRINT1("Dumping ConfigurationDescriptor %p\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 -CUSBDevice::SubmitSetupPacket( - IN PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, - IN OUT ULONG BufferLength, - OUT PVOID Buffer) -{ - NTSTATUS Status; - PMDL Mdl = NULL; - - if (BufferLength) - { - // - // allocate mdl - // - Mdl = IoAllocateMdl(Buffer, BufferLength, FALSE, FALSE, 0); - if (!Mdl) - { - // - // no memory - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // HACK HACK HACK: assume the buffer is build from non paged pool - // - MmBuildMdlForNonPagedPool(Mdl); - } - - // - // commit setup packet - // - Status = CommitSetupPacket(SetupPacket, NULL, BufferLength, Mdl); - - if (Mdl != NULL) - { - // - // free mdl - // - IoFreeMdl(Mdl); - } - - // - // done - // - return Status; -} -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::BuildInterfaceDescriptor( - IN ULONG ConfigurationIndex, - IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, - OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo, - OUT PUSB_INTERFACE *OutUsbInterface) -{ - PUSB_INTERFACE UsbInterface; - PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor; - ULONG PipeIndex; - - // allocate interface handle - UsbInterface = (PUSB_INTERFACE)ExAllocatePool(NonPagedPool, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT)); - if (!UsbInterface) - { - // failed to allocate memory - return STATUS_INSUFFICIENT_RESOURCES; - } - - // zero descriptor - RtlZeroMemory(UsbInterface, sizeof(USB_INTERFACE) + (InterfaceDescriptor->bNumEndpoints - 1) * sizeof(USB_ENDPOINT)); - - // store handle - InterfaceInfo->InterfaceHandle = (USBD_INTERFACE_HANDLE)UsbInterface; - InterfaceInfo->Class = InterfaceDescriptor->bInterfaceClass; - InterfaceInfo->SubClass = InterfaceDescriptor->bInterfaceSubClass; - InterfaceInfo->Protocol = InterfaceDescriptor->bInterfaceProtocol; - InterfaceInfo->Reserved = 0; - - - // init interface handle - UsbInterface->InterfaceDescriptor = InterfaceDescriptor; - InsertTailList(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList, &UsbInterface->ListEntry); - - // grab first endpoint descriptor - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) (InterfaceDescriptor + 1); - - // now copy all endpoint information - for(PipeIndex = 0; PipeIndex < InterfaceDescriptor->bNumEndpoints; PipeIndex++) - { - while(EndpointDescriptor->bDescriptorType != USB_ENDPOINT_DESCRIPTOR_TYPE) - { - // skip intermediate descriptors - if (EndpointDescriptor->bLength == 0 || EndpointDescriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) - { - // bogus configuration descriptor - DPRINT1("[%s] Bogus descriptor found in InterfaceNumber %x Alternate %x EndpointIndex %x bLength %x bDescriptorType %x\n", m_USBType, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, PipeIndex, - EndpointDescriptor->bLength, EndpointDescriptor->bDescriptorType); - - // failed - return STATUS_UNSUCCESSFUL; - } - - // move to next descriptor - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength); - } - - // store in interface info - RtlCopyMemory(&UsbInterface->EndPoints[PipeIndex].EndPointDescriptor, EndpointDescriptor, sizeof(USB_ENDPOINT_DESCRIPTOR)); - - DPRINT("Configuration Descriptor %p Length %lu\n", m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->wTotalLength); - DPRINT("EndpointDescriptor %p DescriptorType %x bLength %x\n", EndpointDescriptor, EndpointDescriptor->bDescriptorType, EndpointDescriptor->bLength); - DPRINT("EndpointDescriptorHandle %p bAddress %x bmAttributes %x\n",&UsbInterface->EndPoints[PipeIndex], UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress, - UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes); - - // copy pipe info - InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.wMaxPacketSize; - InterfaceInfo->Pipes[PipeIndex].EndpointAddress = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress; - InterfaceInfo->Pipes[PipeIndex].Interval = UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval; - InterfaceInfo->Pipes[PipeIndex].PipeType = (USBD_PIPE_TYPE)UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bmAttributes; - InterfaceInfo->Pipes[PipeIndex].PipeHandle = (PVOID)&UsbInterface->EndPoints[PipeIndex]; - - // move to next descriptor - EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)((ULONG_PTR)EndpointDescriptor + EndpointDescriptor->bLength); - } - - if (OutUsbInterface) - { - // output result - *OutUsbInterface = UsbInterface; - } - return STATUS_SUCCESS; - -} - - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::SelectConfiguration( - IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, - IN PUSBD_INTERFACE_INFORMATION InterfaceInfo, - OUT USBD_CONFIGURATION_HANDLE *ConfigurationHandle) -{ - ULONG InterfaceIndex; - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - UCHAR bConfigurationValue = 0; - ULONG ConfigurationIndex = 0, Index; - UCHAR Found = FALSE; - PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - PUSB_INTERFACE UsbInterface; - PLIST_ENTRY Entry; - - if (ConfigurationDescriptor) - { - // find configuration index - for (Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++) - { - if (m_ConfigurationDescriptors[Index].ConfigurationDescriptor->bConfigurationValue == ConfigurationDescriptor->bConfigurationValue) - { - // found configuration index - ConfigurationIndex = Index; - Found = TRUE; - } - } - - if (!Found) - { - DPRINT1("[%s] invalid configuration value %u\n", m_USBType, ConfigurationDescriptor->bConfigurationValue); - return STATUS_INVALID_PARAMETER; - } - - // sanity check - ASSERT(ConfigurationDescriptor->bNumInterfaces <= m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor->bNumInterfaces); - - // get configuration value - bConfigurationValue = ConfigurationDescriptor->bConfigurationValue; - } - - // now build setup packet - RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - CtrlSetup.bRequest = USB_REQUEST_SET_CONFIGURATION; - CtrlSetup.wValue.W = bConfigurationValue; - - // select configuration - Status = CommitSetupPacket(&CtrlSetup, NULL, 0, NULL); - - if (!ConfigurationDescriptor) - { - // unconfigure request - DPRINT1("[%s] SelectConfiguration Unconfigure Request Status %lx\n", m_USBType, Status); - m_ConfigurationIndex = 0; - return Status; - } - - // informal debug print - DPRINT("[%s] SelectConfiguration New Configuration %x Old Configuration %x Result %lx\n", m_USBType, ConfigurationIndex, m_ConfigurationIndex, Status); - if (!NT_SUCCESS(Status)) - { - // - // failed - // - return Status; - } - - // destroy old interface info - while (!IsListEmpty(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList)) - { - // remove entry - Entry = RemoveHeadList(&m_ConfigurationDescriptors[m_ConfigurationIndex].InterfaceList); - - // get interface info - UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry); - - // free interface info - ExFreePool(UsbInterface); - } - - // sanity check - ASSERT(IsListEmpty(&m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList)); - - // store new configuration device index - m_ConfigurationIndex = ConfigurationIndex; - - // store configuration handle - *ConfigurationHandle = &m_ConfigurationDescriptors[ConfigurationIndex]; - - // copy interface info and pipe info - for(InterfaceIndex = 0; InterfaceIndex < ConfigurationDescriptor->bNumInterfaces; InterfaceIndex++) - { - // interface info checks - ASSERT(InterfaceInfo->Length != 0); - -#ifdef _MSC_VER - PC_ASSERT(InterfaceInfo->Length == FIELD_OFFSET(USBD_INTERFACE_INFORMATION, Pipes[InterfaceInfo->NumberOfPipes])); -#endif - - // find interface descriptor - InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting); - - // sanity checks - ASSERT(InterfaceDescriptor != NULL); - - // check if the number of pipes have been properly set - ASSERT(InterfaceInfo->NumberOfPipes == InterfaceDescriptor->bNumEndpoints); - - // copy interface info - Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, NULL); - if (!NT_SUCCESS(Status)) - { - // failed - DPRINT1("[%s] Failed to copy interface descriptor Index %lu InterfaceDescriptor %p InterfaceInfo %p\n", m_USBType, ConfigurationIndex, InterfaceDescriptor, InterfaceInfo); - break; - } - - // move offset - InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length); - } - - // - // done - // - return Status; -} - -//---------------------------------------------------------------------------------------- -NTSTATUS -CUSBDevice::SelectInterface( - IN USBD_CONFIGURATION_HANDLE ConfigurationHandle, - IN OUT PUSBD_INTERFACE_INFORMATION InterfaceInfo) -{ - ULONG PipeIndex; - USB_DEFAULT_PIPE_SETUP_PACKET CtrlSetup; - NTSTATUS Status; - ULONG Index, ConfigurationIndex = 0, Found = FALSE; - PUSB_INTERFACE UsbInterface; - PLIST_ENTRY Entry; - PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor; - - // check if handle is valid - for(Index = 0; Index < m_DeviceDescriptor.bNumConfigurations; Index++) - { - if (&m_ConfigurationDescriptors[Index] == ConfigurationHandle) - { - // found configuration index - ConfigurationIndex = Index; - Found = TRUE; - } - } - - if (!Found) - { - // invalid handle passed - DPRINT1("[%s] Invalid configuration handle passed %p\n", m_USBType, ConfigurationHandle); - return STATUS_INVALID_PARAMETER; - } - - // initialize setup packet - RtlZeroMemory(&CtrlSetup, sizeof(USB_DEFAULT_PIPE_SETUP_PACKET)); - CtrlSetup.bRequest = USB_REQUEST_SET_INTERFACE; - CtrlSetup.wValue.W = InterfaceInfo->AlternateSetting; - CtrlSetup.wIndex.W = InterfaceInfo->InterfaceNumber; - CtrlSetup.bmRequestType.B = 0x01; - - // issue request - Status = CommitSetupPacket(&CtrlSetup, NULL, 0, NULL); - - // informal debug print - DPRINT1("[%s] SelectInterface AlternateSetting %x InterfaceNumber %x Status %lx\n", m_USBType, InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber, Status); -#if 0 - if (!NT_SUCCESS(Status)) - { - // failed to select interface - return Status; - } -#endif - - Status = STATUS_SUCCESS; - - // find interface - Found = FALSE; - Entry = m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList.Flink; - while (Entry != &m_ConfigurationDescriptors[ConfigurationIndex].InterfaceList) - { - // grab interface descriptor - UsbInterface = (PUSB_INTERFACE)CONTAINING_RECORD(Entry, USB_INTERFACE, ListEntry); - if (UsbInterface->InterfaceDescriptor->bAlternateSetting == InterfaceInfo->AlternateSetting && - UsbInterface->InterfaceDescriptor->bInterfaceNumber == InterfaceInfo->InterfaceNumber) - { - // found interface - Found = TRUE; - break; - } - - // next entry - Entry = Entry->Flink; - } - - if (!Found) - { - // find interface descriptor - InterfaceDescriptor = USBD_ParseConfigurationDescriptor(m_ConfigurationDescriptors[ConfigurationIndex].ConfigurationDescriptor, InterfaceInfo->InterfaceNumber, InterfaceInfo->AlternateSetting); - if (!InterfaceDescriptor) - { - DPRINT1("[%s] No such interface Alternate %x InterfaceNumber %x\n", m_USBType, InterfaceInfo->AlternateSetting, InterfaceInfo->InterfaceNumber); - return STATUS_UNSUCCESSFUL; - } - - // build interface descriptor - Status = BuildInterfaceDescriptor(ConfigurationIndex, InterfaceDescriptor, InterfaceInfo, &UsbInterface); - if (!NT_SUCCESS(Status)) - { - // failed - DPRINT1("[%s] Failed to build interface descriptor Status %x\n", m_USBType, Status); - return Status; - } - } - - // assert on pipe length mismatch - DPRINT1("NumberOfPipes %lu Endpoints %lu Length %lu\n", InterfaceInfo->NumberOfPipes, UsbInterface->InterfaceDescriptor->bNumEndpoints, InterfaceInfo->Length); - - // sanity check - ASSERT(GET_USBD_INTERFACE_SIZE(UsbInterface->InterfaceDescriptor->bNumEndpoints) == InterfaceInfo->Length); - - // store number of pipes - InterfaceInfo->NumberOfPipes = UsbInterface->InterfaceDescriptor->bNumEndpoints; - - // copy pipe handles - for (PipeIndex = 0; PipeIndex < UsbInterface->InterfaceDescriptor->bNumEndpoints; PipeIndex++) - { - // copy pipe handle - DPRINT1("PipeIndex %lu\n", PipeIndex); - DPRINT1("EndpointAddress %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress); - DPRINT1("Interval %c\n", InterfaceInfo->Pipes[PipeIndex].Interval); - DPRINT1("MaximumPacketSize %hu\n", InterfaceInfo->Pipes[PipeIndex].MaximumPacketSize); - DPRINT1("MaximumTransferSize %lu\n", InterfaceInfo->Pipes[PipeIndex].MaximumTransferSize); - DPRINT1("PipeFlags %lu\n", InterfaceInfo->Pipes[PipeIndex].PipeFlags); - DPRINT1("PipeType %d\n", InterfaceInfo->Pipes[PipeIndex].PipeType); - DPRINT1("UsbEndPoint %x\n", InterfaceInfo->Pipes[PipeIndex].EndpointAddress); - - // sanity checks - ASSERT(InterfaceInfo->Pipes[PipeIndex].EndpointAddress == UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bEndpointAddress); - ASSERT(InterfaceInfo->Pipes[PipeIndex].Interval == UsbInterface->EndPoints[PipeIndex].EndPointDescriptor.bInterval); - - // store pipe handle - InterfaceInfo->Pipes[PipeIndex].PipeHandle = &UsbInterface->EndPoints[PipeIndex]; - - // data toggle is reset on select interface requests - UsbInterface->EndPoints[PipeIndex].DataToggle = FALSE; - } - - // - // done - // - return Status; -} - -NTSTATUS -CUSBDevice::AbortPipe( - IN PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor) -{ - // - // let it handle usb queue - // - ASSERT(m_Queue); - ASSERT(m_DeviceAddress); - - // - // done - // - return m_Queue->AbortDevicePipe(m_DeviceAddress, EndpointDescriptor); -} - -UCHAR -CUSBDevice::GetMaxPacketSize() -{ - return m_DeviceDescriptor.bMaxPacketSize0; -} - - -//---------------------------------------------------------------------------------------- -NTSTATUS -NTAPI -CreateUSBDevice( - PUSBDEVICE *OutDevice) -{ - CUSBDevice * This; - - // - // allocate controller - // - This = new(NonPagedPool, TAG_USBLIB) CUSBDevice(0); - if (!This) - { - // - // failed to allocate - // - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // add reference count - // - This->AddRef(); - - // - // return result - // - *OutDevice = (PUSBDEVICE)This; - - // - // done - // - return STATUS_SUCCESS; -} -