mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[SDK][USB] Delete old USB drivers and libusb
This commit is contained in:
parent
0685e02d9e
commit
83c07f4e4c
52 changed files with 0 additions and 26396 deletions
|
@ -275,7 +275,6 @@
|
||||||
# R: Extravert-ir, extravert34, Victor Perevertkin
|
# R: Extravert-ir, extravert34, Victor Perevertkin
|
||||||
# S: Maintained
|
# S: Maintained
|
||||||
/drivers/usb/ @ThFabba @Extravert-ir
|
/drivers/usb/ @ThFabba @Extravert-ir
|
||||||
/sdk/lib/drivers/libusb/ @ThFabba @Extravert-ir
|
|
||||||
/sdk/include/reactos/drivers/usbport/ @ThFabba @Extravert-ir
|
/sdk/include/reactos/drivers/usbport/ @ThFabba @Extravert-ir
|
||||||
|
|
||||||
# Virtual CD-ROM
|
# Virtual CD-ROM
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
add_subdirectory(usbccgp)
|
add_subdirectory(usbccgp)
|
||||||
add_subdirectory(usbd)
|
add_subdirectory(usbd)
|
||||||
#add_subdirectory(usbehci)
|
|
||||||
add_subdirectory(usbehci_new)
|
add_subdirectory(usbehci_new)
|
||||||
#add_subdirectory(usbhub)
|
|
||||||
add_subdirectory(usbhub_new)
|
add_subdirectory(usbhub_new)
|
||||||
#add_subdirectory(usbohci)
|
|
||||||
add_subdirectory(usbohci_new)
|
add_subdirectory(usbohci_new)
|
||||||
add_subdirectory(usbport)
|
add_subdirectory(usbport)
|
||||||
add_subdirectory(usbstor)
|
add_subdirectory(usbstor)
|
||||||
#add_subdirectory(usbstor_new)
|
#add_subdirectory(usbstor_new)
|
||||||
#add_subdirectory(usbuhci)
|
|
||||||
add_subdirectory(usbuhci_new)
|
add_subdirectory(usbuhci_new)
|
||||||
|
|
|
@ -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)
|
|
|
@ -1,9 +0,0 @@
|
||||||
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
|
|
||||||
|
|
||||||
#include <wdm.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <wdmguid.h>
|
|
||||||
#include <hubbusif.h>
|
|
||||||
#include <usbbusif.h>
|
|
||||||
|
|
||||||
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
|
@ -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 */
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#ifndef USBEHCI_H__
|
|
||||||
#define USBEHCI_H__
|
|
||||||
|
|
||||||
#include <libusb.h>
|
|
||||||
|
|
||||||
#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__ */
|
|
|
@ -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 <reactos/version.rc>
|
|
|
@ -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)
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +0,0 @@
|
||||||
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
|
|
||||||
|
|
||||||
#include <wdm.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <wdmguid.h>
|
|
||||||
#include <hubbusif.h>
|
|
||||||
#include <usbbusif.h>
|
|
||||||
|
|
||||||
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
|
|
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -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 <wdmguid.h>
|
|
||||||
|
|
||||||
#define NDEBUG
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,225 +0,0 @@
|
||||||
#ifndef _USBHUB_H_
|
|
||||||
#define _USBHUB_H_
|
|
||||||
|
|
||||||
#include <wdm.h>
|
|
||||||
#include <hubbusif.h>
|
|
||||||
#include <usbbusif.h>
|
|
||||||
#include <usbdlib.h>
|
|
||||||
|
|
||||||
#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_ */
|
|
|
@ -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 <reactos/version.rc>
|
|
|
@ -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)
|
|
|
@ -1,9 +0,0 @@
|
||||||
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
|
|
||||||
|
|
||||||
#include <wdm.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <wdmguid.h>
|
|
||||||
#include <hubbusif.h>
|
|
||||||
#include <usbbusif.h>
|
|
||||||
|
|
||||||
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
|
@ -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 */
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
#ifndef USBOHCI_H__
|
|
||||||
#define USBOHCI_H__
|
|
||||||
|
|
||||||
#include <libusb.h>
|
|
||||||
|
|
||||||
#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__ */
|
|
|
@ -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 <reactos/version.rc>
|
|
|
@ -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)
|
|
|
@ -1,9 +0,0 @@
|
||||||
/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */
|
|
||||||
|
|
||||||
#include <wdm.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <wdmguid.h>
|
|
||||||
#include <hubbusif.h>
|
|
||||||
#include <usbbusif.h>
|
|
||||||
|
|
||||||
/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,191 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2004-2006, Haiku Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Michael Lotz <mmlr@mlotz.ch>
|
|
||||||
* 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 */
|
|
|
@ -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 */
|
|
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
#ifndef USBUHCI_H__
|
|
||||||
#define USBUHCI_H__
|
|
||||||
|
|
||||||
#include <libusb.h>
|
|
||||||
|
|
||||||
#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__ */
|
|
|
@ -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 <reactos/version.rc>
|
|
|
@ -4,7 +4,6 @@ add_subdirectory(copysup)
|
||||||
add_subdirectory(csq)
|
add_subdirectory(csq)
|
||||||
add_subdirectory(hidparser)
|
add_subdirectory(hidparser)
|
||||||
add_subdirectory(ip)
|
add_subdirectory(ip)
|
||||||
add_subdirectory(libusb)
|
|
||||||
add_subdirectory(lwip)
|
add_subdirectory(lwip)
|
||||||
add_subdirectory(ntoskrnl_vista)
|
add_subdirectory(ntoskrnl_vista)
|
||||||
add_subdirectory(rdbsslib)
|
add_subdirectory(rdbsslib)
|
||||||
|
|
|
@ -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)
|
|
|
@ -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
|
|
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
#ifndef LIBUSB_H__
|
|
||||||
#define LIBUSB_H__
|
|
||||||
|
|
||||||
#include <ntddk.h>
|
|
||||||
#include <hubbusif.h>
|
|
||||||
#include <usbbusif.h>
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include <usbdlib.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME:
|
|
||||||
// #include <usbprotocoldefs.h>
|
|
||||||
//
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <wdmguid.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// FIXME:
|
|
||||||
// the following includes are required to get kcom to compile
|
|
||||||
//
|
|
||||||
#include <portcls.h>
|
|
||||||
#include <kcom.h>
|
|
||||||
|
|
||||||
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__ */
|
|
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 <debug.h>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
void
|
|
||||||
__cxa_pure_virtual()
|
|
||||||
{
|
|
||||||
// put error handling here
|
|
||||||
|
|
||||||
DbgBreakPoint();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue