Initial Contribution
diff --git a/host/Android.mk b/host/Android.mk
new file mode 100644
index 0000000..5e318e1
--- /dev/null
+++ b/host/Android.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(my-dir)
+
+dir := $(wildcard $(LOCAL_PATH)/$(HOST_PREBUILT_TAG))
+ifdef dir
+  include $(call first-makefiles-under,$(dir))
+endif
diff --git a/host/windows/prebuilt/AdbWinApi.dll b/host/windows/prebuilt/AdbWinApi.dll
new file mode 100644
index 0000000..aa8e956
--- /dev/null
+++ b/host/windows/prebuilt/AdbWinApi.dll
Binary files differ
diff --git a/host/windows/prebuilt/adb.exe b/host/windows/prebuilt/adb.exe
new file mode 100755
index 0000000..4cba503
--- /dev/null
+++ b/host/windows/prebuilt/adb.exe
Binary files differ
diff --git a/host/windows/prebuilt/javawrap.exe b/host/windows/prebuilt/javawrap.exe
new file mode 100755
index 0000000..d42ac2b
--- /dev/null
+++ b/host/windows/prebuilt/javawrap.exe
Binary files differ
diff --git a/host/windows/prebuilt/usb/AdbWinApi.a b/host/windows/prebuilt/usb/AdbWinApi.a
new file mode 100644
index 0000000..93ccd66
--- /dev/null
+++ b/host/windows/prebuilt/usb/AdbWinApi.a
Binary files differ
diff --git a/host/windows/prebuilt/usb/AdbWinApi.def b/host/windows/prebuilt/usb/AdbWinApi.def
new file mode 100644
index 0000000..1894148
--- /dev/null
+++ b/host/windows/prebuilt/usb/AdbWinApi.def
@@ -0,0 +1,15 @@
+LIBRARY AdbWinApi.dll
+EXPORTS
+AdbEnumInterfaces
+AdbNextInterface
+AdbCreateInterfaceByName
+AdbOpenDefaultBulkReadEndpoint
+AdbOpenDefaultBulkWriteEndpoint
+AdbCloseHandle
+AdbGetInterfaceName
+AdbWriteEndpointSync
+AdbReadEndpointSync
+AdbGetSerialNumber
+AdbGetUsbInterfaceDescriptor
+AdbGetUsbDeviceDescriptor
+AdbGetEndpointInformation
diff --git a/host/windows/prebuilt/usb/AdbWinApi.dll b/host/windows/prebuilt/usb/AdbWinApi.dll
new file mode 100755
index 0000000..aa8e956
--- /dev/null
+++ b/host/windows/prebuilt/usb/AdbWinApi.dll
Binary files differ
diff --git a/host/windows/prebuilt/usb/Android.mk b/host/windows/prebuilt/usb/Android.mk
new file mode 100644
index 0000000..1806101
--- /dev/null
+++ b/host/windows/prebuilt/usb/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_LIBS := \
+	AdbWinApi.a
+
+LOCAL_PREBUILT_EXECUTABLES := \
+	AdbWinApi.dll
+	
+.PHONY : kill-adb
+	
+$(LOCAL_PATH)/AdbWinApi.dll : kill-adb
+
+kill-adb:
+	@echo "Killing adb server so we can replace AdbWinApi.dll"
+	@adb kill-server || echo "adb appears to be missing"
+
+# generate AdbWinApi stub library
+#$(LOCAL_PATH)/AdbWinApi.a: $(LOCAL_PATH)/AdbWinApi.def
+#	dlltool --def $(LOCAL_PATH)/AdbWinApi.def --dllname AdbWinApi.dll --output-lib $(LOCAL_PATH)/AdbWinApi.a
+
+include $(BUILD_HOST_PREBUILT)
diff --git a/host/windows/prebuilt/usb/driver/WdfCoInstaller01005.dll b/host/windows/prebuilt/usb/driver/WdfCoInstaller01005.dll
new file mode 100644
index 0000000..12d2768
--- /dev/null
+++ b/host/windows/prebuilt/usb/driver/WdfCoInstaller01005.dll
Binary files differ
diff --git a/host/windows/prebuilt/usb/driver/android_usb.inf b/host/windows/prebuilt/usb/driver/android_usb.inf
new file mode 100644
index 0000000..69a9491
--- /dev/null
+++ b/host/windows/prebuilt/usb/driver/android_usb.inf
@@ -0,0 +1,113 @@
+;/*++
+;
+;Abstract:
+;    Installation inf for the Android USB Bulk device
+;
+;--*/
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=USB
+ClassGuid={F72FE0D4-CBCB-407d-8814-9ED673D0DD6B}
+Provider=%GOOG%
+DriverVer=date,1.0.0009.00000
+CatalogFile=androidusb.cat
+
+; ================= Class section =====================
+
+[ClassInstall32]
+Addreg=AndroidUsbClassReg
+
+[AndroidUsbClassReg]
+HKR,,,0,%ClassName%
+HKR,,Icon,,-5
+
+[DestinationDirs]
+DefaultDestDir = 12
+
+; ================= Device section =====================
+
+[Manufacturer]
+%MfgName%=Google,NTx86
+
+; For Win2K
+[Google]
+; For loopback testing
+%USB\VID_18D1&PID_DDDD.DeviceDescTest%=androidusb.Dev, USB\VID_18D1&PID_DDDD
+; HTC Dream
+%USB\VID_0BB4&PID_0C01.DeviceDescRelease%=androidusb.Dev, USB\VID_0BB4&PID_0C01
+%USB\VID_0BB4&PID_0C02&MI_01.DeviceDescRelease%=androidusb.Dev, USB\VID_0BB4&PID_0C02&MI_01
+
+; For XP and later
+[Google.NTx86]
+; For loopback testing
+%USB\VID_18D1&PID_DDDD.DeviceDescTest%=androidusb.Dev, USB\VID_18D1&PID_DDDD
+; HTC Dream
+%USB\VID_0BB4&PID_0C01.DeviceDescRelease%=androidusb.Dev, USB\VID_0BB4&PID_0C01
+%USB\VID_0BB4&PID_0C02&MI_01.DeviceDescRelease%=androidusb.Dev, USB\VID_0BB4&PID_0C02&MI_01
+
+[androidusb.Dev.NT]
+CopyFiles=androidusb.Files.Ext
+
+[androidusb.Dev.NT.Services]
+Addservice = androidusb, 0x00000002, androidusb.AddService
+
+[androidusb.AddService]
+DisplayName    = %androidusb.SvcDesc%
+ServiceType    = 1                  ; SERVICE_KERNEL_DRIVER
+StartType      = 3                  ; SERVICE_DEMAND_START
+ErrorControl   = 1                  ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %10%\System32\Drivers\androidusb.sys
+AddReg         = androidusb.AddReg
+LoadOrderGroup = Base
+
+[androidusb.AddReg]
+HKR,"Parameters","MaximumTransferSize",0x10001,4096
+HKR,"Parameters","DebugLevel",0x10001,2
+HKR, Parameters\Wdf, VerboseOn,       0x00010001, 1
+HKR, Parameters\Wdf, VerifierOn,      0x00010001, 1
+HKR, Parameters\Wdf, DbgBreakOnError, 0x00010001, 1
+
+[androidusb.Files.Ext]
+androidusb.sys
+
+[SourceDisksNames]
+1=%Disk_Description%,,,
+
+[SourceDisksFiles]
+androidusb.sys = 1
+
+;-------------- WDF Coinstaller installation
+[DestinationDirs]
+CoInstaller_CopyFiles = 11
+
+[androidusb.Dev.NT.CoInstallers]
+AddReg=CoInstaller_AddReg
+CopyFiles=CoInstaller_CopyFiles
+
+[CoInstaller_CopyFiles]
+wdfcoinstaller01005.dll
+
+[SourceDisksFiles]
+wdfcoinstaller01005.dll=1 ; make sure the number matches with SourceDisksNames
+
+[CoInstaller_AddReg]
+HKR,,CoInstallers32,0x00010000, "wdfcoinstaller01005.dll,WdfCoInstaller"
+
+[androidusb.Dev.NT.Wdf]
+KmdfService = androidusb, androidusb_wdfsect
+
+[androidusb_wdfsect]
+KmdfLibraryVersion = 1.5
+
+;---------------------------------------------------------------;
+
+[Strings]
+GOOG            = "Google, Inc"
+MfgName         = "Google, Inc"
+Disk_Description= "ADB Interface Installation Disk"
+androidusb.SvcDesc = "ADB Interface Driver"
+ClassName       = "ADB Interface"
+USB\VID_18D1&PID_DDDD.DeviceDescTest="ADB Testing Interface"
+USB\VID_0BB4&PID_0C01.DeviceDescRelease="HTC Dream"
+USB\VID_0BB4&PID_0C02&MI_01.DeviceDescRelease="HTC Dream Composite ADB Interface"
diff --git a/host/windows/prebuilt/usb/driver/androidusb.sys b/host/windows/prebuilt/usb/driver/androidusb.sys
new file mode 100644
index 0000000..ebd01b8
--- /dev/null
+++ b/host/windows/prebuilt/usb/driver/androidusb.sys
Binary files differ
diff --git a/host/windows/usb/api/AdbWinApi.cpp b/host/windows/usb/api/AdbWinApi.cpp
new file mode 100644
index 0000000..c7e5303
--- /dev/null
+++ b/host/windows/usb/api/AdbWinApi.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// AdbWinApi.cpp : Implementation of DLL Exports.
+
+#include "stdafx.h"
+
+class CAdbWinApiModule : public CAtlDllModuleT< CAdbWinApiModule > {
+public:
+};
+
+CAdbWinApiModule _AtlModule;
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE instance,
+                               DWORD reason,
+                               LPVOID reserved) {
+    return _AtlModule.DllMain(reason, reserved); 
+}
diff --git a/host/windows/usb/api/AdbWinApi.def b/host/windows/usb/api/AdbWinApi.def
new file mode 100644
index 0000000..d55786e
--- /dev/null
+++ b/host/windows/usb/api/AdbWinApi.def
@@ -0,0 +1,5 @@
+; AdbWinApi.def : Declares the module parameters.
+
+LIBRARY      "AdbWinApi.DLL"
+
+EXPORTS
diff --git a/host/windows/usb/api/AdbWinApi.rc b/host/windows/usb/api/AdbWinApi.rc
new file mode 100644
index 0000000..013ea03
--- /dev/null
+++ b/host/windows/usb/api/AdbWinApi.rc
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE  
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE  
+BEGIN
+    "#include ""winres.h""\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904e4"
+        BEGIN
+            VALUE "CompanyName", "Google, inc"
+            VALUE "FileDescription", "TODO: <File description>"
+            VALUE "FileVersion", "1.0.0.1"
+            VALUE "LegalCopyright", "Copyright (C) 2006 The Android Open Source Project"
+            VALUE "InternalName", "AdbWinApi.dll"
+            VALUE "OriginalFilename", "AdbWinApi.dll"
+            VALUE "ProductName", "TODO: <Product name>"
+            VALUE "ProductVersion", "1.0.0.1"
+            VALUE "OLESelfRegister", ""
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+		VALUE "Translation", 0x0409, 1252
+    END
+END
+
+#endif    // !_MAC
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE  
+BEGIN
+	IDS_PROJNAME					"AdbWinApi"
+END
+
+////////////////////////////////////////////////////////////////////////////
+
+
+#endif
+
+#ifndef APSTUDIO_INVOKED
+#endif    // not APSTUDIO_INVOKED
diff --git a/host/windows/usb/api/AdbWinApi.sln b/host/windows/usb/api/AdbWinApi.sln
new file mode 100644
index 0000000..f6f4fc0
--- /dev/null
+++ b/host/windows/usb/api/AdbWinApi.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdbWinApi", "AdbWinApi.vcproj", "{C0A471E9-6892-4270-96DE-DB5F8D526FB1}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Debug.ActiveCfg = Debug|Win32
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Debug.Build.0 = Debug|Win32
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Release.ActiveCfg = Release|Win32
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
diff --git a/host/windows/usb/api/AdbWinApi.vcproj b/host/windows/usb/api/AdbWinApi.vcproj
new file mode 100644
index 0000000..f9d15e5
--- /dev/null
+++ b/host/windows/usb/api/AdbWinApi.vcproj
@@ -0,0 +1,290 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="AdbWinApi"

+	ProjectGUID="{C0A471E9-6892-4270-96DE-DB5F8D526FB1}"

+	Keyword="AtlProj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="2"

+			UseOfATL="1"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE"

+			CharacterSet="1">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="c:\winddk\6000\inc\api;..\common"

+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL;ADBWIN_EXPORTS"

+				MinimalRebuild="FALSE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				BufferSecurityCheck="TRUE"

+				TreatWChar_tAsBuiltInType="TRUE"

+				UsePrecompiledHeader="3"

+				ProgramDataBaseFileName="..\build\$(OutDir)\i386\$(TargetName).pdb"

+				WarningLevel="4"

+				WarnAsError="TRUE"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="4"

+				DisableSpecificWarnings="4100;4200;4702"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				IgnoreImportLibrary="TRUE"

+				AdditionalDependencies="c:\winddk\6000\lib\wxp\i386\usbd.lib setupapi.lib"

+				OutputFile="..\build\$(OutDir)\i386/AdbWinApi.dll"

+				LinkIncremental="2"

+				AdditionalLibraryDirectories=""

+				ModuleDefinitionFile=".\AdbWinApi.def"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="..\build\$(OutDir)\i386/$(ProjectName).pdb"

+				SubSystem="2"

+				ImportLibrary="..\build\$(OutDir)\i386/AdbWinApi.lib"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="_DEBUG"

+				MkTypLibCompatible="FALSE"

+				TargetEnvironment="1"

+				GenerateStublessProxies="TRUE"

+				TypeLibraryName="$(IntDir)/AdbWinApi.tlb"

+				HeaderFileName="AdbWinApi.h"

+				DLLDataFileName=""

+				InterfaceIdentifierFileName="AdbWinApi_i.c"

+				ProxyFileName="AdbWinApi_p.c"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="_DEBUG"

+				Culture="1033"

+				AdditionalIncludeDirectories="$(IntDir)"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="Release"

+			IntermediateDirectory="Release"

+			ConfigurationType="2"

+			UseOfATL="1"

+			ATLMinimizesCRunTimeLibraryUsage="FALSE"

+			CharacterSet="1">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="4"

+				InlineFunctionExpansion="2"

+				AdditionalIncludeDirectories="c:\winddk\6000\inc\api;..\common"

+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL;ADBWIN_EXPORTS"

+				MinimalRebuild="FALSE"

+				RuntimeLibrary="0"

+				BufferSecurityCheck="TRUE"

+				TreatWChar_tAsBuiltInType="TRUE"

+				UsePrecompiledHeader="3"

+				ProgramDataBaseFileName="..\build\$(OutDir)\i386\$(TargetName).pdb"

+				WarningLevel="4"

+				WarnAsError="TRUE"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="3"

+				DisableSpecificWarnings="4100;4200;4702"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				IgnoreImportLibrary="TRUE"

+				AdditionalDependencies="c:\winddk\6000\lib\wxp\i386\usbd.lib setupapi.lib"

+				OutputFile="..\build\$(OutDir)\i386/AdbWinApi.dll"

+				LinkIncremental="1"

+				AdditionalLibraryDirectories=""

+				ModuleDefinitionFile=".\AdbWinApi.def"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="..\build\$(OutDir)\i386/$(ProjectName).pdb"

+				SubSystem="2"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				ImportLibrary="..\build\$(OutDir)\i386/AdbWinApi.lib"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"

+				PreprocessorDefinitions="NDEBUG"

+				MkTypLibCompatible="FALSE"

+				TargetEnvironment="1"

+				GenerateStublessProxies="TRUE"

+				TypeLibraryName="$(IntDir)/AdbWinApi.tlb"

+				HeaderFileName="AdbWinApi.h"

+				DLLDataFileName=""

+				InterfaceIdentifierFileName="AdbWinApi_i.c"

+				ProxyFileName="AdbWinApi_p.c"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"

+				PreprocessorDefinitions="NDEBUG"

+				Culture="1033"

+				AdditionalIncludeDirectories="$(IntDir)"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath=".\adb_api.cpp">

+			</File>

+			<File

+				RelativePath=".\adb_endpoint_object.cpp">

+			</File>

+			<File

+				RelativePath=".\adb_helper_routines.cpp">

+			</File>

+			<File

+				RelativePath=".\adb_interface.cpp">

+			</File>

+			<File

+				RelativePath=".\adb_interface_enum.cpp">

+			</File>

+			<File

+				RelativePath=".\adb_io_completion.cpp">

+			</File>

+			<File

+				RelativePath=".\adb_io_object.cpp">

+			</File>

+			<File

+				RelativePath=".\adb_object_handle.cpp">

+			</File>

+			<File

+				RelativePath=".\AdbWinApi.cpp">

+			</File>

+			<File

+				RelativePath=".\AdbWinApi.def">

+			</File>

+			<File

+				RelativePath=".\stdafx.cpp">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="1"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="1"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+			<File

+				RelativePath=".\adb_api.h">

+			</File>

+			<File

+				RelativePath=".\adb_api_private_defines.h">

+			</File>

+			<File

+				RelativePath=".\adb_endpoint_object.h">

+			</File>

+			<File

+				RelativePath=".\adb_helper_routines.h">

+			</File>

+			<File

+				RelativePath=".\adb_interface.h">

+			</File>

+			<File

+				RelativePath=".\adb_interface_enum.h">

+			</File>

+			<File

+				RelativePath=".\adb_io_completion.h">

+			</File>

+			<File

+				RelativePath=".\adb_io_object.h">

+			</File>

+			<File

+				RelativePath=".\adb_object_handle.h">

+			</File>

+			<File

+				RelativePath=".\Resource.h">

+			</File>

+			<File

+				RelativePath=".\stdafx.h">

+			</File>

+			<Filter

+				Name="common"

+				Filter="">

+				<File

+					RelativePath=".\adb_api_extra.h">

+				</File>

+				<File

+					RelativePath="..\common\android_usb_common_defines.h">

+				</File>

+			</Filter>

+			<Filter

+				Name="USB"

+				Filter="">

+				<File

+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\usb.h">

+				</File>

+				<File

+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\usb100.h">

+				</File>

+				<File

+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\usb200.h">

+				</File>

+				<File

+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\usbdi.h">

+				</File>

+			</Filter>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">

+			<File

+				RelativePath=".\AdbWinApi.rc">

+			</File>

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/host/windows/usb/api/Resource.h b/host/windows/usb/api/Resource.h
new file mode 100644
index 0000000..fd2b2f9
--- /dev/null
+++ b/host/windows/usb/api/Resource.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by AdbWinApi.rc
+//
+
+#define IDS_PROJNAME                    100
+#define IDR_ADBWINAPI	101
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        201
+#define _APS_NEXT_COMMAND_VALUE         32768
+#define _APS_NEXT_CONTROL_VALUE         201
+#define _APS_NEXT_SYMED_VALUE           102
+#endif
+#endif
diff --git a/host/windows/usb/api/adb_api.cpp b/host/windows/usb/api/adb_api.cpp
new file mode 100644
index 0000000..50356c7
--- /dev/null
+++ b/host/windows/usb/api/adb_api.cpp
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of rotines that are exported
+  from this DLL.
+*/
+
+#include "stdafx.h"
+#include "adb_api.h"
+#include "adb_object_handle.h"
+#include "adb_interface_enum.h"
+#include "adb_interface.h"
+#include "adb_endpoint_object.h"
+#include "adb_io_completion.h"
+#include "adb_helper_routines.h"
+
+ADBAPIHANDLE AdbEnumInterfaces(GUID class_id,
+                               bool exclude_not_present,
+                               bool exclude_removed,
+                               bool active_only) {
+  AdbInterfaceEnumObject* enum_obj = NULL;
+  ADBAPIHANDLE ret = NULL;
+
+  try {
+    // Instantiate and initialize enum object
+    enum_obj = new AdbInterfaceEnumObject();
+
+    if (enum_obj->InitializeEnum(class_id,
+                                 exclude_not_present,
+                                 exclude_removed,
+                                 active_only)) {
+      // After successful initialization we can create handle.
+      ret = enum_obj->CreateHandle();
+    }
+  } catch (...) {
+    SetLastError(ERROR_OUTOFMEMORY);
+  }
+
+  if (NULL != enum_obj)
+    enum_obj->Release();
+
+  return ret;
+}
+
+bool AdbNextInterface(ADBAPIHANDLE adb_handle,
+                      AdbInterfaceInfo* info,
+                      unsigned long* size) {
+  if (NULL == size) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return false;
+  }
+
+  // Lookup AdbInterfaceEnumObject object for the handle
+  AdbInterfaceEnumObject* adb_ienum_object =
+    LookupObject<AdbInterfaceEnumObject>(adb_handle);
+  if (NULL == adb_ienum_object)
+    return false;
+
+  // Everything is verified. Pass it down to the object
+  bool ret = adb_ienum_object->Next(info, size);
+
+  adb_ienum_object->Release();
+
+  return ret;
+}
+
+bool AdbResetInterfaceEnum(ADBAPIHANDLE adb_handle) {
+  // Lookup AdbInterfaceEnumObject object for the handle
+  AdbInterfaceEnumObject* adb_ienum_object =
+    LookupObject<AdbInterfaceEnumObject>(adb_handle);
+  if (NULL == adb_ienum_object)
+    return false;
+
+  // Everything is verified. Pass it down to the object
+  bool ret = adb_ienum_object->Reset();
+
+  adb_ienum_object->Release();
+
+  return ret;
+}
+
+ADBWIN_API ADBAPIHANDLE AdbCreateInterfaceByName(
+    const wchar_t* interface_name) {
+  AdbInterfaceObject* obj = NULL;
+  ADBAPIHANDLE ret = NULL;
+
+  try {
+    // Instantiate object
+    obj = new AdbInterfaceObject(interface_name);
+
+    // Create handle for it
+    ret = obj->CreateHandle();
+  } catch (...) {
+    SetLastError(ERROR_OUTOFMEMORY);
+  }
+
+  if (NULL != obj)
+    obj->Release();
+
+  return ret;
+}
+
+ADBAPIHANDLE AdbCreateInterface(GUID class_id,
+                                unsigned short vendor_id,
+                                unsigned short product_id,
+                                unsigned char interface_id) {
+  // Enumerate all active interfaces for the given class
+  AdbEnumInterfaceArray interfaces;
+
+  if (!EnumerateDeviceInterfaces(class_id,
+                                 DIGCF_DEVICEINTERFACE | DIGCF_PRESENT,
+                                 true,
+                                 true,
+                                 &interfaces)) {
+    return NULL;
+  }
+
+  if (interfaces.empty()) {
+    SetLastError(ERROR_DEVICE_NOT_AVAILABLE);
+    return NULL;
+  }
+
+  // Now iterate over active interfaces looking for the name match.
+  // The name is formatted as such:
+  // "\\\\?\\usb#vid_xxxx&pid_xxxx&mi_xx#123456789abcdef#{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
+  // where
+  //    vid_xxxx is for the vendor id (xxxx are hex for the given vendor id),
+  //    pid_xxxx is for the product id (xxxx are hex for the given product id)
+  //    mi_xx is for the interface id  (xx are hex for the given interface id)
+  // EnumerateDeviceInterfaces will guarantee that returned interface names
+  // will have our class id at the end of the name (those last XXXes in the
+  // format). So, we only need to match the beginning of the name
+  wchar_t match_name[64];
+  if (0xFF == interface_id) {
+    // No interface id for the name.
+    swprintf(match_name, L"\\\\?\\usb#vid_%04x&pid_%04x#",
+             vendor_id, product_id);
+  } else {
+    // With interface id for the name.
+    swprintf(match_name, L"\\\\?\\usb#vid_%04x&pid_%04x&mi_%02x#",
+             vendor_id, product_id, interface_id);
+  }
+  size_t match_len = wcslen(match_name);
+
+  for (AdbEnumInterfaceArray::iterator it = interfaces.begin();
+       it != interfaces.end(); it++) {
+    const AdbInstanceEnumEntry& next_interface = *it;
+    if (0 == wcsnicmp(match_name,
+                      next_interface.device_name().c_str(),
+                      match_len)) {
+      // Found requested interface among active interfaces.
+      return AdbCreateInterfaceByName(next_interface.device_name().c_str());
+    }
+  }
+
+  SetLastError(ERROR_DEVICE_NOT_AVAILABLE);
+  return NULL;
+}
+
+bool AdbGetInterfaceName(ADBAPIHANDLE adb_interface,
+                         void* buffer,
+                         unsigned long* buffer_char_size,
+                         bool ansi) {
+  // Lookup interface object for the handle
+  AdbInterfaceObject* adb_object =
+    LookupObject<AdbInterfaceObject>(adb_interface);
+
+  if (NULL != adb_object) {
+    // Dispatch call to the found object
+    bool ret = adb_object->GetInterfaceName(buffer, buffer_char_size, ansi);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbGetSerialNumber(ADBAPIHANDLE adb_interface,
+                        void* buffer,
+                        unsigned long* buffer_char_size,
+                        bool ansi) {
+  // Lookup interface object for the handle
+  AdbInterfaceObject* adb_object =
+    LookupObject<AdbInterfaceObject>(adb_interface);
+
+  if (NULL != adb_object) {
+    // Dispatch call to the found object
+    bool ret = adb_object->GetSerialNumber(buffer, buffer_char_size, ansi);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbGetUsbDeviceDescriptor(ADBAPIHANDLE adb_interface,
+                               USB_DEVICE_DESCRIPTOR* desc) {
+  // Lookup interface object for the handle
+  AdbInterfaceObject* adb_object =
+    LookupObject<AdbInterfaceObject>(adb_interface);
+
+  if (NULL != adb_object) {
+    // Dispatch close to the found object
+    bool ret = adb_object->GetUsbDeviceDescriptor(desc);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbGetUsbConfigurationDescriptor(ADBAPIHANDLE adb_interface,
+                                      USB_CONFIGURATION_DESCRIPTOR* desc) {
+  // Lookup interface object for the handle
+  AdbInterfaceObject* adb_object =
+    LookupObject<AdbInterfaceObject>(adb_interface);
+
+  if (NULL != adb_object) {
+    // Dispatch close to the found object
+    bool ret = adb_object->GetUsbConfigurationDescriptor(desc);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbGetUsbInterfaceDescriptor(ADBAPIHANDLE adb_interface,
+                                  USB_INTERFACE_DESCRIPTOR* desc) {
+  // Lookup interface object for the handle
+  AdbInterfaceObject* adb_object =
+    LookupObject<AdbInterfaceObject>(adb_interface);
+
+  if (NULL != adb_object) {
+    // Dispatch close to the found object
+    bool ret = adb_object->GetUsbInterfaceDescriptor(desc);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbGetEndpointInformation(ADBAPIHANDLE adb_interface,
+                               UCHAR endpoint_index,
+                               AdbEndpointInformation* info) {
+  // Lookup interface object for the handle
+  AdbInterfaceObject* adb_object =
+    LookupObject<AdbInterfaceObject>(adb_interface);
+
+  if (NULL != adb_object) {
+    // Dispatch close to the found object
+    bool ret = adb_object->GetEndpointInformation(endpoint_index, info);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbGetDefaultBulkReadEndpointInformation(ADBAPIHANDLE adb_interface,
+                                              AdbEndpointInformation* info) {
+  return AdbGetEndpointInformation(adb_interface,
+                                   ADB_QUERY_BULK_READ_ENDPOINT_INDEX,
+                                   info);
+}
+
+bool AdbGetDefaultBulkWriteEndpointInformation(ADBAPIHANDLE adb_interface,
+                                               AdbEndpointInformation* info) {
+  return AdbGetEndpointInformation(adb_interface,
+                                   ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX,
+                                   info);
+}
+
+ADBAPIHANDLE AdbOpenEndpoint(ADBAPIHANDLE adb_interface,
+                             unsigned char endpoint_index,
+                             AdbOpenAccessType access_type,
+                             AdbOpenSharingMode sharing_mode) {
+  // Lookup interface object for the handle
+  AdbInterfaceObject* adb_object =
+    LookupObject<AdbInterfaceObject>(adb_interface);
+
+  if (NULL != adb_object) {
+    // Dispatch close to the found object
+    ADBAPIHANDLE ret =
+      adb_object->OpenEndpoint(endpoint_index, access_type, sharing_mode);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return NULL;
+  }
+}
+
+ADBAPIHANDLE AdbOpenDefaultBulkReadEndpoint(ADBAPIHANDLE adb_interface,
+                                            AdbOpenAccessType access_type,
+                                            AdbOpenSharingMode sharing_mode) {
+  return AdbOpenEndpoint(adb_interface,
+                         ADB_QUERY_BULK_READ_ENDPOINT_INDEX,
+                         access_type,
+                         sharing_mode);
+}
+
+ADBAPIHANDLE AdbOpenDefaultBulkWriteEndpoint(ADBAPIHANDLE adb_interface,
+                                             AdbOpenAccessType access_type,
+                                             AdbOpenSharingMode sharing_mode) {
+  return AdbOpenEndpoint(adb_interface,
+                         ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX,
+                         access_type,
+                         sharing_mode);
+}
+
+ADBAPIHANDLE AdbGetEndpointInterface(ADBAPIHANDLE adb_endpoint) {
+  // Lookup endpoint object for the handle
+  AdbEndpointObject* adb_object =
+    LookupObject<AdbEndpointObject>(adb_endpoint);
+
+  if (NULL != adb_object) {
+    // Dispatch the call to the found object
+    ADBAPIHANDLE ret = adb_object->GetParentInterfaceHandle();
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return NULL;
+  }
+}
+
+bool AdbQueryInformationEndpoint(ADBAPIHANDLE adb_endpoint,
+                                 AdbEndpointInformation* info) {
+  // Lookup endpoint object for the handle
+  AdbEndpointObject* adb_object =
+    LookupObject<AdbEndpointObject>(adb_endpoint);
+
+  if (NULL != adb_object) {
+    // Dispatch the call to the found object
+    bool ret = adb_object->GetEndpointInformation(info);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+ADBAPIHANDLE AdbReadEndpointAsync(ADBAPIHANDLE adb_endpoint,
+                                  void* buffer,
+                                  unsigned long bytes_to_read,
+                                  unsigned long* bytes_read,
+                                  unsigned long time_out,
+                                  HANDLE event_handle) {
+  // Lookup endpoint object for the handle
+  AdbEndpointObject* adb_object =
+    LookupObject<AdbEndpointObject>(adb_endpoint);
+
+  if (NULL != adb_object) {
+    // Dispatch the call to the found object
+    ADBAPIHANDLE ret = adb_object->AsyncRead(buffer,
+                                             bytes_to_read,
+                                             bytes_read,
+                                             event_handle,
+                                             time_out);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return NULL;
+  }
+}
+
+ADBAPIHANDLE AdbWriteEndpointAsync(ADBAPIHANDLE adb_endpoint,
+                                   void* buffer,
+                                   unsigned long bytes_to_write,
+                                   unsigned long* bytes_written,
+                                   unsigned long time_out,
+                                   HANDLE event_handle) {
+  // Lookup endpoint object for the handle
+  AdbEndpointObject* adb_object =
+    LookupObject<AdbEndpointObject>(adb_endpoint);
+
+  if (NULL != adb_object) {
+    // Dispatch the call to the found object
+    ADBAPIHANDLE ret = adb_object->AsyncWrite(buffer,
+                                              bytes_to_write,
+                                              bytes_written,
+                                              event_handle,
+                                              time_out);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbReadEndpointSync(ADBAPIHANDLE adb_endpoint,
+                         void* buffer,
+                         unsigned long bytes_to_read,
+                         unsigned long* bytes_read,
+                         unsigned long time_out) {
+  // Lookup endpoint object for the handle
+  AdbEndpointObject* adb_object =
+    LookupObject<AdbEndpointObject>(adb_endpoint);
+
+  if (NULL != adb_object) {
+    // Dispatch the call to the found object
+    bool ret =
+      adb_object->SyncRead(buffer, bytes_to_read, bytes_read, time_out);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return NULL;
+  }
+}
+
+bool AdbWriteEndpointSync(ADBAPIHANDLE adb_endpoint,
+                          void* buffer,
+                          unsigned long bytes_to_write,
+                          unsigned long* bytes_written,
+                          unsigned long time_out) {
+  // Lookup endpoint object for the handle
+  AdbEndpointObject* adb_object =
+    LookupObject<AdbEndpointObject>(adb_endpoint);
+
+  if (NULL != adb_object) {
+    // Dispatch the call to the found object
+    bool ret =
+      adb_object->SyncWrite(buffer, bytes_to_write, bytes_written, time_out);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbGetOvelappedIoResult(ADBAPIHANDLE adb_io_completion,
+                             LPOVERLAPPED overlapped,
+                             unsigned long* bytes_transferred,
+                             bool wait) {
+  // Lookup endpoint object for the handle
+  AdbIOCompletion* adb_object =
+    LookupObject<AdbIOCompletion>(adb_io_completion);
+
+  if (NULL != adb_object) {
+    // Dispatch the call to the found object
+    bool ret =
+      adb_object->GetOvelappedIoResult(overlapped, bytes_transferred, wait);
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
+
+bool AdbHasOvelappedIoComplated(ADBAPIHANDLE adb_io_completion) {
+  // Lookup endpoint object for the handle
+  AdbIOCompletion* adb_object =
+    LookupObject<AdbIOCompletion>(adb_io_completion);
+
+  if (NULL != adb_object) {
+    // Dispatch the call to the found object
+    bool ret =
+      adb_object->IsCompleted();
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return true;
+  }
+}
+
+bool AdbCloseHandle(ADBAPIHANDLE adb_handle) {
+  // Lookup object for the handle
+  AdbObjectHandle* adb_object = AdbObjectHandle::Lookup(adb_handle);
+
+  if (NULL != adb_object) {
+    // Dispatch close to the found object
+    bool ret = adb_object->CloseHandle();
+    adb_object->Release();
+    return ret;
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+}
diff --git a/host/windows/usb/api/adb_api.h b/host/windows/usb/api/adb_api.h
new file mode 100644
index 0000000..98a32dc
--- /dev/null
+++ b/host/windows/usb/api/adb_api.h
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADBWINAPI_H__
+#define ANDROID_USB_API_ADBWINAPI_H__
+/** \file
+  This file consists of declarations of routines exported by the API as well
+  as types, structures, and constants definitions used in the API.
+  Declarations in this file, combined with definitions found in adb_api_extra.h
+  comprise ADB API for windows.
+*/
+
+#include "adb_api_extra.h"
+
+// Enables compillation for "straight" C
+#ifdef __cplusplus
+  #define EXTERN_C    extern "C"
+#else
+  #define EXTERN_C    extern
+  typedef int bool;
+  #define true  1
+  #define false 0
+#endif
+
+// The following ifdef block is the standard way of creating macros which make
+// exporting  from a DLL simpler. All files within this DLL are compiled with
+// the ADBWIN_EXPORTS symbol defined on the command line. this symbol should
+// not be defined on any project that uses this DLL. This way any other project
+// whose source files include this file see ADBWIN_API functions as being
+// imported from a DLL, whereas this DLL sees symbols defined with this macro
+// as being exported.
+#ifdef ADBWIN_EXPORTS
+#define ADBWIN_API EXTERN_C __declspec(dllexport)
+#else
+#define ADBWIN_API EXTERN_C __declspec(dllimport)
+#endif
+
+/** Handle to an API object
+
+  To access USB interface and its components clients must first obtain a
+  handle to the required object. API Objects that are represented by a
+  handle are:
+  1. Interface enumerator that provides access to a list of interfaces that
+     match certain criterias that were specified when interface enumerator
+     has been created. This handle is created in AdbEnumInterfaces routine.
+  2. Interface that is the major object this API deals with. In Windows
+     model of the USB stack each USB device (that is physical device,
+     attached to a USB port) exposes one or more interfaces that become the
+     major entities through which that device gets accessed. Each of these
+     interfaces are represented as Windows Device Objects on the USB stack.
+     So, to this extent, at least as this API is concerned, terms "interface"
+     and "device" are interchangeable, since each interface is represented by
+     a device object on the Windows USB stack. This handle is created in
+     either AdbCreateInterface or AdbCreateInterfaceByName routines.
+  3. Endpoint object (also called a pipe) represents an endpoint on interface
+     through which all I/O operations are performed. This handle is created in
+     one of these routines: AdbOpenEndpoint, AdbOpenDefaultBulkReadEndpoint,
+     or AdbOpenDefaultBulkWriteEndpoint.
+  4. I/O completion object that tracks completion information of asynchronous
+     I/O performed on an endpoint. When an endpoint object gets opened through
+     this API it is opened for asynchronous (or overlapped) I/O. And each time
+     an asynchronous I/O is performed by this API an I/O completion object is
+     created to track the result of that I/O when it gets completed. Clients
+     of the API can then use a handle to I/O completion object to query for
+     the status and result of asynchronous I/O as well as wait for this I/O
+     completion. This handle is created in one of these routines:
+     AdbReadEndpointAsync, or AdbWriteEndpointAsync.
+  After object is no longer needed by the client, its handle must be closed
+  using AdbCloseHandle routine.
+*/
+typedef void* ADBAPIHANDLE;
+
+/** Enumeration AdbOpenAccessType defines access type with which
+  an I/O object (endpoint) should be opened.
+*/
+typedef enum _AdbOpenAccessType {
+  /// Opens for read and write access
+  AdbOpenAccessTypeReadWrite,
+
+  /// Opens for read only access
+  AdbOpenAccessTypeRead,
+
+  /// Opens for write only access
+  AdbOpenAccessTypeWrite,
+
+  /// Opens for querying information
+  AdbOpenAccessTypeQueryInfo,
+} AdbOpenAccessType;
+
+/** Enumeration AdbOpenSharingMode defines sharing mode with which
+  an I/O object (endpoint) should be opened.
+*/
+typedef enum _AdbOpenSharingMode {
+  /// Shares read and write
+  AdbOpenSharingModeReadWrite,
+
+  /// Shares only read
+  AdbOpenSharingModeRead,
+
+  /// Shares only write
+  AdbOpenSharingModeWrite,
+
+  /// Opens exclusive
+  AdbOpenSharingModeExclusive,
+} AdbOpenSharingMode;
+
+/** Structure AdbInterfaceInfo provides information about an interface
+*/
+typedef struct _AdbInterfaceInfo {
+  /// Inteface's class id (see SP_DEVICE_INTERFACE_DATA for details)
+  GUID          class_id;
+
+  /// Interface flags (see SP_DEVICE_INTERFACE_DATA for details)
+  unsigned long flags;
+
+  /// Device name for the interface (see SP_DEVICE_INTERFACE_DETAIL_DATA
+  /// for details)
+  wchar_t       device_name[1];
+} AdbInterfaceInfo;
+
+/** \brief Creates USB interface enumerator
+
+  This routine enumerates all USB interfaces that match provided class ID.
+  This routine uses SetupDiGetClassDevs SDK routine to enumerate devices that
+  match class ID and then SetupDiEnumDeviceInterfaces SDK routine is called
+  to enumerate interfaces on the devices.
+  @param class_id[in] Device class ID, assigned by the driver.
+  @param exclude_not_present[in] If 'true' enumation will include only those
+         devices that are currently present.
+  @param exclude_removed[in] If 'true' interfaces with SPINT_REMOVED flag set
+         will be not included in the enumeration.
+  @param active_only[in] If 'true' only active interfaces (with flag
+           SPINT_ACTIVE set) will be included in the enumeration.
+  @return Handle to the enumerator object or NULL on failure. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbEnumInterfaces(GUID class_id,
+                                          bool exclude_not_present,
+                                          bool exclude_removed,
+                                          bool active_only);
+
+/** \brief Gets next interface information
+
+  @param adb_handle[in] Handle to interface enumerator object obtained via
+         AdbEnumInterfaces call.
+  @param info[out] Upon successful completion will receive interface
+         information. Can be NULL. If it is NULL, upon return from this
+         routine size parameter will contain memory size required for the
+         next entry.
+  @param size[in,out]. On the way in provides size of the memory buffer
+         addressed by info parameter. On the way out (only if buffer was not
+         big enough) will provide memory size required for the next entry.
+  @return true on success, false on error. If false is returned
+          GetLastError() provides extended error information.
+          ERROR_INSUFFICIENT_BUFFER indicates that buffer provided in info
+          parameter was not big enough and size parameter contains memory size
+          required for the next entry. ERROR_NO_MORE_ITEMS indicates that
+          enumeration is over and there are no more entries to return.
+*/
+ADBWIN_API bool AdbNextInterface(ADBAPIHANDLE adb_handle,
+                                 AdbInterfaceInfo* info,
+                                 unsigned long* size);
+
+/** \brief Resets enumerator so next call to AdbNextInterface will start
+  from the beginning.
+
+  @param adb_handle[in] Handle to interface enumerator object obtained via
+         AdbEnumInterfaces call.
+  @return true on success, false on error. If false is returned GetLastError()
+          provides extended error information.
+*/
+ADBWIN_API bool AdbResetInterfaceEnum(ADBAPIHANDLE adb_handle);
+
+/** \brief Creates USB interface object
+
+  This routine creates an object that represents a USB interface.
+  @param interface_name[in] Name of the interface.
+  @return Handle to the interface object or NULL on failure. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbCreateInterfaceByName(const wchar_t* interface_name);
+
+/** \brief
+  Creates USB interface object based on vendor, product and interface IDs.
+
+  This routine creates and object that represents a USB interface on our
+  device. It uses AdbCreateInterfaceByName to actually do the create.
+  @param class_id[in] Device class ID, assigned by the driver.
+  @param vendor_id[in] Device vendor ID
+  @param product_id[in] Device product ID
+  @param interface_id[in] Device interface ID. This parameter is optional.
+         Value 0xFF indicates that interface should be addressed by vendor
+         and product IDs only.
+  @return Handle to the interface object or NULL on failure. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbCreateInterface(GUID class_id,
+                                           unsigned short vendor_id,
+                                           unsigned short product_id,
+                                           unsigned char interface_id);
+
+/** \brief Gets interface name.
+
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param buffer[out] Buffer for the name. Can be NULL in which case
+         buffer_char_size will contain number of characters required for
+         the name.
+  @param buffer_char_size[in/out] On the way in supplies size (in characters)
+         of the buffer. On the way out, if method failed and GetLastError
+         reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters
+         required for the name.
+  @param ansi[in] If 'true' the name will be returned as single character
+         string. Otherwise name will be returned as wide character string.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbGetInterfaceName(ADBAPIHANDLE adb_interface,
+                                    void* buffer,
+                                    unsigned long* buffer_char_size,
+                                    bool ansi);
+
+/** \brief Gets serial number for interface's device.
+
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param buffer[out] Buffer for the serail number string. Can be NULL in which
+         case buffer_char_size will contain number of characters required for
+         the string.
+  @param buffer_char_size[in/out] On the way in supplies size (in characters)
+         of the buffer. On the way out, if method failed and GetLastError
+         reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters
+         required for the name.
+  @param ansi[in] If 'true' the name will be returned as single character
+         string. Otherwise name will be returned as wide character string.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbGetSerialNumber(ADBAPIHANDLE adb_interface,
+                                   void* buffer,
+                                   unsigned long* buffer_char_size,
+                                   bool ansi);
+
+/** \brief Gets device descriptor for the USB device associated with
+  the given interface.
+
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param desc[out] Upon successful completion will have usb device
+         descriptor.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbGetUsbDeviceDescriptor(ADBAPIHANDLE adb_interface,
+                                          USB_DEVICE_DESCRIPTOR* desc);
+
+/** \brief Gets descriptor for the selected USB device configuration.
+
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param desc[out] Upon successful completion will have usb device
+         configuration descriptor.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbGetUsbConfigurationDescriptor(ADBAPIHANDLE adb_interface,
+                                                 USB_CONFIGURATION_DESCRIPTOR* desc);
+
+/** \brief Gets descriptor for the given interface.
+
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param desc[out] Upon successful completion will have usb device
+         configuration descriptor.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbGetUsbInterfaceDescriptor(ADBAPIHANDLE adb_interface,
+                                             USB_INTERFACE_DESCRIPTOR* desc);
+
+/** \brief Gets information about an endpoint on the given interface.
+
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param endpoint_index[in] Zero-based endpoint index. There are two
+         shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX
+         and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide information
+         about bulk write and bulk read endpoints respectively.
+  @param info[out] Upon successful completion will have endpoint information.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbGetEndpointInformation(ADBAPIHANDLE adb_interface,
+                                          unsigned char endpoint_index,
+                                          AdbEndpointInformation* info);
+
+/** \brief
+  Gets information about default bulk read endpoint on the given interface.
+
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param info[out] Upon successful completion will have endpoint information.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbGetDefaultBulkReadEndpointInformation(ADBAPIHANDLE adb_interface,
+                                                         AdbEndpointInformation* info);
+
+/** \brief
+  Gets information about default bulk write endpoint on the given interface.
+
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param info[out] Upon successful completion will have endpoint information.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbGetDefaultBulkWriteEndpointInformation(ADBAPIHANDLE adb_interface,
+                                                          AdbEndpointInformation* info);
+
+/** \brief Opens an endpoint on the given interface.
+
+  Endpoints are always opened for overlapped I/O.
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param endpoint_index[in] Zero-based endpoint index. There are two
+         shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX
+         and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide information
+         about bulk write and bulk read endpoints respectively.
+  @param access_type[in] Desired access type. In the current implementation
+         this parameter has no effect on the way endpoint is opened. It's
+         always read / write access.
+  @param sharing_mode[in] Desired share mode. In the current implementation
+         this parameter has no effect on the way endpoint is opened. It's
+         always shared for read / write.
+  @return Handle to the opened endpoint object or NULL on failure. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbOpenEndpoint(ADBAPIHANDLE adb_interface,
+                                        unsigned char endpoint_index,
+                                        AdbOpenAccessType access_type,
+                                        AdbOpenSharingMode sharing_mode);
+
+/** \brief Opens default bulk read endpoint on the given interface.
+
+  Endpoints are always opened for overlapped I/O.
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param access_type[in] Desired access type. In the current implementation
+         this parameter has no effect on the way endpoint is opened. It's
+         always read / write access.
+  @param sharing_mode[in] Desired share mode. In the current implementation
+         this parameter has no effect on the way endpoint is opened. It's
+         always shared for read / write.
+  @return Handle to the opened endpoint object or NULL on failure. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbOpenDefaultBulkReadEndpoint(ADBAPIHANDLE adb_interface,
+                                                       AdbOpenAccessType access_type,
+                                                       AdbOpenSharingMode sharing_mode);
+
+/** \brief Opens default bulk write endpoint on the given interface.
+
+  Endpoints are always opened for overlapped I/O.
+  @param adb_interface[in] A handle to interface object created with 
+         AdbCreateInterface call.
+  @param access_type[in] Desired access type. In the current implementation
+         this parameter has no effect on the way endpoint is opened. It's
+         always read / write access.
+  @param sharing_mode[in] Desired share mode. In the current implementation
+         this parameter has no effect on the way endpoint is opened. It's
+         always shared for read / write.
+  @return Handle to the opened endpoint object or NULL on failure. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbOpenDefaultBulkWriteEndpoint(ADBAPIHANDLE adb_interface,
+                                                        AdbOpenAccessType access_type,
+                                                        AdbOpenSharingMode sharing_mode);
+
+/** \brief Gets handle to interface object for the given endpoint
+
+  @param adb_endpoint[in] A handle to opened endpoint object, obtained via one
+         of the AdbOpenXxxEndpoint calls.
+  @return Handle to the interface for this endpoint or NULL on failure. If NULL
+          is returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbGetEndpointInterface(ADBAPIHANDLE adb_endpoint);
+
+/** \brief Gets information about the given endpoint.
+
+  @param adb_endpoint[in] A handle to opened endpoint object, obtained via one
+         of the AdbOpenXxxEndpoint calls.
+  @param info[out] Upon successful completion will have endpoint information.
+  @return 'true' on success, 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbQueryInformationEndpoint(ADBAPIHANDLE adb_endpoint,
+                                            AdbEndpointInformation* info);
+
+/** \brief Asynchronously reads from the given endpoint.
+
+  @param adb_endpoint[in] A handle to opened endpoint object, obtained via one
+         of the AdbOpenXxxEndpoint calls.
+  @param buffer[out] Pointer to the buffer that receives the data.
+  @param bytes_to_read[in] Number of bytes to be read.
+  @param bytes_read[out] Number of bytes read. Can be NULL.
+  @param event_handle[in] Event handle that should be signaled when async I/O
+         completes. Can be NULL. If it's not NULL this handle will be used to
+         initialize OVERLAPPED structure for this I/O.
+  @param time_out[in] A timeout (in milliseconds) required for this I/O to
+         complete. Zero value for this parameter means that there is no
+         timeout for this I/O.
+  @return A handle to IO completion object or NULL on failure. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbReadEndpointAsync(ADBAPIHANDLE adb_endpoint,
+                                             void* buffer,
+                                             unsigned long bytes_to_read,
+                                             unsigned long* bytes_read,
+                                             unsigned long time_out,
+                                             HANDLE event_handle);
+
+/** \brief Asynchronously writes to the given endpoint.
+
+  @param adb_endpoint[in] A handle to opened endpoint object, obtained via one
+         of the AdbOpenXxxEndpoint calls.
+  @param buffer[in] Pointer to the buffer containing the data to be written.
+  @param bytes_to_write[in] Number of bytes to be written.
+  @param bytes_written[out] Number of bytes written. Can be NULL.
+  @param event_handle[in] Event handle that should be signaled when async I/O
+         completes. Can be NULL. If it's not NULL this handle will be used to
+         initialize OVERLAPPED structure for this I/O.
+  @param time_out[in] A timeout (in milliseconds) required for this I/O to
+         complete. Zero value for this parameter means that there is no
+         timeout for this I/O.
+  @return A handle to IO completion object or NULL on failure. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API ADBAPIHANDLE AdbWriteEndpointAsync(ADBAPIHANDLE adb_endpoint,
+                                              void* buffer,
+                                              unsigned long bytes_to_write,
+                                              unsigned long* bytes_written,
+                                              unsigned long time_out,
+                                              HANDLE event_handle);
+
+/** \brief Synchronously reads from the given endpoint.
+
+  @param adb_endpoint[in] A handle to opened endpoint object, obtained via one
+         of the AdbOpenXxxEndpoint calls.
+  @param buffer[out] Pointer to the buffer that receives the data.
+  @param bytes_to_read[in] Number of bytes to be read.
+  @param bytes_read[out] Number of bytes read. Can be NULL.
+  @param time_out[in] A timeout (in milliseconds) required for this I/O to
+         complete. Zero value for this parameter means that there is no
+         timeout for this I/O.
+  @return 'true' on success and 'false' on failure. If 'false' is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbReadEndpointSync(ADBAPIHANDLE adb_endpoint,
+                                    void* buffer,
+                                    unsigned long bytes_to_read,
+                                    unsigned long* bytes_read,
+                                    unsigned long time_out);
+
+/** \brief Synchronously writes to the given endpoint.
+
+  @param adb_endpoint[in] A handle to opened endpoint object, obtained via one
+         of the AdbOpenXxxEndpoint calls.
+  @param buffer[in] Pointer to the buffer containing the data to be written.
+  @param bytes_to_write[in] Number of bytes to be written.
+  @param bytes_written[out] Number of bytes written. Can be NULL.
+  @param time_out[in] A timeout (in milliseconds) required for this I/O to
+         complete. Zero value for this parameter means that there is no
+         timeout for this I/O.
+  @return 'true' on success and 'false' on failure. If 'false' is
+          returned GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbWriteEndpointSync(ADBAPIHANDLE adb_endpoint,
+                                     void* buffer,
+                                     unsigned long bytes_to_write,
+                                     unsigned long* bytes_written,
+                                     unsigned long time_out);
+
+/** \brief Gets overlapped I/O result for async I/O performed on the
+  given endpoint
+
+  @param adb_io_completion[in] A handle to an I/O completion object returned
+         from AdbRead/WriteAsync routines.
+  @param ovl_data[out] Buffer for the copy of this object's OVERLAPPED
+         structure. Can be NULL.
+  @param bytes_transferred[out] Pointer to a variable that receives the
+         number of bytes that were actually transferred by a read or write
+         operation. See SDK doc on GetOvelappedResult for more information.
+         Unlike regular GetOvelappedResult call this parameter can be NULL.
+  @param wait[in] If this parameter is 'true', the method does not return
+         until the operation has been completed. If this parameter is 'false'
+         and the operation is still pending, the method returns 'false' and
+         the GetLastError function returns ERROR_IO_INCOMPLETE.
+  @return 'true' if I/O has been completed or 'false' on failure or if request
+         is not yet completed. If 'false' is returned GetLastError() provides
+         extended error information. If GetLastError returns
+         ERROR_IO_INCOMPLETE it means that I/O is not yet completed.
+*/
+ADBWIN_API bool AdbGetOvelappedIoResult(ADBAPIHANDLE adb_io_completion,
+                                        LPOVERLAPPED overlapped,
+                                        unsigned long* bytes_transferred,
+                                        bool wait);
+
+/** \brief Checks if overlapped I/O has been completed.
+
+  @param adb_io_completion[in] A handle to an I/O completion object returned
+         from AdbRead/WriteAsync routines.
+  @return 'true' if I/O has been completed or 'false' if it's still
+          incomplete. Regardless of the returned value, caller should
+          check GetLastError to validate that handle was OK.
+*/
+ADBWIN_API bool AdbHasOvelappedIoComplated(ADBAPIHANDLE adb_io_completion);
+
+/** \brief Closes handle previously opened with one of the API calls
+
+  @param adb_handle[in] ADB handle previously opened with one of the API calls
+  @return 'true' on success or 'false' on failure. If 'false' is returned
+          GetLastError() provides extended error information.
+*/
+ADBWIN_API bool AdbCloseHandle(ADBAPIHANDLE adb_handle);
+
+
+#endif  // ANDROID_USB_API_ADBWINAPI_H__
diff --git a/host/windows/usb/api/adb_api_extra.h b/host/windows/usb/api/adb_api_extra.h
new file mode 100644
index 0000000..cad480d
--- /dev/null
+++ b/host/windows/usb/api/adb_api_extra.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_API_EXTRA_H__
+#define ANDROID_USB_API_ADB_API_EXTRA_H__
+/** \file
+  This file consists of public API declarations that are also used by the
+  driver and as such cannot be declared in adb_api.h
+*/
+
+/** AdbEndpointType enumerates endpoint types. It enum is taken from
+  WDF_USB_PIPE_TYPE enum found in WDK.
+*/
+typedef enum _AdbEndpointType {
+    AdbEndpointTypeInvalid = 0,
+    AdbEndpointTypeControl,
+    AdbEndpointTypeIsochronous,
+    AdbEndpointTypeBulk,
+    AdbEndpointTypeInterrupt,
+} AdbEndpointType;
+
+/** Structure AdbEndpointInformation describes an endpoint. It is
+  based on WDF_USB_PIPE_INFORMATION structure found in WDK.
+*/
+typedef struct _AdbEndpointInformation {
+  /// Maximum packet size this endpoint is capable of
+  unsigned long max_packet_size;
+
+  // Maximum size of one transfer which should be sent to the host controller
+  unsigned long max_transfer_size;
+
+  // The type of the endpoint
+  AdbEndpointType endpoint_type;
+
+  /// Raw endpoint address of the device as described by its descriptor
+  unsigned char endpoint_address;
+
+  /// Polling interval
+  unsigned char polling_interval;
+
+  /// Which alternate setting this structure is relevant for
+  unsigned char setting_index;
+} AdbEndpointInformation;
+
+/// Shortcut to default write bulk endpoint in zero-based endpoint index API
+#define ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX  0xFC
+
+/// Shortcut to default read bulk endpoint in zero-based endpoint index API
+#define ADB_QUERY_BULK_READ_ENDPOINT_INDEX  0xFE
+
+// {F72FE0D4-CBCB-407d-8814-9ED673D0DD6B}
+/// Our USB class id that driver uses to register our device
+#define ANDROID_USB_CLASS_ID \
+{0xf72fe0d4, 0xcbcb, 0x407d, {0x88, 0x14, 0x9e, 0xd6, 0x73, 0xd0, 0xdd, 0x6b}};
+
+/// Defines vendor ID for the device
+#define DEVICE_VENDOR_ID            0x18D1
+
+/// Defines product ID for the device with single interface.
+#define DEVICE_SINGLE_PRODUCT_ID    0xD00D
+
+/// Defines product ID for the composite device.
+#define DEVICE_COMPOSITE_PRODUCT_ID 0xDEED
+
+/// Defines product ID for a SoftUSB device simulator that is used to test
+/// the driver in isolation from hardware.
+#define DEVICE_EMULATOR_PROD_ID     0xDDDD
+
+/// Defines interface ID for the device.
+#define DEVICE_INTERFACE_ID         0x01
+
+#endif  // ANDROID_USB_API_ADB_API_EXTRA_H__
diff --git a/host/windows/usb/api/adb_api_instance.cpp b/host/windows/usb/api/adb_api_instance.cpp
new file mode 100644
index 0000000..4f66b98
--- /dev/null
+++ b/host/windows/usb/api/adb_api_instance.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AdbApiInstance that is a main
+  API object representing a device interface that is in the interest of
+  the API client. All device (interface) related operations go through this
+  class first.
+*/
+
+#include "stdafx.h"
+#include "adb_api_instance.h"
+#include "adb_helper_routines.h"
+
+/// Map that holds all instances of this object
+AdbApiInstanceMap adb_app_instance_map;
+ULONG_PTR adb_app_instance_id = 0;
+CComAutoCriticalSection adb_app_instance_map_locker;
+
+AdbApiInstance::AdbApiInstance()
+    : ref_count_(1) {
+  // Generate inteface handle
+  adb_app_instance_map_locker.Lock();
+  adb_app_instance_id++;
+  adb_app_instance_map_locker.Unlock();
+  instance_handle_ =
+    reinterpret_cast<ADBAPIINSTANCEHANDLE>(adb_app_instance_id);
+}
+
+AdbApiInstance::~AdbApiInstance() {
+}
+
+void AdbApiInstance::LastReferenceReleased() {
+}
diff --git a/host/windows/usb/api/adb_api_instance.h b/host/windows/usb/api/adb_api_instance.h
new file mode 100644
index 0000000..9bc80b8
--- /dev/null
+++ b/host/windows/usb/api/adb_api_instance.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_API_INSTANCE_H__
+#define ANDROID_USB_API_ADB_API_INSTANCE_H__
+/** \file
+  This file consists of declaration of class AdbApiInstance that is a main
+  API object representing a device interface that is in the interest of
+  the API client. All device (interface) related operations go through this
+  class first.
+*/
+
+#include "adb_api.h"
+#include "adb_api_private_defines.h"
+
+/** Class AdbApiInstance is the main API interbal object representing a device
+  interface that is in the interest of the API client. All device (interface)
+  related operations go through this class first. So, before doing anything
+  meaningfull with the API a client must first create instance of the API
+  via CreateAdbApiInstance, select a device interface for that instance and
+  then do everything else.
+  Objects of this class are globally stored in the map that matches
+  ADBAPIINSTANCEHANDLE to the corresponded object.
+  This class is self-referenced with the following reference model:
+  1. When object of this class is created and added to the map, its recount
+     is set to 1.
+  2. Every time the client makes an API call that uses ADBAPIINSTANCEHANDLE
+     a corresponded AdbApiInstance object is looked up in the table and its
+     refcount is incremented. Upon return from the API call that incremented
+     the refcount refcount gets decremented.
+  3. When the client closes ADBAPIINSTANCEHANDLE via DeleteAdbApiInstance call
+     corresponded object gets deleted from the map and its refcount is
+     decremented.
+  So, at the end, this object destroys itself when refcount drops to zero.
+*/
+class AdbApiInstance {
+ public:
+  /** \brief Constructs the object
+    
+    @param handle[in] Instance handle associated with this object
+  */
+  AdbApiInstance();
+
+ private:
+  /// Destructs the object
+  ~AdbApiInstance();
+
+  /** \brief
+    This method is called when last reference to this object has been released
+
+    In this method object is uninitialized and deleted (that is "delete this"
+    is called).
+  */
+  void LastReferenceReleased();
+
+ public:
+   /// Gets name of the USB interface (device name) for this instance
+   const std::wstring& interface_name() const {
+     return interface_name_;
+   }
+
+   /// References the object and returns number of references
+   LONG AddRef() {
+     return InterlockedIncrement(&ref_count_);
+   }
+
+   /** \brief Dereferences the object and returns number of references
+
+    Object may be deleted in this method, so you cannot touch it after
+    this method returns, even if returned value is not zero, because object
+    can be deleted in another thread.
+   */
+   LONG Release() {
+     LONG ret = InterlockedDecrement(&ref_count_);
+     if (0 == ret)
+       LastReferenceReleased();
+
+     return ret;
+   }
+
+   /// Checks if instance has been initialized
+   bool IsInitialized() const {
+     return !interface_name_.empty();
+   }
+
+private:
+  /// Name of the USB interface (device name) for this instance
+  std::wstring          interface_name_;
+
+  /// Instance handle for this object
+  ADBAPIINSTANCEHANDLE  instance_handle_;
+
+  /// Reference counter for this instance
+  LONG                  ref_count_;
+};
+
+/// Defines map that matches ADBAPIINSTANCEHANDLE with AdbApiInstance object
+typedef std::map< ADBAPIINSTANCEHANDLE, AdbApiInstance* > AdbApiInstanceMap;
+
+#endif  // ANDROID_USB_API_ADB_API_INSTANCE_H__
diff --git a/host/windows/usb/api/adb_api_private_defines.h b/host/windows/usb/api/adb_api_private_defines.h
new file mode 100644
index 0000000..e1da7fe
--- /dev/null
+++ b/host/windows/usb/api/adb_api_private_defines.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_ADB_API_PRIVATE_DEFINES_H__
+#define ANDROID_USB_ADB_API_PRIVATE_DEFINES_H__
+/** \file
+  This file consists of private definitions used inside the API
+*/
+
+#include "adb_api.h"
+
+/** Class AdbInstanceEnumEntry encapsulates an entry in the array of
+  enumerated interfaces.
+*/
+class AdbInstanceEnumEntry {
+ public:
+  /** \brief Constructs an empty object.
+  */
+  AdbInstanceEnumEntry()
+      : flags_(0) {
+    ZeroMemory(&class_id_, sizeof(class_id_));
+  }
+
+  /** \brief Copy constructor
+  */
+  AdbInstanceEnumEntry(const AdbInstanceEnumEntry& proto) {
+    Set(proto.device_name().c_str(), proto.class_id(), proto.flags());
+  }
+
+  /** \brief Constructs the object with parameters.
+  */
+  AdbInstanceEnumEntry(const wchar_t* dev_name, GUID cls_id, DWORD flgs) {
+    Set(dev_name, cls_id, flgs);
+  }
+
+  /** \brief Destructs the object.
+  */
+  ~AdbInstanceEnumEntry() {
+  }
+
+  /// Operator =
+  AdbInstanceEnumEntry& operator=(const AdbInstanceEnumEntry& proto) {
+    Set(proto.device_name().c_str(), proto.class_id(), proto.flags());
+    return *this;
+  }
+
+  /// Initializes instance with parameters
+  void Set(const wchar_t* dev_name, GUID cls_id, DWORD flgs) {
+    device_name_ = dev_name;
+    class_id_ = cls_id;
+    flags_ = flgs;
+  }
+
+  /// Calculates memory size needed to save this entry into AdbInterfaceInfo
+  /// structure
+  ULONG GetFlatSize() const {
+    return static_cast<ULONG>(FIELD_OFFSET(AdbInterfaceInfo, device_name) +
+                              (device_name_.length() + 1) * sizeof(wchar_t));
+  }
+
+  /** \brief Saves this entry into AdbInterfaceInfo structure.
+
+    @param info[in] Buffer to save this entry to. Must be big enough to fit it.
+           Use GetFlatSize() method to get buffer size needed for that.
+
+  */
+  void Save(AdbInterfaceInfo* info) const {
+    info->class_id = class_id();
+    info->flags = flags();
+    wcscpy(info->device_name, device_name().c_str());
+  }
+
+  /// Gets interface's device name
+  const std::wstring& device_name() const {
+    return device_name_;
+  }
+
+  /// Gets inteface's class id
+  GUID class_id() const {
+    return class_id_;
+  }
+
+  /// Gets interface flags
+  DWORD flags() const {
+    return flags_;
+  }
+
+ private:
+  /// Inteface's class id (see SP_DEVICE_INTERFACE_DATA)
+  GUID          class_id_;
+
+  /// Interface's device name
+  std::wstring  device_name_;
+
+  /// Interface flags (see SP_DEVICE_INTERFACE_DATA)
+  DWORD         flags_;
+};
+
+/// Defines array of enumerated interface entries
+typedef std::vector< AdbInstanceEnumEntry > AdbEnumInterfaceArray;
+
+#endif  // ANDROID_USB_ADB_API_PRIVATE_DEFINES_H__
diff --git a/host/windows/usb/api/adb_endpoint_object.cpp b/host/windows/usb/api/adb_endpoint_object.cpp
new file mode 100644
index 0000000..90f698f
--- /dev/null
+++ b/host/windows/usb/api/adb_endpoint_object.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AdbIOObject that
+  encapsulates an interface on our USB device.
+*/
+
+#include "stdafx.h"
+#include "adb_endpoint_object.h"
+
+AdbEndpointObject::AdbEndpointObject(AdbInterfaceObject* parent_interf)
+    : AdbIOObject(parent_interf, AdbObjectTypeEndpoint) {
+}
+
+AdbEndpointObject::~AdbEndpointObject() {
+}
+
+bool AdbEndpointObject::IsObjectOfType(AdbObjectType obj_type) const {
+  return ((obj_type == AdbObjectTypeEndpoint) ||
+          (obj_type == AdbObjectTypeIo));
+}
+
+bool AdbEndpointObject::GetEndpointInformation(AdbEndpointInformation* info) {
+  if (!IsOpened() || !IsUsbOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  // Send IOCTL
+  DWORD ret_bytes = 0;
+  BOOL ret = DeviceIoControl(usb_handle(),
+                             ADB_IOCTL_GET_ENDPOINT_INFORMATION,
+                             NULL, 0,
+                             info, sizeof(AdbEndpointInformation),
+                             &ret_bytes,
+                             NULL);
+  ATLASSERT(!ret || (sizeof(AdbEndpointInformation) == ret_bytes));
+
+  return ret ? true : false;
+}
diff --git a/host/windows/usb/api/adb_endpoint_object.h b/host/windows/usb/api/adb_endpoint_object.h
new file mode 100644
index 0000000..eda8ffa
--- /dev/null
+++ b/host/windows/usb/api/adb_endpoint_object.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_ENDPOINT_OBJECT_H__
+#define ANDROID_USB_API_ADB_ENDPOINT_OBJECT_H__
+/** \file
+  This file consists of declaration of class AdbIOObject that encapsulates a
+  handle opened to an endpoint on our device.
+*/
+
+#include "adb_io_object.h"
+
+/** Class AdbEndpointObject encapsulates a handle opened to an endpoint on
+  our device.
+*/
+class AdbEndpointObject : public AdbIOObject {
+ public:
+  /** \brief Constructs the object
+    
+    @param interface[in] Parent interface for this object. Interface will be
+           referenced in this object's constructur and released in the
+           destructor.
+    @param obj_type[in] Object type from AdbObjectType enum
+  */
+  AdbEndpointObject(AdbInterfaceObject* parent_interf);
+
+ protected:
+  /** \brief Destructs the object.
+
+    parent_interface_ will be dereferenced here.
+    We hide destructor in order to prevent ourseves from accidentaly allocating
+    instances on the stack. If such attemp occur, compiler will error.
+  */
+  virtual ~AdbEndpointObject();
+
+ public:
+  /** \brief Gets information about this endpoint.
+
+    @param info[out] Upon successful completion will have endpoint information.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool GetEndpointInformation(AdbEndpointInformation* info);
+
+  /** \brief Checks if this object is of the given type
+
+    @param obj_type[in] One of the AdbObjectType types to check
+    @return 'true' is this object type matches obj_type and 'false' otherwise.
+  */
+  virtual bool IsObjectOfType(AdbObjectType obj_type) const;
+
+  // This is a helper for extracting object from the AdbObjectHandleMap
+  static AdbObjectType Type() {
+    return AdbObjectTypeEndpoint;
+  }
+};
+
+#endif  // ANDROID_USB_API_ADB_ENDPOINT_OBJECT_H__
diff --git a/host/windows/usb/api/adb_helper_routines.cpp b/host/windows/usb/api/adb_helper_routines.cpp
new file mode 100644
index 0000000..f2cd938
--- /dev/null
+++ b/host/windows/usb/api/adb_helper_routines.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of helper routines used
+  in the API.
+*/
+
+#include "stdafx.h"
+#include "adb_api.h"
+#include "adb_helper_routines.h"
+#include "adb_interface_enum.h"
+
+bool GetSDKComplientParam(AdbOpenAccessType access_type,
+                          AdbOpenSharingMode sharing_mode,
+                          ULONG* desired_access,
+                          ULONG* desired_sharing) {
+  if (NULL != desired_access) {
+    switch (access_type) {
+      case AdbOpenAccessTypeReadWrite:
+        *desired_access = GENERIC_READ | GENERIC_WRITE;
+        break;
+
+      case AdbOpenAccessTypeRead:
+        *desired_access = GENERIC_READ;
+        break;
+
+      case AdbOpenAccessTypeWrite:
+        *desired_access = GENERIC_WRITE;
+        break;
+
+      case AdbOpenAccessTypeQueryInfo:
+        *desired_access = FILE_READ_ATTRIBUTES | FILE_READ_EA;
+        break;
+
+      default:
+        AtlTrace("\n!!!!! ADB API -> GetSDKComplientParam %u is unknown access type",
+                 access_type);
+        SetLastError(ERROR_INVALID_ACCESS);
+        return false;
+    }
+  }
+
+  if (NULL != desired_sharing) {
+    switch (sharing_mode) {
+      case AdbOpenSharingModeReadWrite:
+        *desired_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
+        break;
+
+      case AdbOpenSharingModeRead:
+        *desired_sharing = FILE_SHARE_READ;
+        break;
+
+      case AdbOpenSharingModeWrite:
+        *desired_sharing = FILE_SHARE_WRITE;
+        break;
+
+      case AdbOpenSharingModeExclusive:
+        *desired_sharing = 0;
+        break;
+
+      default:
+        AtlTrace("\n!!!!! ADB API -> GetSDKComplientParam %u is unknown share mode",
+                 sharing_mode);
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return false;
+    }
+  }
+
+  return true;
+}
+
+bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
+                               GUID class_id,
+                               bool exclude_removed,
+                               bool active_only,
+                               AdbEnumInterfaceArray* interfaces) {
+  AdbEnumInterfaceArray tmp;
+  bool ret = false;
+
+  // Enumerate interfaces on this device
+  for (ULONG index = 0; ; index++) {
+    SP_DEVICE_INTERFACE_DATA interface_data;
+    interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+    // SetupDiEnumDeviceInterfaces() returns information about device
+    // interfaces exposed by one or more devices defined by our interface
+    // class. Each call returns information about one interface. The routine
+    // can be called repeatedly to get information about several interfaces
+    // exposed by one or more devices.
+    if (SetupDiEnumDeviceInterfaces(hardware_dev_info,
+                                    0, 
+                                    &class_id,
+                                    index,
+                                    &interface_data)) {
+      // Satisfy "exclude removed" and "active only" filters.
+      if ((!exclude_removed || (0 == (interface_data.Flags & SPINT_REMOVED))) &&
+          (!active_only || (interface_data.Flags & SPINT_ACTIVE))) {
+        std::wstring dev_name;
+
+        if (GetUsbDeviceName(hardware_dev_info, &interface_data, &dev_name)) {
+          try {
+            // Add new entry to the array
+            tmp.push_back(AdbInstanceEnumEntry(dev_name.c_str(),
+                                               interface_data.InterfaceClassGuid,
+                                               interface_data.Flags));
+          } catch (... ) {
+            SetLastError(ERROR_OUTOFMEMORY);
+            break;
+          }
+        } else {
+          // Something went wrong in getting device name
+          break;
+        }
+      }
+    } else {
+      if (ERROR_NO_MORE_ITEMS == GetLastError()) {
+        // There are no more items in the list. Enum is completed.
+        ret = true;
+        break;
+      } else {
+        // Something went wrong in SDK enum
+        break;
+      }
+    }
+  }
+
+  // On success, swap temp array with the returning one
+  if (ret)
+    interfaces->swap(tmp);
+
+  return ret;
+}
+
+bool EnumerateDeviceInterfaces(GUID class_id,
+                               ULONG flags,
+                               bool exclude_removed,
+                               bool active_only,
+                               AdbEnumInterfaceArray* interfaces) {
+  // Open a handle to the plug and play dev node.
+  // SetupDiGetClassDevs() returns a device information set that
+  // contains info on all installed devices of a specified class.
+  HDEVINFO hardware_dev_info =
+    SetupDiGetClassDevs(&class_id, NULL, NULL, flags);
+
+  bool ret = false;
+
+  if (INVALID_HANDLE_VALUE != hardware_dev_info) {
+    // Do the enum
+    ret = EnumerateDeviceInterfaces(hardware_dev_info,
+                                    class_id,
+                                    exclude_removed,
+                                    active_only,
+                                    interfaces);
+
+    // Preserve last error accross hardware_dev_info destruction
+    ULONG error_to_report = ret ? NO_ERROR : GetLastError();
+
+    SetupDiDestroyDeviceInfoList(hardware_dev_info);
+
+    if (NO_ERROR != error_to_report)
+      SetLastError(error_to_report);
+  }
+
+  return ret;
+}
+
+bool GetUsbDeviceDetails(
+    HDEVINFO hardware_dev_info,
+    PSP_DEVICE_INTERFACE_DATA dev_info_data,
+    PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data) {
+  ULONG required_len = 0;
+
+  // First query for the structure size. At this point we expect this call
+  // to fail with ERROR_INSUFFICIENT_BUFFER error code.
+  if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
+                                      dev_info_data,
+                                      NULL,
+                                      0,
+                                      &required_len,
+                                      NULL)) {
+    return false;
+  }
+
+  if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
+    return false;
+
+  // Allocate buffer for the structure
+  PSP_DEVICE_INTERFACE_DETAIL_DATA buffer =
+    reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(required_len));
+
+  if (NULL == buffer) {
+    SetLastError(ERROR_OUTOFMEMORY);
+    return false;
+  }
+
+  buffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+  // Retrieve the information from Plug and Play.
+  if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
+                                      dev_info_data,
+                                      buffer,
+                                      required_len,
+                                      &required_len,
+                                      NULL)) {
+    *dev_info_detail_data = buffer;
+    return true;
+  } else {
+    // Free the buffer if this call failed
+    free(buffer);
+
+    return false;
+  }
+}
+
+bool GetUsbDeviceName(HDEVINFO hardware_dev_info,
+                      PSP_DEVICE_INTERFACE_DATA dev_info_data,
+                      std::wstring* name) {
+  PSP_DEVICE_INTERFACE_DETAIL_DATA func_class_dev_data = NULL;
+  if (!GetUsbDeviceDetails(hardware_dev_info,
+                           dev_info_data,
+                           &func_class_dev_data)) {
+    return false;
+  }
+
+  try {
+    *name = func_class_dev_data->DevicePath;
+  } catch (...) {
+    SetLastError(ERROR_OUTOFMEMORY);
+  }
+
+  free(func_class_dev_data);
+
+  return !name->empty();
+}
diff --git a/host/windows/usb/api/adb_helper_routines.h b/host/windows/usb/api/adb_helper_routines.h
new file mode 100644
index 0000000..18709f0
--- /dev/null
+++ b/host/windows/usb/api/adb_helper_routines.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_HELPER_ROUTINES_H__
+#define ANDROID_USB_API_ADB_HELPER_ROUTINES_H__
+/** \file
+  This file consists of declarations of helper routines used
+  in the API.
+*/
+
+#include "adb_api_private_defines.h"
+
+/** \brief Converts access type and share mode from our enum into
+  SDK - complient values.
+
+  @param access_type[in] Enumerated access type
+  @param sharing_mode[in] Enumerated share mode
+  @param desired_access[out] Will receive SDK - complient desired access
+         flags. This parameter can be NULL.
+  @param desired_sharing[out] Will receive SDK - complient share mode.
+         This parameter can be NULL.
+  @return True on success, false on failure, in which case GetLastError()
+          provides extended information about the error that occurred.
+*/
+bool GetSDKComplientParam(AdbOpenAccessType access_type,
+                          AdbOpenSharingMode sharing_mode,
+                          ULONG* desired_access,
+                          ULONG* desired_sharing);
+
+/** \brief
+  Given the hardware device information enumerates interfaces for this device
+
+  @param hardware_dev_info[in] A handle to hardware device information obtained
+         from PnP manager via SetupDiGetClassDevs()
+  @param class_id[in] Device class ID how it is specified by our USB driver
+  @param exclude_removed[in] If true interfaces with SPINT_REMOVED flag set
+         will be not included in the enumeration.
+  @param active_only[in] If 'true' only active interfaces (with flag
+         SPINT_ACTIVE set) will be included in the enumeration.
+  @param interfaces[out] Upon successfull completion will consist of array of
+         all interfaces found for this device (matching all filters).
+  @return True on success, false on failure, in which case GetLastError()
+          provides extended information about the error that occurred.
+*/
+bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
+                               GUID class_id,
+                               bool exclude_removed,
+                               bool active_only,
+                               AdbEnumInterfaceArray* interfaces);
+
+/** \brief Enumerates all interfaces for our device class
+
+  This routine uses SetupDiGetClassDevs to get our device info and calls
+  EnumerateDeviceInterfaces to perform the enumeration.
+  @param class_id[in] Device class ID how it is specified by our USB driver
+  @param flags[in] Flags to pass to SetupDiGetClassDevs to filter devices. See
+         SetupDiGetClassDevs() in SDK for more info on these flags.
+  @param exclude_removed[in] If true interfaces with SPINT_REMOVED flag set
+         will be not included in the enumeration.
+  @param active_only[in] If 'true' only active interfaces (with flag
+         SPINT_ACTIVE set) will be included in the enumeration.
+  @param interfaces[out] Upon successfull completion will consist of array of
+         all interfaces found for this device (matching all filters).
+  @return True on success, false on failure, in which case GetLastError()
+          provides extended information about the error that occurred.
+*/
+bool EnumerateDeviceInterfaces(GUID class_id,
+                               ULONG flags,
+                               bool exclude_removed,
+                               bool active_only,
+                               AdbEnumInterfaceArray* interfaces);
+
+/** \brief Given the hardware device information and data gets data details
+
+  Given the hardware_dev_info, representing a handle to the plug and
+  play information, and dev_info_data, representing a specific usb device,
+  gets detailed data about the device (interface).
+  @param hardware_dev_info[in] A handle to hardware device information obtained
+         from PnP manager via SetupDiGetClassDevs()
+  @param dev_info_data[in] Device information data obtained via call to
+         SetupDiEnumDeviceInterfaces()
+  @param dev_info_detail_data[out] Upon successfull completion will consist of
+         the detailed data about device interface. This routine always
+         allocates memory for the output structure so content of this pointer
+         doesn't matter and will be overwritten by this routine. The caller
+         of this method is responsible for freeing allocated data using free()
+         routine.
+  @return True on success, false on failure, in which case GetLastError()
+          provides extended information about the error that occurred.
+*/
+bool GetUsbDeviceDetails(HDEVINFO hardware_dev_info,
+                         PSP_DEVICE_INTERFACE_DATA dev_info_data,
+                         PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data);
+
+/** \brief Given the hardware device information and data gets device name.
+
+  Given the hardware_dev_info, representing a handle to the plug and
+  play information, and dev_info_data, representing a specific usb device,
+  gets device name. This routine uses GetUsbDeviceDetails to extract device
+  name.
+  @param hardware_dev_info[in] A handle to hardware device information obtained
+         from PnP manager via SetupDiGetClassDevs()
+  @param dev_info_data[in] Device information data obtained via call to
+         SetupDiEnumDeviceInterfaces()
+  @param name[out] Upon successfull completion will have name for the device.
+  @return True on success, false on failure, in which case GetLastError()
+          provides extended information about the error that occurred.
+*/
+bool GetUsbDeviceName(HDEVINFO hardware_dev_info,
+                      PSP_DEVICE_INTERFACE_DATA dev_info_data,
+                      std::wstring* name);
+
+#endif  // ANDROID_USB_API_ADB_HELPER_ROUTINES_H__
diff --git a/host/windows/usb/api/adb_interface.cpp b/host/windows/usb/api/adb_interface.cpp
new file mode 100644
index 0000000..4f6c801
--- /dev/null
+++ b/host/windows/usb/api/adb_interface.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AdbInterfaceObject that
+  encapsulates an interface on our USB device.
+*/
+
+#include "stdafx.h"
+#include "adb_interface.h"
+#include "adb_endpoint_object.h"
+
+AdbInterfaceObject::AdbInterfaceObject(const wchar_t* interf_name)
+    : AdbObjectHandle(AdbObjectTypeInterface),
+      interface_name_(interf_name) {
+  ATLASSERT(NULL != interf_name);
+}
+
+AdbInterfaceObject::~AdbInterfaceObject() {
+}
+
+ADBAPIHANDLE AdbInterfaceObject::CreateHandle() {
+  // Open USB device for this intefface
+  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
+                                        GENERIC_READ | GENERIC_WRITE,
+                                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                        NULL,
+                                        OPEN_EXISTING,
+                                        0,
+                                        NULL);
+  if (INVALID_HANDLE_VALUE == usb_device_handle)
+    return NULL;
+
+  // Now, we ensured that our usb device / interface is up and running.
+  // Lets collect device, interface and pipe information
+  bool ok = true;
+  if (!CacheUsbDeviceDescriptor(usb_device_handle) ||
+      !CacheUsbConfigurationDescriptor(usb_device_handle) ||
+      !CacheUsbInterfaceDescriptor(usb_device_handle)) {
+    ok = false;
+  }
+
+  // Preserve error accross handle close
+  ULONG error = ok ? NO_ERROR : GetLastError();
+
+  ::CloseHandle(usb_device_handle);
+
+  if (NO_ERROR != error)
+    SetLastError(error);
+
+  if (!ok)
+    return false;
+
+  return AdbObjectHandle::CreateHandle();
+}
+
+bool AdbInterfaceObject::GetInterfaceName(void* buffer,
+                                          unsigned long* buffer_char_size,
+                                          bool ansi) {
+  // Lets see if buffer is big enough
+  ULONG name_len = static_cast<ULONG>(interface_name_.length() + 1);
+  if ((NULL == buffer) || (*buffer_char_size < name_len)) {
+    *buffer_char_size = name_len;
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return false;
+  }
+
+  if (!ansi) {
+    // If user asked for wide char name just return it
+    wcscpy(reinterpret_cast<wchar_t*>(buffer), interface_name().c_str());
+    return true;
+  }
+
+  // We need to convert name from wide char to ansi string
+  int res = WideCharToMultiByte(CP_ACP,
+                                0,
+                                interface_name().c_str(),
+                                static_cast<int>(name_len),
+                                reinterpret_cast<PSTR>(buffer),
+                                static_cast<int>(*buffer_char_size),
+                                NULL,
+                                NULL);
+  return (res != 0);
+}
+
+bool AdbInterfaceObject::GetSerialNumber(void* buffer,
+                                         unsigned long* buffer_char_size,
+                                         bool ansi) {
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  // Open USB device for this intefface
+  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
+                                        FILE_READ_ATTRIBUTES | FILE_READ_EA,
+                                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                        NULL,
+                                        OPEN_EXISTING,
+                                        0,
+                                        NULL);
+  if (INVALID_HANDLE_VALUE == usb_device_handle)
+    return NULL;
+
+  WCHAR serial_number[512];
+
+  // Send IOCTL
+  DWORD ret_bytes = 0;
+  BOOL ret = DeviceIoControl(usb_device_handle,
+                             ADB_IOCTL_GET_SERIAL_NUMBER,
+                             NULL, 0,
+                             serial_number, sizeof(serial_number),
+                             &ret_bytes,
+                             NULL);
+
+  // Preserve error accross CloseHandle
+  ULONG error = ret ? NO_ERROR : GetLastError();
+
+  ::CloseHandle(usb_device_handle);
+
+  if (NO_ERROR != error) {
+    SetLastError(error);
+    return false;
+  }
+
+  unsigned long str_len =
+    static_cast<unsigned long>(wcslen(serial_number) + 1);
+
+  if ((NULL == buffer) || (*buffer_char_size < str_len)) {
+    *buffer_char_size = str_len;
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return false;
+  }
+
+  if (!ansi) {
+    // If user asked for wide char name just return it
+    wcscpy(reinterpret_cast<wchar_t*>(buffer), serial_number);
+    return true;
+  }
+
+  // We need to convert name from wide char to ansi string
+  int res = WideCharToMultiByte(CP_ACP,
+                                0,
+                                serial_number,
+                                static_cast<int>(str_len),
+                                reinterpret_cast<PSTR>(buffer),
+                                static_cast<int>(*buffer_char_size),
+                                NULL,
+                                NULL);
+  return (res != 0);
+}
+
+bool AdbInterfaceObject::GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc) {
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  CopyMemory(desc, usb_device_descriptor(), sizeof(USB_DEVICE_DESCRIPTOR));
+
+  return true;
+}
+
+bool AdbInterfaceObject::GetUsbConfigurationDescriptor(
+    USB_CONFIGURATION_DESCRIPTOR* desc) {
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  CopyMemory(desc, usb_config_descriptor(),
+             sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+  return true;
+}
+
+bool AdbInterfaceObject::GetUsbInterfaceDescriptor(
+    USB_INTERFACE_DESCRIPTOR* desc) {
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  CopyMemory(desc, usb_interface_descriptor(), sizeof(USB_INTERFACE_DESCRIPTOR));
+
+  return true;
+}
+
+bool AdbInterfaceObject::GetEndpointInformation(UCHAR endpoint_index,
+                                                AdbEndpointInformation* info) {
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  // Open USB device for this intefface
+  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
+                                        FILE_READ_ATTRIBUTES | FILE_READ_EA,
+                                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                        NULL,
+                                        OPEN_EXISTING,
+                                        0,
+                                        NULL);
+  if (INVALID_HANDLE_VALUE == usb_device_handle)
+    return NULL;
+
+  // Init ICTL param
+  AdbQueryEndpointInformation param;
+  param.endpoint_index = endpoint_index;
+
+  // Send IOCTL
+  DWORD ret_bytes = 0;
+  BOOL ret = DeviceIoControl(usb_device_handle,
+                             ADB_IOCTL_GET_ENDPOINT_INFORMATION,
+                             &param, sizeof(param),
+                             info, sizeof(AdbEndpointInformation),
+                             &ret_bytes,
+                             NULL);
+  ATLASSERT(!ret || (sizeof(AdbEndpointInformation) == ret_bytes));
+
+  // Preserve error accross CloseHandle
+  ULONG error = ret ? NO_ERROR : GetLastError();
+
+  ::CloseHandle(usb_device_handle);
+
+  if (NO_ERROR != error)
+    SetLastError(error);
+
+  return ret ? true : false;
+}
+
+ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(
+    UCHAR endpoint_index,
+    AdbOpenAccessType access_type,
+    AdbOpenSharingMode sharing_mode) {
+  // Convert index into name
+  std::wstring endpoint_name;
+
+  try {
+    if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) {
+      endpoint_name = DEVICE_BULK_READ_PIPE_NAME;
+    } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) {
+      endpoint_name = DEVICE_BULK_WRITE_PIPE_NAME;
+    } else {
+      wchar_t fmt[265];
+      swprintf(fmt, L"%ws%u", DEVICE_PIPE_NAME_PREFIX, endpoint_index);
+      endpoint_name = fmt;
+    }
+  } catch (...) {
+    SetLastError(ERROR_OUTOFMEMORY);
+    return NULL;
+  }
+
+  return OpenEndpoint(endpoint_name.c_str(), access_type, sharing_mode);
+}
+
+ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(
+    const wchar_t* endpoint_name,
+    AdbOpenAccessType access_type,
+    AdbOpenSharingMode sharing_mode) {
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  AdbEndpointObject* adb_endpoint = NULL;
+  
+  try {
+    adb_endpoint = new AdbEndpointObject(this);
+  } catch (...) {
+    SetLastError(ERROR_OUTOFMEMORY);
+    return NULL;
+  }
+
+  // Build full path to the object
+  std::wstring endpoint_path = interface_name();
+  endpoint_path += L"\\";
+  endpoint_path += endpoint_name;
+
+  ADBAPIHANDLE ret = adb_endpoint->CreateHandle(endpoint_path.c_str(),
+                                                access_type,
+                                                sharing_mode);
+
+  adb_endpoint->Release();
+
+  return ret;
+}
+
+bool AdbInterfaceObject::CacheUsbDeviceDescriptor(HANDLE usb_device_handle) {
+  DWORD ret_bytes = 0;
+  BOOL ret = DeviceIoControl(usb_device_handle,
+                             ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,
+                             NULL, 0,
+                             &usb_device_descriptor_,
+                             sizeof(usb_device_descriptor_),
+                             &ret_bytes,
+                             NULL);
+  ATLASSERT(!ret || (sizeof(USB_DEVICE_DESCRIPTOR) == ret_bytes));
+
+  return ret ? true : false;
+}
+
+bool AdbInterfaceObject::CacheUsbConfigurationDescriptor(
+    HANDLE usb_device_handle) {
+  DWORD ret_bytes = 0;
+  BOOL ret = DeviceIoControl(usb_device_handle,
+                             ADB_IOCTL_GET_USB_CONFIGURATION_DESCRIPTOR,
+                             NULL, 0,
+                             &usb_config_descriptor_,
+                             sizeof(usb_config_descriptor_),
+                             &ret_bytes,
+                             NULL);
+  ATLASSERT(!ret || (sizeof(USB_CONFIGURATION_DESCRIPTOR) == ret_bytes));
+
+  return ret ? true : false;
+}
+
+bool AdbInterfaceObject::CacheUsbInterfaceDescriptor(
+    HANDLE usb_device_handle) {
+  DWORD ret_bytes = 0;
+  BOOL ret = DeviceIoControl(usb_device_handle,
+                             ADB_IOCTL_GET_USB_INTERFACE_DESCRIPTOR,
+                             NULL, 0,
+                             &usb_interface_descriptor_,
+                             sizeof(usb_interface_descriptor_),
+                             &ret_bytes,
+                             NULL);
+  ATLASSERT(!ret || (sizeof(USB_INTERFACE_DESCRIPTOR) == ret_bytes));
+
+  return ret ? true : false;
+}
diff --git a/host/windows/usb/api/adb_interface.h b/host/windows/usb/api/adb_interface.h
new file mode 100644
index 0000000..cead454
--- /dev/null
+++ b/host/windows/usb/api/adb_interface.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_INTERFACE_H__
+#define ANDROID_USB_API_ADB_INTERFACE_H__
+/** \file
+  This file consists of declaration of class AdbInterfaceObject that
+  encapsulates an interface on our USB device.
+*/
+
+#include "adb_object_handle.h"
+
+/** Class AdbInterfaceObject encapsulates an interface on our USB device.
+*/
+class AdbInterfaceObject : public AdbObjectHandle {
+ public:
+  /** \brief Constructs the object
+    
+    @param interf_name[in] Name of the interface
+  */
+  explicit AdbInterfaceObject(const wchar_t* interf_name);
+
+ protected:
+  /** \brief Destructs the object.
+
+   We hide destructor in order to prevent ourseves from accidentaly allocating
+   instances on the stack. If such attemp occur, compiler will error.
+  */
+  virtual ~AdbInterfaceObject();
+
+ public:
+  /** \brief Creates handle to this object
+
+    In this call a handle for this object is generated and object is added
+    to the AdbObjectHandleMap. We override this method in order to verify that
+    interface indeed exists and gather device, interface and pipe properties.
+    If this step succeeds then and only then AdbObjectHandle::CreateHandle
+    will be called.
+    @return A handle to this object on success or NULL on an error.
+            If NULL is returned GetLastError() provides extended error
+            information. ERROR_GEN_FAILURE is set if an attempt was
+            made to create already opened object.
+  */
+  virtual ADBAPIHANDLE CreateHandle();
+
+  /** \brief Gets interface device name.
+
+    @param buffer[out] Buffer for the name. Can be NULL in which case
+           buffer_char_size will contain number of characters required to fit
+           the name.
+    @param buffer_char_size[in/out] On the way in supplies size (in characters)
+           of the buffer. On the way out if method failed and GetLastError
+           reports ERROR_INSUFFICIENT_BUFFER will contain number of characters
+           required to fit the name.
+    @param ansi[in] If true the name will be returned as single character
+           string. Otherwise name will be returned as wide character string.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool GetInterfaceName(void* buffer,
+                        unsigned long* buffer_char_size,
+                        bool ansi);
+
+  /** \brief Gets serial number for interface's device.
+
+    @param buffer[out] Buffer for the serail number string. Can be NULL in
+           which case buffer_char_size will contain number of characters
+           required for the string.
+    @param buffer_char_size[in/out] On the way in supplies size (in characters)
+           of the buffer. On the way out, if method failed and GetLastError
+           reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters
+           required for the name.
+    @param ansi[in] If 'true' the name will be returned as single character
+           string. Otherwise name will be returned as wide character string.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool GetSerialNumber(void* buffer,
+                       unsigned long* buffer_char_size,
+                       bool ansi);
+
+  /** \brief Gets device descriptor for the USB device associated with
+    this interface.
+
+    @param desc[out] Upon successful completion will have usb device
+           descriptor.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc);
+
+  /** \brief Gets descriptor for the selected USB device configuration.
+
+    @param desc[out] Upon successful completion will have usb device
+           configuration descriptor.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool GetUsbConfigurationDescriptor(USB_CONFIGURATION_DESCRIPTOR* desc);
+
+  /** \brief Gets descriptor for this interface.
+
+    @param desc[out] Upon successful completion will have interface
+           descriptor.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool GetUsbInterfaceDescriptor(USB_INTERFACE_DESCRIPTOR* desc);
+
+  /** \brief Gets information about an endpoint on this interface.
+
+    @param endpoint_index[in] Zero-based endpoint index. There are two
+           shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX
+           and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about
+           (default?) bulk write and read endpoints respectively.
+    @param info[out] Upon successful completion will have endpoint information.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool GetEndpointInformation(UCHAR endpoint_index, AdbEndpointInformation* info);
+
+  /** \brief Opens an endpoint on this interface.
+
+    @param endpoint_index[in] Zero-based endpoint index. There are two
+           shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX
+           and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about
+           (default?) bulk write and read endpoints respectively.
+    @param access_type[in] Desired access type. In the current implementation
+           this parameter has no effect on the way endpoint is opened. It's
+           always read / write access.
+    @param sharing_mode[in] Desired share mode. In the current implementation
+           this parameter has no effect on the way endpoint is opened. It's
+           always shared for read / write.
+    @return Handle to the opened endpoint object or NULL on failure.
+            If NULL is returned GetLastError() provides extended information
+            about the error that occurred.
+  */
+  ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index,
+                            AdbOpenAccessType access_type,
+                            AdbOpenSharingMode sharing_mode);
+
+  /** \brief Opens an endpoint on this interface.
+
+    @param endpoint_name[in] Endpoint file name.
+    @param access_type[in] Desired access type. In the current implementation
+           this parameter has no effect on the way endpoint is opened. It's
+           always read / write access.
+    @param sharing_mode[in] Desired share mode. In the current implementation
+           this parameter has no effect on the way endpoint is opened. It's
+           always shared for read / write.
+    @return Handle to the opened endpoint object or NULL on failure.
+            If NULL is returned GetLastError() provides extended information
+            about the error that occurred.
+  */
+  ADBAPIHANDLE OpenEndpoint(const wchar_t* endpoint_name,
+                            AdbOpenAccessType access_type,
+                            AdbOpenSharingMode sharing_mode);
+
+ private:
+  /** \brief Caches device descriptor for the USB device associated with
+    this interface.
+
+    This method is called from CreateHandle method to cache some interface
+    information.
+    @param usb_device_handle[in] Handle to USB device.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool CacheUsbDeviceDescriptor(HANDLE usb_device_handle);
+
+  /** \brief Caches descriptor for the selected USB device configuration.
+
+    This method is called from CreateHandle method to cache some interface
+    information.
+    @param usb_device_handle[in] Handle to USB device.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool CacheUsbConfigurationDescriptor(HANDLE usb_device_handle);
+
+  /** \brief Caches descriptor for this interface.
+
+    This method is called from CreateHandle method to cache some interface
+    information.
+    @param usb_device_handle[in] Handle to USB device.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  bool CacheUsbInterfaceDescriptor(HANDLE usb_device_handle);
+
+ public:
+  /// Gets name of the USB interface (device name) for this object
+  const std::wstring& interface_name() const {
+    return interface_name_;
+  }
+
+  // This is a helper for extracting object from the AdbObjectHandleMap
+  static AdbObjectType Type() {
+    return AdbObjectTypeInterface;
+  }
+
+  /// Gets cached usb device descriptor
+  const USB_DEVICE_DESCRIPTOR* usb_device_descriptor() const {
+    return &usb_device_descriptor_;
+  }
+
+  /// Gets cached usb configuration descriptor
+  const USB_CONFIGURATION_DESCRIPTOR* usb_config_descriptor() const {
+    return &usb_config_descriptor_;
+  }
+
+  /// Gets cached usb interface descriptor
+  const USB_INTERFACE_DESCRIPTOR* usb_interface_descriptor() const {
+    return &usb_interface_descriptor_;
+  }
+
+private:
+  /// Name of the USB interface (device name) for this object
+  std::wstring                  interface_name_;
+
+  /// Cached usb device descriptor
+  USB_DEVICE_DESCRIPTOR         usb_device_descriptor_;
+
+  /// Cached usb configuration descriptor
+  USB_CONFIGURATION_DESCRIPTOR  usb_config_descriptor_;
+
+  /// Cached usb interface descriptor
+  USB_INTERFACE_DESCRIPTOR      usb_interface_descriptor_;
+};
+
+#endif  // ANDROID_USB_API_ADB_INTERFACE_H__
diff --git a/host/windows/usb/api/adb_interface_enum.cpp b/host/windows/usb/api/adb_interface_enum.cpp
new file mode 100644
index 0000000..6e2808c
--- /dev/null
+++ b/host/windows/usb/api/adb_interface_enum.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of AdbInterfaceEnumObject class that
+  encapsulates enumerator of USB interfaces available through this API.
+*/
+
+#include "stdafx.h"
+#include "adb_api.h"
+#include "adb_interface_enum.h"
+#include "adb_helper_routines.h"
+
+AdbInterfaceEnumObject::AdbInterfaceEnumObject()
+    : AdbObjectHandle(AdbObjectTypeInterfaceEnumerator) {
+  current_interface_ = interfaces_.begin();
+}
+
+AdbInterfaceEnumObject::~AdbInterfaceEnumObject() {
+}
+
+bool AdbInterfaceEnumObject::InitializeEnum(GUID class_id,
+                                            bool exclude_not_present,
+                                            bool exclude_removed,
+                                            bool active_only) {
+  // Calc flags for SetupDiGetClassDevs
+  DWORD flags = DIGCF_DEVICEINTERFACE;
+  if (exclude_not_present)
+    flags |= DIGCF_PRESENT;
+
+  // Do the enum
+  bool ret = EnumerateDeviceInterfaces(class_id,
+                                       flags,
+                                       exclude_removed,
+                                       active_only,
+                                       &interfaces_);
+
+  // If enum was successfull set current enum pointer
+  // to the beginning of the array
+  if (ret)
+    current_interface_ = interfaces_.begin();
+
+  return ret;
+}
+
+bool AdbInterfaceEnumObject::Next(AdbInterfaceInfo* info, ULONG* size) {
+  // Make sure that it's opened
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  ATLASSERT(NULL != size);
+  if (NULL == size) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return false;
+  }
+
+  // Lets see if enum is over
+  if (interfaces_.end() == current_interface_) {
+    SetLastError(ERROR_NO_MORE_ITEMS);
+    return false;
+  }
+
+  AdbInstanceEnumEntry& entry = *current_interface_;
+
+  // Big enough?
+  if ((NULL == info) || (*size < entry.GetFlatSize())) {
+    *size = entry.GetFlatSize();
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return false;
+  }
+
+  // All checks passed
+  entry.Save(info);
+  current_interface_++;
+  return true;
+}
+
+bool AdbInterfaceEnumObject::Reset() {
+  // Make sure that it's opened
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  current_interface_ = interfaces_.begin();
+
+  return true;
+}
diff --git a/host/windows/usb/api/adb_interface_enum.h b/host/windows/usb/api/adb_interface_enum.h
new file mode 100644
index 0000000..f46b31b
--- /dev/null
+++ b/host/windows/usb/api/adb_interface_enum.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_INTERFACE_ENUM_H__
+#define ANDROID_USB_API_ADB_INTERFACE_ENUM_H__
+/** \file
+  This file consists of declaration of AdbInterfaceEnumObject class that
+  encapsulates enumerator of USB interfaces available through this API.
+*/
+
+#include "adb_object_handle.h"
+
+/** Class AdbInterfaceEnumObject encapsulates enumerator of USB
+  interfaces available through this API.
+*/
+class AdbInterfaceEnumObject : public AdbObjectHandle {
+ public:
+  /** \brief Constructs the object.
+  */
+  AdbInterfaceEnumObject();
+
+ protected:
+  /** \brief Destructs the object.
+
+   We hide destructor in order to prevent ourseves from accidentaly allocating
+   instances on the stack. If such attemp occur, compiler will error.
+  */
+  virtual ~AdbInterfaceEnumObject();
+
+ public:
+  /** \brief Enumerates all interfaces for our device class
+
+    This routine uses SetupDiGetClassDevs to get our device info and calls
+    EnumerateDeviceInterfaces to perform the enumeration.
+    @param class_id[in] Device class ID that is specified by our USB driver
+    @param exclude_not_present[in] If set include only those devices that are
+           currently present.
+    @param exclude_removed[in] If true interfaces with SPINT_REMOVED flag set
+           will be not included in the enumeration.
+    @param active_only[in] If 'true' only active interfaces (with flag
+           SPINT_ACTIVE set) will be included in the enumeration.
+    @return True on success, false on failure, in which case GetLastError()
+            provides extended information about the error that occurred.
+  */
+  bool InitializeEnum(GUID class_id,
+                      bool exclude_not_present,
+                      bool exclude_removed,
+                      bool active_only);
+
+  /** \brief Gets next enumerated interface information
+
+    @param info[out] Upon successful completion will receive interface
+           information. Can be NULL. If it is NULL, upon return from this
+           method *size will have memory size required to fit this entry.
+    @param size[in,out]. On the way in provides size of the memory buffer
+           addressed by info param. On the way out (only if buffer is not
+           big enough) will provide memory size required to fit this entry.
+    @return true on success, false on error. If false is returned
+            GetLastError() provides extended information about the error that
+            occurred. ERROR_INSUFFICIENT_BUFFER indicates that buffer provided
+            in info param was not big enough and *size specifies memory size
+            required to fit this entry. ERROR_NO_MORE_ITEMS indicates that
+            enumeration is over and there are no more entries to return.
+  */
+  bool Next(AdbInterfaceInfo* info, ULONG* size);
+
+  /** \brief Makes enumerator to start from the beginning.
+
+    @return true on success, false on error. If false is returned
+            GetLastError() provides extended information about the error that
+            occurred.
+  */
+  bool Reset();
+
+  // This is a helper for extracting object from the AdbObjectHandleMap
+  static AdbObjectType Type() {
+    return AdbObjectTypeInterfaceEnumerator;
+  }
+
+ protected:
+  /// Array of interfaces enumerated with this object
+  AdbEnumInterfaceArray           interfaces_;
+
+  /// Current enumerator
+  AdbEnumInterfaceArray::iterator current_interface_;
+};
+
+#endif  // ANDROID_USB_API_ADB_INTERFACE_ENUM_H__
diff --git a/host/windows/usb/api/adb_io_completion.cpp b/host/windows/usb/api/adb_io_completion.cpp
new file mode 100644
index 0000000..02519c9
--- /dev/null
+++ b/host/windows/usb/api/adb_io_completion.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AdbIOCompletion that
+  encapsulates a wrapper around OVERLAPPED Win32 structure returned
+  from asynchronous I/O requests.
+*/
+
+#include "stdafx.h"
+#include "adb_io_completion.h"
+
+AdbIOCompletion::AdbIOCompletion(AdbIOObject* parent_io_obj,
+                                 bool is_write_ctl,
+                                 ULONG expected_trans_size,
+                                 HANDLE event_hndl)
+    : AdbObjectHandle(AdbObjectTypeIoCompletion),
+      transferred_bytes_(0),
+      expected_transfer_size_(expected_trans_size),
+      is_write_ioctl_(is_write_ctl),
+      parent_io_object_(parent_io_obj) {
+  ATLASSERT(NULL != parent_io_obj);
+  parent_io_obj->AddRef();
+  ZeroMemory(&overlapped_, sizeof(overlapped_));
+  overlapped_.hEvent = event_hndl;
+}
+
+AdbIOCompletion::~AdbIOCompletion() {
+  parent_io_object_->Release();
+}
+
+bool AdbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data,
+                                           ULONG* bytes_transferred,
+                                           bool wait) {
+  if (NULL != bytes_transferred)
+    *bytes_transferred = 0;
+
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  ULONG transfer;
+  bool ret = GetOverlappedResult(parent_io_object()->usb_handle(),
+                                 overlapped(),
+                                 &transfer,
+                                 wait) ? true :
+                                         false;
+
+  // TODO: This is bizzare but I've seen it happening
+  // that GetOverlappedResult with wait set to true returns "prematurely",
+  // with wrong transferred bytes value and GetLastError reporting
+  // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop!
+  ULONG error = GetLastError();
+
+  if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) &&
+      ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) {
+    for (int trying = 0; trying < 10; trying++) {
+      Sleep(2);
+      ret = GetOverlappedResult(parent_io_object()->usb_handle(),
+                                overlapped(),
+                                &transfer,
+                                wait) ? true :
+                                        false;
+      error = GetLastError();
+      if (!ret || (0 != transfer) ||
+          ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) {
+        break;
+      }
+    }
+  }
+
+  if (NULL != ovl_data)
+    CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED));
+
+  if (NULL != bytes_transferred)
+    *bytes_transferred = is_write_ioctl() ? transferred_bytes_ : transfer;
+
+  return ret;
+}
+
+bool AdbIOCompletion::IsCompleted() {
+  SetLastError(NO_ERROR);
+  if (!IsOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return true;
+  }
+
+  return  HasOverlappedIoCompleted(overlapped()) ? true : false;
+}
diff --git a/host/windows/usb/api/adb_io_completion.h b/host/windows/usb/api/adb_io_completion.h
new file mode 100644
index 0000000..d29f5e1
--- /dev/null
+++ b/host/windows/usb/api/adb_io_completion.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_IO_COMPLETION_H__
+#define ANDROID_USB_API_ADB_IO_COMPLETION_H__
+/** \file
+  This file consists of declaration of class AdbIOCompletion that encapsulates
+  a wrapper around OVERLAPPED Win32 structure returned from asynchronous I/O
+  requests.
+*/
+
+#include "adb_io_object.h"
+
+/** Class AdbIOCompletion encapsulates encapsulates a wrapper around
+  OVERLAPPED Win32 structure returned from asynchronous I/O requests.
+  A handle to this object is returned to the caller of each successful
+  asynchronous I/O request. Just like all other handles this handle
+  must be closed after it's no longer needed.
+*/
+class AdbIOCompletion : public AdbObjectHandle {
+ public:
+  /** \brief Constructs the object
+    
+    @param parent_io_obj[in] Parent I/O object that created this instance.
+           Parent object will be referenced in this object's constructur and
+           released in the destructor.
+    @param is_write_ctl[in] Flag indicating whether or not this completion
+           object is created for ADB_IOCTL_BULK_WRITE I/O.
+    @param event_hndl[in] Event handle that should be signaled when I/O
+           completes. Can be NULL. If it's not NULL this handle will be
+           used to initialize OVERLAPPED structure for this object.
+  */
+  AdbIOCompletion(AdbIOObject* parent_io_obj,
+                  bool is_write_ctl,
+                  ULONG expected_trans_size,
+                  HANDLE event_hndl);
+
+ protected:
+  /** \brief Destructs the object.
+
+    parent_io_object_ will be dereferenced here.
+    We hide destructor in order to prevent ourseves from accidentaly allocating
+    instances on the stack. If such attemp occur, compiler will error.
+  */
+  virtual ~AdbIOCompletion();
+
+ public:
+  /** \brief Gets overlapped I/O result
+
+    @param ovl_data[out] Buffer for the copy of this object's OVERLAPPED
+           structure. Can be NULL.
+    @param bytes_transferred[out] Pointer to a variable that receives the
+           number of bytes that were actually transferred by a read or write
+           operation. See SDK doc on GetOvelappedResult for more information.
+           Unlike regular GetOvelappedResult call this parameter can be NULL.
+    @param wait[in] If this parameter is 'true', the method does not return
+           until the operation has been completed. If this parameter is 'false'
+           and the operation is still pending, the method returns 'false' and
+           the GetLastError function returns ERROR_IO_INCOMPLETE.
+    @return 'true' if I/O has been completed or 'false' on failure or if request
+           is not yet completed. If 'false' is returned GetLastError() provides
+           extended error information. If GetLastError returns
+           ERROR_IO_INCOMPLETE it means that I/O is not yet completed.
+  */
+  virtual bool GetOvelappedIoResult(LPOVERLAPPED ovl_data,
+                                    ULONG* bytes_transferred,
+                                    bool wait);
+
+  /** \brief Checks if I/O that this object represents has completed.
+
+    @return 'true' if I/O has been completed or 'false' if it's still
+            incomplete. Regardless of the returned value, caller should
+            check GetLastError to validate that handle was OK.
+  */
+  virtual bool IsCompleted();
+
+ public:
+  /// Gets overlapped structure for this I/O
+  LPOVERLAPPED overlapped() {
+    return &overlapped_;
+  }
+
+  /// Gets parent object
+  AdbIOObject* parent_io_object() const {
+    return parent_io_object_;
+  }
+
+  /// Gets parent object handle
+  ADBAPIHANDLE GetParentObjectHandle() const {
+    return (NULL != parent_io_object()) ? parent_io_object()->adb_handle() :
+                                          NULL;
+  }
+
+  /// Gets address for ADB_IOCTL_BULK_WRITE output buffer
+  ULONG* transferred_bytes_ptr() {
+    ATLASSERT(is_write_ioctl());
+    return &transferred_bytes_;
+  }
+
+  /// Gets write IOCTL flag
+  bool is_write_ioctl() const {
+    return is_write_ioctl_;
+  }
+
+  // This is a helper for extracting object from the AdbObjectHandleMap
+  static AdbObjectType Type() {
+    return AdbObjectTypeIoCompletion;
+  }
+
+ protected:
+  /// Overlapped structure for this I/O
+  OVERLAPPED    overlapped_;
+
+  /// Parent I/O object
+  AdbIOObject*  parent_io_object_;
+
+  /// Recepient for number of transferred bytes in write IOCTL
+  ULONG         transferred_bytes_;
+
+  /// Expected number of bytes transferred in thi I/O
+  ULONG         expected_transfer_size_;
+
+  /// Write IOCTL flag
+  bool          is_write_ioctl_;
+};
+
+#endif  // ANDROID_USB_API_ADB_IO_COMPLETION_H__
diff --git a/host/windows/usb/api/adb_io_object.cpp b/host/windows/usb/api/adb_io_object.cpp
new file mode 100644
index 0000000..ea4bc8f
--- /dev/null
+++ b/host/windows/usb/api/adb_io_object.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AdbIOObject that encapsulates
+  an item on our device that is opened for read / write / IOCTL I/O.
+*/
+
+#include "stdafx.h"
+#include "adb_io_object.h"
+#include "adb_io_completion.h"
+#include "adb_helper_routines.h"
+
+AdbIOObject::AdbIOObject(AdbInterfaceObject* parent_interf,
+                         AdbObjectType obj_type)
+    : AdbObjectHandle(obj_type),
+      usb_handle_(INVALID_HANDLE_VALUE),
+      parent_interface_(parent_interf) {
+  ATLASSERT(NULL != parent_interf);
+  parent_interf->AddRef();
+}
+
+AdbIOObject::~AdbIOObject() {
+  if (INVALID_HANDLE_VALUE != usb_handle_)
+    ::CloseHandle(usb_handle_);
+  parent_interface_->Release();
+}
+
+ADBAPIHANDLE AdbIOObject::CreateHandle(const wchar_t* item_path,
+                                       AdbOpenAccessType access_type,
+                                       AdbOpenSharingMode share_mode) {
+  // Make sure that we don't have USB handle here
+  if (IsUsbOpened()) {
+    SetLastError(ERROR_GEN_FAILURE);
+    return NULL;
+  }
+
+  // Convert access / share parameters into CreateFile - compatible
+  ULONG desired_access;
+  ULONG desired_sharing;
+
+  if (!GetSDKComplientParam(access_type, share_mode,
+                            &desired_access, &desired_sharing)) {
+    return NULL;
+  }
+
+  // Open USB handle
+  usb_handle_ = CreateFile(item_path,
+                           desired_access,
+                           share_mode,
+                           NULL,
+                           OPEN_EXISTING,
+                           FILE_FLAG_OVERLAPPED,  // Always overlapped!
+                           NULL);
+  if (INVALID_HANDLE_VALUE == usb_handle_)
+    return NULL;
+
+  // Create ADB handle
+  ADBAPIHANDLE ret = AdbObjectHandle::CreateHandle();
+
+  if (NULL == ret) {
+    // If creation of ADB handle failed we have to close USB handle too.
+    ULONG error = GetLastError();
+    ::CloseHandle(usb_handle());
+    usb_handle_ = INVALID_HANDLE_VALUE;
+    SetLastError(error);
+  }
+
+  return ret;
+}
+
+bool AdbIOObject::CloseHandle() {
+  // Lets close USB item first
+  if (IsUsbOpened()) {
+    ::CloseHandle(usb_handle());
+    usb_handle_ = INVALID_HANDLE_VALUE;
+  }
+
+  return AdbObjectHandle::CloseHandle();
+}
+
+ADBAPIHANDLE AdbIOObject::AsyncRead(void* buffer,
+                                    ULONG bytes_to_read,
+                                    ULONG* bytes_read,
+                                    HANDLE event_handle,
+                                    ULONG time_out) {
+  return CommonAsyncReadWrite(true,
+                              buffer,
+                              bytes_to_read,
+                              bytes_read,
+                              event_handle,
+                              time_out);
+}
+
+ADBAPIHANDLE AdbIOObject::AsyncWrite(void* buffer,
+                                     ULONG bytes_to_write,
+                                     ULONG* bytes_written,
+                                     HANDLE event_handle,
+                                     ULONG time_out) {
+  return CommonAsyncReadWrite(false,
+                              buffer,
+                              bytes_to_write,
+                              bytes_written,
+                              event_handle,
+                              time_out);
+}
+
+bool AdbIOObject::SyncRead(void* buffer,
+                           ULONG bytes_to_read,
+                           ULONG* bytes_read,
+                           ULONG time_out) {
+  return CommonSyncReadWrite(true,
+                             buffer,
+                             bytes_to_read,
+                             bytes_read,
+                             time_out);
+}
+
+bool AdbIOObject::SyncWrite(void* buffer,
+                            ULONG bytes_to_write,
+                            ULONG* bytes_written,
+                            ULONG time_out) {
+  return CommonSyncReadWrite(false,
+                             buffer,
+                             bytes_to_write,
+                             bytes_written,
+                             time_out);
+}
+
+ADBAPIHANDLE AdbIOObject::CommonAsyncReadWrite(bool is_read,
+                                               void* buffer,
+                                               ULONG bytes_to_transfer,
+                                               ULONG* bytes_transferred,
+                                               HANDLE event_handle,
+                                               ULONG time_out) {
+  if (NULL != bytes_transferred)
+    *bytes_transferred = 0;
+
+  if (!IsOpened() || !IsUsbOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  bool is_ioctl_write = is_read ? false : (0 != time_out);
+
+  // Create completion i/o object
+  AdbIOCompletion* adb_io_completion = NULL;
+
+  try {
+    adb_io_completion = new AdbIOCompletion(this,
+                                            is_ioctl_write,
+                                            bytes_to_transfer,
+                                            event_handle);
+  } catch (... ) {
+    SetLastError(ERROR_OUTOFMEMORY);
+    return NULL;
+  }
+
+  // Create a handle for it
+  ADBAPIHANDLE ret = adb_io_completion->CreateHandle();
+  ULONG transferred = 0;
+  if (NULL != ret) {
+    BOOL res = TRUE;
+    if (0 == time_out) {
+      // Go the read / write file way
+      res = is_read ? ReadFile(usb_handle(),
+                               buffer,
+                               bytes_to_transfer,
+                               &transferred,
+                               adb_io_completion->overlapped()) :
+                      WriteFile(usb_handle(),
+                                buffer,
+                                bytes_to_transfer,
+                                &transferred,
+                                adb_io_completion->overlapped());
+    } else {
+      // Go IOCTL way
+      AdbBulkTransfer transfer_param;
+      transfer_param.time_out = time_out;
+      transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;
+      transfer_param.write_buffer = is_read ? NULL : buffer;
+
+      res = DeviceIoControl(usb_handle(),
+        is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,
+        &transfer_param, sizeof(transfer_param),
+        is_read ? buffer : adb_io_completion->transferred_bytes_ptr(),
+        is_read ? bytes_to_transfer : sizeof(ULONG),
+        &transferred,
+        adb_io_completion->overlapped());
+    }
+
+    if (NULL != bytes_transferred)
+      *bytes_transferred = transferred;
+
+    ULONG error = GetLastError();
+    if (!res && (ERROR_IO_PENDING != error)) {
+      // I/O failed immediatelly. We need to close i/o completion object
+      // before we return NULL to the caller.
+      adb_io_completion->CloseHandle();
+      ret = NULL;
+      SetLastError(error);
+    }
+  }
+
+  // Offseting 'new'
+  adb_io_completion->Release();
+
+  return ret;
+}
+
+bool AdbIOObject::CommonSyncReadWrite(bool is_read,
+                                      void* buffer,
+                                      ULONG bytes_to_transfer,
+                                      ULONG* bytes_transferred,
+                                      ULONG time_out) {
+  if (NULL != bytes_transferred)
+    *bytes_transferred = 0;
+
+  if (!IsOpened() || !IsUsbOpened()) {
+    SetLastError(ERROR_INVALID_HANDLE);
+    return false;
+  }
+
+  bool is_ioctl_write = is_read ? false : (0 != time_out);
+
+  // This is synchronous I/O. Since we always open I/O items for
+  // overlapped I/O we're obligated to always provide OVERLAPPED
+  // structure to read / write routines. Prepare it now.
+  OVERLAPPED overlapped;
+  ZeroMemory(&overlapped, sizeof(overlapped));
+
+  BOOL ret = TRUE;
+  ULONG ioctl_write_transferred = 0;
+  if (0 == time_out) {
+    // Go the read / write file way
+    ret = is_read ?
+      ReadFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped) :
+      WriteFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped);
+  } else {
+    // Go IOCTL way
+    AdbBulkTransfer transfer_param;
+    transfer_param.time_out = time_out;
+    transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;
+    transfer_param.write_buffer = is_read ? NULL : buffer;
+
+    ULONG tmp;
+    ret = DeviceIoControl(usb_handle(),
+      is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,
+      &transfer_param, sizeof(transfer_param),
+      is_read ? buffer : &ioctl_write_transferred,
+      is_read ? bytes_to_transfer : sizeof(ULONG),
+      &tmp,
+      &overlapped);
+  }
+
+  // Lets see the result
+  if (!ret && (ERROR_IO_PENDING != GetLastError())) {
+    // I/O failed.
+    return false;
+  }
+
+  // Lets wait till I/O completes
+  ULONG transferred = 0;
+  ret = GetOverlappedResult(usb_handle(), &overlapped, &transferred, TRUE);
+  if (ret && (NULL != bytes_transferred)) {
+    *bytes_transferred = is_ioctl_write ? ioctl_write_transferred :
+                                          transferred;
+  }
+
+  return ret ? true : false;
+}
diff --git a/host/windows/usb/api/adb_io_object.h b/host/windows/usb/api/adb_io_object.h
new file mode 100644
index 0000000..7161b67
--- /dev/null
+++ b/host/windows/usb/api/adb_io_object.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_IO_OBJECT_H__
+#define ANDROID_USB_API_ADB_IO_OBJECT_H__
+/** \file
+  This file consists of declaration of class AdbIOObject that encapsulates an
+  item on our device that is opened for read / write / IOCTL I/O.
+*/
+
+#include "adb_interface.h"
+
+/** Class AdbIOObject encapsulates an item on our device that is opened for
+  read / write / IOCTL I/O.. All I/O items (currently only endpoints) are
+  always opened for overlapped I/O (i.e. FILE_OVERLAPPED flag is set in
+  create attributes). This way each object of the derived class automatically
+  supports both, synchronous as well as asynchronous I/O. Since async I/O
+  requires "giving out" some I/O context, we have to provide async I/O caller
+  with some safe handle to this context. This is done wia allocating
+  AdbIOCompletion object that holds async I/O context and returning handle to
+  this object to the caller of async I/O.
+*/
+class AdbIOObject : public AdbObjectHandle {
+ public:
+  /** \brief Constructs the object
+    
+    @param interface[in] Parent interface for this object. Interface will be
+           referenced in this object's constructur and released in the
+           destructor.
+    @param obj_type[in] Object type from AdbObjectType enum
+  */
+  AdbIOObject(AdbInterfaceObject* parent_interf, AdbObjectType obj_type);
+
+ protected:
+  /** \brief Destructs the object.
+
+    parent_interface_ will be dereferenced here.
+    We hide destructor in order to prevent ourseves from accidentaly allocating
+    instances on the stack. If such attemp occur, compiler will error.
+  */
+  virtual ~AdbIOObject();
+
+ public:
+  /** \brief Opens USB item and creates a handle to this object
+
+    We combine in this method ADB handle association and opening required
+    object on our USB device. The sequence is to open USB item first and if
+    (and only if) this open succeedes we proceed to creating ADB handle by
+    calling AdbObjectHandle::CreateHandle(). We always open USB handle for
+    overlapped I/O.
+    @param item_path[in] Path to the item on our USB device.
+    @param access_type[in] Desired access type. In the current implementation
+          this parameter has no effect on the way item is opened. It's
+          always read / write access.
+    @param sharing_mode[in] Desired share mode. In the current implementation
+          this parameter has no effect on the way item is opened. It's
+          always shared for read / write.
+    @return A handle to this object on success or NULL on an error.
+            If NULL is returned GetLastError() provides extended error
+            information. ERROR_GEN_FAILURE is set if an attempt was
+            made to create already opened object.
+  */
+  virtual ADBAPIHANDLE CreateHandle(const wchar_t* item_path,
+                                    AdbOpenAccessType access_type,
+                                    AdbOpenSharingMode share_mode);
+
+  /** \brief This method is called when handle to this object gets closed
+
+    We overwrite this method in order to close USB handle along with this
+    object handle.
+    @return 'true' on success or 'false' if object is already closed. If
+            'false' is returned GetLastError() provides extended error
+            information.
+  */
+  virtual bool CloseHandle();
+
+  /** \brief Reads from opened I/O object asynchronously
+
+    @param buffer[out] Pointer to the buffer that receives the data.
+    @param bytes_to_read[in] Number of bytes to be read.
+    @param bytes_read[out] Number of bytes read. Can be NULL.
+    @param event_handle[in] Event handle that should be signaled when async I/O
+           completes. Can be NULL. If it's not NULL this handle will be used to
+           initialize OVERLAPPED structure for this I/O.
+    @param time_out[in] A timeout (in milliseconds) required for this I/O to
+           complete. Zero value in this parameter means that there is no
+           timeout set for this I/O.
+    @return A handle to IO completion object or NULL on failure. If NULL is
+            returned GetLastError() provides extended error information.
+  */
+  virtual ADBAPIHANDLE AsyncRead(void* buffer,
+                                 ULONG bytes_to_read,
+                                 ULONG* bytes_read,
+                                 HANDLE event_handle,
+                                 ULONG time_out);
+
+  /** \brief Writes to opened I/O object asynchronously
+
+    @param buffer[in] Pointer to the buffer containing the data to be written.
+    @param bytes_to_write[in] Number of bytes to be written.
+    @param bytes_written[out] Number of bytes written. Can be NULL.
+    @param event_handle[in] Event handle that should be signaled when async I/O
+           completes. Can be NULL. If it's not NULL this handle will be used to
+           initialize OVERLAPPED structure for this I/O.
+    @param time_out[in] A timeout (in milliseconds) required for this I/O to
+           complete. Zero value in this parameter means that there is no
+           timeout set for this I/O.
+    @return A handle to IO completion object or NULL on failure. If NULL is
+            returned GetLastError() provides extended error information.
+  */
+  virtual ADBAPIHANDLE AsyncWrite(void* buffer,
+                                  ULONG bytes_to_write,
+                                  ULONG* bytes_written,
+                                  HANDLE event_handle,
+                                  ULONG time_out);
+
+  /** \brief Reads from opened I/O object synchronously
+
+    @param buffer[out] Pointer to the buffer that receives the data.
+    @param bytes_to_read[in] Number of bytes to be read.
+    @param bytes_read[out] Number of bytes read. Can be NULL.
+    @param time_out[in] A timeout (in milliseconds) required for this I/O to
+           complete. Zero value in this parameter means that there is no
+           timeout set for this I/O.
+    @return 'true' on success and 'false' on failure. If 'false' is
+            returned GetLastError() provides extended error information.
+  */
+  virtual bool SyncRead(void* buffer,
+                        ULONG bytes_to_read,
+                        ULONG* bytes_read,
+                        ULONG time_out);
+
+  /** \brief Writes to opened I/O object synchronously
+
+    @param buffer[in] Pointer to the buffer containing the data to be written.
+    @param bytes_to_write[in] Number of bytes to be written.
+    @param bytes_written[out] Number of bytes written. Can be NULL.
+    @param time_out[in] A timeout (in milliseconds) required for this I/O to
+           complete. Zero value in this parameter means that there is no
+           timeout set for this I/O.
+    @return 'true' on success and 'false' on failure. If 'false' is
+            returned GetLastError() provides extended error information.
+  */
+  virtual bool SyncWrite(void* buffer,
+                         ULONG bytes_to_write,
+                         ULONG* bytes_written,
+                         ULONG time_out);
+
+ protected:
+  /** \brief Common code for async read / write
+
+    @param is_read[in] Read or write selector.
+    @param buffer[in,out] Pointer to the buffer for read / write.
+    @param bytes_to_transfer[in] Number of bytes to be read / written.
+    @param bytes_transferred[out] Number of bytes read / written. Can be NULL.
+    @param event_handle[in] Event handle that should be signaled when async I/O
+           completes. Can be NULL. If it's not NULL this handle will be used to
+           initialize OVERLAPPED structure for this I/O.
+    @param time_out[in] A timeout (in milliseconds) required for this I/O to
+           complete. Zero value in this parameter means that there is no
+           timeout set for this I/O.
+    @return A handle to IO completion object or NULL on failure. If NULL is
+            returned GetLastError() provides extended error information.
+  */
+  virtual ADBAPIHANDLE CommonAsyncReadWrite(bool is_read,
+                                            void* buffer,
+                                            ULONG bytes_to_transfer,
+                                            ULONG* bytes_transferred,
+                                            HANDLE event_handle,
+                                            ULONG time_out);
+
+  /** \brief Common code for sync read / write
+
+    @param is_read[in] Read or write selector.
+    @param buffer[in,out] Pointer to the buffer for read / write.
+    @param bytes_to_transfer[in] Number of bytes to be read / written.
+    @param bytes_transferred[out] Number of bytes read / written. Can be NULL.
+    @param time_out[in] A timeout (in milliseconds) required for this I/O to
+           complete. Zero value in this parameter means that there is no
+           timeout set for this I/O.
+    @return 'true' on success, 'false' on failure. If 'false' is returned
+            GetLastError() provides extended error information.
+  */
+  virtual bool CommonSyncReadWrite(bool is_read,
+                                   void* buffer,
+                                   ULONG bytes_to_transfer,
+                                   ULONG* bytes_transferred,
+                                   ULONG time_out);
+
+ public:
+  /// Gets parent interface 
+  AdbInterfaceObject* parent_interface() const {
+    return parent_interface_;
+  }
+
+  /// Gets parent interface handle
+  ADBAPIHANDLE GetParentInterfaceHandle() const {
+    return (NULL != parent_interface()) ? parent_interface()->adb_handle() :
+                                          NULL;
+  }
+
+  /// Gets handle to an item opened on our USB device
+  HANDLE usb_handle() const {
+    return usb_handle_;
+  }
+
+  /// Checks if USB item is opened
+  bool IsUsbOpened() const {
+    return (INVALID_HANDLE_VALUE != usb_handle());
+  }
+
+  // This is a helper for extracting object from the AdbObjectHandleMap
+  static AdbObjectType Type() {
+    return AdbObjectTypeIo;
+  }
+
+ protected:
+  /// Parent interface
+  AdbInterfaceObject* parent_interface_;
+
+  /// Handle to an item opened on our USB device
+  HANDLE              usb_handle_;
+};
+
+#endif  // ANDROID_USB_API_ADB_IO_OBJECT_H__
diff --git a/host/windows/usb/api/adb_object_handle.cpp b/host/windows/usb/api/adb_object_handle.cpp
new file mode 100644
index 0000000..8c643b4
--- /dev/null
+++ b/host/windows/usb/api/adb_object_handle.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of a class AdbObjectHandle that
+  encapsulates an internal API object that is visible to the outside
+  of the API through a handle.
+*/
+
+#include "stdafx.h"
+#include "adb_api.h"
+#include "adb_object_handle.h"
+
+/// Global ADBAPIHANDLE -> AdbObjectHandle* map
+AdbObjectHandleMap      the_map;
+
+/// Locker for the AdbObjectHandleMap instance
+CComAutoCriticalSection the_map_locker;
+
+/// Next adb handle value generator
+ULONG_PTR               next_adb_handle_value = 0;
+
+AdbObjectHandle::AdbObjectHandle(AdbObjectType obj_type)
+    : adb_handle_(NULL),
+      object_type_(obj_type),
+      ref_count_(1) {
+  ATLASSERT(obj_type < AdbObjectTypeMax);
+}
+
+AdbObjectHandle::~AdbObjectHandle() {
+  ATLASSERT(0 == ref_count_);
+  ATLASSERT(NULL == adb_handle_);
+}
+
+LONG AdbObjectHandle::AddRef() {
+  ATLASSERT(ref_count_ > 0);
+  return InterlockedIncrement(&ref_count_);
+}
+
+LONG AdbObjectHandle::Release() {
+  ATLASSERT(ref_count_ > 0);
+  LONG ret = InterlockedDecrement(&ref_count_);
+  ATLASSERT(ret >= 0);
+  if (0 == ret) {
+    LastReferenceReleased();
+    delete this;
+  }
+  return ret;
+}
+
+ADBAPIHANDLE AdbObjectHandle::CreateHandle() {
+  ADBAPIHANDLE ret = NULL;
+
+  // We have to hold this lock while we're dealing with the handle
+  // and the table
+  the_map_locker.Lock();
+  
+  ATLASSERT(!IsOpened());
+
+  if (!IsOpened()) {
+    try {
+      // Generate next handle value
+      next_adb_handle_value++;
+      ret = reinterpret_cast<ADBAPIHANDLE>(next_adb_handle_value);
+
+      // Add ourselves to the map
+      the_map[ret] = this;
+
+      // Save handle, addref and return
+      adb_handle_ = ret;
+      AddRef();
+    } catch (...) {
+      ret = NULL;
+      SetLastError(ERROR_OUTOFMEMORY);
+    }
+  } else {
+    // Signaling that this object is already opened
+    SetLastError(ERROR_GEN_FAILURE);
+  }
+
+  the_map_locker.Unlock();
+
+  return ret;
+}
+
+bool AdbObjectHandle::CloseHandle() {
+  bool ret = false;
+
+  // Addref just in case that last reference to this object is being
+  // held in the map
+  AddRef();
+
+  the_map_locker.Lock();
+  
+  ATLASSERT(IsOpened());
+
+  if (IsOpened()) {
+    try {
+      // Look us up in the map.
+      AdbObjectHandleMap::iterator found = the_map.find(adb_handle());
+      ATLASSERT((found != the_map.end()) && (this == found->second));
+
+      if ((found != the_map.end()) && (this == found->second)) {
+        // Remove ourselves from the map, close and release the object
+        the_map.erase(found);
+        adb_handle_ = NULL;
+        Release();
+        ret = true;
+      } else {
+        SetLastError(ERROR_INVALID_HANDLE);
+      }
+    } catch (...) {
+      ret = false;
+      SetLastError(ERROR_OUTOFMEMORY);
+    }
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+  }
+
+  the_map_locker.Unlock();
+
+  Release();
+
+  return ret;
+}
+
+bool AdbObjectHandle::IsObjectOfType(AdbObjectType obj_type) const {
+  return (obj_type == object_type());
+}
+
+void AdbObjectHandle::LastReferenceReleased() {
+  ATLASSERT(!IsOpened());
+}
+
+AdbObjectHandle* AdbObjectHandle::Lookup(ADBAPIHANDLE adb_hndl) {
+  AdbObjectHandle* ret = NULL;
+
+  the_map_locker.Lock();
+
+  try {
+    // Look us up in the map.
+    AdbObjectHandleMap::iterator found = the_map.find(adb_hndl);
+    if (found != the_map.end()) {
+      ret = found->second;
+      ret->AddRef();
+    }
+  } catch (...) {
+    SetLastError(ERROR_OUTOFMEMORY);
+  }
+
+  the_map_locker.Unlock();
+
+  return ret;
+}
diff --git a/host/windows/usb/api/adb_object_handle.h b/host/windows/usb/api/adb_object_handle.h
new file mode 100644
index 0000000..088971c
--- /dev/null
+++ b/host/windows/usb/api/adb_object_handle.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_API_ADB_OBJECT_HANDLE_H__
+#define ANDROID_USB_API_ADB_OBJECT_HANDLE_H__
+/** \file
+  This file consists of declaration of a class AdbObjectHandle that
+  encapsulates an internal API object that is visible to the outside
+  of the API through a handle.
+*/
+
+#include "adb_api_private_defines.h"
+
+/** AdbObjectType enum defines types of internal API objects
+*/
+enum AdbObjectType {
+  /// Object is AdbInterfaceEnumObject
+  AdbObjectTypeInterfaceEnumerator,
+
+  /// Object is AdbInterfaceObject
+  AdbObjectTypeInterface,
+
+  /// Object is derived from AdbIOObject
+  AdbObjectTypeIo,
+
+  /// Object is AdbEndpointObject
+  AdbObjectTypeEndpoint,
+
+  /// Object is AdbIOCompletion
+  AdbObjectTypeIoCompletion,
+
+  AdbObjectTypeMax
+};
+
+/** Class AdbObjectHandle encapsulates an internal API basic object that is
+  visible to the outside of the API through a handle. In order to prevent
+  crashes when API client tries to access an object through an invalid or
+  already closed handle, we keep track of all opened handles in
+  AdbObjectHandleMap that maps association between valid ADBAPIHANDLE and
+  an object that this handle represents. All objects that are exposed to the
+  outside of API via ADBAPIHANDLE are self-destructing referenced objects.
+  The reference model for these objects is as such:
+  1. When CreateHandle() method is called on an object, a handle (ADBAPIHANDLE
+     that is) is assigned to it, a pair <handle, object> is added to the global
+     AdbObjectHandleMap instance, object is referenced and then handle is
+     returned to the API client.
+  2. Every time API is called with a handle, a lookup is performed in 
+     AdbObjectHandleMap to find an object that is associated with the handle.
+     If object is not found then ERROR_INVALID_HANDLE is immediatelly returned
+     (via SetLastError() call). If object is found then it is referenced and
+     API call is dispatched to appropriate method of the found object. Upon
+     return from this method, just before returning from the API call, object
+     is dereferenced back to match lookup reference.
+  3. When object handle gets closed, assuming object is found in the map, that
+     <handle, object> pair is deleted from the map and object's refcount is
+     decremented to match refcount increment performed when object has been
+     added to the map.
+  4. When object's refcount drops to zero, the object commits suicide by
+     calling "delete this".
+  All API objects that have handles that are sent back to API client must be
+  derived from this class.
+*/
+class AdbObjectHandle {
+ public:
+  /** \brief Constructs the object
+
+    Refernce counter is set to 1 in the constructor.
+    @param obj_type[in] Object type from AdbObjectType enum
+  */
+  explicit AdbObjectHandle(AdbObjectType obj_type);
+
+ protected:
+  /** \brief Destructs the object.
+
+   We hide destructor in order to prevent ourseves from accidentaly allocating
+   instances on the stack. If such attempt occurs, compiler will error.
+  */
+  virtual ~AdbObjectHandle();
+
+ public:
+  /** \brief References the object
+
+    @return Value of the reference counter after object is referenced in this
+            method.
+  */
+  virtual LONG AddRef();
+
+  /** \brief Releases the object
+
+    If refcount drops to zero as the result of this release, the object is
+    destroyed in this method. As a general rule, objects must not be touched
+    after this method returns even if returned value is not zero.
+    @return Value of the reference counter after object is released in this
+            method.
+  */
+  virtual LONG Release();
+
+  /** \brief Creates handle to this object
+
+    In this call a handle for this object is generated and object is added
+    to the AdbObjectHandleMap.
+    @return A handle to this object on success or NULL on an error.
+            If NULL is returned GetLastError() provides extended error
+            information. ERROR_GEN_FAILURE is set if an attempt was
+            made to create already opened object.
+  */
+  virtual ADBAPIHANDLE CreateHandle();
+
+  /** \brief This method is called when handle to this object gets closed
+
+    In this call object is deleted from the AdbObjectHandleMap.
+    @return 'true' on success or 'false' if object is already closed. If
+            'false' is returned GetLastError() provides extended error
+            information.
+  */
+  virtual bool CloseHandle();
+
+  /** \brief Checks if this object is of the given type
+
+    @param obj_type[in] One of the AdbObjectType types to check
+    @return 'true' is this object type matches obj_type, or 'false' otherwise.
+  */
+  virtual bool IsObjectOfType(AdbObjectType obj_type) const;
+
+  /** \brief Looks up AdbObjectHandle instance associated with the given handle
+    in the AdbObjectHandleMap.
+
+    This method increments reference counter for the returned found object.
+    @param adb_handle[in] ADB handle to the object
+    @return API object associated with the handle or NULL if object is not
+            found. If NULL is returned GetLastError() provides extended error
+            information.
+  */
+  static AdbObjectHandle* Lookup(ADBAPIHANDLE adb_handle);
+
+ protected:
+  /** \brief Called when last reference to this object is released.
+
+    Derived object should override this method to perform cleanup that is not
+    suitable for destructors.
+  */
+  virtual void LastReferenceReleased();
+
+ public:
+  /// Gets ADB handle associated with this object
+  ADBAPIHANDLE adb_handle() const {
+    return adb_handle_;
+  }
+
+  /// Gets type of this object
+  AdbObjectType object_type() const {
+    return object_type_;
+  }
+
+  /// Checks if object is still opened. Note that it is not guaranteed that
+  /// object remains opened when this method returns.
+  bool IsOpened() const {
+    return (NULL != adb_handle());
+  }
+
+ protected:
+  /// API handle associated with this object
+  ADBAPIHANDLE  adb_handle_;
+
+  /// Type of this object
+  AdbObjectType object_type_;
+
+  /// This object's reference counter
+  LONG          ref_count_;
+};
+
+/// Maps ADBAPIHANDLE to associated AdbObjectHandle object
+typedef std::map< ADBAPIHANDLE, AdbObjectHandle* > AdbObjectHandleMap;
+
+/** \brief Template routine that unifies extracting of objects of different
+  types from the AdbObjectHandleMap
+
+  @param adb_handle[in] API handle for the object
+  @return Object associated with the handle or NULL on error. If NULL is
+          returned GetLastError() provides extended error information.
+*/
+template<class obj_class>
+obj_class* LookupObject(ADBAPIHANDLE adb_handle) {
+  // Lookup object for the handle in the map
+  AdbObjectHandle* adb_object = AdbObjectHandle::Lookup(adb_handle);
+  if (NULL != adb_object) {
+    // Make sure it's of the correct type
+    if (!adb_object->IsObjectOfType(obj_class::Type())) {
+      adb_object->Release();
+      adb_object = NULL;
+      SetLastError(ERROR_INVALID_HANDLE);
+    }
+  } else {
+    SetLastError(ERROR_INVALID_HANDLE);
+  }
+  return (adb_object != NULL) ? reinterpret_cast<obj_class*>(adb_object) :
+                                NULL;
+}
+
+#endif  // ANDROID_USB_API_ADB_OBJECT_HANDLE_H__
diff --git a/host/windows/usb/api/stdafx.cpp b/host/windows/usb/api/stdafx.cpp
new file mode 100644
index 0000000..87db2cd
--- /dev/null
+++ b/host/windows/usb/api/stdafx.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// stdafx.cpp : source file that includes just the standard includes
+// AdbWinApi.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/host/windows/usb/api/stdafx.h b/host/windows/usb/api/stdafx.h
new file mode 100644
index 0000000..f47936f
--- /dev/null
+++ b/host/windows/usb/api/stdafx.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  Visual Studio generated include file for standard system include files, or
+  project specific include files that are used frequently, but are changed
+  infrequently.
+*/
+
+#pragma once
+
+#ifndef STRICT
+#define STRICT
+#endif
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER				// Allow use of features specific to Windows 95 and Windows NT 4 or later.
+#define WINVER 0x0500		// Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
+#endif
+
+#ifndef _WIN32_WINNT		// Allow use of features specific to Windows NT 4 or later.
+#define _WIN32_WINNT 0x0500	// Change this to the appropriate value to target Windows 2000 or later.
+#endif						
+
+#ifndef _WIN32_WINDOWS		// Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0500 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE			// Allow use of features specific to IE 4.0 or later.
+#define _WIN32_IE 0x0501	// Change this to the appropriate value to target IE 5.0 or later.
+#endif
+
+#define _ATL_APARTMENT_THREADED
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
+
+// turns off ATL's hiding of some common and often safely ignored warning messages
+#define _ATL_ALL_WARNINGS
+
+#pragma warning(disable: 4702)
+#include "resource.h"
+#include <atlbase.h>
+#include <atlcom.h>
+#include <winioctl.h>
+#include <setupapi.h>
+#include <vector>
+#include <map>
+#include <string>
+#pragma warning(disable: 4200)
+extern "C" {
+#include <usbdi.h>
+}
+
+#include "android_usb_common_defines.h"
+
+using namespace ATL;
diff --git a/host/windows/usb/common/android_usb_common_defines.h b/host/windows/usb/common/android_usb_common_defines.h
new file mode 100644
index 0000000..abdeba7
--- /dev/null
+++ b/host/windows/usb/common/android_usb_common_defines.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_COMMON_DEFINES_H__
+#define ANDROID_USB_COMMON_DEFINES_H__
+/** \file
+  This file consists of declarations common for both, User and Kernel mode
+  parts of the system.
+*/
+
+/// Name for the default bulk read pipe
+#define DEVICE_BULK_READ_PIPE_NAME  L"BulkRead"
+
+/// Name for the default bulk write pipe
+#define DEVICE_BULK_WRITE_PIPE_NAME L"BulkWrite"
+
+/// Prefix for an index-based pipe name 
+#define DEVICE_PIPE_NAME_PREFIX     L"PIPE_"
+
+/** \name IOCTL codes for the driver
+*/
+///@{
+
+/// Control code for IOCTL that gets USB_DEVICE_DESCRIPTOR
+#define ADB_CTL_GET_USB_DEVICE_DESCRIPTOR         10
+
+/// Control code for IOCTL that gets USB_CONFIGURATION_DESCRIPTOR
+#define ADB_CTL_GET_USB_CONFIGURATION_DESCRIPTOR  11
+
+/// Control code for IOCTL that gets USB_INTERFACE_DESCRIPTOR
+#define ADB_CTL_GET_USB_INTERFACE_DESCRIPTOR      12
+
+/// Control code for IOCTL that gets endpoint information
+#define ADB_CTL_GET_ENDPOINT_INFORMATION          13
+
+/// Control code for bulk read IOCTL
+#define ADB_CTL_BULK_READ                         14
+
+/// Control code for bulk write IOCTL
+#define ADB_CTL_BULK_WRITE                        15
+
+/// Control code for IOCTL that gets device serial number
+#define ADB_CTL_GET_SERIAL_NUMBER                 16
+
+/// IOCTL that gets USB_DEVICE_DESCRIPTOR
+#define ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR \
+              CTL_CODE(FILE_DEVICE_UNKNOWN, \
+                       ADB_CTL_GET_USB_DEVICE_DESCRIPTOR, \
+                       METHOD_BUFFERED, \
+                       FILE_ANY_ACCESS)
+
+/// IOCTL that gets USB_CONFIGURATION_DESCRIPTOR
+#define ADB_IOCTL_GET_USB_CONFIGURATION_DESCRIPTOR \
+              CTL_CODE(FILE_DEVICE_UNKNOWN, \
+                       ADB_CTL_GET_USB_CONFIGURATION_DESCRIPTOR, \
+                       METHOD_BUFFERED, \
+                       FILE_ANY_ACCESS)
+
+/// IOCTL that gets USB_INTERFACE_DESCRIPTOR
+#define ADB_IOCTL_GET_USB_INTERFACE_DESCRIPTOR \
+              CTL_CODE(FILE_DEVICE_UNKNOWN, \
+                       ADB_CTL_GET_USB_INTERFACE_DESCRIPTOR, \
+                       METHOD_BUFFERED, \
+                       FILE_ANY_ACCESS)
+
+/// IOCTL that gets endpoint information
+#define ADB_IOCTL_GET_ENDPOINT_INFORMATION \
+              CTL_CODE(FILE_DEVICE_UNKNOWN, \
+                       ADB_CTL_GET_ENDPOINT_INFORMATION, \
+                       METHOD_BUFFERED, \
+                       FILE_ANY_ACCESS)
+
+/// Bulk read IOCTL
+#define ADB_IOCTL_BULK_READ \
+              CTL_CODE(FILE_DEVICE_UNKNOWN, \
+                       ADB_CTL_BULK_READ, \
+                       METHOD_OUT_DIRECT, \
+                       FILE_ANY_ACCESS)
+
+// For bulk write IOCTL we send request data in the form of AdbBulkTransfer
+// structure and output buffer is just ULONG that receives number of bytes
+// actually written. Since both of these are tiny we can use buffered I/O
+// for this IOCTL.
+/// Bulk write IOCTL
+#define ADB_IOCTL_BULK_WRITE \
+              CTL_CODE(FILE_DEVICE_UNKNOWN, \
+                       ADB_CTL_BULK_WRITE, \
+                       METHOD_BUFFERED, \
+                       FILE_ANY_ACCESS)
+
+/// IOCTL that gets device serial number
+#define ADB_IOCTL_GET_SERIAL_NUMBER \
+              CTL_CODE(FILE_DEVICE_UNKNOWN, \
+                       ADB_CTL_GET_SERIAL_NUMBER, \
+                       METHOD_BUFFERED, \
+                       FILE_ANY_ACCESS)
+
+///@}
+
+/** Structure AdbQueryEndpointInformation formats input for
+  ADB_IOCTL_GET_ENDPOINT_INFORMATION IOCTL request
+*/
+struct AdbQueryEndpointInformation {
+  /// Zero-based endpoint index for which information is queried.
+  /// See ADB_QUERY_BULK_xxx_ENDPOINT_INDEX for shortcuts.
+  UCHAR endpoint_index;
+};
+
+/** Structure AdbBulkTransfer formats parameters for ADB_CTL_BULK_READ and
+  ADB_CTL_BULK_WRITE IOCTL requests.
+*/
+struct AdbBulkTransfer {
+  /// Time in milliseconds to complete this request
+  ULONG time_out;
+
+  /// Size of the data to transfer. This parameter is used only for
+  /// ADB_CTL_BULK_WRITE request. For ADB_CTL_BULK_READ requests transfer
+  /// size is defined by the output buffer size.
+  ULONG transfer_size;
+
+  /// Pointer to the actual buffer for ADB_CTL_BULK_WRITE request. This field
+  /// is not used in ADB_CTL_BULK_READ request.
+  void* write_buffer;
+};
+
+#endif  // ANDROID_USB_COMMON_DEFINES_H__
diff --git a/host/windows/usb/driver/android_usb.inf b/host/windows/usb/driver/android_usb.inf
new file mode 100644
index 0000000..69a9491
--- /dev/null
+++ b/host/windows/usb/driver/android_usb.inf
@@ -0,0 +1,113 @@
+;/*++
+;
+;Abstract:
+;    Installation inf for the Android USB Bulk device
+;
+;--*/
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=USB
+ClassGuid={F72FE0D4-CBCB-407d-8814-9ED673D0DD6B}
+Provider=%GOOG%
+DriverVer=date,1.0.0009.00000
+CatalogFile=androidusb.cat
+
+; ================= Class section =====================
+
+[ClassInstall32]
+Addreg=AndroidUsbClassReg
+
+[AndroidUsbClassReg]
+HKR,,,0,%ClassName%
+HKR,,Icon,,-5
+
+[DestinationDirs]
+DefaultDestDir = 12
+
+; ================= Device section =====================
+
+[Manufacturer]
+%MfgName%=Google,NTx86
+
+; For Win2K
+[Google]
+; For loopback testing
+%USB\VID_18D1&PID_DDDD.DeviceDescTest%=androidusb.Dev, USB\VID_18D1&PID_DDDD
+; HTC Dream
+%USB\VID_0BB4&PID_0C01.DeviceDescRelease%=androidusb.Dev, USB\VID_0BB4&PID_0C01
+%USB\VID_0BB4&PID_0C02&MI_01.DeviceDescRelease%=androidusb.Dev, USB\VID_0BB4&PID_0C02&MI_01
+
+; For XP and later
+[Google.NTx86]
+; For loopback testing
+%USB\VID_18D1&PID_DDDD.DeviceDescTest%=androidusb.Dev, USB\VID_18D1&PID_DDDD
+; HTC Dream
+%USB\VID_0BB4&PID_0C01.DeviceDescRelease%=androidusb.Dev, USB\VID_0BB4&PID_0C01
+%USB\VID_0BB4&PID_0C02&MI_01.DeviceDescRelease%=androidusb.Dev, USB\VID_0BB4&PID_0C02&MI_01
+
+[androidusb.Dev.NT]
+CopyFiles=androidusb.Files.Ext
+
+[androidusb.Dev.NT.Services]
+Addservice = androidusb, 0x00000002, androidusb.AddService
+
+[androidusb.AddService]
+DisplayName    = %androidusb.SvcDesc%
+ServiceType    = 1                  ; SERVICE_KERNEL_DRIVER
+StartType      = 3                  ; SERVICE_DEMAND_START
+ErrorControl   = 1                  ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %10%\System32\Drivers\androidusb.sys
+AddReg         = androidusb.AddReg
+LoadOrderGroup = Base
+
+[androidusb.AddReg]
+HKR,"Parameters","MaximumTransferSize",0x10001,4096
+HKR,"Parameters","DebugLevel",0x10001,2
+HKR, Parameters\Wdf, VerboseOn,       0x00010001, 1
+HKR, Parameters\Wdf, VerifierOn,      0x00010001, 1
+HKR, Parameters\Wdf, DbgBreakOnError, 0x00010001, 1
+
+[androidusb.Files.Ext]
+androidusb.sys
+
+[SourceDisksNames]
+1=%Disk_Description%,,,
+
+[SourceDisksFiles]
+androidusb.sys = 1
+
+;-------------- WDF Coinstaller installation
+[DestinationDirs]
+CoInstaller_CopyFiles = 11
+
+[androidusb.Dev.NT.CoInstallers]
+AddReg=CoInstaller_AddReg
+CopyFiles=CoInstaller_CopyFiles
+
+[CoInstaller_CopyFiles]
+wdfcoinstaller01005.dll
+
+[SourceDisksFiles]
+wdfcoinstaller01005.dll=1 ; make sure the number matches with SourceDisksNames
+
+[CoInstaller_AddReg]
+HKR,,CoInstallers32,0x00010000, "wdfcoinstaller01005.dll,WdfCoInstaller"
+
+[androidusb.Dev.NT.Wdf]
+KmdfService = androidusb, androidusb_wdfsect
+
+[androidusb_wdfsect]
+KmdfLibraryVersion = 1.5
+
+;---------------------------------------------------------------;
+
+[Strings]
+GOOG            = "Google, Inc"
+MfgName         = "Google, Inc"
+Disk_Description= "ADB Interface Installation Disk"
+androidusb.SvcDesc = "ADB Interface Driver"
+ClassName       = "ADB Interface"
+USB\VID_18D1&PID_DDDD.DeviceDescTest="ADB Testing Interface"
+USB\VID_0BB4&PID_0C01.DeviceDescRelease="HTC Dream"
+USB\VID_0BB4&PID_0C02&MI_01.DeviceDescRelease="HTC Dream Composite ADB Interface"
diff --git a/host/windows/usb/driver/android_usb.rc b/host/windows/usb/driver/android_usb.rc
new file mode 100644
index 0000000..3b19416
--- /dev/null
+++ b/host/windows/usb/driver/android_usb.rc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <windows.h>
+
+// Don't let the resource editor in here
+#ifdef APSTUDIO_INVOKED
+    #error this file is not editable by Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+#define VER_FILETYPE    VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR     "ADB Interface"
+#define VER_INTERNALNAME_STR        "androidusb.sys"
+#define VER_ORIGINALFILENAME_STR    "androidusb.sys"
+#define VER_FILEOS VOS_NT
+#define VER_FILEFLAGSMASK (VS_FF_DEBUG | VS_FF_PRERELEASE)
+
+#if DBG
+  #define VER_FILEFLAGS     VS_FF_DEBUG | VS_FF_PRERELEASE
+#else  // DBG
+  #define VER_FILEFLAGS     VS_FF_PRERELEASE
+#endif // DBG
+
+#include "common.ver"
diff --git a/host/windows/usb/driver/android_usb.sln b/host/windows/usb/driver/android_usb.sln
new file mode 100644
index 0000000..1c5193e
--- /dev/null
+++ b/host/windows/usb/driver/android_usb.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android_usb", "android_usb.vcproj", "{D980BE56-A7AB-4E05-919B-677FB7716307}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{D980BE56-A7AB-4E05-919B-677FB7716307}.Debug.ActiveCfg = Debug|Win32
+		{D980BE56-A7AB-4E05-919B-677FB7716307}.Debug.Build.0 = Debug|Win32
+		{D980BE56-A7AB-4E05-919B-677FB7716307}.Release.ActiveCfg = Release|Win32
+		{D980BE56-A7AB-4E05-919B-677FB7716307}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
diff --git a/host/windows/usb/driver/android_usb.vcproj b/host/windows/usb/driver/android_usb.vcproj
new file mode 100644
index 0000000..5c21aa4
--- /dev/null
+++ b/host/windows/usb/driver/android_usb.vcproj
@@ -0,0 +1,1186 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="android_usb"
+	ProjectGUID="{D980BE56-A7AB-4E05-919B-677FB7716307}"
+	RootNamespace="android_usb"
+	Keyword="MakeFileProj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="0">
+			<Tool
+				Name="VCNMakeTool"
+				BuildCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ chk WXP
+set PROJECTDIR=$(ProjectDir)
+set DRIVE=%PROJECTDIR:~0,2%
+%DRIVE%
+cd %PROJECTDIR%
+build -beEIFZ
+cd %PROJECTDIR%
+copy android_usb.inf ..\build\debug\i386\android_usb.inf"
+				ReBuildCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ chk WXP
+set PROJECTDIR=$(ProjectDir)
+set DRIVE=%PROJECTDIR:~0,2%
+%DRIVE%
+cd %PROJECTDIR%
+build -cbeEIFZ
+cd %PROJECTDIR%
+copy android_usb.inf ..\build\debug\i386\android_usb.inf
+cd ..\build\debug\i386
+set Path=%Path%;$(VCInstallDir)bin;$(VSInstallDir)Common7\IDE
+dumpbin /ALL /OUT:androidusb.txt androidusb.sys
+"
+				CleanCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ chk WXP
+set PROJECTDIR=$(ProjectDir)
+set DRIVE=%PROJECTDIR:~0,2%
+%DRIVE%
+cd %PROJECTDIR%
+build -c0
+"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="0">
+			<Tool
+				Name="VCNMakeTool"
+				BuildCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ free WXP
+set PROJECTDIR=$(ProjectDir)
+set DRIVE=%PROJECTDIR:~0,2%
+%DRIVE%
+cd %PROJECTDIR%
+build -beEIFZ
+cd %PROJECTDIR%
+copy android_usb.inf ..\build\release\i386\android_usb.inf"
+				ReBuildCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ free WXP
+set PROJECTDIR=$(ProjectDir)
+set DRIVE=%PROJECTDIR:~0,2%
+%DRIVE%
+cd %PROJECTDIR%
+build -cbeEIFZ
+cd %PROJECTDIR%
+copy android_usb.inf ..\build\release\i386\android_usb.inf"
+				CleanCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ free WXP
+set PROJECTDIR=$(ProjectDir)
+set DRIVE=%PROJECTDIR:~0,2%
+%DRIVE%
+cd %PROJECTDIR%
+build -c0
+"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\android_usb_device_object.cpp">
+			</File>
+			<File
+				RelativePath=".\android_usb_driver_object.cpp">
+			</File>
+			<File
+				RelativePath=".\android_usb_wdf_object.cpp">
+			</File>
+			<Filter
+				Name="File"
+				Filter="">
+				<File
+					RelativePath=".\android_usb_bulk_file_object.cpp">
+				</File>
+				<File
+					RelativePath=".\android_usb_device_file_object.cpp">
+				</File>
+				<File
+					RelativePath=".\android_usb_file_object.cpp">
+				</File>
+				<File
+					RelativePath=".\android_usb_interrupt_file_object.cpp">
+				</File>
+				<File
+					RelativePath=".\android_usb_pipe_file_object.cpp">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\android_usb_device_object.h">
+			</File>
+			<File
+				RelativePath=".\android_usb_driver_defines.h">
+			</File>
+			<File
+				RelativePath=".\android_usb_driver_object.h">
+			</File>
+			<File
+				RelativePath=".\android_usb_inl.h">
+			</File>
+			<File
+				RelativePath=".\android_usb_new_delete.h">
+			</File>
+			<File
+				RelativePath=".\android_usb_pool_tags.h">
+			</File>
+			<File
+				RelativePath=".\android_usb_wdf_object.h">
+			</File>
+			<File
+				RelativePath=".\precomp.h">
+			</File>
+			<Filter
+				Name="DDK"
+				Filter="">
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\1394.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\61883.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\accctrl.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\acpiioct.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\amtvuids.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ata.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\atm.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\aux_klib.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\avc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\avcstrm.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\backpack.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\bdasup.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\bthddi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\bthguid.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\bthioctl.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\bthref.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\bthsdpddi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\buffring.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\classpnp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\clfs.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\clfslsn.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\clfsmsg.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\cloneviewhelper.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\cloneviewhelper.idl">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\codecapi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\csq.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\d3dhal.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\d3dhalex.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\d3dkmdt.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\d3dukmdt.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\d3dvec.inl">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\d4drvif.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\d4iface.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dciddi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dciman.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dderror.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dispmprt.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dmusicks.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dmusics.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dmusprop.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\driverspecs.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\drivinit.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\drmk.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dsfhrmports.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dsfif.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dxapi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\dxva9typ.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ExDispid.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\fcb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\fcbtable.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\filterpipeline.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\filterpipelineutil.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\fltKernel.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\fltsafe.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\fltUser.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\fltUserStructures.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\fltWinError.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\fsctlbuf.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\hbaapi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\hbapiwmi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\hdaudio.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\hidclass.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\hidpddi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\hidport.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\hubbusif.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\i2cgpio.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\imgerror.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\imgerror.idl">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ioaccess.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iointex.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ip6firewall.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ipfirewall.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ipinfo.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\irb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\irclass_ioctl.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iscsicfg.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iscsidef.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iscsierr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iscsifnd.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iscsilog.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iscsimgt.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iscsiop.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\iscsiprf.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\isvbop.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\isvbop.inc">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\kbdmou.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ksi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\lmstats.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\lmuseflg.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\lmwksta.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\lowio.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mcd.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mce.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mf.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\midatlax.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\miniport.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\minitape.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mmc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mountdev.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mountmgr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mrx.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mrxfcb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\msdadc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\msdaguid.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\msdasc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mshtmhst.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\mshtml.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\msviddrv.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\namcache.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ndis.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ndisguid.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ndistapi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ndiswan.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ndr64types.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\netioddk.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\netpnp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\nodetype.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\npapi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntagp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntddk.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntddnlb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntddpcm.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntddsd.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntddsfio.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntifs.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntimage.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntintsafe.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntlmsp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntnls.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntpoapi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntrxdef.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntsam.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\ntstatus.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\api\ntstatus.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ntstrsafe.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\oledberr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\oprghdlr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\parallel.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\pciprop.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\pfhook.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\poclass.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\portabledevice.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\portabledeviceclassextension.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\portabledeviceclassextension.idl">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\portabledevicetypes.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\portabledevicetypes.idl">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\portcls.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\prefix.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\prnasnot.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ptpusd.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\punknown.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rdbss.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\richedit.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\richole.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rx.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxassert.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxce.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxcehdlr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxcommon.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxcontx.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxdata.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxdebug.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxexcept.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxlog.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxovride.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxpooltg.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxprocs.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxstruc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxtimer.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxtrace.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxtypes.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\rxworkq.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\scarderr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\scavengr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\scsi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\scsiscan.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\scsiwmi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\sddef.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\sdplib.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\sdpnode.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\sffdisk.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\sffprtcl.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\softehciif.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\softhidusbif.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\softusbif.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\srb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\stdcall.inc">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\stdunk.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\stiusd.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\storduid.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\storport.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\storswtr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\stortrce.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\strmini.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\struchdr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\swenum.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\tdikrnl.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\tdistat.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\upssvc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\usb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\api\usb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\usb100.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\api\usb100.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\usb200.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\usbbusif.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\api\usbdi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\usbdlib.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\usbdrivr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\usbkern.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\usbprint.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\USBProtocolDefs.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\usbscan.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\vcclr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\vfwext.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\video.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\videoagp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdf.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdf.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdf10.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdf10.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdf11.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdf11.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfassert.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfassert.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfbugcodes.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfbugcodes.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfchildlist.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfchildlist.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfcollection.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfcollection.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfcommonbuffer.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfcommonbuffer.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfcontrol.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfcontrol.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfcore.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfcore.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdevice.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdevice.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdmaenabler.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdmaenabler.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdmatransaction.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdmatransaction.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdpc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdpc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdriver.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfdriver.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdffdo.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdffdo.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdffileobject.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdffileobject.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdffuncenum.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdffuncenum.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfglobals.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfglobals.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfinstaller.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfinstaller.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfinterrupt.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfinterrupt.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfio.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfio.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfiotarget.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfiotarget.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfmemory.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfmemory.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfminiport.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfminiport.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfobject.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfobject.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfpdo.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfpdo.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfpool.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfpool.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfqueryinterface.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfqueryinterface.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfregistry.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfregistry.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfrequest.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfrequest.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfresource.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfresource.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfstatus.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfstatus.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfstring.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfstring.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfsync.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfsync.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdftimer.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdftimer.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdftraceenums.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdftraceenums.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdftypes.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdftypes.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfusb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfusb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfverifier.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfverifier.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfwmi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfwmi.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfworkitem.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\wdf\kmdf\10\wdfworkitem.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wdm.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\..\..\..\..\Winddk\6000\inc\ddk\wdm.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wdmguid.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wdmsec.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wdmwarn4.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wia_lh.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wia_xp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wiaintfc.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wiamdef.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wiamicro.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wiamindr.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wiamindr_lh.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wiamindr_xp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wiatwcmp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wiautil.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\WindowsSideShow.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\WindowsSideShowClassExtension.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\WindowsSideShowDriverEvents.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\Winusb.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\Winusbio.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wmidata.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wmiguid.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wmilib.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ws2san.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\ws2sdp.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\wsk.h">
+				</File>
+				<File
+					RelativePath="..\..\..\..\Winddk\6000\inc\ddk\xfilter.h">
+				</File>
+			</Filter>
+			<Filter
+				Name="File"
+				Filter="">
+				<File
+					RelativePath=".\android_usb_bulk_file_object.h">
+				</File>
+				<File
+					RelativePath=".\android_usb_device_file_object.h">
+				</File>
+				<File
+					RelativePath=".\android_usb_file_object.h">
+				</File>
+				<File
+					RelativePath=".\android_usb_interrupt_file_object.h">
+				</File>
+				<File
+					RelativePath=".\android_usb_pipe_file_object.h">
+				</File>
+			</Filter>
+			<Filter
+				Name="common"
+				Filter="">
+				<File
+					RelativePath="..\api\adb_api_extra.h">
+				</File>
+				<File
+					RelativePath="..\common\android_usb_common_defines.h">
+				</File>
+			</Filter>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+			<File
+				RelativePath=".\android_usb.rc">
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\android_usb.inf">
+		</File>
+		<File
+			RelativePath=".\makefile">
+		</File>
+		<File
+			RelativePath=".\makefile.inc">
+		</File>
+		<File
+			RelativePath=".\sources">
+		</File>
+		<File
+			RelativePath=".\sources.inc">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/host/windows/usb/driver/android_usb_bulk_file_object.cpp b/host/windows/usb/driver/android_usb_bulk_file_object.cpp
new file mode 100644
index 0000000..9b3a59c
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_bulk_file_object.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AndroidUsbBulkPipeFileObject
+  that encapsulates extension to a bulk pipe file objects.
+*/
+#pragma data_seg()
+#pragma code_seg()
+
+#include "precomp.h"
+#include "android_usb_bulk_file_object.h"
+
+#pragma data_seg()
+#pragma code_seg("PAGE")
+
+AndroidUsbBulkPipeFileObject::AndroidUsbBulkPipeFileObject(
+    AndroidUsbDeviceObject* dev_obj,
+    WDFFILEOBJECT wdf_fo,
+    WDFUSBPIPE wdf_pipe_obj)
+    : AndroidUsbPipeFileObject(dev_obj, wdf_fo, wdf_pipe_obj) {
+  ASSERT_IRQL_PASSIVE();
+
+#if DBG
+  WDF_USB_PIPE_INFORMATION pipe_info;
+  WDF_USB_PIPE_INFORMATION_INIT(&pipe_info);
+  WdfUsbTargetPipeGetInformation(wdf_pipe_obj, &pipe_info);
+  ASSERT(WdfUsbPipeTypeBulk == pipe_info.PipeType);
+#endif  // DBG
+}
+
+#pragma code_seg()
+
+AndroidUsbBulkPipeFileObject::~AndroidUsbBulkPipeFileObject() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+}
+
+#pragma data_seg()
+#pragma code_seg()
diff --git a/host/windows/usb/driver/android_usb_bulk_file_object.h b/host/windows/usb/driver/android_usb_bulk_file_object.h
new file mode 100644
index 0000000..8b75eee
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_bulk_file_object.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_BULK_PIPE_FILE_OBJECT_H__
+#define ANDROID_USB_BULK_PIPE_FILE_OBJECT_H__
+/** \file
+  This file consists of declaration of class AndroidUsbBulkPipeFileObject
+  that encapsulates extension to a bulk pipe file objects.
+*/
+
+#include "android_usb_pipe_file_object.h"
+
+/** AndroidUsbBulkPipeFileObject class encapsulates extension to a KMDF file
+  object that represent opened bulk pipe. Instances of this class must be
+  allocated from NonPagedPool.
+*/
+class AndroidUsbBulkPipeFileObject : public AndroidUsbPipeFileObject {
+ public:
+  /** \brief Constructs the object.
+
+    This method must be called at low IRQL.
+    @param dev_obj[in] Our device object for which this file has been created
+    @param wdf_fo[in] KMDF file object this extension wraps
+    @param wdf_pipe_obj[in] KMDF pipe for this file
+  */
+  AndroidUsbBulkPipeFileObject(AndroidUsbDeviceObject* dev_obj,
+                               WDFFILEOBJECT wdf_fo,
+                               WDFUSBPIPE wdf_pipe_obj);
+
+  /** \brief Destructs the object.
+
+    This method can be called at any IRQL.
+  */
+   virtual ~AndroidUsbBulkPipeFileObject();
+};
+
+#endif  // ANDROID_USB_BULK_PIPE_FILE_OBJECT_H__
diff --git a/host/windows/usb/driver/android_usb_device_file_object.cpp b/host/windows/usb/driver/android_usb_device_file_object.cpp
new file mode 100644
index 0000000..0655aed
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_device_file_object.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AndroidUsbDeviceFileObject
+  that encapsulates an extension for a KMDF file object that represent
+  opened device.
+*/
+#pragma data_seg()
+#pragma code_seg()
+
+#include "precomp.h"
+#include "android_usb_device_file_object.h"
+
+#pragma data_seg()
+#pragma code_seg("PAGE")
+
+AndroidUsbDeviceFileObject::AndroidUsbDeviceFileObject(
+    AndroidUsbDeviceObject* dev_obj,
+    WDFFILEOBJECT wdf_fo)
+    : AndroidUsbFileObject(AndroidUsbFileObjectTypeDevice, dev_obj, wdf_fo) {
+  ASSERT_IRQL_PASSIVE();
+}
+
+#pragma code_seg()
+
+AndroidUsbDeviceFileObject::~AndroidUsbDeviceFileObject() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+}
+
+void AndroidUsbDeviceFileObject::OnEvtIoDeviceControl(WDFREQUEST request,
+                                                      size_t output_buf_len,
+                                                      size_t input_buf_len,
+                                                      ULONG ioctl_code) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  switch (GetCtlCode(ioctl_code)) {
+    case ADB_CTL_GET_USB_DEVICE_DESCRIPTOR:
+      device_object()->OnGetUsbDeviceDescriptorCtl(request, output_buf_len);
+      break;
+
+    case ADB_CTL_GET_USB_CONFIGURATION_DESCRIPTOR:
+      device_object()->OnGetUsbConfigDescriptorCtl(request, output_buf_len);
+      break;
+
+    case ADB_CTL_GET_USB_INTERFACE_DESCRIPTOR:
+      device_object()->OnGetUsbInterfaceDescriptorCtl(request, output_buf_len);
+      break;
+
+    case ADB_CTL_GET_ENDPOINT_INFORMATION:
+      device_object()->OnGetEndpointInformationCtl(request,
+                                                   input_buf_len,
+                                                   output_buf_len);
+      break;
+
+    case ADB_CTL_GET_SERIAL_NUMBER:
+      device_object()->OnGetSerialNumberCtl(request, output_buf_len);
+      break;
+
+    default:
+      AndroidUsbFileObject::OnEvtIoDeviceControl(request,
+                                                 output_buf_len,
+                                                 input_buf_len,
+                                                 ioctl_code);
+      break;
+  }
+}
+
+#pragma data_seg()
+#pragma code_seg()
diff --git a/host/windows/usb/driver/android_usb_device_file_object.h b/host/windows/usb/driver/android_usb_device_file_object.h
new file mode 100644
index 0000000..c40bb50
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_device_file_object.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_DEVICE_FILE_OBJECT_H__
+#define ANDROID_USB_DEVICE_FILE_OBJECT_H__
+/** \file
+  This file consists of declaration of class AndroidUsbDeviceFileObject that
+  encapsulates an extension for a KMDF file object that represent opened
+  device.
+*/
+
+#include "android_usb_file_object.h"
+
+/** AndroidUsbDeviceFileObject class encapsulates an extension for a KMDF
+  file object that represent opened device. Instances of this class must be
+  allocated from NonPagedPool.
+*/
+class AndroidUsbDeviceFileObject : public AndroidUsbFileObject  {
+ public:
+  /** \brief Constructs the object.
+
+    This method must be called at low IRQL.
+    @param dev_obj[in] Our device object for which this file has been created
+    @param wdf_fo[in] KMDF file object this extension wraps
+  */
+  AndroidUsbDeviceFileObject(AndroidUsbDeviceObject* dev_obj,
+                             WDFFILEOBJECT wdf_fo);
+
+  /** \brief Destructs the object.
+
+    This method can be called at any IRQL.
+  */
+   virtual ~AndroidUsbDeviceFileObject();
+
+  /** \brief IOCTL event handler
+
+    This method is called when a device control request comes to the file
+    object this extension wraps. We override this method to handle the
+    following IOCTL requests:
+      1. ADB_CTL_GET_USB_DEVICE_DESCRIPTOR
+      2. ADB_CTL_GET_USB_CONFIGURATION_DESCRIPTOR
+      3. ADB_CTL_GET_USB_INTERFACE_DESCRIPTOR
+      4. ADB_CTL_GET_ENDPOINT_INFORMATION
+    This callback can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+    @param input_buf_len[in] The length, in bytes, of the request's input
+           buffer, if an input buffer is available.
+    @param ioctl_code[in] The driver-defined or system-defined I/O control code
+           that is associated with the request.
+    @return Successful status or an appropriate error code
+  */
+  virtual void OnEvtIoDeviceControl(WDFREQUEST request,
+                                    size_t output_buf_len,
+                                    size_t input_buf_len,
+                                    ULONG ioctl_code);
+};
+
+#endif  // ANDROID_USB_DEVICE_FILE_OBJECT_H__
diff --git a/host/windows/usb/driver/android_usb_device_object.cpp b/host/windows/usb/driver/android_usb_device_object.cpp
new file mode 100644
index 0000000..b20c1b7
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_device_object.cpp
@@ -0,0 +1,1216 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AndroidUsbDeviceObject that
+  encapsulates an extension for KMDF device (FDO) object.
+*/
+#pragma data_seg()
+#pragma code_seg()
+
+#include "precomp.h"
+#include "android_usb_device_object.h"
+#include "android_usb_file_object.h"
+#include "android_usb_device_file_object.h"
+#include "android_usb_pipe_file_object.h"
+#include "android_usb_bulk_file_object.h"
+#include "android_usb_interrupt_file_object.h"
+
+#pragma data_seg()
+
+/// Buffer for bulk read pipe name
+const WCHAR bulk_read_pipe_str[] = L"\\" DEVICE_BULK_READ_PIPE_NAME;
+
+/// Unicode string for bulk read pipe name
+UNICODE_STRING bulk_read_pipe_name = {
+  sizeof(bulk_read_pipe_str) - sizeof(WCHAR),
+  sizeof(bulk_read_pipe_str) - sizeof(WCHAR),
+  const_cast<PWSTR>(bulk_read_pipe_str)
+};
+
+/// Buffer for bulk write pipe name
+const WCHAR bulk_write_pipe_str[] = L"\\" DEVICE_BULK_WRITE_PIPE_NAME;
+
+/// Unicode string for bulk write pipe name
+UNICODE_STRING bulk_write_pipe_name = {
+  sizeof(bulk_write_pipe_str) - sizeof(WCHAR),
+  sizeof(bulk_write_pipe_str) - sizeof(WCHAR),
+  const_cast<PWSTR>(bulk_write_pipe_str)
+};
+
+/// Buffer for an index-based pipe name prefix
+const WCHAR index_pipe_prefix_str[] = L"\\" DEVICE_PIPE_NAME_PREFIX;
+
+/// Unicode string for index-based pipe name prefix
+UNICODE_STRING index_pipe_prefix = {
+  sizeof(index_pipe_prefix_str) - sizeof(WCHAR),
+  sizeof(index_pipe_prefix_str) - sizeof(WCHAR),
+  const_cast<PWSTR>(index_pipe_prefix_str)
+};
+
+/// GUID that sets class ID for our device
+const GUID android_guid = ANDROID_USB_CLASS_ID;
+
+#pragma code_seg("PAGE")
+
+AndroidUsbDeviceObject::AndroidUsbDeviceObject()
+    : AndroidUsbWdfObject(AndroidUsbWdfObjectTypeDevice),
+      wdf_target_device_(NULL),
+      wdf_usb_interface_(NULL),
+      serial_number_handle_(NULL),
+      serial_number_char_len_(0),
+      configured_pipes_num_(0),
+      bulk_read_pipe_index_(INVALID_UCHAR),
+      bulk_write_pipe_index_(INVALID_UCHAR),
+      configuration_descriptor_(NULL) {
+  ASSERT_IRQL_PASSIVE();
+}
+
+#pragma code_seg()
+
+AndroidUsbDeviceObject::~AndroidUsbDeviceObject() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  if (NULL != serial_number_handle_)
+    WdfObjectDelete(serial_number_handle_);
+}
+
+#pragma code_seg("PAGE")
+
+NTSTATUS AndroidUsbDeviceObject::CreateFDODevice(PWDFDEVICE_INIT device_init) {
+  ASSERT_IRQL_PASSIVE();
+
+  ASSERT(!IsTaretDeviceCreated());
+  if (IsTaretDeviceCreated())
+    return STATUS_INTERNAL_ERROR;
+
+  // Initialize our object attributes first
+  WDF_OBJECT_ATTRIBUTES device_attr;
+  NTSTATUS status = InitObjectAttributes(&device_attr, NULL);
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Initialize the pnp_power_callbacks structure.  Callback events for PnP
+  // and Power are specified here. If we don't supply any callbacks, the
+  // KMDF will take appropriate default actions for an FDO device object.
+  // EvtDevicePrepareHardware and EvtDeviceReleaseHardware are major entry
+  // points for initializing / cleaning up our device. Probably, we can leave
+  // the rest to the framework.
+  WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
+  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
+  pnp_power_callbacks.EvtDevicePrepareHardware =
+    EvtDevicePrepareHardwareEntry;
+  pnp_power_callbacks.EvtDeviceReleaseHardware =
+    EvtDeviceReleaseHardwareEntry;
+  WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
+
+  // Initialize the request attributes to specify the context size and type
+  // for every request created by framework for this device.
+  WDF_OBJECT_ATTRIBUTES request_attr;
+  WDF_OBJECT_ATTRIBUTES_INIT(&request_attr);
+  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&request_attr, AndroidUsbWdfRequestContext);
+  WdfDeviceInitSetRequestAttributes(device_init, &request_attr);
+
+  // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the KMDF that we are
+  // interested in handling Create requests that get genereated when an
+  // application or another kernel component opens a handle through the device.
+  // We are not interested in receiving cleanup / close IRPs at this point.
+  WDF_FILEOBJECT_CONFIG file_config;
+  WDF_OBJECT_ATTRIBUTES file_attr;
+  WDF_FILEOBJECT_CONFIG_INIT(&file_config,
+                             EvtDeviceFileCreateEntry,
+                             WDF_NO_EVENT_CALLBACK,
+                             WDF_NO_EVENT_CALLBACK);
+  WDF_OBJECT_ATTRIBUTES_INIT(&file_attr);
+  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&file_attr,
+                                         AndroidUsbWdfObjectContext);
+  file_attr.EvtCleanupCallback = AndroidUsbWdfObject::EvtCleanupCallbackEntry;
+  file_attr.EvtDestroyCallback = AndroidUsbWdfObject::EvtDestroyCallbackEntry;
+  // We will provide our own synchronization for file access
+  file_attr.SynchronizationScope = WdfSynchronizationScopeNone;
+  WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attr);
+
+  // I/O type is buffered by default. It could be very inefficient if we have
+  // large reads / writes through our device.
+  WdfDeviceInitSetIoType(device_init, WdfDeviceIoDirect);
+
+  // DeviceInit is completely initialized. So call the framework
+  // to create the device and attach it to the lower stack.
+  WDFDEVICE wdf_dev = NULL;
+  status = WdfDeviceCreate(&device_init, &device_attr, &wdf_dev);
+  ASSERT(NT_SUCCESS(status) && (NULL != wdf_dev));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Save handle to the created device
+  set_wdf_object(wdf_dev);
+
+  // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
+  // that we don't get the popup in usermode (on Win2K) when we surprise
+  // remove the device.
+  WDF_DEVICE_PNP_CAPABILITIES pnp_caps;
+  WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnp_caps);
+  pnp_caps.SurpriseRemovalOK = WdfTrue;
+  WdfDeviceSetPnpCapabilities(wdf_device(), &pnp_caps);
+
+  // Create our default queue object for this device to start receiving I/O
+  status = CreateDefaultQueue();
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Register a device interface so that app can find our device and talk to it.
+  status = WdfDeviceCreateDeviceInterface(wdf_device(), &android_guid, NULL);
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Initialize our extension to that device. We will do this at the very end
+  // so we know that we successfully passed entire device create chain when
+  // we are called with other callbacks to that device.
+  status = InitializeContext();
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS AndroidUsbDeviceObject::ResetDevice() {
+  ASSERT_IRQL_PASSIVE();
+
+  if (!IsTaretDeviceCreated())
+    return STATUS_SUCCESS;
+
+  // Reset the device
+  NTSTATUS status =
+    status = WdfUsbTargetDeviceResetPortSynchronously(wdf_target_device());
+
+  // !!!!! Note that after the call to WdfUsbTargetDeviceResetPortSynchronously
+  // this object may be no longer valid !!!!!
+
+  if (!NT_SUCCESS(status))
+    GoogleDbgPrint("\n!!!!! AndroidUsbDeviceObject::ResetDevice failed %X", status);
+
+  return status;
+}
+
+NTSTATUS AndroidUsbDeviceObject::OnEvtDevicePrepareHardware(
+    WDFCMRESLIST resources_raw,
+    WDFCMRESLIST resources_translated) {
+  ASSERT_IRQL_PASSIVE();
+
+  // Create a USB device handle so that we can communicate with the underlying
+  // USB stack. The wdf_target_device_ handle is used to query, configure, and
+  // manage all aspects of the USB device. These aspects include device
+  // properties, bus properties, and I/O creation and synchronization. This
+  // call gets the device and configuration descriptors and stores them in
+  // wdf_target_device_ object.
+  NTSTATUS status = WdfUsbTargetDeviceCreate(wdf_device(),
+                                             WDF_NO_OBJECT_ATTRIBUTES,
+                                             &wdf_target_device_);
+  ASSERT(NT_SUCCESS(status) && (NULL != wdf_target_device_));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Retrieve USBD version information, port driver capabilites and device
+  // capabilites such as speed, power, etc.
+  WDF_USB_DEVICE_INFORMATION_INIT(&usb_device_info_);
+  status = WdfUsbTargetDeviceRetrieveInformation(wdf_target_device(),
+                                                 &usb_device_info_);
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  WdfUsbTargetDeviceGetDeviceDescriptor(wdf_target_device(),
+                                        &usb_device_descriptor_);
+#if DBG
+  PrintUsbTargedDeviceInformation(usb_device_info());
+  PrintUsbDeviceDescriptor(&usb_device_descriptor_);
+#endif  // DBG
+
+  // Save device serial number
+  status =

+    WdfUsbTargetDeviceAllocAndQueryString(wdf_target_device(),

+                                          WDF_NO_OBJECT_ATTRIBUTES,

+                                          &serial_number_handle_,

+                                          &serial_number_char_len_,

+                                          usb_device_descriptor_.iSerialNumber,

+                                          0x0409);  // English (US)

+  if (!NT_SUCCESS(status))

+    return status;

+

+#if DBG

+  UNICODE_STRING ser_num;

+  ser_num.Length = serial_number_byte_len();

+  ser_num.MaximumLength = ser_num.Length;

+  ser_num.Buffer = const_cast<WCHAR*>

+    (serial_number());

+  GoogleDbgPrint("\n*** Device serial number %wZ", &ser_num);

+#endif  // DBG

+

+  // Configure our device now
+  status = ConfigureDevice();
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Select device interfaces
+  status = SelectInterfaces();
+  if (!NT_SUCCESS(status))
+    return status;
+
+  return status;
+}
+
+NTSTATUS AndroidUsbDeviceObject::OnEvtDeviceReleaseHardware(
+    WDFCMRESLIST resources_translated) {
+  ASSERT_IRQL_PASSIVE();
+
+  // It's possible that Preparehardware failed half way thru. So make
+  // sure the target device exists.
+  if (!IsTaretDeviceCreated())
+    return STATUS_SUCCESS;
+
+  // Cancel all the currently queued I/O. This is better than sending an
+  // explicit USB abort request down because release hardware gets
+  // called even when the device surprise-removed.
+  WdfIoTargetStop(WdfUsbTargetDeviceGetIoTarget(wdf_target_device()),
+                  WdfIoTargetCancelSentIo);
+
+  // Unselect all selected configurations
+  WDF_USB_DEVICE_SELECT_CONFIG_PARAMS config_params;
+  WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_DECONFIG(&config_params);
+
+  NTSTATUS status = WdfUsbTargetDeviceSelectConfig(wdf_target_device(),
+                                                   WDF_NO_OBJECT_ATTRIBUTES,
+                                                   &config_params);
+  ASSERT(NT_SUCCESS(status) || (STATUS_DEVICE_NOT_CONNECTED == status));
+  return status;
+}
+
+void AndroidUsbDeviceObject::OnEvtDeviceFileCreate(WDFREQUEST request,
+                                                   WDFFILEOBJECT wdf_fo) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT(IsInterfaceSelected());
+  if (!IsInterfaceSelected()) {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
+    return;
+  }
+
+  PUNICODE_STRING file_name = WdfFileObjectGetFileName(wdf_fo);
+  ASSERT(NULL != file_name);
+  if (NULL == file_name) {
+    WdfRequestComplete(request, STATUS_OBJECT_NAME_INVALID);
+    return;
+  }
+
+  WDFUSBPIPE wdf_pipe_obj = NULL;
+  WDF_USB_PIPE_INFORMATION pipe_info;
+
+  // TODO: Share / access check here?
+
+  // Lets see if this is a device open
+  if (0 != file_name->Length) {
+    // This is a pipe open. Lets retrieve pipe index from the name
+    UCHAR pipe_index = GetPipeIndexFromFileName(file_name);
+    if (INVALID_UCHAR == pipe_index) {
+      GoogleDbgPrint("\n!!!!! There is no pipe index for file %wZ", file_name);
+      WdfRequestComplete(request, STATUS_OBJECT_NAME_INVALID);
+      return;
+    }
+
+    // Make sure that pipe index doesn't exceed number of pipes
+    if (pipe_index >= configured_pipes_num()) {
+      WdfRequestComplete(request, STATUS_OBJECT_NAME_NOT_FOUND);
+      return;
+    }
+
+    // Retrieve the pipe along with the pipe info
+    WDF_USB_PIPE_INFORMATION_INIT(&pipe_info);
+    wdf_pipe_obj = WdfUsbInterfaceGetConfiguredPipe(wdf_usb_interface(),
+                                                    pipe_index,
+                                                    &pipe_info);
+    if (NULL == wdf_pipe_obj) {
+      GoogleDbgPrint("\n!!!!! There is no pipe for index %u for file %wZ",
+                     pipe_index, file_name);
+      WdfRequestComplete(request, STATUS_OBJECT_NAME_NOT_FOUND);
+      return;
+    }
+  }
+
+  // If we're here this must be either device open or pipe open
+  ASSERT((NULL != wdf_pipe_obj) || (0 == file_name->Length));
+
+  // Create our file object extension for this file
+  AndroidUsbFileObject* wdf_file_ext = NULL;
+  NTSTATUS status;
+
+  if (0 == file_name->Length) {
+    // This is a device FO. Create wrapper for device FO
+    ASSERT(NULL == wdf_pipe_obj);
+    wdf_file_ext = new(NonPagedPool, GANDR_POOL_TAG_DEVICE_FO)
+      AndroidUsbDeviceFileObject(this, wdf_fo);
+    ASSERT(NULL != wdf_file_ext);
+    if (NULL == wdf_file_ext) {
+      WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
+      return;
+    }
+
+    // Initialize extension
+    status = wdf_file_ext->Initialize();
+    if (!NT_SUCCESS(status)) {
+      delete wdf_file_ext;
+      WdfRequestComplete(request, status);
+      return;
+    }
+  } else {
+    // This is a pipe file. Create and initialize appropriate extension for it.
+    status =
+      CreatePipeFileObjectExt(wdf_fo, wdf_pipe_obj, &pipe_info, &wdf_file_ext);
+    ASSERT((NULL != wdf_file_ext) || !NT_SUCCESS(status));
+    if (!NT_SUCCESS(status)) {
+      WdfRequestComplete(request, status);
+      return;
+    }
+  }
+  ASSERT(GetAndroidUsbFileObjectFromHandle(wdf_fo) == wdf_file_ext);
+  WdfRequestComplete(request, STATUS_SUCCESS);
+}
+
+NTSTATUS AndroidUsbDeviceObject::EvtDevicePrepareHardwareEntry(
+    WDFDEVICE wdf_dev,
+    WDFCMRESLIST resources_raw,
+    WDFCMRESLIST resources_translated) {
+  ASSERT_IRQL_PASSIVE();
+
+  // Get our wrapper for the device and redirect event to its handler
+  AndroidUsbDeviceObject* wdf_device_ext =
+    GetAndroidUsbDeviceObjectFromHandle(wdf_dev);
+  ASSERT(NULL != wdf_device_ext);
+  return (NULL != wdf_device_ext) ?
+    wdf_device_ext->OnEvtDevicePrepareHardware(resources_raw,
+                                               resources_translated) :
+    STATUS_INVALID_DEVICE_REQUEST;
+}
+
+NTSTATUS AndroidUsbDeviceObject::EvtDeviceReleaseHardwareEntry(
+    WDFDEVICE wdf_dev,
+    WDFCMRESLIST resources_translated) {
+  ASSERT_IRQL_PASSIVE();
+
+  // Get our wrapper for the device and redirect event to its handler
+  AndroidUsbDeviceObject* wdf_device_ext =
+    GetAndroidUsbDeviceObjectFromHandle(wdf_dev);
+  ASSERT(NULL != wdf_device_ext);
+  return (NULL != wdf_device_ext) ?
+    wdf_device_ext->OnEvtDeviceReleaseHardware(resources_translated) :
+    STATUS_INVALID_DEVICE_REQUEST;
+}
+
+void AndroidUsbDeviceObject::EvtDeviceFileCreateEntry(
+    WDFDEVICE wdf_dev,
+    WDFREQUEST request,
+    WDFFILEOBJECT wdf_fo) {
+  ASSERT_IRQL_PASSIVE();
+
+  ASSERT(NULL != wdf_fo);
+  if (NULL == wdf_fo) {
+    WdfRequestComplete(request, STATUS_INVALID_PARAMETER);
+    return;
+  }
+
+  // Get our wrapper for the device and redirect event to its handler
+  AndroidUsbDeviceObject* wdf_device_ext =
+    GetAndroidUsbDeviceObjectFromHandle(wdf_dev);
+  ASSERT(NULL != wdf_device_ext);
+  if (NULL != wdf_device_ext) {
+    wdf_device_ext->OnEvtDeviceFileCreate(request, wdf_fo);
+  } else {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+  }
+}
+
+#pragma code_seg()
+
+void AndroidUsbDeviceObject::OnEvtIoRead(WDFREQUEST request,
+                                         size_t length) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  ASSERT(IsInterfaceSelected());
+  if (!IsInterfaceSelected()) {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
+    return;
+  }
+
+  // Get our file extension and dispatch this event to its handler
+  AndroidUsbFileObject* wdf_file_ext =
+    GetAndroidUsbFileObjectForRequest(request);
+  ASSERT(NULL != wdf_file_ext);
+  if (NULL != wdf_file_ext) {
+    wdf_file_ext->OnEvtIoRead(request, length);
+  } else {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+  }
+}
+
+void AndroidUsbDeviceObject::OnEvtIoWrite(WDFREQUEST request,
+                                          size_t length) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  ASSERT(IsInterfaceSelected());
+  if (!IsInterfaceSelected()) {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
+    return;
+  }
+
+  // Get our file extension and dispatch this event to its handler
+  AndroidUsbFileObject* wdf_file_ext =
+    GetAndroidUsbFileObjectForRequest(request);
+  ASSERT(NULL != wdf_file_ext);
+  if (NULL != wdf_file_ext) {
+    wdf_file_ext->OnEvtIoWrite(request, length);
+  } else {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+  }
+}
+
+void AndroidUsbDeviceObject::OnEvtIoDeviceControl(WDFREQUEST request,
+                                                  size_t output_buf_len,
+                                                  size_t input_buf_len,
+                                                  ULONG ioctl_code) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  ASSERT(IsInterfaceSelected());
+  if (!IsInterfaceSelected()) {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
+    return;
+  }
+
+  // Get our file extension and dispatch this event to its handler
+  AndroidUsbFileObject* wdf_file_ext =
+    GetAndroidUsbFileObjectForRequest(request);
+  ASSERT(NULL != wdf_file_ext);
+  if (NULL != wdf_file_ext) {
+    wdf_file_ext->OnEvtIoDeviceControl(request,
+                                       output_buf_len,
+                                       input_buf_len,
+                                       ioctl_code);
+  } else {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+  }
+}
+
+void AndroidUsbDeviceObject::EvtIoReadEntry(WDFQUEUE queue,
+                                            WDFREQUEST request,
+                                            size_t length) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Get our file extension and dispatch this event to the appropriate handler
+  // inside our device extension.
+  AndroidUsbFileObject* wdf_file_ext =
+    GetAndroidUsbFileObjectForRequest(request);
+  ASSERT(NULL != wdf_file_ext);
+  if (NULL != wdf_file_ext) {
+    wdf_file_ext->device_object()->OnEvtIoRead(request, length);
+  } else {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+  }
+}
+
+void AndroidUsbDeviceObject::EvtIoWriteEntry(WDFQUEUE queue,
+                                            WDFREQUEST request,
+                                            size_t length) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Get our file extension and dispatch this event to the appropriate handler
+  // inside our device extension.
+  AndroidUsbFileObject* wdf_file_ext =
+    GetAndroidUsbFileObjectForRequest(request);
+  ASSERT(NULL != wdf_file_ext);
+  if (NULL != wdf_file_ext) {
+    wdf_file_ext->device_object()->OnEvtIoWrite(request, length);
+  } else {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+  }
+}
+
+void AndroidUsbDeviceObject::EvtIoDeviceControlEntry(WDFQUEUE queue,
+                                                    WDFREQUEST request,
+                                                    size_t output_buf_len,
+                                                    size_t input_buf_len,
+                                                    ULONG ioctl_code) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Get our file extension and dispatch this event to the appropriate handler
+  // inside our device extension.
+  AndroidUsbFileObject* wdf_file_ext =
+    GetAndroidUsbFileObjectForRequest(request);
+  ASSERT(NULL != wdf_file_ext);
+  if (NULL != wdf_file_ext) {
+    wdf_file_ext->device_object()->OnEvtIoDeviceControl(request,
+                                                        output_buf_len,
+                                                        input_buf_len,
+                                                        ioctl_code);
+  } else {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+  }
+}
+
+void AndroidUsbDeviceObject::OnGetUsbDeviceDescriptorCtl(WDFREQUEST request,
+                                                         size_t output_buf_len) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Check the buffer first
+  if (output_buf_len >= sizeof(USB_DEVICE_DESCRIPTOR)) {
+    // Get the output buffer
+    NTSTATUS status;
+    void* ret_info = OutAddress(request, &status);
+    ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
+    if (NT_SUCCESS(status)) {
+      // Copy requested info into output buffer and complete request
+      RtlCopyMemory(ret_info,
+                    usb_device_descriptor(),
+                    sizeof(USB_DEVICE_DESCRIPTOR));
+
+      WdfRequestCompleteWithInformation(request,
+                                        STATUS_SUCCESS,
+                                        sizeof(USB_DEVICE_DESCRIPTOR));
+    } else {
+      WdfRequestComplete(request, status);
+    }
+  } else {
+    WdfRequestCompleteWithInformation(request,
+                                      STATUS_BUFFER_TOO_SMALL,
+                                      sizeof(USB_DEVICE_DESCRIPTOR));
+  }
+}
+
+void AndroidUsbDeviceObject::OnGetUsbConfigDescriptorCtl(WDFREQUEST request,
+                                                         size_t output_buf_len) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  if (NULL != configuration_descriptor()) {
+    // Check the buffer first
+    if (output_buf_len >= sizeof(USB_CONFIGURATION_DESCRIPTOR)) {
+      // Get the output buffer
+      NTSTATUS status;
+      void* ret_info = OutAddress(request, &status);
+      ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
+      if (NT_SUCCESS(status)) {
+        // Copy requested info into output buffer and complete request
+        RtlCopyMemory(ret_info,
+                      configuration_descriptor(),
+                      sizeof(USB_CONFIGURATION_DESCRIPTOR));
+
+        WdfRequestCompleteWithInformation(request,
+                                          STATUS_SUCCESS,
+                                          sizeof(USB_CONFIGURATION_DESCRIPTOR));
+      } else {
+        WdfRequestComplete(request, status);
+      }
+    } else {
+      WdfRequestCompleteWithInformation(request,
+                                        STATUS_BUFFER_TOO_SMALL,
+                                        sizeof(USB_CONFIGURATION_DESCRIPTOR));
+    }
+  } else {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+  }
+}
+
+void AndroidUsbDeviceObject::OnGetUsbInterfaceDescriptorCtl(WDFREQUEST request,
+                                                            size_t output_buf_len) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Check the buffer first
+  if (output_buf_len >= sizeof(USB_INTERFACE_DESCRIPTOR)) {
+    // Get the output buffer
+    NTSTATUS status;
+    void* ret_info = OutAddress(request, &status);
+    ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
+    if (NT_SUCCESS(status)) {
+      // Copy requested info into output buffer and complete request
+      RtlCopyMemory(ret_info,
+                    interface_descriptor(),
+                    sizeof(USB_INTERFACE_DESCRIPTOR));
+
+      WdfRequestCompleteWithInformation(request,
+                                        STATUS_SUCCESS,
+                                        sizeof(USB_INTERFACE_DESCRIPTOR));
+    } else {
+      WdfRequestComplete(request, status);
+    }
+  } else {
+    WdfRequestCompleteWithInformation(request,
+                                      STATUS_BUFFER_TOO_SMALL,
+                                      sizeof(USB_INTERFACE_DESCRIPTOR));
+  }
+}
+
+void AndroidUsbDeviceObject::OnGetEndpointInformationCtl(
+    WDFREQUEST request,
+    size_t input_buf_len,
+    size_t output_buf_len) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Check the buffers first
+  if (input_buf_len < sizeof(AdbQueryEndpointInformation)) {
+    WdfRequestComplete(request, STATUS_INVALID_BUFFER_SIZE);
+    return;
+  }
+
+  if (output_buf_len < sizeof(AdbEndpointInformation)) {
+    WdfRequestCompleteWithInformation(request,
+                                      STATUS_BUFFER_TOO_SMALL,
+                                      sizeof(AdbEndpointInformation));
+    return;
+  }
+
+  // Get the output buffer
+  NTSTATUS status;
+  AdbEndpointInformation* ret_info = reinterpret_cast<AdbEndpointInformation*>
+    (OutAddress(request, &status));
+  ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
+  if (!NT_SUCCESS(status)) {
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Get the input buffer
+  AdbQueryEndpointInformation* in = reinterpret_cast<AdbQueryEndpointInformation*>
+    (InAddress(request, &status));
+  ASSERT(NT_SUCCESS(status) && (NULL != in));
+  if (!NT_SUCCESS(status)) {
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Lets see what exactly is queried
+  UCHAR endpoint_index = in->endpoint_index;
+  if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index)
+    endpoint_index = bulk_write_pipe_index();
+  else if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index)
+    endpoint_index = bulk_read_pipe_index();
+
+  // Make sure index is valid and within interface range
+  if ((INVALID_UCHAR == endpoint_index) ||
+      (endpoint_index >= configured_pipes_num())) {
+    WdfRequestComplete(request, STATUS_NOT_FOUND);
+    return;
+  }
+
+  // Get endpoint information
+  WDF_USB_PIPE_INFORMATION pipe_info;
+  WDF_USB_PIPE_INFORMATION_INIT(&pipe_info);
+  WDFUSBPIPE wdf_pipe_obj =
+      WdfUsbInterfaceGetConfiguredPipe(wdf_usb_interface(), endpoint_index, &pipe_info);
+  if (NULL == wdf_pipe_obj) {
+    WdfRequestComplete(request, STATUS_NOT_FOUND);
+    return;
+  }
+
+  // Copy endpoint info to the output
+  ret_info->max_packet_size = pipe_info.MaximumPacketSize;
+  ret_info->endpoint_address = pipe_info.EndpointAddress;
+  ret_info->polling_interval = pipe_info.Interval;
+  ret_info->setting_index = pipe_info.SettingIndex;
+  ret_info->endpoint_type = static_cast<AdbEndpointType>(pipe_info.PipeType);
+  ret_info->max_transfer_size = pipe_info.MaximumTransferSize;
+
+  WdfRequestCompleteWithInformation(request,
+                                    STATUS_SUCCESS,
+                                    sizeof(AdbEndpointInformation));
+}
+
+void AndroidUsbDeviceObject::OnGetSerialNumberCtl(WDFREQUEST request,
+                                                  size_t output_buf_len) {
+  ASSERT_IRQL_LOW();
+
+  if (NULL == serial_number()) {
+    // There is no serial number saved for this device!
+    WdfRequestComplete(request, STATUS_INTERNAL_ERROR);
+    return;
+  }
+
+  size_t expected_len = serial_number_byte_len() + sizeof(WCHAR);
+
+  // Check the buffer first
+  if (output_buf_len >= expected_len) {
+    // Get the output buffer
+    NTSTATUS status;
+    WCHAR* ret_info = reinterpret_cast<WCHAR*>(OutAddress(request, &status));
+    ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
+    if (NT_SUCCESS(status)) {
+      // Copy serial number
+      RtlCopyMemory(ret_info, serial_number(), serial_number_byte_len());
+      ret_info[serial_number_char_len()] = L'\0';
+      WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, expected_len);
+    } else {
+      WdfRequestComplete(request, status);
+    }
+  } else {
+    WdfRequestCompleteWithInformation(request,
+                                      STATUS_BUFFER_TOO_SMALL,
+                                      sizeof(expected_len));
+  }
+}
+
+#pragma code_seg("PAGE")
+
+NTSTATUS AndroidUsbDeviceObject::CreateDefaultQueue() {
+  ASSERT_IRQL_PASSIVE();
+
+  // Register I/O callbacks to tell the framework that we are interested
+  // in handling WdfRequestTypeRead, WdfRequestTypeWrite, and
+  // WdfRequestTypeDeviceControl requests. WdfIoQueueDispatchParallel means
+  // that we are capable of handling all the I/O request simultaneously and we
+  // are responsible for protecting data that could be accessed by these
+  // callbacks simultaneously. This queue will be, by default, automanaged by
+  // the framework with respect to PnP and Power events. That is, framework
+  // will take care of queuing, failing, dispatching incoming requests based
+  // on the current PnP / Power state of the device. We also need to register
+  // a EvtIoStop handler so that we can acknowledge requests that are pending
+  // at the target driver.
+  WDF_IO_QUEUE_CONFIG io_queue_config;
+  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&io_queue_config,
+                                         WdfIoQueueDispatchParallel);
+
+  io_queue_config.EvtIoDeviceControl = EvtIoDeviceControlEntry;
+  io_queue_config.EvtIoRead = EvtIoReadEntry;
+  io_queue_config.EvtIoWrite = EvtIoWriteEntry;
+  io_queue_config.AllowZeroLengthRequests = TRUE;
+  // By default KMDF will take care of the power management of this queue
+  io_queue_config.PowerManaged = WdfUseDefault;
+
+  // Create queue object
+  WDFQUEUE wdf_queue_obj = NULL;
+  NTSTATUS status = WdfIoQueueCreate(wdf_device(),
+                                     &io_queue_config,
+                                     WDF_NO_OBJECT_ATTRIBUTES,
+                                     &wdf_queue_obj);
+  ASSERT(NT_SUCCESS(status) && (NULL != wdf_queue_obj));
+  if (!NT_SUCCESS(status))
+    return status;
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS AndroidUsbDeviceObject::ConfigureDevice() {
+  ASSERT_IRQL_PASSIVE();
+
+  ASSERT(IsTaretDeviceCreated());
+  if (!IsTaretDeviceCreated())
+    return STATUS_INTERNAL_ERROR;
+
+  // In order to get the configuration descriptor we must first query for its
+  // size (by supplying NULL for the descriptor's address), allocate enough
+  // memory and then retrieve the descriptor.
+  USHORT size = 0;
+
+  // Query descriptor size first
+  NTSTATUS status =
+    WdfUsbTargetDeviceRetrieveConfigDescriptor(wdf_target_device(),
+                                               WDF_NO_HANDLE,
+                                               &size);
+  ASSERT((status == STATUS_BUFFER_TOO_SMALL) || !NT_SUCCESS(status));
+  if (status != STATUS_BUFFER_TOO_SMALL)
+    return status;
+
+  // Create a memory object and specify our device as the parent so that
+  // it will be freed automatically along with our device.
+  WDFMEMORY memory = NULL;
+  WDF_OBJECT_ATTRIBUTES attributes;
+  WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+  attributes.ParentObject = wdf_device();
+  status = WdfMemoryCreate(&attributes,
+                           NonPagedPool,
+                           GANDR_POOL_TAG_DEV_CFG_DESC,
+                           size,
+                           &memory,
+                           reinterpret_cast<PVOID*>(&configuration_descriptor_));
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Now retrieve configuration descriptor
+  status =
+    WdfUsbTargetDeviceRetrieveConfigDescriptor(wdf_target_device(),
+                                               configuration_descriptor_,
+                                               &size);
+  ASSERT(NT_SUCCESS(status) && (NULL != configuration_descriptor_));
+  if (!NT_SUCCESS(status))
+    return status;
+
+#if DBG
+  PrintConfigDescriptor(configuration_descriptor(), size);
+#endif  // DBG
+
+  return status;
+}
+
+NTSTATUS AndroidUsbDeviceObject::SelectInterfaces() {
+  ASSERT_IRQL_PASSIVE();
+
+  ASSERT(IsDeviceConfigured());
+  if (!IsDeviceConfigured())
+    return STATUS_INTERNAL_ERROR;
+
+  WDF_USB_DEVICE_SELECT_CONFIG_PARAMS config_params;
+  PWDF_USB_INTERFACE_SETTING_PAIR pairs = NULL;
+  // TODO: We need to find a way (possibly by looking at each
+  // interface descriptor) to get index of the ADB interface in multiinterface
+  // configuration.
+  UCHAR adb_interface_index = 0;
+
+  if (IsSingleInterfaceDevice()) {
+    // Our device has only one interface, so we don't have to bother with
+    // multiple interfaces at all.
+    GoogleDbgPrint("\n********** Device reports single interface");
+    // Select single interface configuration
+    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&config_params);
+  } else {
+    // Configure multiple interfaces
+    ULONG num_interf = GetInterfaceCount();
+    GoogleDbgPrint("\n********** Device reports %u interfaces",
+             num_interf);
+
+    // Allocate pairs for each interface
+    pairs = new(PagedPool, GANDR_POOL_TAG_INTERF_PAIRS)
+              WDF_USB_INTERFACE_SETTING_PAIR[num_interf];
+    ASSERT(NULL != pairs);
+    if (NULL == pairs)
+      return STATUS_INSUFFICIENT_RESOURCES;
+
+    adb_interface_index = 1;
+    // Initialize each interface pair
+    for (UCHAR pair = 0; pair < num_interf; pair++) {
+      pairs[pair].SettingIndex = 0;
+      pairs[pair].UsbInterface =
+        WdfUsbTargetDeviceGetInterface(wdf_target_device(), pair);
+      ASSERT(NULL != pairs[pair].UsbInterface);
+      if (NULL == pairs[pair].UsbInterface) {
+        delete[] pairs;
+        return STATUS_INTERNAL_ERROR;
+      }
+    }
+
+    // Select multiinterface configuration
+    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&config_params,
+                                                                 (UCHAR)num_interf,
+                                                                 pairs);
+  }
+
+  NTSTATUS status =
+    WdfUsbTargetDeviceSelectConfig(wdf_target_device(),
+                                   WDF_NO_OBJECT_ATTRIBUTES,
+                                   &config_params);
+  if (NULL != pairs)
+    delete[] pairs;
+
+  // ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+#if DBG
+  PrintSelectedConfig(&config_params);
+#endif  // DBG
+
+  wdf_usb_interface_ =
+    WdfUsbTargetDeviceGetInterface(wdf_target_device(), adb_interface_index);
+  ASSERT(NULL != wdf_usb_interface_);
+  if (NULL == wdf_usb_interface_)
+    return STATUS_INTERNAL_ERROR;
+
+  configured_pipes_num_ = WdfUsbInterfaceGetNumEndpoints(wdf_usb_interface(), 0);
+  ASSERT(0 != configured_pipes_num_);
+
+  // Cache selected interface descriptor
+  BYTE setting_index =
+    WdfUsbInterfaceGetConfiguredSettingIndex(wdf_usb_interface());
+
+  WdfUsbInterfaceGetDescriptor(wdf_usb_interface(),
+                               setting_index,
+                               &interface_descriptor_);
+
+#if DBG
+  PrintInterfaceDescriptor(interface_descriptor());
+#endif  // DBG
+
+  // Iterate over pipes, decoding and saving info about bulk r/w pipes for
+  // easier and faster addressing later on when they get opened
+  for (UCHAR pipe = 0; pipe < configured_pipes_num(); pipe++) {
+    WDF_USB_PIPE_INFORMATION pipe_info;
+    WDF_USB_PIPE_INFORMATION_INIT(&pipe_info);
+    WDFUSBPIPE wdf_pipe_obj =
+      WdfUsbInterfaceGetConfiguredPipe(wdf_usb_interface(), pipe, &pipe_info);
+    ASSERT(NULL != wdf_pipe_obj);
+    if (NULL != wdf_pipe_obj) {
+      if ((WdfUsbPipeTypeBulk  == pipe_info.PipeType) &&
+          WDF_USB_PIPE_DIRECTION_IN(pipe_info.EndpointAddress)) {
+        // This is a bulk read pipe
+        ASSERT(!IsBulkReadPipeKnown());
+        bulk_read_pipe_index_ = pipe;
+      } else {
+        ASSERT(!IsBulkWritePipeKnown());
+        bulk_write_pipe_index_ = pipe;
+      }
+    }
+#if DBG
+    PrintPipeInformation(&pipe_info, pipe);
+#endif  // DBG
+  }
+
+  // At the end we must have calculated indexes for both,
+  // bulk read and write pipes
+  ASSERT(!NT_SUCCESS(status) || (IsBulkReadPipeKnown() &&
+                                 IsBulkWritePipeKnown()));
+
+  return status;
+}
+
+UCHAR AndroidUsbDeviceObject::GetPipeIndexFromFileName(
+    PUNICODE_STRING file_path) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT((NULL != file_path) && (0 != file_path->Length) && (NULL != file_path->Buffer));
+  if ((NULL == file_path) ||
+      (0 == file_path->Length) ||
+      (NULL == file_path->Buffer)) {
+    return INVALID_UCHAR;
+  }
+
+  // Lets check for explicit r/w pipe names
+  if (0 == RtlCompareUnicodeString(file_path, &bulk_read_pipe_name, TRUE))
+    return bulk_read_pipe_index();
+  if (0 == RtlCompareUnicodeString(file_path, &bulk_write_pipe_name, TRUE))
+    return bulk_write_pipe_index();
+
+  // Lets check path format
+  if (file_path->Length <= index_pipe_prefix.Length) {
+    GoogleDbgPrint("\n!!!!! Bad format for pipe name: %wZ", file_path);
+    return INVALID_UCHAR;
+  }
+
+  // Now when whe know that file_path->Length is sufficient lets match this
+  // path with the prefix
+  UNICODE_STRING prefix_match = *file_path;
+  prefix_match.Length = index_pipe_prefix.Length;
+  prefix_match.MaximumLength = prefix_match.Length;
+
+  if (0 != RtlCompareUnicodeString(&prefix_match, &index_pipe_prefix, TRUE)) {
+    GoogleDbgPrint("\n!!!!! Bad format for pipe name: %wZ", file_path);
+    return INVALID_UCHAR;
+  }
+
+  // Prefix matches. Make sure that remaining chars are all decimal digits.
+  // Pipe index begins right after the prefix ends.
+  const ULONG index_begins_at = WcharLen(index_pipe_prefix.Length);
+  const ULONG name_len = WcharLen(file_path->Length);
+  for (ULONG index = index_begins_at; index < name_len; index++) {
+    if ((file_path->Buffer[index] > L'9') ||
+        (file_path->Buffer[index] < L'0')) {
+      GoogleDbgPrint("\n!!!!! Bad format for pipe name: %wZ", file_path);
+      return INVALID_UCHAR;
+    }
+  }
+
+  // Parse the pipe#
+  ULONG uval = 0;
+  ULONG umultiplier = 1;
+
+  // traversing least to most significant digits.
+  for (ULONG index = name_len - 1; index >= index_begins_at; index--) {
+    uval += (umultiplier * static_cast<ULONG>(file_path->Buffer[index] - L'0'));
+    umultiplier *= 10;
+  }
+
+  return static_cast<UCHAR>(uval);
+}
+
+NTSTATUS AndroidUsbDeviceObject::CreatePipeFileObjectExt(
+    WDFFILEOBJECT wdf_fo,
+    WDFUSBPIPE wdf_pipe_obj,
+    const WDF_USB_PIPE_INFORMATION* pipe_info,
+    AndroidUsbFileObject** wdf_file_ext) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT((NULL != wdf_fo) && (NULL != wdf_pipe_obj) && (NULL != pipe_info) && (NULL != wdf_file_ext));
+  if ((NULL == wdf_fo) || (NULL == wdf_pipe_obj) || (NULL == pipe_info) || (NULL == wdf_file_ext)) {
+    return STATUS_INTERNAL_ERROR;
+  }
+  *wdf_file_ext = NULL;
+
+  AndroidUsbPipeFileObject* wdf_pipe_file_ext = NULL;
+
+  // We support only WdfUsbPipeTypeBulk and WdfUsbPipeTypeInterrupt files
+  // at this point.
+  switch (pipe_info->PipeType) {
+    case WdfUsbPipeTypeBulk:
+      wdf_pipe_file_ext = new(NonPagedPool, GANDR_POOL_TAG_BULK_FILE)
+            AndroidUsbBulkPipeFileObject(this, wdf_fo, wdf_pipe_obj);
+      break;
+
+    case WdfUsbPipeTypeInterrupt:
+      wdf_pipe_file_ext = new(NonPagedPool, GANDR_POOL_TAG_INTERRUPT_FILE)
+          AndroidUsbInterruptPipeFileObject(this, wdf_fo, wdf_pipe_obj);
+      break;;
+
+    case WdfUsbPipeTypeIsochronous:
+    case WdfUsbPipeTypeControl:
+    case WdfUsbPipeTypeInvalid:
+    default:
+      return STATUS_OBJECT_TYPE_MISMATCH;
+  }
+
+  // If we reached here instance of a file wrapper must be created.
+  ASSERT(NULL != wdf_pipe_file_ext);
+  if (NULL == wdf_pipe_file_ext)
+    return STATUS_INSUFFICIENT_RESOURCES;
+    
+  // Initialize the wrapper.
+  NTSTATUS status = wdf_pipe_file_ext->InitializePipe(pipe_info);
+  ASSERT(NT_SUCCESS(status));
+  if (NT_SUCCESS(status)) {
+    *wdf_file_ext = wdf_pipe_file_ext;
+  } else {
+    delete wdf_pipe_file_ext;
+  }
+
+  return STATUS_SUCCESS;
+}
+
+#if DBG
+#pragma code_seg()
+
+void AndroidUsbDeviceObject::PrintUsbDeviceDescriptor(
+    const USB_DEVICE_DESCRIPTOR* desc) {
+  GoogleDbgPrint("\n***** USB_DEVICE_DESCRIPTOR %p for device %p", desc, this);
+  GoogleDbgPrint("\n      bDescriptorType    = %u", desc->bDescriptorType);
+  GoogleDbgPrint("\n      bcdUSB             = x%02X", desc->bcdUSB);
+  GoogleDbgPrint("\n      bDeviceClass       = x%02X", desc->bDeviceClass);
+  GoogleDbgPrint("\n      bDeviceSubClass    = x%02X", desc->bDeviceSubClass);
+  GoogleDbgPrint("\n      bDeviceProtocol    = x%02X", desc->bDeviceProtocol);
+  GoogleDbgPrint("\n      bMaxPacketSize     = %u", desc->bMaxPacketSize0);
+  GoogleDbgPrint("\n      idVendor           = x%04X", desc->idVendor);
+  GoogleDbgPrint("\n      idProduct          = x%04X", desc->idProduct);
+  GoogleDbgPrint("\n      bcdDevice          = x%02X", desc->bcdDevice);
+  GoogleDbgPrint("\n      iManufacturer      = %u", desc->iManufacturer);
+  GoogleDbgPrint("\n      iProduct           = %u", desc->iProduct);
+  GoogleDbgPrint("\n      iSerialNumber      = %u", desc->iSerialNumber);
+  GoogleDbgPrint("\n      bNumConfigurations = %u", desc->bNumConfigurations);
+}
+
+void AndroidUsbDeviceObject::PrintUsbTargedDeviceInformation(
+    const WDF_USB_DEVICE_INFORMATION* info) {
+  GoogleDbgPrint("\n***** WDF_USB_DEVICE_INFORMATION %p for device %p", info, this);
+  GoogleDbgPrint("\n      HcdPortCapabilities               = x%08X", info->HcdPortCapabilities);
+  GoogleDbgPrint("\n      Traits                            = x%08X", info->Traits);
+  GoogleDbgPrint("\n      VersionInfo.USBDI_Version         = x%08X",
+           info->UsbdVersionInformation.USBDI_Version);
+  GoogleDbgPrint("\n      VersionInfo.Supported_USB_Version = x%08X",
+           info->UsbdVersionInformation.Supported_USB_Version);
+}
+
+void AndroidUsbDeviceObject::PrintConfigDescriptor(
+    const USB_CONFIGURATION_DESCRIPTOR* desc,
+    ULONG size) {
+  GoogleDbgPrint("\n***** USB_CONFIGURATION_DESCRIPTOR %p for device %p size %u",
+           desc, this, size);
+  GoogleDbgPrint("\n      bDescriptorType     = %u", desc->bDescriptorType);
+  GoogleDbgPrint("\n      wTotalLength        = %u", desc->wTotalLength);
+  GoogleDbgPrint("\n      bNumInterfaces      = %u", desc->bNumInterfaces);
+  GoogleDbgPrint("\n      bConfigurationValue = %u", desc->bConfigurationValue);
+  GoogleDbgPrint("\n      iConfiguration      = %u", desc->iConfiguration);
+  GoogleDbgPrint("\n      bmAttributes        = %u", desc->bmAttributes);
+  GoogleDbgPrint("\n      MaxPower            = %u", desc->MaxPower);
+}
+
+void AndroidUsbDeviceObject::PrintSelectedConfig(
+    const WDF_USB_DEVICE_SELECT_CONFIG_PARAMS* config) {
+  GoogleDbgPrint("\n***** WDF_USB_DEVICE_SELECT_CONFIG_PARAMS %p for device %p", config, this);
+  GoogleDbgPrint("\n      Type = %u", config->Type);
+  switch (config->Type) {
+    case WdfUsbTargetDeviceSelectConfigTypeSingleInterface:
+      GoogleDbgPrint("\n      SingleInterface:");
+      GoogleDbgPrint("\n         NumberConfiguredPipes  = %u",
+               config->Types.SingleInterface.NumberConfiguredPipes);
+      GoogleDbgPrint("\n         ConfiguredUsbInterface = %p",
+               config->Types.SingleInterface.ConfiguredUsbInterface);
+      break;
+
+    case WdfUsbTargetDeviceSelectConfigTypeMultiInterface:
+      GoogleDbgPrint("\n      MultiInterface:");
+      GoogleDbgPrint("\n         NumberInterfaces              = %u",
+               config->Types.MultiInterface.NumberInterfaces);
+      GoogleDbgPrint("\n         NumberOfConfiguredInterfaces  = %u",
+               config->Types.MultiInterface.NumberOfConfiguredInterfaces);
+      GoogleDbgPrint("\n         Pairs                         = %p",
+               config->Types.MultiInterface.Pairs);
+      break;
+
+    case WdfUsbTargetDeviceSelectConfigTypeInterfacesDescriptor:
+      GoogleDbgPrint("\n      Descriptor:");
+      GoogleDbgPrint("\n         NumInterfaceDescriptors = %u",
+               config->Types.Descriptor.NumInterfaceDescriptors);
+      GoogleDbgPrint("\n         ConfigurationDescriptor = %p",
+               config->Types.Descriptor.ConfigurationDescriptor);
+      GoogleDbgPrint("\n         InterfaceDescriptors    = %p",
+               config->Types.Descriptor.InterfaceDescriptors);
+      break;
+
+    case WdfUsbTargetDeviceSelectConfigTypeUrb:
+      GoogleDbgPrint("\n      Urb:");
+      GoogleDbgPrint("\n         Urb = %p",
+               config->Types.Urb.Urb);
+      break;
+
+    case WdfUsbTargetDeviceSelectConfigTypeInterfacesPairs:
+    case WdfUsbTargetDeviceSelectConfigTypeInvalid:
+    case WdfUsbTargetDeviceSelectConfigTypeDeconfig:
+    default:
+      GoogleDbgPrint("\n      Config type is unknown or invalid or not printable.");
+      break;
+  }
+}
+
+void AndroidUsbDeviceObject::PrintInterfaceDescriptor(
+    const USB_INTERFACE_DESCRIPTOR* desc) {
+  GoogleDbgPrint("\n***** USB_INTERFACE_DESCRIPTOR %p for device %p",
+           desc, this);
+  GoogleDbgPrint("\n      bLength            = %u", desc->bLength);
+  GoogleDbgPrint("\n      bDescriptorType    = %u", desc->bDescriptorType);
+  GoogleDbgPrint("\n      bInterfaceNumber   = %u", desc->bInterfaceNumber);
+  GoogleDbgPrint("\n      bAlternateSetting  = %u", desc->bAlternateSetting);
+  GoogleDbgPrint("\n      bNumEndpoints      = %u", desc->bNumEndpoints);
+  GoogleDbgPrint("\n      bInterfaceClass    = x%02X", desc->bInterfaceClass);
+  GoogleDbgPrint("\n      bInterfaceSubClass = x%02X", desc->bInterfaceSubClass);
+  GoogleDbgPrint("\n      bInterfaceProtocol = x%02X", desc->bInterfaceProtocol);
+  GoogleDbgPrint("\n      iInterface         = %u", desc->iInterface);
+}
+
+void AndroidUsbDeviceObject::PrintPipeInformation(
+    const WDF_USB_PIPE_INFORMATION* info,
+    UCHAR pipe_index) {
+  GoogleDbgPrint("\n***** WDF_USB_PIPE_INFORMATION[%u] %p for device %p",
+           pipe_index, info, this);
+  GoogleDbgPrint("\n      Size                = %u", info->Size);
+  GoogleDbgPrint("\n      MaximumPacketSize   = %u", info->MaximumPacketSize);
+  GoogleDbgPrint("\n      EndpointAddress     = x%02X", info->EndpointAddress);
+  GoogleDbgPrint("\n      Interval            = %u", info->Interval);
+  GoogleDbgPrint("\n      SettingIndex        = %u", info->SettingIndex);
+  GoogleDbgPrint("\n      PipeType            = %u", info->PipeType);
+  GoogleDbgPrint("\n      MaximumTransferSize = %u", info->MaximumTransferSize);
+}
+
+#endif  // DBG
+
+#pragma data_seg()
+#pragma code_seg()
diff --git a/host/windows/usb/driver/android_usb_device_object.h b/host/windows/usb/driver/android_usb_device_object.h
new file mode 100644
index 0000000..5c97e9c
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_device_object.h
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_DEVICE_OBJECT_H__
+#define ANDROID_USB_DEVICE_OBJECT_H__
+/** \file
+  This file consists of declaration of class AndroidUsbDeviceObject that
+  encapsulates an extension for KMDF device (FDO) object.
+*/
+
+#include "android_usb_wdf_object.h"
+
+// Forward declaration for file object extension
+class AndroidUsbFileObject;
+
+/** AndroidUsbDeviceObject class encapsulates an extension for KMDF FDO device
+  object. Instances of this class must be allocated from NonPagedPool.
+*/
+class AndroidUsbDeviceObject : public AndroidUsbWdfObject {
+ public:
+  /** \brief Constructs the object.
+
+    This method must be called at low IRQL.
+  */
+  AndroidUsbDeviceObject();
+
+  /** \brief Destructs the object.
+
+    This method can be called at any IRQL.
+  */
+   ~AndroidUsbDeviceObject();
+
+ public:
+  /** \brief Creates and initializes FDO device object extension
+
+    This method is called from driver's OnAddDevice method in response to
+    AddDevice call from the PnP manager
+    @param device_init[in] A pointer to a framework-allocated WDFDEVICE_INIT
+           structure.
+    @return If the routine succeeds, it returns STATUS_SUCCESS. Otherwise,
+            it returns one of the error status values defined in ntstatus.h.
+  */
+  NTSTATUS CreateFDODevice(PWDFDEVICE_INIT device_init);
+
+  /** \brief Resets target device
+
+    When executing this method instance of this class may be deleted!
+    This method must be called at PASSIVE IRQL.
+    @return STATUS_SUCCESS or an appropriate error code
+  */
+  NTSTATUS ResetDevice();
+
+ private:
+  /** \name Device event handlers and callbacks
+  */
+  ///@{
+
+  /** \brief Handler for PnP prepare hardware event
+
+    This method performs any operations that are needed to make a device
+    accessible to the driver. The framework calls this callback after the PnP
+    manager has assigned hardware resources to the device and after the device
+    has entered its uninitialized D0 state. This callback is called before
+    calling the driver's EvtDeviceD0Entry callback function.
+    This method is called at PASSIVE IRQL.
+    @param resources_raw[in] A handle to a framework resource-list object that
+           identifies the raw hardware resources that the PnP manager has
+           assigned to the device.
+    @param resources_translated[in] A handle to a framework resource-list
+           object that identifies the translated hardware resources that the
+           PnP manager has assigned to the device. 
+    @return Successful status or an appropriate error code
+  */
+  NTSTATUS OnEvtDevicePrepareHardware(WDFCMRESLIST resources_raw,
+                                      WDFCMRESLIST resources_translated);
+
+  /** \brief Handler for PnP release hardware event
+
+    This method performs operations that  that are needed when a device is no
+    longer accessible. Framework calls the callback function if the device is
+    being removed, or if the PnP manager is attempting to redistribute hardware
+    resources. The framework calls the EvtDeviceReleaseHardware callback
+    function after the driver's device has been shut off, the PnP manager has
+    reclaimed the hardware resources that it assigned to the device, and the
+    device is no longer accessible. (The PCI configuration state is still
+    accessible.) Typically, a EvtDeviceReleaseHardware callback function unmaps
+    memory that the driver's EvtDevicePrepareHardware callback function mapped.
+    Usually, all other hardware shutdown operations should take place in the
+    driver's EvtDeviceD0Exit callback function.
+    This method is called at PASSIVE IRQL.
+    @param wdf_device[in] A handle to a framework device object. 
+    @param resources_translated[in] A handle to a framework resource-list
+           object that identifies the translated hardware resources that the
+           PnP manager has assigned to the device. 
+    @return Successful status or an appropriate error code
+  */
+  NTSTATUS OnEvtDeviceReleaseHardware(WDFCMRESLIST resources_translated);
+
+  /** \brief Handler for create file event (request)
+
+    This method performs operations that are needed when an application
+    requests access to an item within this device path (including device
+    itself). This method is called synchronously, in the context of the
+    user thread that opens the item.
+    This method is called at PASSIVE IRQL.
+    @param request[in] A handle to a framework request object that represents
+           a file creation request.
+    @param wdf_fo[in] A handle to a framework file object that describes a
+           file that is being created with this request.
+    @return Successful status or an appropriate error code
+  */
+  void OnEvtDeviceFileCreate(WDFREQUEST request, WDFFILEOBJECT wdf_fo);
+
+  /** \brief Entry point for PnP prepare hardware event
+
+    This callback performs any operations that are needed to make a device
+    accessible to the driver. The framework calls this callback after the PnP
+    manager has assigned hardware resources to the device and after the device
+    has entered its uninitialized D0 state. This callback is called before
+    calling the driver's EvtDeviceD0Entry callback function.
+    This callback is called at PASSIVE IRQL.
+    @param wdf_dev[in] A handle to a framework device object. 
+    @param resources_raw[in] A handle to a framework resource-list object that
+           identifies the raw hardware resources that the PnP manager has
+           assigned to the device.
+    @param resources_translated[in] A handle to a framework resource-list
+           object that identifies the translated hardware resources that the
+           PnP manager has assigned to the device. 
+    @return Successful status or an appropriate error code
+  */
+  static NTSTATUS EvtDevicePrepareHardwareEntry(WDFDEVICE wdf_dev,
+                                                WDFCMRESLIST resources_raw,
+                                                WDFCMRESLIST resources_translated);
+
+  /** \brief Entry point for PnP release hardware event
+
+    This callback performs operations that  that are needed when a device is no
+    longer accessible. Framework calls the callback function if the device is
+    being removed, or if the PnP manager is attempting to redistribute hardware
+    resources. The framework calls the EvtDeviceReleaseHardware callback
+    function after the driver's device has been shut off, the PnP manager has
+    reclaimed the hardware resources that it assigned to the device, and the
+    device is no longer accessible. (The PCI configuration state is still
+    accessible.) Typically, a EvtDeviceReleaseHardware callback function unmaps
+    memory that the driver's EvtDevicePrepareHardware callback function mapped.
+    Usually, all other hardware shutdown operations should take place in the
+    driver's EvtDeviceD0Exit callback function.
+    This callback is called at PASSIVE IRQL.
+    @param wdf_dev[in] A handle to a framework device object. 
+    @param resources_translated[in] A handle to a framework resource-list
+           object that identifies the translated hardware resources that the
+           PnP manager has assigned to the device. 
+    @return Successful status or an appropriate error code
+  */
+  static NTSTATUS EvtDeviceReleaseHardwareEntry(WDFDEVICE wdf_dev,
+                                                WDFCMRESLIST resources_translated);
+
+  /** \brief Entry point for create file event (request)
+
+    This callback performs operations that that are needed when an application
+    requests access to a device. The framework calls a driver's
+    EvtDeviceFileCreate callback function when a user application or another
+    driver opens the device (or file on this device) to perform an I/O
+    operation, such as reading or writing a file. This callback function is
+    called synchronously, in the context of the user thread that opens the
+    device.
+    This callback is called at PASSIVE IRQL.
+    @param wdf_dev[in] A handle to a framework device object. 
+    @param request[in] A handle to a framework request object that represents
+           a file creation request.
+    @param wdf_fo[in] A handle to a framework file object that describes a
+           file that is being created with this request.
+    @return Successful status or an appropriate error code
+  */
+  static void EvtDeviceFileCreateEntry(WDFDEVICE wdf_dev,
+                                       WDFREQUEST request,
+                                       WDFFILEOBJECT wdf_fo);
+
+  ///@}
+
+ private:
+  /** \name I/O request event handlers and callbacks
+  */
+  ///@{
+
+  /** \brief Read event handler
+
+    This method is called when a read request comes to a file object opened
+    on this device.
+    This method can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param length[in] The number of bytes to be read.
+  */
+  void OnEvtIoRead(WDFREQUEST request, size_t length);
+
+  /** \brief Write event handler
+
+    This method is called when a write request comes to a file object opened
+    on this device.
+    This method can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param length[in] The number of bytes to be written.
+  */
+  void OnEvtIoWrite(WDFREQUEST request, size_t length);
+
+  /** \brief IOCTL event handler
+
+    This method is called when a device control request comes to a file object
+    opened on this device.
+    This method can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+    @param input_buf_len[in] The length, in bytes, of the request's input
+           buffer, if an input buffer is available.
+    @param ioctl_code[in] The driver-defined or system-defined I/O control code
+           that is associated with the request.
+  */
+  void OnEvtIoDeviceControl(WDFREQUEST request,
+                            size_t output_buf_len,
+                            size_t input_buf_len,
+                            ULONG ioctl_code);
+
+  /** \brief Entry point for read event
+
+    This callback is called when a read request comes to a file object opened
+    on this device.
+    This callback can be called IRQL <= DISPATCH_LEVEL.
+    @param queue[in] A handle to the framework queue object that is associated
+           with the I/O request.
+    @param request[in] A handle to a framework request object.
+    @param length[in] The number of bytes to be read.
+  */
+  static void EvtIoReadEntry(WDFQUEUE queue,
+                             WDFREQUEST request,
+                             size_t length);
+
+  /** \brief Entry point for write event
+
+    This callback is called when a write request comes to a file object opened
+    on this device.
+    This callback can be called IRQL <= DISPATCH_LEVEL.
+    @param queue[in] A handle to the framework queue object that is associated
+           with the I/O request.
+    @param request[in] A handle to a framework request object.
+    @param length[in] The number of bytes to be written.
+  */
+  static void EvtIoWriteEntry(WDFQUEUE queue,
+                              WDFREQUEST request,
+                              size_t length);
+
+  /** \brief Entry point for device IOCTL event
+
+    This callback is called when a device control request comes to a file
+    object opened on this device.
+    This callback can be called IRQL <= DISPATCH_LEVEL.
+    @param queue[in] A handle to the framework queue object that is associated
+           with the I/O request.
+    @param request[in] A handle to a framework request object.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+    @param input_buf_len[in] The length, in bytes, of the request's input
+           buffer, if an input buffer is available.
+    @param ioctl_code[in] The driver-defined or system-defined I/O control code
+           that is associated with the request.
+  */
+  static void EvtIoDeviceControlEntry(WDFQUEUE queue,
+                                      WDFREQUEST request,
+                                      size_t output_buf_len,
+                                      size_t input_buf_len,
+                                      ULONG ioctl_code);
+
+  ///@}
+
+ public:
+  /** \name Device level I/O request handlers
+  */
+  ///@{
+
+  /** \brief Gets USB device descriptor
+
+    This method can be called at IRQL <= DISPATCH_LEVEL
+    @param request[in] A handle to a framework request object for this IOCTL.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+  */
+  void OnGetUsbDeviceDescriptorCtl(WDFREQUEST request, size_t output_buf_len);
+
+  /** \brief Gets USB configuration descriptor for the selected configuration.
+
+    This method can be called at IRQL <= DISPATCH_LEVEL
+    @param request[in] A handle to a framework request object for this IOCTL.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+  */
+  void OnGetUsbConfigDescriptorCtl(WDFREQUEST request, size_t output_buf_len);
+
+  /** \brief Gets USB configuration descriptor for the selected interface.
+
+    This method can be called at IRQL <= DISPATCH_LEVEL
+    @param request[in] A handle to a framework request object for this IOCTL.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+  */
+  void OnGetUsbInterfaceDescriptorCtl(WDFREQUEST request, size_t output_buf_len);
+
+  /** \brief Gets information about an endpoint.
+
+    This method can be called at IRQL <= DISPATCH_LEVEL
+    @param request[in] A handle to a framework request object for this IOCTL.
+    @param input_buf_len[in] The length, in bytes, of the request's input
+           buffer, if an input buffer is available.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+  */
+  void OnGetEndpointInformationCtl(WDFREQUEST request,
+                                   size_t input_buf_len,
+                                   size_t output_buf_len);
+
+  /** \brief Gets device serial number.
+
+    Serial number is returned in form of zero-terminated string that in the
+    output buffer. This method must be called at low IRQL.
+    @param request[in] A handle to a framework request object for this IOCTL.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+  */
+  void OnGetSerialNumberCtl(WDFREQUEST request, size_t output_buf_len);
+
+  ///@}
+
+ private:
+  /** \name Internal methods
+  */
+  ///@{
+
+  /** \brief Creates default request queue for this device.
+
+    In KMDF all I/O requests are coming through the queue object. So, in order
+    to enable our device to receive I/O requests we must create a queue for it.
+    This method is called at PASSIVE IRQL.
+    @return STATUS_SUCCESS or an appropriate error code.
+  */
+  NTSTATUS CreateDefaultQueue();
+
+  /** \brief Configures our device.
+
+    This method is called from the prepare hardware handler after underlying
+    FDO device has been created.
+    This method is called at PASSSIVE IRQL.
+    @return STATUS_SUCCESS or an appropriate error code.
+  */
+  NTSTATUS ConfigureDevice();
+
+  /** \brief Selects interfaces on our device.
+
+    This method is called from the prepare hardware handler after underlying
+    FDO device has been created and configured.
+    This method is called at PASSSIVE IRQL.
+    @return STATUS_SUCCESS or an appropriate error code.
+  */
+  NTSTATUS SelectInterfaces();
+  
+  /** \brief Gets pipe index from a file name
+
+    This method is called from OnEvtDeviceFileCreate to determine index of
+    the pipe this file is addressing.
+    This method is called at PASSIVE IRQL.
+    @param file_path[in] Path to the file that being opened.
+    @return Pipe index or INVALID_UCHAR if index cannot be calculated.
+  */
+  UCHAR GetPipeIndexFromFileName(PUNICODE_STRING file_path);
+
+  /** \brief Creates file object extension for a pipe
+
+    This method is called from OnEvtDeviceFileCreate to create an appropriate
+    file object extension for a particular pipe type.
+    This method is called at PASSIVE IRQL.
+    @param wdf_fo[in] KMDF file to extend.
+    @param wdf_pipe_obj[in] KMDF pipe for this extension
+    @param pipe_info[in] Pipe information
+    @param wdf_file_ext[out] Upon successfull completion will receive instance
+           of the extension.
+    @return STATUS_SUCCESS or an appropriate error code
+  */
+  NTSTATUS CreatePipeFileObjectExt(WDFFILEOBJECT wdf_fo,
+                                   WDFUSBPIPE wdf_pipe_obj,
+                                   const WDF_USB_PIPE_INFORMATION* pipe_info,
+                                   AndroidUsbFileObject** wdf_file_ext);
+
+  ///@}
+
+ private:
+  /** \name Debugging support
+  */
+  ///@{
+
+#if DBG
+  /// Prints USB_DEVICE_DESCRIPTOR to debug output
+  void PrintUsbDeviceDescriptor(const USB_DEVICE_DESCRIPTOR* desc);
+
+  /// Prints WDF_USB_DEVICE_INFORMATION to debug output
+  void PrintUsbTargedDeviceInformation(const WDF_USB_DEVICE_INFORMATION* info);
+
+  /// Prints USB_CONFIGURATION_DESCRIPTOR to debug output
+  void PrintConfigDescriptor(const USB_CONFIGURATION_DESCRIPTOR* desc,
+                             ULONG size);
+
+  /// Prints WDF_USB_DEVICE_SELECT_CONFIG_PARAMS to debug output
+  void PrintSelectedConfig(const WDF_USB_DEVICE_SELECT_CONFIG_PARAMS* config);
+
+  /// Prints USB_INTERFACE_DESCRIPTOR to debug output
+  void PrintInterfaceDescriptor(const USB_INTERFACE_DESCRIPTOR* desc);
+
+  /// Prints WDF_USB_PIPE_INFORMATION to debug output
+  void PrintPipeInformation(const WDF_USB_PIPE_INFORMATION* info,
+                            UCHAR pipe_index);
+
+#endif  // DBG
+
+  ///@}
+
+ public:
+  /// Gets WDF device handle for this device
+  __forceinline WDFDEVICE wdf_device() const {
+    return reinterpret_cast<WDFDEVICE>(wdf_object());
+  }
+
+  /// Gets target USB device descriptor
+  __forceinline const USB_DEVICE_DESCRIPTOR* usb_device_descriptor() const {
+    return &usb_device_descriptor_;
+  }
+
+  /// Gets target USB device information
+  __forceinline const WDF_USB_DEVICE_INFORMATION* usb_device_info() const {
+    return &usb_device_info_;
+  }
+
+  /// Gets selected interface descriptor
+  __forceinline const USB_INTERFACE_DESCRIPTOR* interface_descriptor() const {
+    return &interface_descriptor_;
+  }
+
+  /// Gets target (PDO) device handle
+  __forceinline WDFUSBDEVICE wdf_target_device() const {
+    return wdf_target_device_;
+  }
+
+  /// Checks if target device has been created
+  __forceinline bool IsTaretDeviceCreated() const {
+    return (NULL != wdf_target_device());
+  }
+
+  /// Gets USB configuration descriptor
+  __forceinline const USB_CONFIGURATION_DESCRIPTOR* configuration_descriptor() const {
+    return configuration_descriptor_;
+  }
+
+  /// Checks if device has been configured
+  __forceinline bool IsDeviceConfigured() const {
+    return (NULL != configuration_descriptor());
+  }
+
+  /// Gets number of interfaces for this device
+  __forceinline UCHAR GetInterfaceCount() const {
+    ASSERT(IsDeviceConfigured());
+    return IsDeviceConfigured() ? configuration_descriptor()->bNumInterfaces : 0;
+  }
+
+  /// Checks if this is "single interface" device
+  __forceinline bool IsSingleInterfaceDevice() const {
+    return (1 == GetInterfaceCount());
+  }
+
+  /// Gets USB interface selected on this device
+  __forceinline WDFUSBINTERFACE wdf_usb_interface() const {
+    return wdf_usb_interface_;
+  }
+
+  /// Checks if an interface has been selected on this device
+  __forceinline bool IsInterfaceSelected() const {
+    return (NULL != wdf_usb_interface());
+  }
+
+  /// Gets number of pipes configured on this device
+  __forceinline UCHAR configured_pipes_num() const {
+    return configured_pipes_num_;
+  }
+
+  /// Gets index of the bulk read pipe
+  __forceinline UCHAR bulk_read_pipe_index() const {
+    return bulk_read_pipe_index_;
+  }
+
+  /// Gets index of the bulk write pipe
+  __forceinline UCHAR bulk_write_pipe_index() const {
+    return bulk_write_pipe_index_;
+  }
+
+  /// Checks if this is a high speed device
+  __forceinline bool IsHighSpeed() const {
+    return (0 != (usb_device_info()->Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED));
+  }
+
+  /// Checks if bulk read pipe index is known
+  __forceinline bool IsBulkReadPipeKnown() const {
+    return (INVALID_UCHAR != bulk_read_pipe_index());
+  }
+
+  /// Checks if bulk write pipe index is known
+  __forceinline bool IsBulkWritePipeKnown() const {
+    return (INVALID_UCHAR != bulk_write_pipe_index());
+  }
+
+  /// Gets device serial number string. Note that string may be
+  /// not zero-terminated. Use serial_number_len() to get actual
+  /// length of this string.
+  __forceinline const WCHAR* serial_number() const {
+    ASSERT(NULL != serial_number_handle_);
+    return (NULL != serial_number_handle_) ?
+      reinterpret_cast<const WCHAR*>
+        (WdfMemoryGetBuffer(serial_number_handle_, NULL)) :
+      NULL;
+  }
+
+  /// Gets length (in bytes) of device serial number string
+  __forceinline USHORT serial_number_char_len() const {
+    return serial_number_char_len_;
+  }
+
+  /// Gets length (in bytes) of device serial number string
+  __forceinline USHORT serial_number_byte_len() const {
+    return serial_number_char_len() * sizeof(WCHAR);
+  }
+
+ protected:
+  /// Target USB device descriptor
+  USB_DEVICE_DESCRIPTOR         usb_device_descriptor_;
+
+  /// Target USB device information
+  WDF_USB_DEVICE_INFORMATION    usb_device_info_;
+
+  /// Selected interface descriptor
+  USB_INTERFACE_DESCRIPTOR      interface_descriptor_;
+
+  /// USB configuration descriptor
+  PUSB_CONFIGURATION_DESCRIPTOR configuration_descriptor_;
+
+  /// Target (PDO?) device handle
+  WDFUSBDEVICE                  wdf_target_device_;
+
+  /// USB interface selected on this device
+  WDFUSBINTERFACE               wdf_usb_interface_;
+
+  /// Device serial number
+  WDFMEMORY                     serial_number_handle_;
+
+  /// Device serial number string length
+  USHORT                        serial_number_char_len_;
+
+  /// Number of pipes configured on this device
+  UCHAR                         configured_pipes_num_;
+
+  /// Index of the bulk read pipe
+  UCHAR                         bulk_read_pipe_index_;
+
+  /// Index of the bulk write pipe
+  UCHAR                         bulk_write_pipe_index_;
+};
+
+/** \brief Gets device KMDF object extension for the given KMDF object
+
+  @param wdf_dev[in] KMDF handle describing device object
+  @return Instance of AndroidUsbDeviceObject associated with KMDF object or
+          NULL if association is not found.
+*/
+__forceinline AndroidUsbDeviceObject* GetAndroidUsbDeviceObjectFromHandle(
+    WDFDEVICE wdf_dev) {
+  AndroidUsbWdfObject* wdf_object_ext =
+    GetAndroidUsbWdfObjectFromHandle(wdf_dev);
+  ASSERT((NULL != wdf_object_ext) &&
+         wdf_object_ext->Is(AndroidUsbWdfObjectTypeDevice));
+  if ((NULL != wdf_object_ext) &&
+      wdf_object_ext->Is(AndroidUsbWdfObjectTypeDevice)) {
+    return reinterpret_cast<AndroidUsbDeviceObject*>(wdf_object_ext);
+  }
+  return NULL;
+}
+
+#endif  // ANDROID_USB_DEVICE_OBJECT_H__
diff --git a/host/windows/usb/driver/android_usb_driver_defines.h b/host/windows/usb/driver/android_usb_driver_defines.h
new file mode 100644
index 0000000..4fe25d7
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_driver_defines.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_DRIVER_DEFINES_H__
+#define ANDROID_USB_DRIVER_DEFINES_H__
+/** \file
+  This file consists of constants, types and macros used (and useful) in driver
+  development.
+*/
+
+/** \name IRQL assertions
+  These assertions help to verify that code is running at expected IRQL
+*/
+///@{
+
+/// Asserts that current IRQL is less than provided level
+#define ASSERT_IRQL_LESS(irql_level) ASSERT(KeGetCurrentIrql() < irql_level)
+/// Asserts that current IRQL is less or equal than provided level
+#define ASSERT_IRQL_LESS_OR_EQUAL(irql_level) ASSERT(KeGetCurrentIrql() <= irql_level)
+/// Asserts that current IRQL is the same as provided level
+#define ASSERT_IRQL_IS(irql_level) ASSERT(irql_level == KeGetCurrentIrql())
+/// Asserts that current IRQL is less than DISPATCH_LEVEL
+#define ASSERT_IRQL_LOW() ASSERT_IRQL_LESS(DISPATCH_LEVEL)
+/// Asserts that current IRQL is above APC_LEVEL
+#define ASSERT_IRQL_HIGH() ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL)
+/// Asserts that current IRQL is at PASSIVE_LEVEL
+#define ASSERT_IRQL_PASSIVE() ASSERT_IRQL_IS(PASSIVE_LEVEL)
+/// Asserts that current IRQL is at APC_LEVEL
+#define ASSERT_IRQL_APC() ASSERT_IRQL_IS(APC_LEVEL)
+/// Asserts that current IRQL is at DISPATCH_LEVEL
+#define ASSERT_IRQL_DISPATCH() ASSERT_IRQL_IS(DISPATCH_LEVEL)
+/// Asserts that current IRQL is at APC or DISPATCH_LEVEL
+#define ASSERT_IRQL_APC_OR_DISPATCH() \
+  ASSERT((KeGetCurrentIrql() == APC_LEVEL) || (KeGetCurrentIrql() == DISPATCH_LEVEL))
+/// Asserts that current IRQL is less or equal DISPATCH_LEVEL
+#define ASSERT_IRQL_LOW_OR_DISPATCH() \
+  ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL)
+
+///@}
+
+#if DBG
+/** \brief Overrides DbgPrint to make sure that nothing gets printed
+  to debug output in release build.
+*/
+ULONG __cdecl GoogleDbgPrint(char* format, ...);
+#else 
+#define GoogleDbgPrint(Arg) NOTHING
+#endif
+
+/// Invalid UCHAR value
+#define INVALID_UCHAR   (static_cast<UCHAR>(0xFF))
+
+/// Invalid ULONG value
+#define INVALID_ULONG   (static_cast<ULONG>(-1))
+
+/** Enum AndroidUsbWdfObjectType enumerates types of KMDF objects that
+  we extend in our driver.
+*/
+enum AndroidUsbWdfObjectType {
+  // We start enum with 1 insetead of 0 to protect orselves from a dangling
+  // or uninitialized context structures because KMDF will zero our extension
+  // when it gets created.
+
+  /// Device object context
+  AndroidUsbWdfObjectTypeDevice = 1,
+
+  /// File object context
+  AndroidUsbWdfObjectTypeFile,
+
+  /// Request object context
+  AndroidUsbWdfObjectTypeRequest,
+
+  /// Workitem object context
+  AndroidUsbWdfObjectTypeWorkitem,
+
+  /// Illegal (maximum) context id
+  AndroidUsbWdfObjectTypeMax
+};
+
+/** Structure AndroidUsbWdfObjectContext represents our context that extends
+  every KMDF object (device, file, pipe, etc).
+*/
+typedef struct TagAndroidUsbWdfObjectContext {
+  /// KMDF object type that is extended with this context
+  AndroidUsbWdfObjectType     object_type;
+
+  /// Instance of the class that extends KMDF object with this context
+  class AndroidUsbWdfObject*  wdf_object_ext;
+} AndroidUsbWdfObjectContext;
+
+// KMDF woodoo to register our extension and implement accessor method
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(AndroidUsbWdfObjectContext,
+                                   GetAndroidUsbWdfObjectContext)
+
+/** Structure AndroidUsbWdfRequestContext represents our context that is
+  associated with every request recevied by the driver.
+*/
+typedef struct TagAndroidUsbWdfRequestContext {
+  /// KMDF object type that is extended with this context
+  /// (must be AndroidUsbWdfObjectTypeRequest)
+  AndroidUsbWdfObjectType object_type;
+
+  /// System time request has been first scheduled
+  // (time of the first WdfRequestSend is called for it)
+  LARGE_INTEGER           sent_at;
+
+  /// KMDF descriptor for the memory allocated for URB
+  WDFMEMORY               urb_mem;
+
+  /// MDL describing the transfer buffer
+  PMDL                    transfer_mdl;
+
+  /// Private MDL that we build in order to perform the transfer
+  PMDL                    mdl;
+
+  // Virtual address for the current segment of transfer.
+  void*                   virtual_address;
+
+  /// Number of bytes remaining to transfer
+  ULONG                   length;
+
+  /// Number of bytes requested to transfer
+  ULONG                   transfer_size;
+
+  /// Accummulated number of bytes transferred
+  ULONG                   num_xfer;
+
+  /// Initial timeout (in millisec) set for this request
+  ULONG                   initial_time_out;
+
+  // Read / Write selector
+  bool                    is_read;
+
+  // IOCTL selector
+  bool                    is_ioctl;
+} AndroidUsbWdfRequestContext;
+
+// KMDF woodoo to register our extension and implement accessor method
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(AndroidUsbWdfRequestContext,
+                                   GetAndroidUsbWdfRequestContext)
+
+/** Structure AndroidUsbWorkitemContext represents our context that is
+  associated with workitems created by our driver.
+*/
+typedef struct TagAndroidUsbWorkitemContext {
+  /// KMDF object type that is extended with this context
+  /// (must be AndroidUsbWdfObjectTypeWorkitem)
+  AndroidUsbWdfObjectType         object_type;
+
+  /// Pipe file object extension that enqueued this work item
+  class AndroidUsbPipeFileObject* pipe_file_ext;
+} AndroidUsbWorkitemContext;
+
+// KMDF woodoo to register our extension and implement accessor method
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(AndroidUsbWorkitemContext,
+                                   GetAndroidUsbWorkitemContext)
+
+#endif  // ANDROID_USB_DRIVER_DEFINES_H__
diff --git a/host/windows/usb/driver/android_usb_driver_object.cpp b/host/windows/usb/driver/android_usb_driver_object.cpp
new file mode 100644
index 0000000..d8be50f
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_driver_object.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AndroidUsbDriverObject that
+  encapsulates our driver object
+*/
+#pragma data_seg()
+#pragma code_seg()
+
+#include "precomp.h"
+#include "android_usb_device_object.h"
+#include "android_usb_driver_object.h"
+
+#pragma data_seg()
+
+/** Globally accessible instance of the AndroidUsbDriverObject.
+  NT OS design allows us using of a global pointer to our driver object
+  instance since it can't be created or destroyed concurently and its value
+  is not going to change between creation and destruction.
+*/
+AndroidUsbDriverObject* global_driver_object = NULL;
+
+#pragma code_seg("INIT")
+
+extern "C" {
+
+/// Main entry point to the driver
+NTSTATUS DriverEntry(PDRIVER_OBJECT drv_object, PUNICODE_STRING reg_path) {
+  // Just pass it down inside the class
+  return AndroidUsbDriverObject::DriverEntry(drv_object, reg_path);
+}
+
+}  // extern "C"
+
+NTSTATUS AndroidUsbDriverObject::DriverEntry(PDRIVER_OBJECT drv_object,
+                                             PUNICODE_STRING reg_path) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT(NULL != drv_object);
+  ASSERT((NULL != reg_path) &&
+         (NULL != reg_path->Buffer) &&
+         (0 != reg_path->Length));
+
+  // Instantiate driver object
+  global_driver_object = new(NonPagedPool, GANDR_POOL_TAG_DRIVER_OBJECT)
+    AndroidUsbDriverObject(drv_object, reg_path);
+  ASSERT(NULL != global_driver_object);
+  if (NULL == global_driver_object)
+    return STATUS_INSUFFICIENT_RESOURCES;
+
+  // Initialize driver object
+  NTSTATUS status = global_driver_object->OnDriverEntry(drv_object, reg_path);
+
+  if (!NT_SUCCESS(status)) {
+    // Something went wrong. Delete our driver object and get out of here.
+    delete global_driver_object;
+  }
+
+  return status;
+}
+
+AndroidUsbDriverObject::AndroidUsbDriverObject(PDRIVER_OBJECT drv_object,
+                                               PUNICODE_STRING reg_path)
+    : driver_object_(drv_object),
+      wdf_driver_(NULL) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT(NULL != driver_object());
+}
+
+NTSTATUS AndroidUsbDriverObject::OnDriverEntry(PDRIVER_OBJECT drv_object,
+                                               PUNICODE_STRING reg_path) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT(driver_object() == drv_object);
+
+  // Initiialize driver config, specifying our unload callback and default
+  // pool tag for memory allocations that KMDF does on our behalf.
+  WDF_DRIVER_CONFIG config;
+  WDF_DRIVER_CONFIG_INIT(&config, EvtDeviceAddEntry);
+  config.EvtDriverUnload = EvtDriverUnloadEntry;
+  config.DriverPoolTag = GANDR_POOL_TAG_DEFAULT;
+
+  // Create a framework driver object to represent our driver.
+  NTSTATUS status = WdfDriverCreate(drv_object,
+                                    reg_path,
+                                    WDF_NO_OBJECT_ATTRIBUTES,
+                                    &config,
+                                    &wdf_driver_);
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  GoogleDbgPrint("\n>>>>>>>>>> Android USB driver has started >>>>>>>>>>");
+
+  return STATUS_SUCCESS;
+}
+
+#pragma code_seg("PAGE")
+
+AndroidUsbDriverObject::~AndroidUsbDriverObject() {
+  ASSERT_IRQL_PASSIVE();
+}
+
+NTSTATUS AndroidUsbDriverObject::OnAddDevice(PWDFDEVICE_INIT device_init) {
+  ASSERT_IRQL_PASSIVE();
+  GoogleDbgPrint("\n++++++++++ AndroidUsbDriverObject::OnAddDevice ++++++++++");
+  // Instantiate our device object extension for this device
+  AndroidUsbDeviceObject* wdf_device_ext =
+    new(NonPagedPool, GANDR_POOL_TAG_KMDF_DEVICE) AndroidUsbDeviceObject();
+  ASSERT(NULL != wdf_device_ext);
+  if (NULL == wdf_device_ext)
+    return STATUS_INSUFFICIENT_RESOURCES;
+
+  // Create and initialize FDO device
+  NTSTATUS status = wdf_device_ext->CreateFDODevice(device_init);
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    delete wdf_device_ext;
+
+  return status;
+}
+
+void AndroidUsbDriverObject::OnDriverUnload() {
+  ASSERT_IRQL_PASSIVE();
+  GoogleDbgPrint("\n<<<<<<<<<< Android USB driver is unloaded <<<<<<<<<<");
+}
+
+NTSTATUS AndroidUsbDriverObject::EvtDeviceAddEntry(
+    WDFDRIVER wdf_drv,
+    PWDFDEVICE_INIT device_init) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT((NULL != global_driver_object) && (global_driver_object->wdf_driver() == wdf_drv));
+
+  // Pass it down to our driver object
+  if ((NULL == global_driver_object) ||
+      (global_driver_object->wdf_driver() != wdf_drv)) {
+    return STATUS_INTERNAL_ERROR;
+  }
+
+  return global_driver_object->OnAddDevice(device_init);
+}
+
+VOID AndroidUsbDriverObject::EvtDriverUnloadEntry(WDFDRIVER wdf_drv) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT((NULL != global_driver_object) &&
+         (global_driver_object->wdf_driver() == wdf_drv));
+
+  // Pass it down to our driver object
+  if ((NULL != global_driver_object) &&
+      (global_driver_object->wdf_driver() == wdf_drv)) {
+    global_driver_object->OnDriverUnload();
+    // Now we can (and have to) delete our driver object
+    delete global_driver_object;
+  }
+}
+
+#if DBG
+
+#pragma code_seg()
+
+ULONG __cdecl GoogleDbgPrint(char* format, ...) {
+  va_list arg_list;
+  va_start(arg_list, format);
+  ULONG ret =
+    vDbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, arg_list);
+  va_end(arg_list);
+
+  return ret;
+}
+
+#endif  // DBG
+
+#pragma data_seg()
+#pragma code_seg()
diff --git a/host/windows/usb/driver/android_usb_driver_object.h b/host/windows/usb/driver/android_usb_driver_object.h
new file mode 100644
index 0000000..8f68a80
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_driver_object.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_DRIVER_OBJECT_H__
+#define ANDROID_USB_DRIVER_OBJECT_H__
+/** \file
+  This file consists of declaration of class AndroidUsbDriverObject that
+  encapsulates our driver object.
+*/
+
+/// Globally accessible pointer to the driver object
+extern class AndroidUsbDriverObject* global_driver_object;
+
+/** AndroidUsbDriverObject class encapsulates driver object and provides
+  overall initialization / cleanup as well as management of globally used
+  resources. We use KMDF framework for this driver because it takes care of
+  most of the USB related "things" (like PnP, power management and other
+  stuff) so we can concentrate more on real functionality. This driver is
+  based on KMDF's usbsamp driver sample available at DDK's src\kmdf\usbsamp
+  directory. Instance of this class (always one) must be allocated from
+  NonPagedPool.
+*/
+class AndroidUsbDriverObject {
+
+ public:
+  /** \brief Driver initialization entry point.
+
+    This method is a "gate" to our driver class from main DriverEntry routine.
+    Since this method is called from within DriverEntry only it is placed in
+    "INIT" code segment.
+    This method is called at IRQL PASSIVE_LEVEL.
+    @param drv_object[in] Driver object passed to DriverEntry routine
+    @param reg_path[in] Path to the driver's Registry passed to DriverEntry
+          routine
+    @returns STATUS_SUCCESS on success or an appropriate error code.
+  */
+  static NTSTATUS DriverEntry(PDRIVER_OBJECT drv_object,
+                              PUNICODE_STRING reg_path);
+
+ private:
+  /** \brief Constructs driver object.
+
+    Constructor for driver class must be as light as possible. All
+    initialization that may fail must be deferred to OnDriverEntry method.
+    Since this method is called from within DriverEntry only it is placed in
+    "INIT" code segment.
+    This method is called at IRQL PASSIVE_LEVEL.
+    @param drv_object[in] Driver object passed to DriverEntry routine
+    @param reg_path[in] Path to the driver's Registry passed to DriverEntry
+          routine
+  */
+  AndroidUsbDriverObject(PDRIVER_OBJECT drv_object, PUNICODE_STRING reg_path);
+
+  /** \brief Destructs driver object.
+
+    Destructor for driver class must be as light as possible. All
+    uninitialization must be done in OnDriverUnload method.
+    This method must be called at PASSIVE IRQL.
+  */
+   ~AndroidUsbDriverObject();
+
+  /** \brief Initializes instance of the driver object.
+
+    This method is called immediatelly after driver object has been
+    instantiated to perform actual initialization of the driver. Since this
+    method is called from within DriverEntry only it is placed in
+    "INIT" code segment.
+    This method is called at IRQL PASSIVE_LEVEL.
+    @param drv_object[in] Driver object passed to DriverEntry routine
+    @param reg_path[in] Path to the driver's Registry passed to DriverEntry
+          routine
+    @returns STATUS_SUCCESS on success or an appropriate error code.
+  */
+  NTSTATUS OnDriverEntry(PDRIVER_OBJECT drv_object, PUNICODE_STRING reg_path);
+
+  /** \brief Actual handler for KMDF's AddDevice event
+
+    This method is called by the framework in response to AddDevice call from
+    the PnP manager. We create and initialize a device object to represent a
+    new instance of the device.
+    This method is called at IRQL PASSIVE_LEVEL.
+    @param device_init[in] A pointer to a framework-allocated WDFDEVICE_INIT
+           structure.
+    @return If the routine succeeds, it returns STATUS_SUCCESS. Otherwise,
+            it returns one of the error status values defined in ntstatus.h.
+  */
+  NTSTATUS OnAddDevice(PWDFDEVICE_INIT device_init);
+
+  /** \brief Actual driver unload event handler.
+
+    This method is called when driver is being unloaded.
+    This method is called at IRQL PASSIVE_LEVEL.
+  */
+  void OnDriverUnload();
+
+  /** \brief KMDF's DeviceAdd event entry point
+
+    This callback is called by the framework in response to AddDevice call from
+    the PnP manager. We create and initialize a device object to represent a
+    new instance of the device. All the software resources should be allocated
+    in this callback.
+    This method is called at IRQL PASSIVE_LEVEL.
+    @param wdf_drv[in] WDF driver handle.
+    @param device_init[in] A pointer to a framework-allocated WDFDEVICE_INIT
+           structure.
+    @return If the routine succeeds, it returns STATUS_SUCCESS. Otherwise,
+            it returns one of the error status values defined in ntstatus.h.
+  */
+  static NTSTATUS EvtDeviceAddEntry(WDFDRIVER wdf_drv,
+                                    PWDFDEVICE_INIT device_init);
+
+  /** \brief Driver unload event entry point.
+
+    Framework calls this callback when driver is being unloaded.
+    This method is called at IRQL PASSIVE_LEVEL.
+  */
+  static VOID EvtDriverUnloadEntry(WDFDRIVER wdf_drv);
+
+ public:
+
+  /// Gets this driver's DRIVER_OBJECT
+  __forceinline PDRIVER_OBJECT driver_object() const {
+    return driver_object_;
+  }
+
+  /// Gets KMDF driver handle
+  __forceinline WDFDRIVER wdf_driver() const {
+    return wdf_driver_;
+  }
+
+ private:
+  /// This driver's driver object
+  PDRIVER_OBJECT    driver_object_;
+
+  /// KMDF driver handle
+  WDFDRIVER         wdf_driver_;
+};
+
+#endif  // ANDROID_USB_DRIVER_OBJECT_H__
diff --git a/host/windows/usb/driver/android_usb_file_object.cpp b/host/windows/usb/driver/android_usb_file_object.cpp
new file mode 100644
index 0000000..e5ce0a2
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_file_object.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AndroidUsbFileObject that
+  encapsulates a common extension for all KMDF file object types.
+*/
+#pragma data_seg()
+#pragma code_seg()
+
+#include "precomp.h"
+#include "android_usb_file_object.h"
+
+#pragma data_seg()
+#pragma code_seg("PAGE")
+
+AndroidUsbFileObject::AndroidUsbFileObject(AndroidUsbFileObjectType fo_type,
+                                           AndroidUsbDeviceObject* dev_obj,
+                                           WDFFILEOBJECT wdf_fo)
+    : AndroidUsbWdfObject(AndroidUsbWdfObjectTypeFile),
+      file_type_(fo_type),
+      device_object_(dev_obj) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT(NULL != dev_obj);
+  ASSERT(fo_type < AndroidUsbFileObjectTypeMax);
+  ASSERT(NULL != wdf_fo);
+  set_wdf_object(wdf_fo);
+}
+
+#pragma code_seg()
+
+AndroidUsbFileObject::~AndroidUsbFileObject() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+}
+
+#pragma code_seg("PAGE")
+
+NTSTATUS AndroidUsbFileObject::Initialize() {
+  ASSERT_IRQL_LOW();
+  ASSERT(NULL != wdf_file());
+  if (NULL == wdf_file())
+    return STATUS_INTERNAL_ERROR;
+  
+  // Register context for this file object
+  return InitializeContext();
+}
+
+#pragma code_seg()
+
+void AndroidUsbFileObject::OnEvtIoRead(WDFREQUEST request,
+                                       size_t length) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  ASSERT(WdfRequestGetFileObject(request) == wdf_file());
+  // Complete zero reads with success
+  if (0 == length) {
+    WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, 0);
+    return;
+  }
+
+  WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+}
+
+void AndroidUsbFileObject::OnEvtIoWrite(WDFREQUEST request,
+                                        size_t length) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  ASSERT(WdfRequestGetFileObject(request) == wdf_file());
+  // Complete zero writes with success
+  if (0 == length) {
+    WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, 0);
+    return;
+  }
+
+  WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+}
+
+void AndroidUsbFileObject::OnEvtIoDeviceControl(WDFREQUEST request,
+                                                size_t output_buf_len,
+                                                size_t input_buf_len,
+                                                ULONG ioctl_code) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  ASSERT(WdfRequestGetFileObject(request) == wdf_file());
+
+  WdfRequestComplete(request, STATUS_INVALID_DEVICE_REQUEST);
+}
+
+#pragma data_seg()
+#pragma code_seg()
diff --git a/host/windows/usb/driver/android_usb_file_object.h b/host/windows/usb/driver/android_usb_file_object.h
new file mode 100644
index 0000000..1dbb92b
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_file_object.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_FILE_OBJECT_H__
+#define ANDROID_USB_FILE_OBJECT_H__
+/** \file
+  This file consists of declaration of class AndroidUsbFileObject that
+  encapsulates a common extension for all KMDF file object types.
+*/
+
+#include "android_usb_wdf_object.h"
+#include "android_usb_device_object.h"
+
+/** Enumerator AndroidUsbFileObjectType defines possible types for our file
+  object extension.
+*/
+enum AndroidUsbFileObjectType {
+  /// File extends device FO
+  AndroidUsbFileObjectTypeDevice,
+
+  // File extends a pipe FO
+  AndroidUsbFileObjectTypePipe,
+
+  AndroidUsbFileObjectTypeMax,
+};
+
+/** AndroidUsbFileObject class encapsulates a common extension for all KMDF
+  file object types. Instances of this class must be allocated from
+  NonPagedPool.
+*/
+class AndroidUsbFileObject : public AndroidUsbWdfObject {
+ public:
+  /** \brief Constructs the object.
+
+    This method must be called at low IRQL.
+    @param fo_type[in] Type of the file object that this object extends
+    @param dev_obj[in] Our device object for which this file has been created
+    @param wdf_fo[in] KMDF file object for this extension 
+  */
+  AndroidUsbFileObject(AndroidUsbFileObjectType fo_type,
+                       AndroidUsbDeviceObject* dev_obj,
+                       WDFFILEOBJECT wdf_fo);
+
+  /** \brief Destructs the object.
+
+    This method can be called at any IRQL.
+  */
+   virtual ~AndroidUsbFileObject();
+
+  /** \brief Initializes the object
+
+    This method verifies that instance has been created and calls base class's
+    InitializeContext method to register itself with the wrapped FO. All
+    derived classes must call this method when initializing.
+    This method must be called at low IRQL.
+    @return STATUS_SUCCESS on success or an appropriate error code
+  */
+  virtual NTSTATUS Initialize();
+
+  /** \brief Read event handler
+
+    This method is called when a read request comes to the file object this
+    class extends.
+    This method can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param length[in] The number of bytes to be read.
+    @return Successful status or an appropriate error code
+  */
+  virtual void OnEvtIoRead(WDFREQUEST request, size_t length);
+
+  /** \brief Write event handler
+
+    This method is called when a write request comes to the file object this
+    class extends.
+    This callback can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param length[in] The number of bytes to be written.
+    @return Successful status or an appropriate error code
+  */
+  virtual void OnEvtIoWrite(WDFREQUEST request, size_t length);
+
+  /** \brief IOCTL event handler
+
+    This method is called when a device control request comes to the file
+    object this class extends.
+    This callback can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+    @param input_buf_len[in] The length, in bytes, of the request's input
+           buffer, if an input buffer is available.
+    @param ioctl_code[in] The driver-defined or system-defined I/O control code
+           that is associated with the request.
+    @return Successful status or an appropriate error code
+  */
+  virtual void OnEvtIoDeviceControl(WDFREQUEST request,
+                                    size_t output_buf_len,
+                                    size_t input_buf_len,
+                                    ULONG ioctl_code);
+
+ public:
+  /// Gets KMDF file handle for this extension
+  __forceinline WDFFILEOBJECT wdf_file() const {
+    return reinterpret_cast<WDFFILEOBJECT>(wdf_object());
+  }
+
+  /// Gets device object that owns this file
+  __forceinline AndroidUsbDeviceObject* device_object() const {
+    return device_object_;
+  }
+
+  /// Gets type of the file object that this extension wraps
+  __forceinline AndroidUsbFileObjectType file_type() const {
+    return file_type_;
+  }
+
+  /// Gets WDF device handle for device that owns this file
+  __forceinline WDFDEVICE wdf_device() const {
+    ASSERT(NULL != device_object());
+    return (NULL != device_object()) ? device_object()->wdf_device() :
+                                       NULL;
+  }
+
+  /// Gets target (PDO) device handle for the device that owns this file
+  __forceinline WDFUSBDEVICE wdf_target_device() const {
+    ASSERT(NULL != device_object());
+    return (NULL != device_object()) ? device_object()->wdf_target_device() :
+                                       NULL;
+  }
+
+ protected:
+  /// Device object that owns this file
+  AndroidUsbDeviceObject*   device_object_;
+
+  /// Type of the file object that this extension wraps
+  AndroidUsbFileObjectType  file_type_;
+};
+
+/** \brief Gets file KMDF object extension for the given KMDF file object
+
+  This method can be called at any IRQL
+  @param wdf_fo[in] KMDF file handle describing file object
+  @return Instance of AndroidUsbFileObject associated with this object or NULL
+          if association is not found.
+*/
+__forceinline AndroidUsbFileObject* GetAndroidUsbFileObjectFromHandle(
+    WDFFILEOBJECT wdf_fo) {
+  AndroidUsbWdfObject* wdf_object_ext =
+    GetAndroidUsbWdfObjectFromHandle(wdf_fo);
+  ASSERT(NULL != wdf_object_ext);
+  if (NULL != wdf_object_ext) {
+    ASSERT(wdf_object_ext->Is(AndroidUsbWdfObjectTypeFile));
+    if (wdf_object_ext->Is(AndroidUsbWdfObjectTypeFile))
+      return reinterpret_cast<AndroidUsbFileObject*>(wdf_object_ext);
+  }
+  return NULL;
+}
+
+/** \brief Gets file KMDF file object extension for the given request
+
+  This method can be called at any IRQL
+  @param request[in] KMDF request object
+  @return Instance of AndroidUsbFileObject associated with this request or NULL
+          if association is not found.
+*/
+__forceinline AndroidUsbFileObject* GetAndroidUsbFileObjectForRequest(
+    WDFREQUEST request) {
+  return GetAndroidUsbFileObjectFromHandle(WdfRequestGetFileObject(request));
+}
+
+#endif  // ANDROID_USB_FILE_OBJECT_H__
diff --git a/host/windows/usb/driver/android_usb_inl.h b/host/windows/usb/driver/android_usb_inl.h
new file mode 100644
index 0000000..8d697cf
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_inl.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_INL_H__
+#define ANDROID_USB_INL_H__
+/** \file
+  This file consists of inline routines for the driver.
+*/
+
+/// Gets control code out of the entire IOCTL code packet
+__forceinline ULONG GetCtlCode(ULONG ioctl_code) {
+  return (ioctl_code >> 2) & 0x0FFF;
+}
+
+/** \brief
+  Converts string length from number of wide characters into number of bytes.
+*/
+__forceinline USHORT ByteLen(USHORT wchar_len) {
+  return static_cast<USHORT>(wchar_len * sizeof(WCHAR));
+}
+
+/** \brief Gets byte length of a zero-terminated string not including
+  zero terminator. Must be called at low IRQL.
+*/
+__forceinline USHORT ByteLen(const WCHAR* str) {
+  ASSERT_IRQL_LOW();
+  return (NULL != str) ? ByteLen(static_cast<USHORT>(wcslen(str))) : 0;
+}
+
+/** \brief
+  Converts string length from number of bytes into number of wide characters.
+  Can be called at any IRQL.
+*/
+__forceinline USHORT WcharLen(USHORT byte_len) {
+  return byte_len / sizeof(WCHAR);
+}
+
+/** \brief Retrieves pointer out of the WDFMEMORY handle
+*/
+__forceinline void* GetAddress(WDFMEMORY wdf_mem) {
+  ASSERT(NULL != wdf_mem);
+  return (NULL != wdf_mem) ? WdfMemoryGetBuffer(wdf_mem, NULL) : NULL;
+}
+
+/** \brief Retrieves output memory address for WDFREQUEST
+
+  @param request[in] A handle to KMDF request object
+  @param status[out] Receives status of the call. Can be NULL.
+*/
+__forceinline void* OutAddress(WDFREQUEST request, NTSTATUS* status) {
+  ASSERT(NULL != request);
+  WDFMEMORY wdf_mem = NULL;
+  NTSTATUS stat = WdfRequestRetrieveOutputMemory(request, &wdf_mem);
+  ASSERT((NULL != wdf_mem) || (!NT_SUCCESS(stat)));
+  if (NULL != status)
+    *status = stat;
+  return NT_SUCCESS(stat) ? GetAddress(wdf_mem) : NULL;
+}
+
+/** \brief Retrieves input memory address for WDFREQUEST
+
+  @param request[in] A handle to KMDF request object
+  @param status[out] Receives status of the call. Can be NULL.
+*/
+__forceinline void* InAddress(WDFREQUEST request, NTSTATUS* status) {
+  ASSERT(NULL != request);
+  WDFMEMORY wdf_mem = NULL;
+  NTSTATUS stat = WdfRequestRetrieveInputMemory(request, &wdf_mem);
+  ASSERT((NULL != wdf_mem) || (!NT_SUCCESS(stat)));
+  if (NULL != status)
+    *status = stat;
+  return NT_SUCCESS(stat) ? GetAddress(wdf_mem) : NULL;
+}
+
+#endif  // ANDROID_USB_INL_H__
diff --git a/host/windows/usb/driver/android_usb_interrupt_file_object.cpp b/host/windows/usb/driver/android_usb_interrupt_file_object.cpp
new file mode 100644
index 0000000..d6303bb
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_interrupt_file_object.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AndroidUsbInterruptPipeFileObject
+  that encapsulates extension to an interrupt pipe file objects.
+*/
+#pragma data_seg()
+#pragma code_seg()
+
+#include "precomp.h"
+#include "android_usb_interrupt_file_object.h"
+
+#pragma data_seg()
+#pragma code_seg("PAGE")
+
+AndroidUsbInterruptPipeFileObject::AndroidUsbInterruptPipeFileObject(
+    AndroidUsbDeviceObject* dev_obj,
+    WDFFILEOBJECT wdf_fo,
+    WDFUSBPIPE wdf_pipe_obj)
+    : AndroidUsbPipeFileObject(dev_obj, wdf_fo, wdf_pipe_obj) {
+  ASSERT_IRQL_PASSIVE();
+
+#if DBG
+  WDF_USB_PIPE_INFORMATION pipe_info;
+  WDF_USB_PIPE_INFORMATION_INIT(&pipe_info);
+  WdfUsbTargetPipeGetInformation(wdf_pipe_obj, &pipe_info);
+  ASSERT(WdfUsbPipeTypeInterrupt == pipe_info.PipeType);
+#endif  // DBG
+
+}
+
+#pragma code_seg()
+
+AndroidUsbInterruptPipeFileObject::~AndroidUsbInterruptPipeFileObject() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+}
+
+#pragma data_seg()
+#pragma code_seg()
diff --git a/host/windows/usb/driver/android_usb_interrupt_file_object.h b/host/windows/usb/driver/android_usb_interrupt_file_object.h
new file mode 100644
index 0000000..5bf097b
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_interrupt_file_object.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_INTERRUPT_PIPE_FILE_OBJECT_H__
+#define ANDROID_USB_INTERRUPT_PIPE_FILE_OBJECT_H__
+/** \file
+  This file consists of declaration of class AndroidUsbInterruptPipeFileObject
+  that encapsulates extension to an interrupt pipe file objects.
+*/
+
+#include "android_usb_pipe_file_object.h"
+
+/** AndroidUsbInterruptPipeFileObject class encapsulates extension for a KMDF
+  file object that represent opened interrupt pipe. Instances of this class
+  must be allocated from NonPagedPool.
+*/
+class AndroidUsbInterruptPipeFileObject : public AndroidUsbPipeFileObject {
+ public:
+  /** \brief Constructs the object.
+
+    This method must be called at low IRQL.
+    @param dev_obj[in] Our device object for which this file has been created
+    @param wdf_fo[in] KMDF file object this extension wraps
+    @param wdf_pipe_obj[in] KMDF pipe for this file
+  */
+  AndroidUsbInterruptPipeFileObject(AndroidUsbDeviceObject* dev_obj,
+                                    WDFFILEOBJECT wdf_fo,
+                                    WDFUSBPIPE wdf_pipe_obj);
+
+  /** \brief Destructs the object.
+
+    This method can be called at any IRQL.
+  */
+   virtual ~AndroidUsbInterruptPipeFileObject();
+};
+
+#endif  // ANDROID_USB_INTERRUPT_PIPE_FILE_OBJECT_H__
diff --git a/host/windows/usb/driver/android_usb_new_delete.h b/host/windows/usb/driver/android_usb_new_delete.h
new file mode 100644
index 0000000..dc4634d
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_new_delete.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_NEW_DELETE_H__
+#define ANDROID_USB_NEW_DELETE_H__
+/** \file
+  This file consists implementations of our 'new' and 'delete' operators
+*/
+
+#include "android_usb_pool_tags.h"
+
+/** \brief Checks if given pool type is one of NonPaged pool kinds.
+
+  All numeric values for all NonPaged pool types are even numbers while all
+  numeric values for all PagedPool types are odd numbers (see definition of
+  POOL_TYPE enum). So this routine utilizes this to see whether given pool
+  type is one of NonPaged pool kinds. This routine can be called at any IRQL.
+  @param pool_type[in] Pool type
+  @return True if pool type is one of NonPaged pool types, false otherwise
+*/
+__forceinline bool IsPoolNonPaged(POOL_TYPE pool_type) {
+  return (0 == (pool_type & 0x1));
+}
+
+/** @name Operators new and delete
+ 
+  In Kernel Mode development each memory allocation must specify type of the
+  pool from which memory should be allocated, usualy PagedPool or NonPagedPool.
+  Because of that "traditional" operator 'new' that takes only one parameter
+  (memory size) is not good so we modify that operator by adding two more
+  parameters: pool type and memory tag (last one is optional but highly
+  encouraged). To prevent from mistakes, traditional operator 'new' is also
+  defined. It will allocate requested number of bytes from NonPagedPool with
+  default memory tag but it will always assert on checked (debug) builds.
+  Since there is no infrastructure for C++ exceptions in Kernel Mode we are
+  not using them to report memory allocation error. So, on failure operators
+  'new' are returning NULL instead of throwing an exception.
+*/
+///@{
+
+/** \brief Main operator new
+
+  This is the main operator new that allocates specified number of bytes from
+  the specified pool and assigns a custom tag to the allocated memory.
+  Inherits IRQL restrictions for ExAllocatePoolWithTag (see the DDK doc).
+  @param size[in] Number of bytes to allocate.
+  @param pool_type[in] Type of the pool to allocate from.
+  @param pool_tag[in] A tag to attach to the allocated memory. Since utilities
+         that display tags use their ASCII representations it's advisable to
+         use tag values that are ASCII symbols, f.i. 'ATag'. Note that due to
+         inversion of bytes in stored ULONG value, to read 'ATag' in the tag
+         displaying utility, the actual value passed to operator 'new' must be
+         'gaTA'
+  @return Pointer to allocated memory on success, NULL on error.
+*/
+__forceinline void* __cdecl operator new(size_t size,
+                                         POOL_TYPE pool_type,
+                                         ULONG pool_tag) {
+  ASSERT((pool_type < MaxPoolType) && (0 != size));
+  // Enforce IRQL restriction check.
+  ASSERT(IsPoolNonPaged(pool_type) || (KeGetCurrentIrql() < DISPATCH_LEVEL));
+  return size ? ExAllocatePoolWithTag(pool_type,
+                                      static_cast<ULONG>(size),
+                                      pool_tag) :
+                NULL;
+}
+
+/** \brief
+  Short operator new that attaches a default tag to the allocated memory.
+
+  This version of operator new allocates specified number of bytes from the
+  specified pool and assigns a default tag (GANDR_POOL_TAG_DEFAULT) to the
+  allocated memory. Inherits IRQL restrictions for ExAllocatePoolWithTag.
+  @param size[in] Number of bytes to allocate.
+  @param pool_type[in] Type of the pool to allocate from.
+  @return Pointer to allocated memory on success, NULL on error.
+*/
+__forceinline void* __cdecl operator new(size_t size, POOL_TYPE pool_type) {
+  ASSERT((pool_type < MaxPoolType) && (0 != size));
+  // Enforce IRQL restriction check.
+  ASSERT(IsPoolNonPaged(pool_type) || (KeGetCurrentIrql() < DISPATCH_LEVEL));
+  return size ? ExAllocatePoolWithTag(pool_type,
+                                      static_cast<ULONG>(size),
+                                      GANDR_POOL_TAG_DEFAULT) :
+                NULL;
+}
+
+/** \brief Traditional operator new that should never be used.
+
+  Using of this version of operator 'new' is prohibited in Kernel Mode
+  development. For the sake of safety it is implemented though to allocate
+  requested number of bytes from the NonPagedPool and attach default tag
+  to the allocated memory. It will assert on checked (debug) builds.
+  Inherits IRQL restrictions for ExAllocatePoolWithTag.
+  @param size[in] Number of bytes to allocate.
+  @return Pointer to memory allocated from NonPagedPool on success or NULL on
+          error.
+*/
+__forceinline void* __cdecl operator new(size_t size) {
+  ASSERTMSG("\n!!! Using of operator new(size_t size) is detected!\n"
+    "This is illegal in our driver C++ development environment to use "
+    "this version of operator 'new'. Please switch to\n"
+    "new(size_t size, POOL_TYPE pool_type) or "
+    "new(size_t size, POOL_TYPE pool_type, ULONG pool_tag) ASAP!!!\n",
+    false);
+  ASSERT(0 != size);
+  return size ? ExAllocatePoolWithTag(NonPagedPool,
+                                      static_cast<ULONG>(size),
+                                      GANDR_POOL_TAG_DEFAULT) :
+                NULL;
+}
+
+/** \brief Operator delete.
+
+  Frees memory allocated by 'new' operator.
+  @param pointer[in] Memory to free. If this parameter is NULL operator does
+         nothing but asserts on checked build. Inherits IRQL restrictions
+         for ExFreePool.
+*/
+__forceinline void __cdecl operator delete(void* pointer) {
+  ASSERT(NULL != pointer);
+  if (NULL != pointer)
+    ExFreePool(pointer);
+}
+
+/** \brief Operator delete for arrays.
+
+  Frees memory allocated by 'new' operator.
+  @param pointer[in] Memory to free. If this parameter is NULL operator does
+         nothing but asserts on checked build. Inherits IRQL restrictions
+         for ExFreePool.
+*/
+__forceinline void __cdecl operator delete[](void* pointer) {
+  ASSERT(NULL != pointer);
+  if (NULL != pointer)
+    ExFreePool(pointer);
+}
+
+///@}
+
+#endif  // ANDROID_USB_NEW_DELETE_H__
diff --git a/host/windows/usb/driver/android_usb_pipe_file_object.cpp b/host/windows/usb/driver/android_usb_pipe_file_object.cpp
new file mode 100644
index 0000000..08d0165
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_pipe_file_object.cpp
@@ -0,0 +1,738 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of class AndroidUsbPipeFileObject that
+  encapsulates a common extension for pipe file objects.
+*/
+#pragma data_seg()
+#pragma code_seg()
+
+#include "precomp.h"
+#include "android_usb_pipe_file_object.h"
+
+#pragma data_seg()
+#pragma code_seg("PAGE")
+
+AndroidUsbPipeFileObject::AndroidUsbPipeFileObject(
+    AndroidUsbDeviceObject* dev_obj,
+    WDFFILEOBJECT wdf_fo,
+    WDFUSBPIPE wdf_pipe_obj)
+    : AndroidUsbFileObject(AndroidUsbFileObjectTypePipe, dev_obj, wdf_fo),
+      wdf_pipe_(wdf_pipe_obj) {
+  ASSERT_IRQL_PASSIVE();
+  ASSERT(NULL != wdf_pipe_obj);
+}
+
+#pragma code_seg()
+
+AndroidUsbPipeFileObject::~AndroidUsbPipeFileObject() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+}
+
+#pragma code_seg("PAGE")
+
+NTSTATUS AndroidUsbPipeFileObject::InitializePipe(
+    const WDF_USB_PIPE_INFORMATION* pipe_info) {
+  ASSERT_IRQL_LOW();
+  ASSERT(IsPipeAttached());
+  if (!IsPipeAttached())
+    return STATUS_INTERNAL_ERROR;
+
+  // Initialize base class
+  NTSTATUS status = AndroidUsbFileObject::Initialize();
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Save pipe information
+  pipe_information_ = *pipe_info;
+
+  // We will provide size check ourselves (less surprizes always better)
+  WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(wdf_pipe());
+
+  GoogleDbgPrint("\n===== File %p for %s pipe. max_transfer_size = %X, max_packet_size = %X",
+                 this, is_input_pipe() ? "read" : "write",
+                 max_transfer_size(), max_packet_size());
+  return STATUS_SUCCESS;
+}
+
+#pragma code_seg()
+
+void AndroidUsbPipeFileObject::OnEvtIoRead(WDFREQUEST request,
+                                           size_t length) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Make sure that this is an input pipe
+  if (is_output_pipe()) {
+    GoogleDbgPrint("\n!!!! Attempt to read from output pipe %p", this);
+    WdfRequestComplete(request, STATUS_ACCESS_DENIED);
+    return;
+  }
+
+  // Make sure zero length I/O doesn't go through
+  if (0 == length) {
+    WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, 0);
+    return;
+  }
+
+  // Get MDL for this request.
+  PMDL request_mdl = NULL;
+  NTSTATUS status = WdfRequestRetrieveOutputWdmMdl(request, &request_mdl);
+  ASSERT(NT_SUCCESS(status) && (NULL != request_mdl));
+  if (NT_SUCCESS(status)) {
+    CommonBulkReadWrite(request,
+                        request_mdl,
+                        static_cast<ULONG>(length),
+                        true,
+                        0,
+                        false);
+  } else {
+    WdfRequestComplete(request, status);
+  }
+}
+
+void AndroidUsbPipeFileObject::OnEvtIoWrite(WDFREQUEST request,
+                                            size_t length) {
+
+  // Make sure that this is an output pipe
+  if (is_input_pipe()) {
+    GoogleDbgPrint("\n!!!! Attempt to write to input pipe %p", this);
+    WdfRequestComplete(request, STATUS_ACCESS_DENIED);
+    return;
+  }
+
+  // Make sure zero length I/O doesn't go through
+  if (0 == length) {
+    WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, 0);
+    return;
+  }
+
+  // Get MDL for this request.
+  PMDL request_mdl = NULL;
+  NTSTATUS status = WdfRequestRetrieveInputWdmMdl(request, &request_mdl);
+  ASSERT(NT_SUCCESS(status) && (NULL != request_mdl));
+  if (NT_SUCCESS(status)) {
+    CommonBulkReadWrite(request,
+                        request_mdl,
+                        static_cast<ULONG>(length),
+                        false,
+                        0,
+                        false);
+  } else {
+    WdfRequestComplete(request, status);
+  }
+}
+
+void AndroidUsbPipeFileObject::OnEvtIoDeviceControl(WDFREQUEST request,
+                                                    size_t output_buf_len,
+                                                    size_t input_buf_len,
+                                                    ULONG ioctl_code) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  switch (GetCtlCode(ioctl_code)) {
+    case ADB_CTL_GET_ENDPOINT_INFORMATION:
+      OnCtlGetEndpointInformation(request, output_buf_len);
+      break;
+
+    case ADB_CTL_BULK_READ:
+      OnCtlBulkRead(request, output_buf_len, input_buf_len);
+      break;
+
+    case ADB_CTL_BULK_WRITE:
+      OnCtlBulkWrite(request, output_buf_len, input_buf_len);
+      break;
+
+    default:
+      AndroidUsbFileObject::OnEvtIoDeviceControl(request,
+                                                 output_buf_len,
+                                                 input_buf_len,
+                                                 ioctl_code);
+      break;
+  }
+}
+
+void AndroidUsbPipeFileObject::OnCtlGetEndpointInformation(
+    WDFREQUEST request,
+    size_t output_buf_len) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Verify output buffer
+  if (output_buf_len < sizeof(AdbEndpointInformation)) {
+    WdfRequestCompleteWithInformation(request,
+                                      STATUS_BUFFER_TOO_SMALL,
+                                      sizeof(AdbEndpointInformation));
+    return;
+  }
+
+  // Get the output buffer
+  NTSTATUS status;
+  AdbEndpointInformation* ret_info =
+    reinterpret_cast<AdbEndpointInformation*>(OutAddress(request, &status));
+  ASSERT(NT_SUCCESS(status) && (NULL != ret_info));
+  if (!NT_SUCCESS(status)) {
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Copy endpoint info to the output
+  ret_info->max_packet_size = pipe_information_.MaximumPacketSize;
+  ret_info->endpoint_address = pipe_information_.EndpointAddress;
+  ret_info->polling_interval = pipe_information_.Interval;
+  ret_info->setting_index = pipe_information_.SettingIndex;
+  ret_info->endpoint_type =
+    static_cast<AdbEndpointType>(pipe_information_.PipeType);
+  ret_info->max_transfer_size = pipe_information_.MaximumTransferSize;
+
+  WdfRequestCompleteWithInformation(request,
+                                    STATUS_SUCCESS,
+                                    sizeof(AdbEndpointInformation));
+}
+
+void AndroidUsbPipeFileObject::OnCtlBulkRead(WDFREQUEST request,
+                                             size_t output_buf_len,
+                                             size_t input_buf_len) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Make sure that this is an input pipe
+  if (is_output_pipe()) {
+    GoogleDbgPrint("\n!!!! Attempt to IOCTL read from output pipe %p", this);
+    WdfRequestComplete(request, STATUS_ACCESS_DENIED);
+    return;
+  }
+
+  // Make sure zero length I/O doesn't go through
+  if (0 == output_buf_len) {
+    WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, 0);
+    return;
+  }
+
+  // Verify buffers
+  ASSERT(input_buf_len >= sizeof(AdbBulkTransfer));
+  if (input_buf_len < sizeof(AdbBulkTransfer)) {
+    WdfRequestComplete(request, STATUS_INVALID_BUFFER_SIZE);
+    return;
+  }
+
+  // Get the input buffer
+  NTSTATUS status;
+  AdbBulkTransfer* transfer_param =
+    reinterpret_cast<AdbBulkTransfer*>(InAddress(request, &status));
+  ASSERT(NT_SUCCESS(status) && (NULL != transfer_param));
+  if (!NT_SUCCESS(status)) {
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Get MDL for this request.
+  PMDL request_mdl = NULL;
+  status = WdfRequestRetrieveOutputWdmMdl(request, &request_mdl);
+  ASSERT(NT_SUCCESS(status) && (NULL != request_mdl));
+  if (NT_SUCCESS(status)) {
+    // Perform the read
+    CommonBulkReadWrite(request,
+                        request_mdl,
+                        static_cast<ULONG>(output_buf_len),
+                        true,
+                        transfer_param->time_out,
+                        true);
+  } else {
+    WdfRequestComplete(request, status);
+  }
+}
+
+void AndroidUsbPipeFileObject::OnCtlBulkWrite(WDFREQUEST request,
+                                              size_t output_buf_len,
+                                              size_t input_buf_len) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Make sure that this is an output pipe
+  if (is_input_pipe()) {
+    GoogleDbgPrint("\n!!!! Attempt to IOCTL write to input pipe %p", this);
+    WdfRequestComplete(request, STATUS_ACCESS_DENIED);
+    return;
+  }
+
+  // Verify buffers
+  ASSERT(input_buf_len >= sizeof(AdbBulkTransfer));
+  // Output buffer points to ULONG that receives number of transferred bytes
+  ASSERT(output_buf_len >= sizeof(ULONG));
+  if ((input_buf_len < sizeof(AdbBulkTransfer)) ||
+      (output_buf_len < sizeof(ULONG))) {
+    WdfRequestComplete(request, STATUS_INVALID_BUFFER_SIZE);
+    return;
+  }
+
+  // Get the input buffer
+  NTSTATUS status = STATUS_SUCCESS;
+  AdbBulkTransfer* transfer_param =
+    reinterpret_cast<AdbBulkTransfer*>(InAddress(request, &status));
+  ASSERT(NT_SUCCESS(status) && (NULL != transfer_param));
+  if (!NT_SUCCESS(status)) {
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Get the output buffer
+  ULONG* ret_transfer =
+    reinterpret_cast<ULONG*>(OutAddress(request, &status));
+  ASSERT(NT_SUCCESS(status) && (NULL != ret_transfer));
+  if (!NT_SUCCESS(status)) {
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Cache these param to prevent us from sudden change after we've chacked it.
+  // This is common practice in protecting ourselves from malicious code:
+  // 1. Never trust anything that comes from the User Mode.
+  // 2. Never assume that anything that User Mode buffer has will remain
+  // unchanged.
+  void* transfer_buffer = transfer_param->write_buffer;
+  ULONG transfer_size = transfer_param->transfer_size;
+
+  // Make sure zero length I/O doesn't go through
+  if (0 == transfer_size) {
+    *ret_transfer = 0;
+    WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, sizeof(ULONG));
+    return;
+  }
+
+  // Make sure that buffer is not NULL
+  ASSERT(NULL != transfer_buffer);
+  if (NULL == transfer_buffer) {
+    WdfRequestComplete(request, STATUS_INVALID_PARAMETER);
+    return;
+  }
+
+  // At this point we are ready to build MDL for the user buffer.
+  PMDL write_mdl =
+    IoAllocateMdl(transfer_buffer, transfer_size, FALSE, FALSE, NULL);
+  ASSERT(NULL != write_mdl);
+  if (NULL == write_mdl) {
+    WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
+    return;
+  }
+
+  // Now we need to probe/lock this mdl
+  __try {
+    MmProbeAndLockPages(write_mdl,
+                        WdfRequestGetRequestorMode(request),
+                        IoReadAccess);
+    status = STATUS_SUCCESS;
+  } __except (EXCEPTION_EXECUTE_HANDLER) {
+    status = GetExceptionCode();
+    ASSERTMSG("\n!!!!! AndroidUsbPipeFileObject::OnCtlBulkWrite exception",
+              false);
+  }
+
+  if (!NT_SUCCESS(status)) {
+    IoFreeMdl(write_mdl);
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Perform the write
+  status = CommonBulkReadWrite(request,
+                               write_mdl,
+                               transfer_size,
+                               false,
+                               transfer_param->time_out,
+                               true);
+  if (!NT_SUCCESS(status)) {
+    // If CommonBulkReadWrite failed we need to unlock and free MDL here
+    MmUnlockPages(write_mdl);
+    IoFreeMdl(write_mdl);
+  }
+}
+
+NTSTATUS AndroidUsbPipeFileObject::CommonBulkReadWrite(
+    WDFREQUEST request,
+    PMDL transfer_mdl,
+    ULONG length,
+    bool is_read,
+    ULONG time_out,
+    bool is_ioctl) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  ASSERT(IsPipeAttached());
+  if (!IsPipeAttached()) {
+    WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
+    return STATUS_INVALID_DEVICE_STATE;
+  }
+
+  // Quick access check. Might be redundant though...
+  ASSERT((is_read && is_input_pipe()) || (!is_read && is_output_pipe()));
+  if ((is_read && is_output_pipe()) || (!is_read && is_input_pipe())) {
+    WdfRequestComplete(request, STATUS_ACCESS_DENIED);
+    return STATUS_ACCESS_DENIED;
+  }
+
+  // Set URB flags
+  ULONG urb_flags = USBD_SHORT_TRANSFER_OK | (is_read ?
+                                                USBD_TRANSFER_DIRECTION_IN :
+                                                USBD_TRANSFER_DIRECTION_OUT);
+
+  // Calculate transfer length for this stage.
+  ULONG stage_len =
+    (length > GetTransferGranularity()) ? GetTransferGranularity() : length;
+
+  // Get virtual address that we're gonna use in the transfer.
+  // We rely here on the fact that we're in the context of the calling thread.
+  void* virtual_address = MmGetMdlVirtualAddress(transfer_mdl);
+
+  // Allocate our private MDL for this address which we will use for the transfer
+  PMDL new_mdl = IoAllocateMdl(virtual_address, length, FALSE, FALSE, NULL);
+  ASSERT(NULL != new_mdl);
+  if (NULL == new_mdl) {
+    WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+
+  // Map the portion of user buffer that we're going to transfer at this stage
+  // to our mdl.
+  IoBuildPartialMdl(transfer_mdl, new_mdl, virtual_address, stage_len);
+
+  // Allocate memory for URB and associate it with this request
+  WDF_OBJECT_ATTRIBUTES mem_attrib;
+  WDF_OBJECT_ATTRIBUTES_INIT(&mem_attrib);
+  mem_attrib.ParentObject = request;
+
+  WDFMEMORY urb_mem = NULL;
+  PURB urb = NULL;
+  NTSTATUS status =
+    WdfMemoryCreate(&mem_attrib,
+                    NonPagedPool,
+                    GANDR_POOL_TAG_BULKRW_URB,
+                    sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+                    &urb_mem,
+                    reinterpret_cast<PVOID*>(&urb));
+  ASSERT(NT_SUCCESS(status) && (NULL != urb));
+  if (!NT_SUCCESS(status)) {
+    IoFreeMdl(new_mdl);
+    WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+
+  // Get USB pipe handle for our pipe and initialize transfer request for it
+  USBD_PIPE_HANDLE usbd_pipe_hndl = usbd_pipe();
+  ASSERT(NULL != usbd_pipe_hndl);
+  if (NULL == usbd_pipe_hndl) {
+    IoFreeMdl(new_mdl);
+    WdfRequestComplete(request, STATUS_INTERNAL_ERROR);
+    return STATUS_INTERNAL_ERROR;
+  }
+
+  // Initialize URB with request information
+  UsbBuildInterruptOrBulkTransferRequest(
+    urb,
+    sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+    usbd_pipe_hndl,
+    NULL,
+    new_mdl,
+    stage_len,
+    urb_flags,
+    NULL);
+
+  // Build transfer request
+  status = WdfUsbTargetPipeFormatRequestForUrb(wdf_pipe(),
+                                               request,
+                                               urb_mem,
+                                               NULL);
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status)) {
+    IoFreeMdl(new_mdl);
+    WdfRequestComplete(request, status);
+    return status;
+  }
+
+  // Initialize our request context.
+  AndroidUsbWdfRequestContext* context =
+    GetAndroidUsbWdfRequestContext(request);
+  ASSERT(NULL != context);
+  if (NULL == context) {
+    IoFreeMdl(new_mdl);
+    WdfRequestComplete(request, STATUS_INTERNAL_ERROR);
+    return STATUS_INTERNAL_ERROR;
+  }
+
+  context->object_type = AndroidUsbWdfObjectTypeRequest;
+  context->urb_mem = urb_mem;
+  context->transfer_mdl = transfer_mdl;
+  context->mdl = new_mdl;
+  context->length = length;
+  context->transfer_size = stage_len;
+  context->num_xfer = 0;
+  context->virtual_address = virtual_address;
+  context->is_read = is_read;
+  context->initial_time_out = time_out;
+  context->is_ioctl = is_ioctl;
+
+  // Set our completion routine
+  WdfRequestSetCompletionRoutine(request,
+                                 CommonReadWriteCompletionEntry,
+                                 this);
+
+  // Init send options (our timeout goes here)
+  WDF_REQUEST_SEND_OPTIONS send_options;
+  if (0 != time_out) {
+    WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_TIMEOUT);
+    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&send_options, WDF_REL_TIMEOUT_IN_MS(time_out));
+  }
+
+  // Timestamp first WdfRequestSend
+  KeQuerySystemTime(&context->sent_at);
+
+  // Send request asynchronously.
+  if (WdfRequestSend(request, wdf_pipe_io_target(),
+                     (0 == time_out) ? WDF_NO_SEND_OPTIONS : &send_options)) {
+    return STATUS_SUCCESS;
+  }
+
+  // Something went wrong here
+  status = WdfRequestGetStatus(request);
+  ASSERT(!NT_SUCCESS(status));
+  GoogleDbgPrint("\n!!!!! CommonBulkReadWrite: WdfRequestGetStatus (is_read = %u) failed: %08X",
+           is_read, status);
+  WdfRequestCompleteWithInformation(request, status, 0);
+
+  return status;
+}
+
+void AndroidUsbPipeFileObject::OnCommonReadWriteCompletion(
+    WDFREQUEST request,
+    PWDF_REQUEST_COMPLETION_PARAMS completion_params,
+    AndroidUsbWdfRequestContext* context) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  NTSTATUS status = completion_params->IoStatus.Status;
+  if (!NT_SUCCESS(status)){
+    GoogleDbgPrint("\n========== Request completed with failure: %X", status);
+    IoFreeMdl(context->mdl);
+    // If this was IOCTL-originated write we must unlock and free
+    // our transfer MDL.
+    if (context->is_ioctl && !context->is_read) {
+      MmUnlockPages(context->transfer_mdl);
+      IoFreeMdl(context->transfer_mdl);
+    }
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Get our URB buffer
+  PURB urb
+    = reinterpret_cast<PURB>(WdfMemoryGetBuffer(context->urb_mem, NULL));
+  ASSERT(NULL != urb);
+
+  // Lets see how much has been transfered and update our counters accordingly
+  ULONG bytes_transfered =
+    urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
+  // We expect writes to transfer entire packet
+  ASSERT((bytes_transfered == context->transfer_size) || context->is_read);
+  context->num_xfer += bytes_transfered;
+  context->length -= bytes_transfered;
+
+  // Is there anything left to transfer? Now, by the protocol we should
+  // successfuly complete partial reads, instead of waiting on full set
+  // of requested bytes being accumulated in the read buffer.
+  if ((0 == context->length) || context->is_read) {
+    status = STATUS_SUCCESS;
+
+    // This was the last transfer
+    if (context->is_ioctl && !context->is_read) {
+      // For IOCTL-originated writes we have to return transfer size through
+      // the IOCTL's output buffer.
+      ULONG* ret_transfer =
+        reinterpret_cast<ULONG*>(OutAddress(request, NULL));
+      ASSERT(NULL != ret_transfer);
+      if (NULL != ret_transfer)
+        *ret_transfer = context->num_xfer;
+      WdfRequestSetInformation(request, sizeof(ULONG));
+
+      // We also must unlock / free transfer MDL
+      MmUnlockPages(context->transfer_mdl);
+      IoFreeMdl(context->transfer_mdl);
+    } else {
+      // For other requests we report transfer size through the request I/O
+      // completion status.
+      WdfRequestSetInformation(request, context->num_xfer);
+    }
+    IoFreeMdl(context->mdl);
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // There are something left for the transfer. Prepare for it.
+  // Required to free any mapping made on the partial MDL and
+  // reset internal MDL state.
+  MmPrepareMdlForReuse(context->mdl);
+
+  // Update our virtual address
+  context->virtual_address = 
+    reinterpret_cast<char*>(context->virtual_address) + bytes_transfered;
+
+  // Calculate size of this transfer
+  ULONG stage_len =
+    (context->length > GetTransferGranularity()) ? GetTransferGranularity() :
+                                                   context->length;
+
+  IoBuildPartialMdl(context->transfer_mdl,
+                    context->mdl,
+                    context->virtual_address,
+                    stage_len);
+
+  // Reinitialize the urb and context
+  urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stage_len;
+  context->transfer_size = stage_len;
+
+  // Format the request to send a URB to a USB pipe.
+  status = WdfUsbTargetPipeFormatRequestForUrb(wdf_pipe(),
+                                               request,
+                                               context->urb_mem,
+                                               NULL);
+  ASSERT(NT_SUCCESS(status));
+  if (!NT_SUCCESS(status)) {
+    if (context->is_ioctl && !context->is_read) {
+      MmUnlockPages(context->transfer_mdl);
+      IoFreeMdl(context->transfer_mdl);
+    }
+    IoFreeMdl(context->mdl);
+    WdfRequestComplete(request, status);
+    return;
+  }
+
+  // Reset the completion routine
+  WdfRequestSetCompletionRoutine(request,
+                                 CommonReadWriteCompletionEntry,
+                                 this);
+
+  // Send the request asynchronously.
+  if (!WdfRequestSend(request, wdf_pipe_io_target(), WDF_NO_SEND_OPTIONS)) {
+    if (context->is_ioctl && !context->is_read) {
+      MmUnlockPages(context->transfer_mdl);
+      IoFreeMdl(context->transfer_mdl);
+    }
+    status = WdfRequestGetStatus(request);
+    IoFreeMdl(context->mdl);
+    WdfRequestComplete(request, status);
+  }
+}
+
+NTSTATUS AndroidUsbPipeFileObject::ResetPipe() {
+  ASSERT_IRQL_PASSIVE();
+
+  // This routine synchronously submits a URB_FUNCTION_RESET_PIPE
+  // request down the stack.
+  NTSTATUS status = WdfUsbTargetPipeAbortSynchronously(wdf_pipe(),
+                                                       WDF_NO_HANDLE,
+                                                       NULL);
+  if (NT_SUCCESS(status)) {
+    status = WdfUsbTargetPipeResetSynchronously(wdf_pipe(),
+                                                WDF_NO_HANDLE,
+                                                NULL);
+    if (!NT_SUCCESS(status))
+      GoogleDbgPrint("\n!!!!! AndroidUsbPipeFileObject::ResetPipe failed %X", status);
+  } else {
+      GoogleDbgPrint("\n!!!!! WdfUsbTargetPipeAbortSynchronously failed %X", status);
+  }
+
+  return status;
+}
+
+NTSTATUS AndroidUsbPipeFileObject::QueueResetPipePassiveCallback() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // Initialize workitem
+  WDF_OBJECT_ATTRIBUTES attr;
+  WDF_OBJECT_ATTRIBUTES_INIT(&attr);
+  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attr, AndroidUsbWorkitemContext);
+  attr.ParentObject = wdf_device();
+
+  WDFWORKITEM wdf_work_item = NULL;
+  WDF_WORKITEM_CONFIG workitem_config;
+  WDF_WORKITEM_CONFIG_INIT(&workitem_config, ResetPipePassiveCallbackEntry);
+  NTSTATUS status = WdfWorkItemCreate(&workitem_config,
+                                      &attr,
+                                      &wdf_work_item);
+  ASSERT(NT_SUCCESS(status) && (NULL != wdf_work_item));
+  if (!NT_SUCCESS(status))
+    return status;
+
+  // Initialize our extension to work item
+  AndroidUsbWorkitemContext* context =
+    GetAndroidUsbWorkitemContext(wdf_work_item);
+  ASSERT(NULL != context);
+  if (NULL == context) {
+    WdfObjectDelete(wdf_work_item);
+    return STATUS_INTERNAL_ERROR;
+  }
+
+  context->object_type = AndroidUsbWdfObjectTypeWorkitem;
+  context->pipe_file_ext = this;
+
+  // Enqueue this work item.
+  WdfWorkItemEnqueue(wdf_work_item);
+
+  return STATUS_SUCCESS;
+}
+
+void AndroidUsbPipeFileObject::CommonReadWriteCompletionEntry(
+    WDFREQUEST request,
+    WDFIOTARGET wdf_target,
+    PWDF_REQUEST_COMPLETION_PARAMS completion_params,
+    WDFCONTEXT completion_context) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  AndroidUsbWdfRequestContext*
+    context = GetAndroidUsbWdfRequestContext(request);
+  ASSERT((NULL != context) && (AndroidUsbWdfObjectTypeRequest == context->object_type));
+
+  AndroidUsbPipeFileObject* pipe_file_ext =
+    reinterpret_cast<AndroidUsbPipeFileObject*>(completion_context);
+  ASSERT((NULL != pipe_file_ext) &&
+         (pipe_file_ext->wdf_pipe() == (WDFUSBPIPE)wdf_target));
+
+  pipe_file_ext->OnCommonReadWriteCompletion(request,
+                                             completion_params,
+                                             context);
+}
+
+void AndroidUsbPipeFileObject::ResetPipePassiveCallbackEntry(
+    WDFWORKITEM wdf_work_item) {
+  ASSERT_IRQL_PASSIVE();
+
+  AndroidUsbWorkitemContext* context =
+    GetAndroidUsbWorkitemContext(wdf_work_item);
+  ASSERT((NULL != context) &&
+         (AndroidUsbWdfObjectTypeWorkitem == context->object_type));
+  if ((NULL == context) ||
+      (AndroidUsbWdfObjectTypeWorkitem != context->object_type)) {
+    WdfObjectDelete(wdf_work_item);
+    return;
+  }
+
+  // In the sample they reset the device if pipe reset failed
+  AndroidUsbDeviceObject* wdf_device_ext =
+    context->pipe_file_ext->device_object();
+
+  NTSTATUS status = context->pipe_file_ext->ResetPipe();
+  if (!NT_SUCCESS(status))
+    status = wdf_device_ext->ResetDevice();
+  
+  WdfObjectDelete(wdf_work_item);
+}
+
+#pragma data_seg()
+#pragma code_seg()
diff --git a/host/windows/usb/driver/android_usb_pipe_file_object.h b/host/windows/usb/driver/android_usb_pipe_file_object.h
new file mode 100644
index 0000000..b0db9a8
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_pipe_file_object.h
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_PIPE_FILE_OBJECT_H__
+#define ANDROID_USB_PIPE_FILE_OBJECT_H__
+/** \file
+  This file consists of declaration of class AndroidUsbPipeFileObject that
+  encapsulates a common extension for pipe file objects.
+*/
+
+#include "android_usb_file_object.h"
+
+/** AndroidUsbPipeFileObject class encapsulates extension for a KMDF file
+  object that represents opened pipe. Instances of this class must be
+  allocated from NonPagedPool.
+*/
+class AndroidUsbPipeFileObject : public AndroidUsbFileObject {
+ public:
+  /** \brief Constructs the object.
+
+    This method must be called at low IRQL.
+    @param dev_obj[in] Our device object for which this file has been created
+    @param wdf_fo[in] KMDF file object this extension wraps
+    @param wdf_pipe_obj[in] KMDF pipe for this file
+  */
+  AndroidUsbPipeFileObject(AndroidUsbDeviceObject* dev_obj,
+                           WDFFILEOBJECT wdf_fo,
+                           WDFUSBPIPE wdf_pipe_obj);
+
+  /** \brief Destructs the object.
+
+    This method can be called at any IRQL.
+  */
+   virtual ~AndroidUsbPipeFileObject();
+
+  /** \brief Initializes the pipe file object extension
+
+    This method internally calls AndroidUsbFileObject::Initialize()
+    This method must be called at low IRQL
+    @param pipe_info[in] Pipe information
+    @return STATUS_SUCCESS or an appropriate error code
+  */
+  virtual NTSTATUS InitializePipe(const WDF_USB_PIPE_INFORMATION* pipe_info);
+
+  /** \brief Read event handler
+
+    This method is called when a read request comes to the file object this
+    extension wraps. This method is an override.
+    This method can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param length[in] The number of bytes to be read.
+    @return Successful status or an appropriate error code
+  */
+  virtual void OnEvtIoRead(WDFREQUEST request, size_t length);
+
+  /** \brief Write event handler
+
+    This method is called when a write request comes to the file object this
+    extension wraps. This method is an override.
+    This method can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param length[in] The number of bytes to be written.
+    @return Successful status or an appropriate error code
+  */
+  virtual void OnEvtIoWrite(WDFREQUEST request, size_t length);
+
+  /** \brief IOCTL event handler
+
+    This method is called when a device control request comes to the file
+    object this extension wraps. We hanlde the following IOCTLs here:
+    1. ADB_CTL_GET_ENDPOINT_INFORMATION
+    2. ADB_CTL_BULK_READ
+    3. ADB_CTL_BULK_WRITE
+    This method can be called IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+    @param input_buf_len[in] The length, in bytes, of the request's input
+           buffer, if an input buffer is available.
+    @param ioctl_code[in] The driver-defined or system-defined I/O control code
+           that is associated with the request.
+    @return Successful status or an appropriate error code
+  */
+  virtual void OnEvtIoDeviceControl(WDFREQUEST request,
+                                    size_t output_buf_len,
+                                    size_t input_buf_len,
+                                    ULONG ioctl_code);
+
+ protected:
+  /** \brief Handler for ADB_CTL_GET_ENDPOINT_INFORMATION IOCTL request
+    
+    @param request[in] A handle to a framework request object.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+  */
+  virtual void OnCtlGetEndpointInformation(WDFREQUEST request,
+                                           size_t output_buf_len);
+
+  /** \brief Handler for ADB_CTL_BULK_READ IOCTL request
+    
+    @param request[in] A handle to a framework request object.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+    @param input_buf_len[in] The length, in bytes, of the request's input
+           buffer, if an input buffer is available.
+  */
+  virtual void OnCtlBulkRead(WDFREQUEST request,
+                             size_t output_buf_len,
+                             size_t input_buf_len);
+
+  /** \brief Handler for ADB_CTL_BULK_WRITE IOCTL request
+    
+    @param request[in] A handle to a framework request object.
+    @param output_buf_len[in] The length, in bytes, of the request's output
+           buffer, if an output buffer is available.
+    @param input_buf_len[in] The length, in bytes, of the request's input
+           buffer, if an input buffer is available.
+  */
+  virtual void OnCtlBulkWrite(WDFREQUEST request,
+                              size_t output_buf_len,
+                              size_t input_buf_len);
+
+  /** \brief Performs common bulk read / write on the pipe
+
+    This method is called from bulk and interrupt pipe file extensions to
+    perform read to / write from the pipe this file represents. Typicaly,
+    this method is called from OnEvtIoRead / OnEvtIoWrite /
+    OnEvtIoDeviceControl methods. One very special case for this method is
+    IOCTL-originated write request. If this is IOCTL-originated write request
+    we can't report transfer size through the request's status block. Instead,
+    for IOCTL-originated writes, the output buffer must a) exist and b) point
+    to an ULONG that will receive size of the transfer. Besides, for this type
+    of writes we create / lock write buffer MDL ourselves so we need to unlock
+    and free it in the completion routine.
+    This method can be called at IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object.
+    @param transfer_mdl[in] MDL for the transferring buffer. The MDL must be
+           locked prior to this call.
+    @param length[in] The number of bytes to be read / written. If this method
+           is actually IOCTL originated write request this parameter must be
+           taken from AdbBulkTransfer.transfer_size by the caller of this
+           method. AdbBulkTransfer is available at the beginning of the input
+           buffer for bulk read / write IOCTLs.
+    @param is_read[in] If true this is a read operation, otherwise it's write
+           operation.
+    @param time_out[in] Number of milliseconds for this request to complete.
+           If this parameter is zero there will be no timeout associated with
+           the request. Otherwise, if request doesn't complete within the given
+           timeframe it will be cancelled.
+    @param is_ioctl[in] If 'true' this method has been called from IOCTL
+           handler. Otherwise it has been called from read / write handler. If
+           this is IOCTL-originated write request we need to report bytes
+           transferred through the IOCTL's output buffer.
+    This method can be called IRQL <= DISPATCH_LEVEL.
+    @return STATUS_SUCCESS or an appropriate error code
+  */
+  virtual NTSTATUS CommonBulkReadWrite(WDFREQUEST request,
+                                       PMDL transfer_mdl,
+                                       ULONG length,
+                                       bool is_read,
+                                       ULONG time_out,
+                                       bool is_ioctl);
+
+  /** \brief Handles request completion for CommonBulkReadWrite
+
+    This method is called from CommonReadWriteCompletionEntry.
+    This method can be called at IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object that is being
+           completed.
+    @param params[in] A pointer to a WDF_REQUEST_COMPLETION_PARAMS structure
+           that contains information about the completed request.
+    @param context[in] Context associated with this request in
+           CommonBulkReadWrite
+    This method can be called IRQL <= DISPATCH_LEVEL.
+  */
+  virtual void OnCommonReadWriteCompletion(WDFREQUEST request,
+                                           PWDF_REQUEST_COMPLETION_PARAMS completion_params,
+                                           AndroidUsbWdfRequestContext* context);
+
+  /** \brief Resets pipe associated with this file
+
+    After reseting the pipe this object might be destroyed.
+    This method must be called at PASSIVE IRQL.
+    @param read_device_on_failure[in] If true and reset pipe has failed this
+           method will attempt to reset the device.
+    @return STATUS_SUCCESS on success or an appropriate error code
+  */
+  virtual NTSTATUS ResetPipe();
+
+  /** \brief Queues a workitem to launch pipe reset at PASSIVE IRQL
+
+    This method can be called at IRQL <= DISPATCH_LEVEL.
+    @return STATUS_SUCCESS or an appropriate error code.
+  */
+  virtual NTSTATUS QueueResetPipePassiveCallback();
+
+ private:
+  /** \brief Request completion routine for CommonBulkReadWrite
+
+    This method can be called at IRQL <= DISPATCH_LEVEL.
+    @param request[in] A handle to a framework request object that is being
+           completed.
+    @param wdf_target[in] A handle to an I/O target object that represents the
+           I/O target that completed the request. In this case this is a pipe.
+    @param params[in] A pointer to a WDF_REQUEST_COMPLETION_PARAMS structure
+           that contains information about the completed request.
+    @param completion_context[in] A handle to driver-supplied context
+           information, which the driver specified in a previous call to 
+           WdfRequestSetCompletionRoutine. In our case this is a pointer
+           to this class instance that issued the request.
+    This method can be called IRQL <= DISPATCH_LEVEL.
+  */
+  static void CommonReadWriteCompletionEntry(WDFREQUEST request,
+                                             WDFIOTARGET wdf_target,
+                                             PWDF_REQUEST_COMPLETION_PARAMS params,
+                                             WDFCONTEXT completion_context);
+
+  /** \brief Entry point for pipe reset workitem callback
+
+    This method is called at PASSIVE IRQL
+    @param wdf_work_item[in] A handle to a framework work item object.
+  */
+  static void ResetPipePassiveCallbackEntry(WDFWORKITEM wdf_work_item);
+
+ public:
+  /// Gets KMDF pipe handle for this file
+  __forceinline WDFUSBPIPE wdf_pipe() const {
+    return wdf_pipe_;
+  }
+
+  /// Gets maximum transfer size for this pipe
+  __forceinline ULONG max_transfer_size() const {
+    ASSERT(0 != pipe_information_.MaximumTransferSize);
+    return pipe_information_.MaximumTransferSize;
+  }
+
+  /// Gets maximum packet size this pipe is capable of
+  __forceinline ULONG max_packet_size() const {
+    ASSERT(0 != pipe_information_.MaximumPacketSize);
+    return pipe_information_.MaximumPacketSize;
+  }
+
+  /// Gets transfer granularity
+  // TODO: It looks like device USB is capable of handling
+  // packets with size greater than pipe_information_.MaximumPacketSize!
+  // So, looks like we are not bound by this parameter in this driver.
+  __forceinline ULONG GetTransferGranularity() const {
+    return max_transfer_size();
+  }
+
+  /// Checks if this is an input pipe
+  __forceinline bool is_input_pipe() const {
+    return WDF_USB_PIPE_DIRECTION_IN(pipe_information_.EndpointAddress) ?
+          true : false;
+  }
+
+  /// Checks if this is an output pipe
+  __forceinline bool is_output_pipe() const {
+    return WDF_USB_PIPE_DIRECTION_OUT(pipe_information_.EndpointAddress) ?
+          true : false;
+  }
+
+  /// Checks if pipe is attached to this file
+  __forceinline bool IsPipeAttached() const {
+    return (NULL != wdf_pipe());
+  }
+
+  /// Gets USBD pipe handle
+  // TODO: Can we cache this?
+  __forceinline USBD_PIPE_HANDLE usbd_pipe() const {
+    ASSERT(IsPipeAttached());
+    return (IsPipeAttached()) ? WdfUsbTargetPipeWdmGetPipeHandle(wdf_pipe()) :
+                                NULL;
+  }
+
+  /// Gets I/O target handle for this pipe
+  // TODO: Can we cache this?
+  __forceinline WDFIOTARGET wdf_pipe_io_target() const {
+    ASSERT(IsPipeAttached());
+    return (IsPipeAttached()) ? WdfUsbTargetPipeGetIoTarget(wdf_pipe()) :
+                                NULL;
+  }
+
+ protected:
+  /// Cached pipe information
+  WDF_USB_PIPE_INFORMATION  pipe_information_;
+
+  /// KMDF pipe handle for this file
+  WDFUSBPIPE                wdf_pipe_;
+};
+
+#endif  // ANDROID_USB_PIPE_FILE_OBJECT_H__
diff --git a/host/windows/usb/driver/android_usb_pool_tags.h b/host/windows/usb/driver/android_usb_pool_tags.h
new file mode 100644
index 0000000..708dcb7
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_pool_tags.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_POOL_TAGS_H__
+#define ANDROID_USB_POOL_TAGS_H__
+/** \file 
+  This file consists definitions for pool tags used in memory allocations for
+  the driver.
+*/
+
+/// Default pool tag for memory allocations (GAND)
+#define GANDR_POOL_TAG_DEFAULT                  'DNAG'
+
+/// Pool tag for the driver object (GADR)
+#define GANDR_POOL_TAG_DRIVER_OBJECT            'RDAG'
+
+/// Pool tag for KMDF device object extension (GADx)
+#define GANDR_POOL_TAG_KMDF_DEVICE              'xDAG'
+
+/// Pool tag for target device configuration descriptor (GACD)
+#define GANDR_POOL_TAG_DEV_CFG_DESC             'DCAG'
+
+/// Pool tag for device file object extension (GADf)
+#define GANDR_POOL_TAG_DEVICE_FO                'fDAG'
+
+/// Pool tag for a bulk file object extension (GABx)
+#define GANDR_POOL_TAG_BULK_FILE                'xBAG'
+
+/// Pool tag for an interrupt file object extension (GAIx)
+#define GANDR_POOL_TAG_INTERRUPT_FILE           'xIAG'
+
+/// Pool tag for URB allocated in bulk read / write (GAbu)
+#define GANDR_POOL_TAG_BULKRW_URB               'ubAG'
+
+/// Pool tag for interface pairs (GAip)
+#define GANDR_POOL_TAG_INTERF_PAIRS             'piAG'
+
+#endif  // ANDROID_USB_POOL_TAGS_H__
diff --git a/host/windows/usb/driver/android_usb_wdf_object.cpp b/host/windows/usb/driver/android_usb_wdf_object.cpp
new file mode 100644
index 0000000..68e2f99
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_wdf_object.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  This file consists of implementation of a class AndroidUsbWdfObject that
+  encapsulates a basic extension to all KMDF objects. Currently, device and
+  file object extensions ared derived from it.
+*/
+#pragma data_seg()
+#pragma code_seg()
+
+#include "precomp.h"
+#include "android_usb_wdf_object.h"
+
+#pragma data_seg()
+#pragma code_seg("PAGE")
+
+AndroidUsbWdfObject::AndroidUsbWdfObject(AndroidUsbWdfObjectType obj_type)
+    : wdf_object_(NULL),
+      object_type_(obj_type) {
+  ASSERT_IRQL_LOW();
+  ASSERT(obj_type < AndroidUsbWdfObjectTypeMax);
+}
+
+#pragma code_seg()
+
+AndroidUsbWdfObject::~AndroidUsbWdfObject() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+}
+
+#pragma code_seg("PAGE")
+
+NTSTATUS AndroidUsbWdfObject::InitObjectAttributes(
+    PWDF_OBJECT_ATTRIBUTES wdf_obj_attr,
+    WDFOBJECT parent) {
+  ASSERT_IRQL_LOW();
+
+  // Enforce file object extension exception.
+  ASSERT(!Is(AndroidUsbWdfObjectTypeFile));
+  if (Is(AndroidUsbWdfObjectTypeFile))
+    return STATUS_INTERNAL_ERROR;
+
+  // Initialize attributes and set cleanup and destroy callbacks
+  WDF_OBJECT_ATTRIBUTES_INIT(wdf_obj_attr);
+  WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(wdf_obj_attr,
+                                         AndroidUsbWdfObjectContext);
+  wdf_obj_attr->EvtCleanupCallback = EvtCleanupCallbackEntry;
+  wdf_obj_attr->EvtDestroyCallback = EvtDestroyCallbackEntry;
+  wdf_obj_attr->ParentObject = parent;
+  wdf_obj_attr->SynchronizationScope = GetWdfSynchronizationScope();
+
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS AndroidUsbWdfObject::InitializeContext() {
+  ASSERT_IRQL_LOW();
+  ASSERT(IsAttached());
+  if (!IsAttached())
+    return STATUS_INTERNAL_ERROR;
+
+  // Initialize our extension to that object
+  AndroidUsbWdfObjectContext* context =
+    GetAndroidUsbWdfObjectContext(wdf_object());
+  ASSERT(NULL != context);
+  if (NULL == context)
+    return STATUS_INTERNAL_ERROR;
+
+  // Make sure that extension has not been initialized
+  ASSERT((0 == context->object_type) && (NULL == context->wdf_object_ext));
+  if ((0 != context->object_type) || (NULL != context->wdf_object_ext))
+    return STATUS_INTERNAL_ERROR;
+
+  context->object_type = object_type();
+  context->wdf_object_ext = this;
+  ASSERT(this == GetAndroidUsbWdfObjectFromHandle(wdf_object()));
+
+  return STATUS_SUCCESS;
+}
+
+#pragma code_seg()
+
+WDF_SYNCHRONIZATION_SCOPE AndroidUsbWdfObject::GetWdfSynchronizationScope() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  // By default we don't want KMDF to synchronize access to our objects
+  return WdfSynchronizationScopeNone;
+}
+
+void AndroidUsbWdfObject::OnEvtCleanupCallback() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  GoogleDbgPrint("\n----- Object %p of type %u is cleaned up",
+           this, object_type());
+}
+
+void AndroidUsbWdfObject::OnEvtDestroyCallback() {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+  GoogleDbgPrint("\n----- Object %p of type %u is destroyed",
+           this, object_type());
+}
+
+void AndroidUsbWdfObject::EvtCleanupCallbackEntry(WDFOBJECT wdf_obj) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  AndroidUsbWdfObjectContext* context = GetAndroidUsbWdfObjectContext(wdf_obj);
+  ASSERT(NULL != context);
+  if (NULL != context) {
+    // For file objects we will be always called here even though we didn't
+    // create any extension for them. In this case the context must not be
+    // initialized.
+    ASSERT(((0 == context->object_type) && (NULL == context->wdf_object_ext)) ||
+           ((0 != context->object_type) && (NULL != context->wdf_object_ext)));
+    if (NULL != context->wdf_object_ext) {
+      ASSERT(context->wdf_object_ext->Is(context->object_type));
+      context->wdf_object_ext->OnEvtCleanupCallback();
+    }
+  }
+}
+
+void AndroidUsbWdfObject::EvtDestroyCallbackEntry(WDFOBJECT wdf_obj) {
+  ASSERT_IRQL_LOW_OR_DISPATCH();
+
+  AndroidUsbWdfObjectContext* context =
+    GetAndroidUsbWdfObjectContext(wdf_obj);
+  ASSERT(NULL != context);
+  if (NULL != context) {
+    // For file objects we will be always called here even though we didn't
+    // create any extension for them. In this case the context must not be
+    // initialized.
+    ASSERT(((0 == context->object_type) && (NULL == context->wdf_object_ext)) ||
+          ((0 != context->object_type) && (NULL != context->wdf_object_ext)));
+    if (NULL != context->wdf_object_ext) {
+      ASSERT(context->wdf_object_ext->Is(context->object_type));
+      context->wdf_object_ext->OnEvtDestroyCallback();
+      delete context->wdf_object_ext;
+    }
+  }
+}
+
+#pragma data_seg()
+#pragma code_seg()
diff --git a/host/windows/usb/driver/android_usb_wdf_object.h b/host/windows/usb/driver/android_usb_wdf_object.h
new file mode 100644
index 0000000..aedd14a
--- /dev/null
+++ b/host/windows/usb/driver/android_usb_wdf_object.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_USB_WDF_OBJECT_H__
+#define ANDROID_USB_WDF_OBJECT_H__
+/** \file
+  This file consists of declaration of a class AndroidUsbWdfObject that
+  encapsulates a basic extension to all KMDF objects. Currently, device and
+  file object extensions ared derived from it.
+*/
+
+/** AndroidUsbWdfObject class encapsulates a basic extension to all KMDF
+  objects. Currently, device and file object extensions ared derived from it.
+  Instances of this and derived classes must be allocated from NonPagedPool.
+*/
+class AndroidUsbWdfObject {
+ public:
+  /** \brief Constructs the object.
+
+    @param obj_type[in] Type of the object that this wrapper represents.
+    This method must be called at low IRQL.
+  */
+  AndroidUsbWdfObject(AndroidUsbWdfObjectType obj_type);
+
+  /** \brief Destructs the object.
+
+    This method can be called at any IRQL.
+  */
+  virtual ~AndroidUsbWdfObject();
+
+  /** \brief Initializes object attributes for new KMDF object.
+
+    Each KMDF extension object must perform attribute initializations in order
+    to register an extension with KMDF framework. Since all our extensions are
+    derived from the base AndroidUsbWdfObject we use a single WDF object
+    extension context for all KMDF objects that we extend. So we can initialize
+    and register our context extension structure here. Note that object
+    attributes for file object wrappers are initialized globaly, when device
+    object is created. So file object extensions must not call this method.
+    This method must be called at low IRQL.
+    @param wdf_obj_attr[out] Object attributes to initialize.
+    @param parent[in] Parent object for this object. Can be NULL.
+    @return STATUS_SUCCESS on success or an appropriate error code.
+  */
+  virtual NTSTATUS InitObjectAttributes(PWDF_OBJECT_ATTRIBUTES wdf_obj_attr,
+                                        WDFOBJECT parent);
+
+  /** \brief Initializes context for this extension
+
+    This method initializes AndroidUsbWdfObjectContext structure that KMDF
+    allocated for the object that is being extended with this class.
+    InitObjectAttributes method must be called prior to the call to this
+    method. Besides, before calling this method, instance of this class must
+    be already attached to the KMDF object it represents. Otherwise this
+    method will fail with STATUS_INTERNAL_ERROR.
+    This method must be called at low IRQL.
+    @return STATUS_SUCCESS on success or an appropriate error code
+  */
+  virtual NTSTATUS InitializeContext();
+
+
+ protected:
+  /** \brief Returns syncronisation scope for this extension type.
+
+    This method is called from InitObjectAttributes method to specify what
+    type of synchronization is required for instances of this type. By
+    default we return WdfSynchronizationScopeNone which makes KMDF not
+    to synchronize access to this type of object.
+    This method can be called at IRQL <= DISPATCH_LEVEL.
+  */
+  virtual WDF_SYNCHRONIZATION_SCOPE GetWdfSynchronizationScope();
+
+  /** \brief Handler for cleanup event fired for associated KMDF object.
+
+    The framework calls this callback function when either the framework or a
+    driver attempts to delete the object.
+    This method can be called at IRQL <= DISPATCH_LEVEL.
+  */
+  virtual void OnEvtCleanupCallback();
+
+  /** \brief Handler for destroy callback
+
+    The framework calls the EvtDestroyCallback callback function after the
+    object's reference count has been decremented to zero. The framework
+    deletes the object immediately after the EvtDestroyCallback callback
+    function returns.
+    This callback can be called at IRQL <= DISPATCH_LEVEL.
+  */
+  virtual void OnEvtDestroyCallback();
+
+  /** \brief Removes driver's references on an object so it can be deleted.
+
+    The framework calls the callback function when either the framework or a
+    driver attempts to delete the object.
+    This callback can be called at IRQL <= DISPATCH_LEVEL.
+    @param wdf_obj[in] A handle to a framework object this class wraps.
+  */
+  static void EvtCleanupCallbackEntry(WDFOBJECT wdf_obj);
+
+  /** \brief Called when framework object is being deleted
+
+    The framework calls the EvtDestroyCallback callback function after the
+    object's reference count has been decremented to zero. The framework
+    deletes the object immediately after the EvtDestroyCallback callback
+    function returns.
+    This callback can be called at IRQL <= DISPATCH_LEVEL.
+    @param wdf_obj[in] A handle to a framework object this class wraps.
+  */
+  static void EvtDestroyCallbackEntry(WDFOBJECT wdf_obj);
+
+ public:
+
+  /// Gets KMDF object extended with this instance
+  __forceinline WDFOBJECT wdf_object() const {
+    return wdf_object_;
+  }
+
+  /// Sets KMDF object associated with this extension
+  __forceinline void set_wdf_object(WDFOBJECT wdf_obj) {
+    ASSERT(NULL == wdf_object_);
+    wdf_object_ = wdf_obj;
+  }
+
+  /// Gets KMDF object type for this extension
+  __forceinline AndroidUsbWdfObjectType object_type() const {
+    return object_type_;
+  }
+
+  /** \brief Checks if this extension represends KMDF object of the given type
+
+    @param obj_type[in] Object type to check
+    @return true if this wrapper represents object of that type and
+            false otherwise.
+  */
+  __forceinline Is(AndroidUsbWdfObjectType obj_type) const {
+    return (obj_type == object_type());
+  }
+
+  /// Checks if extension is attached to a KMDF object
+  __forceinline bool IsAttached() const {
+    return (NULL != wdf_object());
+  }
+
+ protected:
+  /// KMDF object that is extended with this instance
+  WDFOBJECT               wdf_object_;
+
+  /// KMDF object type for this extension
+  AndroidUsbWdfObjectType object_type_;
+};
+
+/** \brief Gets our extension for the given KMDF object
+
+  This method can be called at any IRQL
+  @param wdf_obj[in] KMDF handle describing an object
+  @return Instance of AndroidUsbWdfObject associated with this object or NULL
+          if association is not found.
+*/
+__forceinline AndroidUsbWdfObject* GetAndroidUsbWdfObjectFromHandle(
+    WDFOBJECT wdf_obj) {
+  ASSERT(NULL != wdf_obj);
+  if (NULL != wdf_obj) {
+    AndroidUsbWdfObjectContext* context =
+      GetAndroidUsbWdfObjectContext(wdf_obj);
+    ASSERT((NULL != context) && (NULL != context->wdf_object_ext) &&
+           (context->wdf_object_ext->Is(context->object_type)));
+    if ((NULL != context) && (NULL != context->wdf_object_ext) &&
+        context->wdf_object_ext->Is(context->object_type)) {
+      return context->wdf_object_ext;
+    }
+  }
+  return NULL;
+}
+
+#endif  // ANDROID_USB_WDF_OBJECT_H__
diff --git a/host/windows/usb/driver/makefile b/host/windows/usb/driver/makefile
new file mode 100644
index 0000000..3c0d3a5
--- /dev/null
+++ b/host/windows/usb/driver/makefile
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (C) 2006 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Module Name:
+
+    makefile.
+
+Notes:
+
+    DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+    file to this component.  This file merely indirects to the real make file
+    that is shared by all the components of Windows NT (DDK)
+
+!ENDIF
+
+!if "$(DDK_TARGET_OS)"=="Win2K"
+!message This driver is not intended to target the Windows 2000 platform.
+!elseif "$(DDK_TARGET_OS)"=="WinNET"
+!INCLUDE $(NTMAKEENV)\makefile.def
+!else
+!INCLUDE $(NTMAKEENV)\makefile.def
+!endif
+
diff --git a/host/windows/usb/driver/makefile.inc b/host/windows/usb/driver/makefile.inc
new file mode 100644
index 0000000..1955cef
--- /dev/null
+++ b/host/windows/usb/driver/makefile.inc
@@ -0,0 +1,7 @@
+_LNG=$(LANGUAGE)
+_INX=.
+STAMP=stampinf -f $@ -a $(_BUILDARCH)
+
+$(OBJ_PATH)\$(O)\$(INF_NAME).inf: $(_INX)\$(INF_NAME).inx 
+    copy $(_INX)\$(@B).inx $@
+    $(STAMP)
diff --git a/host/windows/usb/driver/precomp.h b/host/windows/usb/driver/precomp.h
new file mode 100644
index 0000000..97be2a6
--- /dev/null
+++ b/host/windows/usb/driver/precomp.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  Standard precompile file
+*/
+#pragma warning(disable:4200)
+#pragma warning(disable:4201)  // nameless struct/union
+#pragma warning(disable:4214)  // bit field types other than int
+extern "C" {
+#include <initguid.h>
+#include <ntddk.h>
+#include <ntintsafe.h>
+#include <ntstrsafe.h>
+#include "usbdi.h"
+#include "usbdlib.h"
+#include <wdf.h>
+#include <wdfusb.h>
+}  // extern "C"
+#pragma warning(default:4200)
+#pragma warning(default:4201)
+#pragma warning(default:4214)
+
+#include "adb_api_extra.h"
+#include "android_usb_common_defines.h"
+#include "android_usb_pool_tags.h"
+#include "android_usb_driver_defines.h"
+#include "android_usb_new_delete.h"
+#include "android_usb_inl.h"
diff --git a/host/windows/usb/driver/sources b/host/windows/usb/driver/sources
new file mode 100644
index 0000000..07fce7e
--- /dev/null
+++ b/host/windows/usb/driver/sources
@@ -0,0 +1,32 @@
+!IF 0
+
+Copyright (C) 2007 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Module Name:
+
+    sources.
+
+Abstract:
+
+    This file specifies the target component being built and the list of
+    sources files needed to build that component.  Also specifies optional
+    compiler switches and libraries that are unique for the component being
+    built.
+
+!ENDIF
+
+!include sources.inc
+
+SOURCES= $(MOST_SOURCES) android_usb.rc
diff --git a/host/windows/usb/driver/sources.inc b/host/windows/usb/driver/sources.inc
new file mode 100644
index 0000000..5928f73
--- /dev/null
+++ b/host/windows/usb/driver/sources.inc
@@ -0,0 +1,84 @@
+!IF 0
+
+Copyright (C) 2007 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Module Name:
+
+    sources.
+
+Abstract:
+
+    This file specifies the target component being built and the list of
+    sources files needed to build that driver.  Also specifies optional
+    compiler switches and libraries that are unique for the component being
+    built.
+
+!ENDIF
+
+TARGETNAME=androidusb
+!IF "$(DDKBUILDENV)"=="chk"
+TARGETPATH=..\build\Debug
+!ELSE
+TARGETPATH=..\build\Release
+!ENDIF
+TARGETTYPE=DRIVER
+KMDF_VERSION=1
+USECXX_FLAG=/TP
+USER_C_FLAGS=$(USER_C_FLAGS) /wd4100 /wd4002 /wd4509 /wd4390 /TP
+
+INCLUDES=$(INCLUDES); \
+    	 $(IFSKIT_INC_PATH); \
+    	 ..\common; \
+    	 ..\api;
+
+TARGETLIBS=$(DDK_LIB_PATH)\usbd.lib
+
+MSC_WARNING_LEVEL=/W4 /WX /Wp64
+MSC_OPTIMIZATION = /Oi /Ob1
+C_DEFINES=$(C_DEFINES) -DEXPLODE_POOLTAGS -DRTL_USE_AVL_TABLES
+
+RCOPTIONS=$(RCOPTIONS) /dVER_COMPANYNAME_STR="\"Google Inc\"" 
+RCOPTIONS=$(RCOPTIONS) /dVER_LEGALCOPYRIGHT_YEARS="\"2007\"" 
+RCOPTIONS=$(RCOPTIONS) /dVER_LEGALCOPYRIGHT_STR="\"\251 Google Inc. All rights reserved.\"" 
+RCOPTIONS=$(RCOPTIONS) /dVER_PRODUCTNAME_STR="\"Google Android USB Driver\"" 
+RCOPTIONS=$(RCOPTIONS) /dVER_PRODUCTVERSION="1,00,01,001" 
+RCOPTIONS=$(RCOPTIONS) /dVER_PRODUCTVERSION_STR="\"1.00\""
+
+!IF 0
+
+By overriding .rsrc section properties (!D removes Discardable attribute)
+we make sure that all our vtables will be placed properly into non-discardable
+data segment. Because of the nature of this driver we don't need to have
+vtables in NonPaged data sections because all our objects can be paged.
+Otherwise we may want to add /SECTION:.rsrc,X option that locks section in memory
+
+!ENDIF
+
+LINKER_FLAGS=$(LINKER_FLAGS) /MAP /MAPINFO:LINES /SECTION:.rsrc,!D
+
+MOST_SOURCES=  \
+  android_usb_driver_object.cpp \
+  android_usb_wdf_object.cpp \
+  android_usb_device_object.cpp \
+  android_usb_file_object.cpp \
+  android_usb_device_file_object.cpp \
+  android_usb_pipe_file_object.cpp \
+  android_usb_bulk_file_object.cpp \
+  android_usb_interrupt_file_object.cpp
+
+PRECOMPILED_INCLUDE=precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
+
diff --git a/host/windows/usb/test/android_usb_test/android_usb_test.cpp b/host/windows/usb/test/android_usb_test/android_usb_test.cpp
new file mode 100644
index 0000000..a5c3906
--- /dev/null
+++ b/host/windows/usb/test/android_usb_test/android_usb_test.cpp
@@ -0,0 +1,1366 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// android_usb_test.cpp : Defines the entry point for the console application.

+//

+

+#include "stdafx.h"

+#include <stdio.h>

+#include <conio.h>

+

+#define MAX_PAYLOAD 4096
+
+#define A_SYNC 0x434e5953
+#define A_CNXN 0x4e584e43
+#define A_OPEN 0x4e45504f
+#define A_OKAY 0x59414b4f
+#define A_CLSE 0x45534c43
+#define A_WRTE 0x45545257
+
+#define A_VERSION 0x01000000
+

+struct message {
+    unsigned int command;       /* command identifier constant      */
+    unsigned int arg0;          /* first argument                   */
+    unsigned int arg1;          /* second argument                  */
+    unsigned int data_length;   /* length of payload (0 is allowed) */
+    unsigned int data_crc32;    /* crc32 of data payload            */
+    unsigned int magic;         /* command ^ 0xffffffff             */
+};
+

+USB_DEVICE_DESCRIPTOR test_dev_desc = {

+  sizeof(USB_DEVICE_DESCRIPTOR),

+  1,      // bDescriptorType

+  0x200,  // bcdUSB

+  0xFF,   // bDeviceClass

+  0xFF,   // bDeviceSubClass

+  0xFF,   // bDeviceProtocol

+  64,     // bMaxPacketSize

+  0x18D1, // idVendor

+  0xDDDD, // idProduct

+  0x100,  // bcdDevice

+  1,      // iManufacturer

+  2,      // iProduct

+  3,      // iSerialNumber

+  1       // bNumConfigurations

+};

+

+USB_CONFIGURATION_DESCRIPTOR test_config_desc = {

+  9,      // bLength

+  2,      // bDescriptorType

+  32,     // wTotalLength

+  1,      // bNumInterfaces

+  1,      // bConfigurationValue

+  4,      // iConfiguration

+  64,     // bmAttributes

+  50      // MaxPower

+};

+

+USB_INTERFACE_DESCRIPTOR test_interface_desc = {

+  9,      // bLength

+  4,      // bDescriptorType

+  0,      // bInterfaceNumber

+  0,      // bAlternateSetting

+  2,      // bNumEndpoints

+  0xFF,   // bInterfaceClass

+  0xFF,   // bInterfaceSubClass

+  0xFF,   // bInterfaceProtocol

+  5       // iInterface

+};

+

+AdbEndpointInformation test_pipe_00 = {

+  1024,       // MaximumPacketSize

+  0xFFFFFFFF, // MaximumTransferSize

+  static_cast<AdbEndpointType>(3),          // PipeType

+  0x81,       // EndpointAddress

+  0,          // Interval

+  0           // SettingIndex

+};

+

+AdbEndpointInformation test_pipe_01 = {

+  1024,       // MaximumPacketSize

+  0xFFFFFFFF, // MaximumTransferSize

+  static_cast<AdbEndpointType>(3),          // PipeType

+  0x02,       // EndpointAddress

+  0,          // Interval

+  0           // SettingIndex

+};

+

+AdbEndpointInformation* test_read_pipe = &test_pipe_00;

+AdbEndpointInformation* test_write_pipe = &test_pipe_01;

+

+const UCHAR test_read_pipe_index = 0;

+const UCHAR test_write_pipe_index = 1;

+

+bool device_active = false;

+

+GUID adb_class_id = ANDROID_USB_CLASS_ID;

+const wchar_t test_interface_name[] = L"\\\\?\\usb#vid_18d1&pid_dddd#123456789abcdef#{F72FE0D4-CBCB-407d-8814-9ED673D0DD6B}";

+bool RunInterfaceEnumTest();

+bool RunInterfaceEnumTest(bool exclude_not_present,

+                          bool exclude_removed,

+                          bool active_only);

+bool RunInterfaceCreateTest();

+bool RunEndpointInfoTest();

+bool RunEndpointInfoTest(ADBAPIHANDLE adb_interface, UCHAR index);

+bool RunEndpointOpenTest();

+bool RunEndpointOpenTest(ADBAPIHANDLE adb_interface, UCHAR index);

+bool RunEndpointIoTest(ULONG time_out_base);

+bool RunTimeoutsTest();

+bool RunGeneralTests();

+bool DeviceHandShake();

+bool CheckEndpointInfo(UCHAR index, AdbEndpointInformation* info);

+

+int _tmain(int argc, _TCHAR* argv[]) {

+  argc = argc;

+  argv = argv;

+

+  // General startup tests.

+  if (!RunGeneralTests())

+    return 1;

+

+	return 0;

+}

+

+bool RunGeneralTests() {

+  // Test interface enum

+  if (!RunInterfaceEnumTest())

+    return false;

+

+  // Test interface create

+  if (!RunInterfaceCreateTest())

+    return false;

+

+  // Test endpoint information

+  if (!RunEndpointInfoTest())

+    return false;

+

+  // Test endpoint open

+  if (!RunEndpointOpenTest())

+    return false;

+

+  // Test timeout i/o

+  if (!RunTimeoutsTest())

+    return false;

+

+  // Test read / write (no timeouts)

+  if (!RunEndpointIoTest(0))

+    return false;

+

+  // Test read / write (OK timeouts)

+  if (!RunEndpointIoTest(10))

+    return false;

+

+  return true;

+/*

+  if (!DeviceHandShake())

+    return false;

+

+  return true;

+*/

+}

+

+bool DeviceHandShake() {

+  printf("\n\n===== Running DeviceHandShake... ");

+

+  // Get interface

+  ADBAPIHANDLE adb_interface = AdbCreateInterface(adb_class_id,

+                                                  DEVICE_VENDOR_ID,

+                                                  DEVICE_COMPOSITE_PRODUCT_ID,

+                                                  DEVICE_INTERFACE_ID);

+  if (NULL == adb_interface) {

+    adb_interface = AdbCreateInterface(adb_class_id,

+                                       DEVICE_VENDOR_ID,

+                                       DEVICE_SINGLE_PRODUCT_ID,

+                                       0xFF);

+  }

+

+  if (NULL == adb_interface) {

+    printf("\n      AdbCreateInterface returned error %u", GetLastError());

+    return false;

+  }

+

+  char interf_name[1024];

+  unsigned long name_size = sizeof(interf_name);

+

+  if (!AdbGetInterfaceName(adb_interface, interf_name, &name_size, true)) {

+    printf("\n      AdbGetInterfaceName returned error %u", GetLastError());

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  printf("\n      Interface name is %s", interf_name);

+

+  char* ser_num = NULL;

+  name_size = 0;

+  if (!AdbGetSerialNumber(adb_interface, ser_num, &name_size, true)) {

+    ser_num = reinterpret_cast<char*>(malloc(name_size));

+    if (NULL != ser_num) {

+      if (!AdbGetSerialNumber(adb_interface, ser_num, &name_size, true)) {

+        printf("\n      AdbGetSerialNumber returned error %u", GetLastError());

+        AdbCloseHandle(adb_interface);

+        return false;

+      }

+      printf("\n      Interface serial number is %s", ser_num);

+      free(ser_num);

+    }

+  } else {

+    printf("\nAdbGetSerialNumber(adb_interface, ser_num, &name_size, true)");

+  }

+

+  // Get default read endpoint

+  ADBAPIHANDLE adb_read = AdbOpenDefaultBulkReadEndpoint(adb_interface,

+                                                         AdbOpenAccessTypeReadWrite,

+                                                         AdbOpenSharingModeReadWrite);

+  if (NULL == adb_read) {

+    printf("\n      AdbOpenDefaultBulkReadEndpoint returned error %u", GetLastError());

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  // Get default write endpoint

+  ADBAPIHANDLE adb_write = AdbOpenDefaultBulkWriteEndpoint(adb_interface,

+                                                           AdbOpenAccessTypeReadWrite,

+                                                           AdbOpenSharingModeReadWrite);

+  if (NULL == adb_write) {

+    printf("\n      AdbOpenDefaultBulkWriteEndpoint returned error %u", GetLastError());

+    AdbCloseHandle(adb_read);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  // Send connect message

+  message msg_send;

+  msg_send.command = A_CNXN;

+  msg_send.arg0 = A_VERSION;
+  msg_send.arg1 = MAX_PAYLOAD;
+  msg_send.data_length = 0;
+  msg_send.data_crc32 = 0;
+  msg_send.magic = msg_send.command ^ 0xffffffff;
+

+  ULONG written_bytes = 0;

+  bool write_res = AdbWriteEndpointSync(adb_write, &msg_send, sizeof(msg_send), &written_bytes, 0);

+  if (!write_res) {

+    printf("\n       AdbWriteEndpointSync returned error %u", GetLastError());

+    AdbCloseHandle(adb_write);

+    AdbCloseHandle(adb_read);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  // Receive handshake

+  message msg_rcv;

+  ULONG read_bytes = 0;

+  bool read_res = AdbReadEndpointSync(adb_read, &msg_rcv, sizeof(msg_rcv), &read_bytes, 0);

+  if (!read_res) {

+    printf("\n       AdbReadEndpointSync returned error %u", GetLastError());

+    AdbCloseHandle(adb_write);

+    AdbCloseHandle(adb_read);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  printf("\n      Read handshake: %u bytes received", read_bytes);

+  char* cmd_ansi = reinterpret_cast<char*>(&msg_rcv.command);

+  printf("\n         command     = %08X (%c%c%c%c)", msg_rcv.command,

+         cmd_ansi[0], cmd_ansi[1], cmd_ansi[2], cmd_ansi[3]);

+  printf("\n         arg0        = %08X", msg_rcv.arg0);

+  printf("\n         arg1        = %08X", msg_rcv.arg1);

+  printf("\n         data_length = %u", msg_rcv.data_length);

+  printf("\n         data_crc32  = %08X", msg_rcv.data_crc32);

+  printf("\n         magic       = %08X", msg_rcv.magic);

+

+  if (0 != msg_rcv.data_length) {

+    char* buf = reinterpret_cast<char*>(malloc(msg_rcv.data_length));

+    read_res = AdbReadEndpointSync(adb_read, buf, msg_rcv.data_length, &read_bytes, 0);

+    if (!read_res) {

+      printf("\n       AdbReadEndpointSync (data) returned error %u", GetLastError());

+      free(buf);

+      AdbCloseHandle(adb_write);

+      AdbCloseHandle(adb_read);

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+

+    for (ULONG n = 0; n < read_bytes; n++) {

+      if (0 == (n % 16))

+        printf("\n          ");

+      printf("%02X ", buf[n]);

+    }

+

+    printf("\n          %s", buf);

+

+    delete buf;

+  }

+

+  printf("\nPress any key to close handles...");

+  getch();

+  AdbCloseHandle(adb_write);

+  AdbCloseHandle(adb_read);

+  AdbCloseHandle(adb_interface);

+

+  return true;

+}

+

+bool RunInterfaceEnumTest() {

+  if (!RunInterfaceEnumTest(true, true, true))

+    return false;

+

+  if (!RunInterfaceEnumTest(false, false, false))

+    return false;

+

+  if (device_active) {

+    return true;

+  } else {

+    // Device has not found in the list of active devices

+    printf("\nPlease start the USB device emulator to run the tests");

+    return false;

+  }

+}

+

+bool RunInterfaceEnumTest(bool exclude_not_present,

+                          bool exclude_removed,

+                          bool active_only) {

+  printf("\n\n=== Running RunInterfaceEnumTest(%s, %s, %s)... ",

+         exclude_not_present ? "true" : "false",

+         exclude_removed ? "true" : "false",

+         active_only ? "true" : "false");

+

+  ADBAPIHANDLE adb_handle =

+    AdbEnumInterfaces(adb_class_id, exclude_not_present, exclude_removed, active_only);

+  if (NULL == adb_handle) {

+    printf("\n     Unable to AdbEnumInterfaces. Error %u", GetLastError());

+    return false;

+  }

+

+  bool res;

+

+  do {

+    AdbInterfaceInfo* info = NULL;

+    ULONG size = 0;

+

+    res = AdbNextInterface(adb_handle, NULL, &size);

+    // We expect 'false' and GetLastError() being either ERROR_NO_MORE_ITEMS

+    // or ERROR_INSUFFICIENT_BUFFER

+    if (res || ((ERROR_INSUFFICIENT_BUFFER != GetLastError()) &&

+                (ERROR_NO_MORE_ITEMS != GetLastError()))) {

+      printf("\n    Unexpected AdbNextInterface(NULL) result. Res = %u, Error = %u",

+             res, GetLastError());

+      AdbCloseHandle(adb_handle);

+      return false;

+    }

+

+    if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {

+      info = reinterpret_cast<AdbInterfaceInfo*>(malloc(size));

+      // Try one byte less than required length

+      size--;

+      res = AdbNextInterface(adb_handle, info, &size);

+      if (res || (ERROR_INSUFFICIENT_BUFFER != GetLastError())) {

+        printf("\n    Unexpected AdbNextInterface(small) result. Res = %u, Error = %u",

+               res, GetLastError());

+        free(info);

+        AdbCloseHandle(adb_handle);

+        return false;

+      }

+

+      size++;

+      res = AdbNextInterface(adb_handle, info, &size);

+

+      if (res) {

+        if (exclude_not_present && active_only &&

+            (0 == wcsicmp(info->device_name, test_interface_name))) {

+          device_active = true;

+        }

+      } else {

+        printf("\n    AdbNextInterface failed: %u", GetLastError());

+        free(info);

+        AdbCloseHandle(adb_handle);

+        return false;

+      }

+

+      free(info);

+    } else {

+      res = false;

+    }

+  } while (res);

+

+  res = AdbCloseHandle(adb_handle);

+  if (!res) {

+    printf("\n    Unable to AdbCloseHandle:  %u", GetLastError());

+    return false;

+  }

+

+  // Closing closed handle

+  res = AdbCloseHandle(adb_handle);

+  if (res || (ERROR_INVALID_HANDLE != GetLastError())) {

+    printf("\n    Unexpected AdbCloseHandle(closed) result. Ret = %u, Error = %u",

+           res, GetLastError());

+    return false;

+  }

+

+  printf(" SUCCESS.");

+  return true;

+}

+

+bool RunInterfaceCreateTest() {

+  printf("\n\n=== Running RunInterfaceCreateTest()... ");

+

+  ADBAPIHANDLE adb_interface = AdbCreateInterface(adb_class_id,

+                                                  DEVICE_VENDOR_ID,

+                                                  DEVICE_EMULATOR_PROD_ID,

+                                                  0xFF);

+  if (NULL == adb_interface) {

+    printf("\n    AdbCreateInterface returned error %u", GetLastError());

+    return false;

+  }

+

+  // Gather information

+  USB_DEVICE_DESCRIPTOR dev_desc;

+  USB_CONFIGURATION_DESCRIPTOR config_desc;

+  USB_INTERFACE_DESCRIPTOR interface_desc;

+

+  bool res = AdbGetUsbDeviceDescriptor(adb_interface, &dev_desc);

+  if (!res) {

+    printf("\n    AdbGetUsbDeviceDescriptor error %u", GetLastError());

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  res = AdbGetUsbConfigurationDescriptor(adb_interface, &config_desc);

+  if (!res) {

+    printf("\n    AdbGetUsbDeviceDescriptor error %u", GetLastError());

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  res = AdbGetUsbInterfaceDescriptor(adb_interface, &interface_desc);

+  if (!res) {

+    printf("\n    AdbGetUsbDeviceDescriptor error %u", GetLastError());

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  wchar_t* wide_buffer = NULL;

+  char* char_buffer = NULL;

+  ULONG buffer_size = 0;

+

+  res = AdbGetInterfaceName(adb_interface, wide_buffer, &buffer_size, false);

+  if (!res) {

+    if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {

+      printf("\n    Unable to AdbGetInterfaceName(NULL). Error %u", GetLastError());

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+    wide_buffer = reinterpret_cast<wchar_t*>(malloc(buffer_size * sizeof(wchar_t)));

+    res = AdbGetInterfaceName(adb_interface, wide_buffer, &buffer_size, false);

+    if (!res) {

+      printf("\n    Unable to AdbGetInterfaceName(%u). Error %u", buffer_size, GetLastError());

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+  }

+

+  res = AdbGetInterfaceName(adb_interface, char_buffer, &buffer_size, true);

+  if (!res) {

+    if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {

+      printf("\n    Unable to AdbGetInterfaceName(NULL). Error %u", GetLastError());

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+    char_buffer = reinterpret_cast<char*>(malloc(buffer_size * sizeof(char)));

+    res = AdbGetInterfaceName(adb_interface, char_buffer, &buffer_size, true);

+    if (!res) {

+      printf("\n    Unable to AdbGetInterfaceName(%u). Error %u", buffer_size, GetLastError());

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+  }

+

+  res = AdbCloseHandle(adb_interface);

+  if (!res) {

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+    printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  res = AdbCloseHandle(adb_interface);

+  if (res || (ERROR_INVALID_HANDLE != GetLastError())) {

+    printf("\n    Unexpected AdbCloseHandle(closed) result. Ret = %u, Error = %u",

+           res, GetLastError());

+    return false;

+  }

+

+  if (0 != memcmp(&dev_desc, &test_dev_desc, sizeof(USB_DEVICE_DESCRIPTOR))) {

+    printf("\n    Wrong USB_DEVICE_DESCRIPTOR");

+    return false;

+  }

+

+  if (0 != memcmp(&config_desc, &test_config_desc, sizeof(USB_CONFIGURATION_DESCRIPTOR))) {

+    printf("\n    Wrong USB_CONFIGURATION_DESCRIPTOR");

+    return false;

+  }

+

+  if (0 != memcmp(&interface_desc, &test_interface_desc, sizeof(USB_INTERFACE_DESCRIPTOR))) {

+    printf("\n    Wrong USB_INTERFACE_DESCRIPTOR");

+    return false;

+  }

+

+  printf(" SUCCESS.");

+  return true;

+}

+

+bool RunEndpointInfoTest() {

+  printf("\n\n=== Running RunEndpointInfoTest()");

+  ADBAPIHANDLE adb_interface = AdbCreateInterface(adb_class_id,

+                                                  DEVICE_VENDOR_ID,

+                                                  DEVICE_EMULATOR_PROD_ID,

+                                                  0xFF);

+  if (NULL == adb_interface) {

+    printf("\n    AdbCreateInterface returned error %u", GetLastError());

+    return false;

+  }

+

+  USB_INTERFACE_DESCRIPTOR interface_desc;

+  BOOL res = AdbGetUsbInterfaceDescriptor(adb_interface, &interface_desc);

+  if (!res) {

+    printf("\n    AdbGetUsbDeviceDescriptor error %u", GetLastError());

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  if (0 != memcmp(&interface_desc, &test_interface_desc, sizeof(USB_INTERFACE_DESCRIPTOR))) {

+    printf("\n    Wrong USB_INTERFACE_DESCRIPTOR");

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  for (UCHAR index = 0; index < interface_desc.bNumEndpoints; index++) {

+    if (!RunEndpointInfoTest(adb_interface, index)) {

+      res = AdbCloseHandle(adb_interface);

+      if (!res)

+        printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+      return false;

+    }

+  }

+

+  if (RunEndpointInfoTest(adb_interface, index)) {

+    printf("\n    Unexpected success of RunEndpointInfoTest(%u - invalid index)", index);

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  if (!RunEndpointInfoTest(adb_interface, ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX))

+    return false;

+

+  if (!RunEndpointInfoTest(adb_interface, ADB_QUERY_BULK_READ_ENDPOINT_INDEX))

+    return false;

+

+  res = AdbCloseHandle(adb_interface);

+  if (!res) {

+    printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  return true;

+}

+

+bool RunEndpointInfoTest(ADBAPIHANDLE adb_interface, UCHAR index) {

+  printf("\n======= Running RunEndpointInfoTest(%X)... ", index);

+

+  AdbEndpointInformation info;

+

+  if (!AdbGetEndpointInformation(adb_interface, index, &info)) {

+    if ((index < 2) || (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == index) ||

+        (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == index)) {

+      printf("\n        AdbGetEndpointInformation(u) failed: %u", index, GetLastError());

+    }

+    return false;

+  }

+

+  if (!CheckEndpointInfo(index, &info)) {

+    printf("\n        Wrong AdbEndpointInformation(%X)", index);

+    return false;

+  }

+

+  printf(" SUCCESS.");

+  return true;

+}

+

+bool RunEndpointOpenTest() {

+  printf("\n\n=== Running RunEndpointOpenTest()... ");

+  ADBAPIHANDLE adb_interface = AdbCreateInterface(adb_class_id,

+                                                  DEVICE_VENDOR_ID,

+                                                  DEVICE_EMULATOR_PROD_ID,

+                                                  0xFF);

+  if (NULL == adb_interface) {

+    printf("\n    AdbCreateInterface returned error %u", GetLastError());

+    return false;

+  }

+

+  USB_INTERFACE_DESCRIPTOR interface_desc;

+  BOOL res = AdbGetUsbInterfaceDescriptor(adb_interface, &interface_desc);

+  if (!res) {

+    printf("\n    AdbGetUsbDeviceDescriptor error %u", GetLastError());

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  ADBAPIHANDLE adb_endpoint = AdbOpenDefaultBulkReadEndpoint(adb_interface,

+                                                             AdbOpenAccessTypeReadWrite,

+                                                             AdbOpenSharingModeReadWrite);

+  if (NULL == adb_endpoint) {

+    printf("\n    AdbOpenDefaultBulkReadEndpoint error %u", GetLastError());

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  // Make sure that we can't write to it

+  ULONG transfer = 0;

+  res = AdbWriteEndpointSync(adb_endpoint,

+                         &adb_endpoint,

+                         sizeof(adb_endpoint),

+                         &transfer,

+                         0);

+  if (res || (ERROR_ACCESS_DENIED != GetLastError())) {

+    printf("\n    AdbWriteEndpoint failure: Ret = %u, error = %u", res, GetLastError());

+    AdbCloseHandle(adb_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  AdbCloseHandle(adb_endpoint);

+

+  adb_endpoint = AdbOpenDefaultBulkWriteEndpoint(adb_interface,

+                                                 AdbOpenAccessTypeReadWrite,

+                                                 AdbOpenSharingModeReadWrite);

+  if (NULL == adb_endpoint) {

+    printf("\n    AdbOpenDefaultBulkWriteEndpoint error %u", GetLastError());

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  // Make sure we cannot read from it

+  ULONG to_read;

+  res = AdbReadEndpointSync(adb_endpoint,

+                        &to_read,

+                        sizeof(to_read),

+                        &transfer,

+                        0);

+  if (res || (ERROR_ACCESS_DENIED != GetLastError())) {

+    printf("\n    AdbReadEndpoint failure: Ret = %u, error = %u", res, GetLastError());

+    AdbCloseHandle(adb_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  AdbCloseHandle(adb_endpoint);

+

+  for (UCHAR index = 0; index < interface_desc.bNumEndpoints; index++) {

+    if (!RunEndpointOpenTest(adb_interface, index)) {

+      res = AdbCloseHandle(adb_interface);

+      if (!res)

+        printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+      return false;

+    }

+  }

+

+  if (RunEndpointOpenTest(adb_interface, index)) {

+    printf("\nRunEndpointOpenTest failed: succeeded on invalid EP %u", index);

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  if (!RunEndpointOpenTest(adb_interface, ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX)) {

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  if (!RunEndpointOpenTest(adb_interface, ADB_QUERY_BULK_READ_ENDPOINT_INDEX)) {

+    res = AdbCloseHandle(adb_interface);

+    if (!res)

+      printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  res = AdbCloseHandle(adb_interface);

+  if (!res) {

+    printf("\n    Unable to AdbCloseHandle. Error %u", GetLastError());

+    return false;

+  }

+

+  return true;

+}

+

+bool RunEndpointOpenTest(ADBAPIHANDLE adb_interface, UCHAR index) {

+  printf("\n======= Running RunEndpointOpenTest(%X)... ", index);

+  ADBAPIHANDLE adb_endpoint = AdbOpenEndpoint(adb_interface,

+                                              index,

+                                              AdbOpenAccessTypeReadWrite,

+                                              AdbOpenSharingModeReadWrite);

+  if (NULL == adb_endpoint) {

+    if ((index < 2) || (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == index) ||

+        (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == index)) {

+      printf("\n        AdbOpenEndpoint(%X) error %u", index, GetLastError());

+    }

+    return false;

+  }

+

+  ADBAPIHANDLE parent = AdbGetEndpointInterface(adb_endpoint);

+  if (parent != adb_interface) {

+    printf("\n        AdbGetEndpointInterface(%X) failure: expected %p returned %p, error %u",

+           index, adb_interface, parent, GetLastError());

+    AdbCloseHandle(adb_endpoint);

+    return false;

+  }

+

+  AdbEndpointInformation info;

+  if (!AdbQueryInformationEndpoint(adb_endpoint, &info)) {

+    printf("\n    Unable to AdbGetEndpointInformationForHandle(%X): %u",

+           index, GetLastError());

+    AdbCloseHandle(adb_endpoint);

+    return false;

+  }

+

+  if (!CheckEndpointInfo(index, &info)) {

+    printf("\n        Wrong AdbEndpointInformation(%X)", index);

+    AdbCloseHandle(adb_endpoint);

+    return false;

+  }

+

+  AdbCloseHandle(adb_endpoint);

+

+  printf(" SUCCESS");

+  return true;

+}

+

+bool RunEndpointIoTest(ULONG time_out_base) {

+  printf("\n\n=== Running RunEndpointIoTest(%u)... ", time_out_base);

+  ADBAPIHANDLE adb_interface = AdbCreateInterface(adb_class_id,

+                                                  DEVICE_VENDOR_ID,

+                                                  DEVICE_EMULATOR_PROD_ID,

+                                                  0xFF);

+  if (NULL == adb_interface) {

+    printf("\n    AdbCreateInterface returned error %u", GetLastError());

+    return false;

+  }

+

+  ADBAPIHANDLE adb_read_endpoint =

+    AdbOpenDefaultBulkReadEndpoint(adb_interface,

+                                   AdbOpenAccessTypeReadWrite,

+                                   AdbOpenSharingModeReadWrite);

+  if (NULL == adb_read_endpoint) {

+    printf("\n    AdbOpenDefaultBulkReadEndpoint error %u", GetLastError());

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  ADBAPIHANDLE adb_write_endpoint =

+    AdbOpenDefaultBulkWriteEndpoint(adb_interface,

+                                    AdbOpenAccessTypeReadWrite,

+                                    AdbOpenSharingModeReadWrite);

+  if (NULL == adb_write_endpoint) {

+    printf("\n    AdbOpenDefaultBulkWriteEndpoint error %u", GetLastError());

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  AdbEndpointInformation read_info;

+  AdbEndpointInformation write_info;

+

+  if (!AdbQueryInformationEndpoint(adb_read_endpoint, &read_info)) {

+    printf("\n    AdbQueryInformationEndpoint(read) error %u", GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  if (!AdbQueryInformationEndpoint(adb_write_endpoint, &write_info)) {

+    printf("\n    AdbQueryInformationEndpoint(write) error %u", GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  char read_buf[40960];

+  char write_buf[40960];

+  ULONG written, read;

+  ULONG small_block = 101;

+  ULONG partial_small_block = small_block - 10;

+  ULONG large_block = write_info.max_packet_size * 3 + 3;

+

+  bool wr_res;

+  bool rd_res;

+

+  // Simple synchronous write / read of a small block

+  memset(write_buf, '0', small_block);

+  wr_res = AdbWriteEndpointSync(adb_write_endpoint, write_buf, small_block, &written, time_out_base * small_block);

+  if (!wr_res || (written != small_block)) {

+    printf("\n    AdbWriteEndpointSync(%u) failure (%u). Written %u. Error %u",

+           small_block, wr_res, written, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  rd_res = AdbReadEndpointSync(adb_read_endpoint, read_buf, small_block, &read, time_out_base * small_block);

+  if (!rd_res || (small_block != read)) {

+    printf("\n    AdbReadEndpointSync(%u) failure (%u). Read %u. Error %u",

+           small_block, rd_res, read, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  if (0 != memcmp(read_buf, write_buf, read)) {

+    printf("\n    Simple sync r/w %u data wrong.", small_block);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  // Simple synchronous write / read of a large block

+  memset(write_buf, '1', large_block);

+  wr_res = AdbWriteEndpointSync(adb_write_endpoint, write_buf, large_block, &written, time_out_base * large_block);

+  if (!wr_res || (written != large_block)) {

+    printf("\n    AdbWriteEndpointSync(%u) failure (%u). Written %u. Error %u",

+           large_block, wr_res, written, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  rd_res = AdbReadEndpointSync(adb_read_endpoint, read_buf, large_block, &read, time_out_base * large_block);

+  if (!rd_res || (large_block != read)) {

+    printf("\n    AdbReadEndpointSync(%u) failure (%u). Read %u. Error %u",

+           large_block, rd_res, read, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  if (0 != memcmp(read_buf, write_buf, read)) {

+    printf("\n    Simple sync r/w %u data wrong.", large_block);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  // Simple synchronous write / partial read of a small block

+  memset(write_buf, 'u', small_block);

+  wr_res = AdbWriteEndpointSync(adb_write_endpoint, write_buf, partial_small_block, &written, time_out_base * small_block);

+  if (!wr_res || (written != partial_small_block)) {

+    printf("\n    AdbWriteEndpointSync(%u) failure (%u). Written %u. Error %u",

+           partial_small_block, wr_res, written, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  rd_res = AdbReadEndpointSync(adb_read_endpoint, read_buf, small_block, &read, time_out_base * small_block);

+  if (!rd_res || (partial_small_block != read)) {

+    printf("\n    AdbReadEndpointSync(%u) failure (%u). Read %u. Error %u",

+           partial_small_block, rd_res, read, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  if (0 != memcmp(read_buf, write_buf, read)) {

+    printf("\n    Simple sync r/w %u data wrong.", small_block);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  // Simple Aynchronous write / read

+  memset(write_buf, 'A', small_block);

+

+  ADBAPIHANDLE adb_w_complete = 

+    AdbWriteEndpointAsync(adb_write_endpoint, write_buf, small_block, &written, time_out_base * small_block, NULL);

+

+  if (NULL == adb_w_complete) {

+    printf("\n    AdbWriteEndpointAsync(%u) error %u",

+           small_block, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  wr_res = AdbGetOvelappedIoResult(adb_w_complete, NULL, &written, true);

+  if (!wr_res || (small_block != written)) {

+    printf("\n    AdbGetOvelappedIoResult(write %u) failure (%u). Error %u, written %u",

+           small_block, wr_res, GetLastError(), written);

+    AdbCloseHandle(adb_w_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+  AdbCloseHandle(adb_w_complete);

+

+  ADBAPIHANDLE adb_r_complete = 

+    AdbReadEndpointAsync(adb_read_endpoint, read_buf, small_block, &read, time_out_base * small_block, NULL);

+  if (NULL == adb_r_complete) {

+    printf("\n    AdbReadEndpointAsync(%u) error %u", small_block, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  rd_res = AdbGetOvelappedIoResult(adb_r_complete, NULL, &read, true);

+  if (!rd_res || (read != small_block)) {

+    printf("\n    AdbGetOvelappedIoResult(read %u) failure (%u). Error %u, read %u",

+           small_block, rd_res, GetLastError(), read);

+    AdbCloseHandle(adb_r_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+  AdbCloseHandle(adb_r_complete);

+

+  if (0 != memcmp(read_buf, write_buf, read)) {

+    printf("\n    Simple async r/w %u data wrong", small_block);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  // Large Aynchronous write / read

+  memset(write_buf, 'B', large_block);

+

+  adb_w_complete = 

+    AdbWriteEndpointAsync(adb_write_endpoint, write_buf, large_block, &written, time_out_base * large_block, NULL);

+

+  if (NULL == adb_w_complete) {

+    printf("\n    AdbWriteEndpointAsync(%u) error %u",

+           large_block, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  wr_res = AdbGetOvelappedIoResult(adb_w_complete, NULL, &written, true);

+  if (!wr_res || (large_block != written)) {

+    printf("\n    AdbGetOvelappedIoResult(write %u) failure (%u). Error %u, written %u",

+           large_block, wr_res, GetLastError(), written);

+    AdbCloseHandle(adb_w_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+  AdbCloseHandle(adb_w_complete);

+

+  adb_r_complete = 

+    AdbReadEndpointAsync(adb_read_endpoint, read_buf, large_block, &read, time_out_base * large_block, NULL);

+  if (NULL == adb_r_complete) {

+    printf("\n    AdbReadEndpointAsync(%u) error %u", large_block, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  rd_res = AdbGetOvelappedIoResult(adb_r_complete, NULL, &read, true);

+  if (!rd_res || (read != large_block)) {

+    printf("\n    AdbGetOvelappedIoResult(read %u) failure (%u). Error %u, read %u",

+           large_block, rd_res, GetLastError(), read);

+    AdbCloseHandle(adb_r_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+  AdbCloseHandle(adb_r_complete);

+

+  if (0 != memcmp(read_buf, write_buf, read)) {

+    printf("\n    Simple async r/w %u data wrong", large_block);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  // We disable this test because our new read model is no longer accumulative

+#if 0

+  // One async read, many async writes

+  ULONG total = write_info.max_packet_size * 5 + 3;

+  ULONG block1 = write_info.max_packet_size + 1;

+  ULONG block2 = write_info.max_packet_size * 3 + 7;

+  ULONG block3 = total - block2 - block1;

+  memset(write_buf, 'a', block1);

+  memset(write_buf + block1, 'b', block2);

+  memset(write_buf + block1 + block2, 'c', block3);

+

+  adb_r_complete = 

+    AdbReadEndpointAsync(adb_read_endpoint, read_buf, total, &read, time_out_base * total, NULL);

+  if (NULL == adb_r_complete) {

+    printf("\n    AdbReadEndpointAsync(%u) error %u", total, GetLastError());

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  rd_res = AdbGetOvelappedIoResult(adb_r_complete, NULL, &read, false);

+  if (rd_res || (GetLastError() != ERROR_IO_INCOMPLETE)) {

+    printf("\n    AdbGetOvelappedIoResult(read %u) failure (%u). Error %u, read %u",

+           total, rd_res, GetLastError(), read);

+    AdbCloseHandle(adb_r_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  ADBAPIHANDLE adb_w_complete1 = 

+    AdbWriteEndpointAsync(adb_write_endpoint, write_buf, block1, &written, time_out_base * block1, NULL);

+  if (NULL == adb_w_complete1) {

+    printf("\n    Multiwrite block 1 AdbWriteEndpointAsync(%u) error %u",

+           block1, GetLastError());

+    AdbCloseHandle(adb_r_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  ADBAPIHANDLE adb_w_complete2 = 

+    AdbWriteEndpointAsync(adb_write_endpoint, write_buf + block1, block2, &written, time_out_base * block2, NULL);

+  if (NULL == adb_w_complete2) {

+    printf("\n    Multiwrite block 2 AdbWriteEndpointAsync(%u) error %u",

+           block1, GetLastError());

+    AdbCloseHandle(adb_w_complete1);

+    AdbCloseHandle(adb_r_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  ADBAPIHANDLE adb_w_complete3 = 

+    AdbWriteEndpointAsync(adb_write_endpoint, write_buf + block1 + block2, block3, &written, time_out_base * block3, NULL);

+  if (NULL == adb_w_complete3) {

+    printf("\n    Multiwrite block 3 AdbWriteEndpointAsync(%u) error %u",

+           block1, GetLastError());

+    AdbCloseHandle(adb_w_complete2);

+    AdbCloseHandle(adb_w_complete1);

+    AdbCloseHandle(adb_r_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  rd_res = AdbGetOvelappedIoResult(adb_r_complete, NULL, &read, true);

+  if (!rd_res || (read != total)) {

+    printf("\n    AdbGetOvelappedIoResult(read %u) failure (%u). Error %u, read %u",

+           total, rd_res, GetLastError(), read);

+    AdbCloseHandle(adb_w_complete3);

+    AdbCloseHandle(adb_w_complete2);

+    AdbCloseHandle(adb_w_complete1);

+    AdbCloseHandle(adb_r_complete);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+  AdbCloseHandle(adb_r_complete);

+

+  wr_res = AdbGetOvelappedIoResult(adb_w_complete3, NULL, &written, true);

+  if (!wr_res || (block3 != written)) {

+    printf("\n    Multiwrite block 3 AdbGetOvelappedIoResult(write %u) failure (%u). Error %u, written %u",

+           block3, wr_res, GetLastError(), written);

+    AdbCloseHandle(adb_w_complete3);

+    AdbCloseHandle(adb_w_complete2);

+    AdbCloseHandle(adb_w_complete1);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+  AdbCloseHandle(adb_w_complete3);

+

+  wr_res = AdbGetOvelappedIoResult(adb_w_complete2, NULL, &written, true);

+  if (!wr_res || (block2 != written)) {

+    printf("\n    Multiwrite block 2 AdbGetOvelappedIoResult(write %u) failure (%u). Error %u, written %u",

+           block2, wr_res, GetLastError(), written);

+    AdbCloseHandle(adb_w_complete2);

+    AdbCloseHandle(adb_w_complete1);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+  AdbCloseHandle(adb_w_complete2);

+

+  wr_res = AdbGetOvelappedIoResult(adb_w_complete1, NULL, &written, true);

+  if (!wr_res || (block1 != written)) {

+    printf("\n    Multiwrite block 1 AdbGetOvelappedIoResult(write %u) failure (%u). Error %u, written %u",

+           block1, wr_res, GetLastError(), written);

+    AdbCloseHandle(adb_w_complete1);

+    AdbCloseHandle(adb_write_endpoint);

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+  AdbCloseHandle(adb_w_complete1);

+#endif  // 0

+

+#if 0

+  // Async writes are not syncronized

+  if (0 != memcmp(read_buf, write_buf, block1)) {

+    printf("\n   First block wrong");

+  } else {

+    if (0 != memcmp(read_buf + block1, write_buf + block1, block2)) {

+      printf("\n   Second block wrong");

+    } else {

+      if (0 != memcmp(read_buf + block1 + block2, write_buf + block1 + block2, block3)) {

+        printf("\n   Second block wrong");

+      }

+    }

+  }

+#endif  // 0

+

+  AdbCloseHandle(adb_write_endpoint);

+  AdbCloseHandle(adb_read_endpoint);

+  AdbCloseHandle(adb_interface);

+

+  printf(" SUCCESS.");

+  return true;

+}

+

+bool RunTimeoutsTest() {

+  printf("\n\n=== Running RunTimeoutsTest... ");

+  ADBAPIHANDLE adb_interface = AdbCreateInterface(adb_class_id,

+                                                  DEVICE_VENDOR_ID,

+                                                  DEVICE_EMULATOR_PROD_ID,

+                                                  0xFF);

+  if (NULL == adb_interface) {

+    printf("\n    AdbCreateInterface returned error %u", GetLastError());

+    return false;

+  }

+

+  ADBAPIHANDLE adb_read_endpoint =

+    AdbOpenDefaultBulkReadEndpoint(adb_interface,

+                                   AdbOpenAccessTypeReadWrite,

+                                   AdbOpenSharingModeReadWrite);

+  if (NULL == adb_read_endpoint) {

+    printf("\n    AdbOpenDefaultBulkReadEndpoint error %u", GetLastError());

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  ADBAPIHANDLE adb_write_endpoint =

+    AdbOpenDefaultBulkWriteEndpoint(adb_interface,

+                                    AdbOpenAccessTypeReadWrite,

+                                    AdbOpenSharingModeReadWrite);

+  if (NULL == adb_write_endpoint) {

+    printf("\n    AdbOpenDefaultBulkWriteEndpoint error %u", GetLastError());

+    AdbCloseHandle(adb_read_endpoint);

+    AdbCloseHandle(adb_interface);

+    return false;

+  }

+

+  char read_buf[40960];

+  char write_buf[40960];

+  ULONG written, read;

+  ULONG small_block = 60;

+

+  // Test virtually no timeouts

+  for (int n = 0; n < 8; n++) {

+    memset(write_buf, 'S', small_block);

+    bool wr_res = AdbWriteEndpointSync(adb_write_endpoint, write_buf, small_block, &written, 0xFFFFFFF);

+    if (!wr_res || (written != small_block)) {

+      printf("\n    AdbWriteEndpointSync(%u) failure (%u). Written %u. Error %u",

+            small_block, wr_res, written, GetLastError());

+      AdbCloseHandle(adb_write_endpoint);

+      AdbCloseHandle(adb_read_endpoint);

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+

+    bool rd_res = AdbReadEndpointSync(adb_read_endpoint, read_buf, small_block, &read, 0xFFFFFFF);

+    if (!rd_res || (small_block != read)) {

+      printf("\n    AdbReadEndpointSync(%u) failure (%u). Read %u. Error %u",

+            small_block, rd_res, read, GetLastError());

+      AdbCloseHandle(adb_write_endpoint);

+      AdbCloseHandle(adb_read_endpoint);

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+

+    if (0 != memcmp(read_buf, write_buf, read)) {

+      printf("\n    Simple sync r/w %u data wrong.", small_block);

+      AdbCloseHandle(adb_write_endpoint);

+      AdbCloseHandle(adb_read_endpoint);

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+  }

+/*

+  ULONG large_block = 2048;

+

+  // Test rediculously small timeouts

+  for (n = 0; n < 20; n++) {

+    memset(write_buf, 'L', large_block);

+    bool wr_res = AdbWriteEndpointSync(adb_write_endpoint, write_buf, large_block, &written, 1);

+    if (!wr_res || (written != small_block)) {

+      printf("\n    AdbWriteEndpointSync(%u) failure (%u). Written %u. Error %u",

+            large_block, wr_res, written, GetLastError());

+      AdbCloseHandle(adb_write_endpoint);

+      AdbCloseHandle(adb_read_endpoint);

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+

+    bool rd_res = AdbReadEndpointSync(adb_read_endpoint, read_buf, large_block, &read, 1);

+    if (!rd_res || (small_block != read)) {

+      printf("\n    AdbReadEndpointSync(%u) failure (%u). Read %u. Error %u",

+            large_block, rd_res, read, GetLastError());

+      AdbCloseHandle(adb_write_endpoint);

+      AdbCloseHandle(adb_read_endpoint);

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+

+    if (0 != memcmp(read_buf, write_buf, read)) {

+      printf("\n    Simple sync r/w %u data wrong.", small_block);

+      AdbCloseHandle(adb_write_endpoint);

+      AdbCloseHandle(adb_read_endpoint);

+      AdbCloseHandle(adb_interface);

+      return false;

+    }

+  }

+*/

+  AdbCloseHandle(adb_write_endpoint);

+  AdbCloseHandle(adb_read_endpoint);

+  AdbCloseHandle(adb_interface);

+

+  printf(" SUCCESS.");

+  return true;

+}

+

+bool CheckEndpointInfo(UCHAR index, AdbEndpointInformation* info) {

+  AdbEndpointInformation* cmp;

+

+  switch (index) {

+    case test_read_pipe_index:

+    case ADB_QUERY_BULK_READ_ENDPOINT_INDEX:

+      cmp = test_read_pipe;

+      break;

+

+    default:

+      cmp = test_write_pipe;

+      break;

+  };

+

+  if ((info->max_packet_size != cmp->max_packet_size) ||

+      (info->endpoint_address != cmp->endpoint_address) ||

+      (info->polling_interval != cmp->polling_interval) ||

+      (info->setting_index != cmp->setting_index) ||

+      (info->endpoint_type != cmp->endpoint_type) ||

+      (info->max_transfer_size != cmp->max_transfer_size)) {

+    return false;

+  }

+

+  return true;

+}

+

+/*

+  printf("\n***** USB_DEVICE_DESCRIPTOR");

+  printf("\n      bDescriptorType    = %u", dev_desc.bDescriptorType);

+  printf("\n      bcdUSB             = x%02X", dev_desc.bcdUSB);

+  printf("\n      bDeviceClass       = x%02X", dev_desc.bDeviceClass);

+  printf("\n      bDeviceSubClass    = x%02X", dev_desc.bDeviceSubClass);

+  printf("\n      bDeviceProtocol    = x%02X", dev_desc.bDeviceProtocol);

+  printf("\n      bMaxPacketSize     = %u", dev_desc.bMaxPacketSize0);

+  printf("\n      idVendor           = x%04X", dev_desc.idVendor);

+  printf("\n      idProduct          = x%04X", dev_desc.idProduct);

+  printf("\n      bcdDevice          = x%02X", dev_desc.bcdDevice);

+  printf("\n      iManufacturer      = %u", dev_desc.iManufacturer);

+  printf("\n      iProduct           = %u", dev_desc.iProduct);

+  printf("\n      iSerialNumber      = %u", dev_desc.iSerialNumber);

+  printf("\n      bNumConfigurations = %u", dev_desc.bNumConfigurations);

+

+  printf("\n\n***** USB_CONFIGURATION_DESCRIPTOR");

+  printf("\n      bDescriptorType     = %u", config_desc.bDescriptorType);

+  printf("\n      wTotalLength        = %u", config_desc.wTotalLength);

+  printf("\n      bNumInterfaces      = %u", config_desc.bNumInterfaces);

+  printf("\n      bConfigurationValue = %u", config_desc.bConfigurationValue);

+  printf("\n      iConfiguration      = %u", config_desc.iConfiguration);

+  printf("\n      bmAttributes        = %u", config_desc.bmAttributes);

+  printf("\n      MaxPower            = %u", config_desc.MaxPower);

+

+  printf("\n\n***** USB_INTERFACE_DESCRIPTOR");

+  printf("\n      bLength            = %u", interface_desc.bLength);

+  printf("\n      bDescriptorType    = %u", interface_desc.bDescriptorType);

+  printf("\n      bInterfaceNumber   = %u", interface_desc.bInterfaceNumber);

+  printf("\n      bAlternateSetting  = %u", interface_desc.bAlternateSetting);

+  printf("\n      bNumEndpoints      = %u", interface_desc.bNumEndpoints);

+  printf("\n      bInterfaceClass    = x%02X", interface_desc.bInterfaceClass);

+  printf("\n      bInterfaceSubClass = x%02X", interface_desc.bInterfaceSubClass);

+  printf("\n      bInterfaceProtocol = x%02X", interface_desc.bInterfaceProtocol);

+  printf("\n      iInterface         = %u", interface_desc.iInterface);

+

+  printf("\n***** ENDPOINT[%X]", index);

+  printf("\n      MaximumPacketSize   = %u", info.max_packet_size);

+  printf("\n      EndpointAddress     = x%02X", info.endpoint_address);

+  printf("\n      Interval            = %u", info.polling_interval);

+  printf("\n      SettingIndex        = %u", info.setting_index);

+  printf("\n      PipeType            = %u", info.endpoint_type);

+  printf("\n      MaximumTransferSize = %u", info.max_transfer_size);

+*/
diff --git a/host/windows/usb/test/android_usb_test/android_usb_test.sln b/host/windows/usb/test/android_usb_test/android_usb_test.sln
new file mode 100644
index 0000000..1202096
--- /dev/null
+++ b/host/windows/usb/test/android_usb_test/android_usb_test.sln
@@ -0,0 +1,29 @@
+Microsoft Visual Studio Solution File, Format Version 8.00

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android_usb_test", "android_usb_test.vcproj", "{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdbWinApi", "..\..\api\AdbWinApi.vcproj", "{C0A471E9-6892-4270-96DE-DB5F8D526FB1}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Global

+	GlobalSection(SolutionConfiguration) = preSolution

+		Debug = Debug

+		Release = Release

+	EndGlobalSection

+	GlobalSection(ProjectConfiguration) = postSolution

+		{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}.Debug.ActiveCfg = Debug|Win32

+		{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}.Debug.Build.0 = Debug|Win32

+		{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}.Release.ActiveCfg = Release|Win32

+		{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}.Release.Build.0 = Release|Win32

+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Debug.ActiveCfg = Debug|Win32

+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Debug.Build.0 = Debug|Win32

+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Release.ActiveCfg = Release|Win32

+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Release.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ExtensibilityGlobals) = postSolution

+	EndGlobalSection

+	GlobalSection(ExtensibilityAddIns) = postSolution

+	EndGlobalSection

+EndGlobal

diff --git a/host/windows/usb/test/android_usb_test/android_usb_test.vcproj b/host/windows/usb/test/android_usb_test/android_usb_test.vcproj
new file mode 100644
index 0000000..ff93586
--- /dev/null
+++ b/host/windows/usb/test/android_usb_test/android_usb_test.vcproj
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="android_usb_test"

+	ProjectGUID="{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}"

+	RootNamespace="android_usb_test"

+	Keyword="Win32Proj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="1"

+			UseOfATL="1"

+			CharacterSet="1">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="0"

+				AdditionalIncludeDirectories="C:\WINDDK\6000\inc\api;..\..\common;..\..\api;..\..\..\..\..\..\..\..\google3\testing\base"

+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"

+				MinimalRebuild="TRUE"

+				ExceptionHandling="TRUE"

+				BasicRuntimeChecks="3"

+				RuntimeLibrary="1"

+				TreatWChar_tAsBuiltInType="TRUE"

+				UsePrecompiledHeader="3"

+				ProgramDataBaseFileName="..\..\build\$(OutDir)\i386\$(TargetName).pdb"

+				WarningLevel="4"

+				WarnAsError="TRUE"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="4"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="AdbWinApi.lib shlwapi.lib"

+				OutputFile="..\..\build\$(OutDir)\i386/android_usb_test.exe"

+				LinkIncremental="2"

+				AdditionalLibraryDirectories="&quot;..\..\build\$(OutDir)\i386&quot;"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="..\..\build\$(OutDir)\i386\$(TargetName).pdb"

+				SubSystem="1"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"

+				Description="Set DDK environment"

+				CommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ chk WXP"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="Release"

+			IntermediateDirectory="Release"

+			ConfigurationType="1"

+			UseOfATL="1"

+			CharacterSet="1">

+			<Tool

+				Name="VCCLCompilerTool"

+				Optimization="4"

+				InlineFunctionExpansion="1"

+				AdditionalIncludeDirectories="C:\WINDDK\6000\inc\api;..\..\common;..\..\api;..\..\..\..\..\..\..\..\google3\testing\base"

+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"

+				ExceptionHandling="TRUE"

+				RuntimeLibrary="0"

+				TreatWChar_tAsBuiltInType="TRUE"

+				UsePrecompiledHeader="3"

+				ProgramDataBaseFileName="..\..\build\$(OutDir)\i386\$(TargetName).pdb"

+				WarningLevel="4"

+				WarnAsError="TRUE"

+				Detect64BitPortabilityProblems="TRUE"

+				DebugInformationFormat="3"/>

+			<Tool

+				Name="VCCustomBuildTool"/>

+			<Tool

+				Name="VCLinkerTool"

+				AdditionalDependencies="AdbWinApi.lib"

+				OutputFile="..\..\build\$(OutDir)\i386/android_usb_test.exe"

+				LinkIncremental="1"

+				AdditionalLibraryDirectories="&quot;..\..\build\$(OutDir)\i386&quot;"

+				GenerateDebugInformation="TRUE"

+				ProgramDatabaseFile="..\..\build\$(OutDir)\i386\$(TargetName).pdb"

+				SubSystem="1"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

+				TargetMachine="1"/>

+			<Tool

+				Name="VCMIDLTool"/>

+			<Tool

+				Name="VCPostBuildEventTool"/>

+			<Tool

+				Name="VCPreBuildEventTool"

+				Description="Set DKK environment"

+				CommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ fre WXP"/>

+			<Tool

+				Name="VCPreLinkEventTool"/>

+			<Tool

+				Name="VCResourceCompilerTool"/>

+			<Tool

+				Name="VCWebServiceProxyGeneratorTool"/>

+			<Tool

+				Name="VCXMLDataGeneratorTool"/>

+			<Tool

+				Name="VCWebDeploymentTool"/>

+			<Tool

+				Name="VCManagedWrapperGeneratorTool"/>

+			<Tool

+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath=".\android_usb_test.cpp">

+			</File>

+			<File

+				RelativePath=".\stdafx.cpp">

+				<FileConfiguration

+					Name="Debug|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="1"/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release|Win32">

+					<Tool

+						Name="VCCLCompilerTool"

+						UsePrecompiledHeader="1"/>

+				</FileConfiguration>

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+			<File

+				RelativePath=".\stdafx.h">

+			</File>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">

+		</Filter>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/host/windows/usb/test/android_usb_test/stdafx.cpp b/host/windows/usb/test/android_usb_test/stdafx.cpp
new file mode 100644
index 0000000..536a4ef
--- /dev/null
+++ b/host/windows/usb/test/android_usb_test/stdafx.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// stdafx.cpp : source file that includes just the standard includes

+// android_usb_test.pch will be the pre-compiled header

+// stdafx.obj will contain the pre-compiled type information

+

+#include "stdafx.h"

+

+// TODO: reference any additional headers you need in STDAFX.H

+// and not in this file

diff --git a/host/windows/usb/test/android_usb_test/stdafx.h b/host/windows/usb/test/android_usb_test/stdafx.h
new file mode 100644
index 0000000..ab0e165
--- /dev/null
+++ b/host/windows/usb/test/android_usb_test/stdafx.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// stdafx.h : include file for standard system include files,

+// or project specific include files that are used frequently, but

+// are changed infrequently

+//

+

+#pragma once

+

+

+#include <iostream>

+#include <tchar.h>

+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit

+

+#include <atlbase.h>

+#pragma warning(disable: 4200)
+extern "C" {
+#include <usbdi.h>

+}

+#include "android_usb_common_defines.h"
+#include "adb_api.h"

+

+// TODO: reference additional headers your program requires here

diff --git a/host/windows/usb/test/device_emulator/DeviceEmulator.cpp b/host/windows/usb/test/device_emulator/DeviceEmulator.cpp
new file mode 100644
index 0000000..155a6f6
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/DeviceEmulator.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file

+  This file definies entry point for the DLL.

+  This project has been created from DDK's SoftUSBLoopback sample project

+  that is located at $(DDK_PATH)\src\Test\DSF\USB\SoftUSBLoopback

+*/

+    

+#include "stdafx.h"

+#include "resource.h"

+#include <dsfif.h>

+#include <USBProtocolDefs.h>

+#include <softusbif.h>

+#include "LoopbackDevice.h"

+#include "DeviceEmulator.h"

+

+class CDeviceEmulatorModule : public CAtlDllModuleT<CDeviceEmulatorModule> {

+ public: 

+  DECLARE_LIBID(LIBID_DeviceEmulatorLib)

+  DECLARE_REGISTRY_APPID_RESOURCEID(IDR_DEVICEEMULATOR, "{D1C80253-8DB4-4F72-BF74-270A0EDA1FA9}")

+};

+

+CDeviceEmulatorModule _AtlModule;

+

+/////////////////////////////////////////////////////////////////////////////

+// DLL Entry Point

+

+extern "C"

+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {

+  hInstance;

+  return _AtlModule.DllMain(dwReason, lpReserved);

+}

+

+/////////////////////////////////////////////////////////////////////////////

+// Used to determine whether the DLL can be unloaded by OLE

+

+STDAPI DllCanUnloadNow(void) {

+  return (_AtlModule.DllCanUnloadNow());

+}

+

+/////////////////////////////////////////////////////////////////////////////

+// Returns a class factory to create an object of the requested type

+

+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {

+  return _AtlModule.DllGetClassObject(rclsid, riid, ppv);

+}

+

+/////////////////////////////////////////////////////////////////////////////

+// DllRegisterServer - Adds entries to the system registry

+

+STDAPI DllRegisterServer(void) {

+  // registers object, typelib and all interfaces in typelib

+  HRESULT hr =  _AtlModule.DllRegisterServer();

+  return hr;

+}

+

+/////////////////////////////////////////////////////////////////////////////

+// DllUnregisterServer - Removes entries from the system registry

+

+STDAPI DllUnregisterServer(void) {

+  HRESULT hr = _AtlModule.DllUnregisterServer();

+  return hr;

+}

+

+

+

+

+

diff --git a/host/windows/usb/test/device_emulator/DeviceEmulator.def b/host/windows/usb/test/device_emulator/DeviceEmulator.def
new file mode 100644
index 0000000..2a7cd7c
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/DeviceEmulator.def
@@ -0,0 +1,16 @@
+;Module Name:

+;

+;   DeviceEmulator.def 

+;

+;Abstract:

+;    Declares the module parameters

+;

+

+LIBRARY      "DeviceEmulator.DLL"

+

+EXPORTS

+    DllCanUnloadNow     PRIVATE

+    DllGetClassObject   PRIVATE

+    DllRegisterServer   PRIVATE

+    DllUnregisterServer PRIVATE

+

diff --git a/host/windows/usb/test/device_emulator/DeviceEmulator.idl b/host/windows/usb/test/device_emulator/DeviceEmulator.idl
new file mode 100644
index 0000000..9b60eb2
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/DeviceEmulator.idl
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file

+  This file consists of library definition for DeviceEmulator device.

+  This project has been created from DDK's SoftUSBLoopback sample project

+  that is located at $(DDK_PATH)\src\Test\DSF\USB\SoftUSBLoopback

+*/

+

+import "oaidl.idl";

+import "ocidl.idl";

+

+[

+    uuid(0C206596-5CC2-4d16-898D-4D1699BB6282),

+    version(1.0),

+    helpstring("DeviceEmulator 1.0 Type Library")

+]

+library DeviceEmulatorLib

+{

+    importlib("stdole2.tlb");

+    importlib("dsfif.tlb");

+

+

+    [

+        object,

+        uuid(0A7E88B6-E38F-4d78-ABA3-AA30DC836B7D),

+        oleautomation,

+        dual,

+        nonextensible,

+        helpstring("ILoopbackDevice Interface"),

+        pointer_default(unique)

+    ]

+    interface ILoopbackDevice : IDispatch

+    {

+        [

+            propget, 

+            id(1), 

+            helpstring("property DSFDevice")

+        ]

+        HRESULT DSFDevice([out, retval] DSFDevice** ppDSFDEevice);

+

+        [

+            id(2),

+            helpstring("Demonstrates how to use the queue method to read/write data")

+        ]

+        HRESULT _stdcall DoPolledLoopback([in] long LoopInterval);

+

+        [

+            id(3),

+            helpstring("Demonstrates how to use the eventing mechanism to read/write data")

+        ]

+        HRESULT _stdcall StartEventProcessing();

+

+        [

+            id(4),

+            helpstring("Starts event-driven simulation and returns immediately to caller.")

+        ]

+        HRESULT _stdcall StartAsyncEventProcessing();

+

+        [

+            id(5),

+            helpstring("Stops event-driven simulation started by a prior call to StartAsyncEventProcessing.")

+        ]

+        HRESULT _stdcall StopAsyncEventProcessing();

+

+        [

+            id(6),

+            helpstring("Check to see if there is any key strokes to be processed")

+        ]

+        HRESULT AreKeystrokesWaiting([out, retval] VARIANT_BOOL *pfvarKeysWaiting);

+    };

+

+    [

+        uuid(4F28A221-47B1-4f74-9ECC-CEADEDA0A287),

+        nonextensible,

+        helpstring("Loopback device event interface."),

+

+    ]

+    dispinterface ILoopbackDeviceEvents

+    {

+        properties:

+        methods:

+        [

+            id(1),

+            helpstring("Detemine if the device should stop polling the endpoint for data")

+        ]

+        HRESULT _stdcall ContinueToPoll([out,retval] VARIANT_BOOL *pfvarConitnue);

+

+        [

+            id(2),

+            helpstring("Detemine if the device should stop the event processing")

+        ]

+        HRESULT _stdcall ContinueEventProcessing([out,retval] VARIANT_BOOL *pfvarConitnue);

+    }

+

+    [

+        uuid(9A0BD4A6-E346-4668-A89C-ACA546212CD4),

+        helpstring("LoopbackDevice Class")

+    ]

+    coclass LoopbackDevice

+    {

+        [default] interface ILoopbackDevice;

+        [default, source] dispinterface ILoopbackDeviceEvents;

+    };

+};

+

diff --git a/host/windows/usb/test/device_emulator/DeviceEmulator.rc b/host/windows/usb/test/device_emulator/DeviceEmulator.rc
new file mode 100644
index 0000000..89fcd04
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/DeviceEmulator.rc
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file
+  Resource file for Device USB emulator.
+*/
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""winres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "1 TYPELIB ""DeviceEmulator.tlb""\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904e4"
+        BEGIN
+            VALUE "CompanyName", "Google, Inc."
+            VALUE "FileDescription", "Device USB Device Emulator"
+            VALUE "FileVersion", "1.0.0.1"
+            VALUE "LegalCopyright", "Copyright (C) 2007 The Android Open Source Project"
+            VALUE "InternalName", "DeviceEmulator.dll"
+            VALUE "OriginalFilename", "DeviceEmulator.dll"
+            VALUE "ProductName", "Android"
+            VALUE "ProductVersion", "1.0.0.1"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1252
+    END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_DEVICEEMULATOR      REGISTRY                "DeviceEmulator.rgs"
+IDR_LOOPBACKDEVICE      REGISTRY                "LoopbackDevice.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE 
+BEGIN
+    IDS_PROJNAME            "DeviceEmulator"
+END
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "DeviceEmulator.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
+
diff --git a/host/windows/usb/test/device_emulator/DeviceEmulator.rgs b/host/windows/usb/test/device_emulator/DeviceEmulator.rgs
new file mode 100644
index 0000000..a660ea5
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/DeviceEmulator.rgs
@@ -0,0 +1,12 @@
+HKCR

+{

+    NoRemove AppID

+    {

+        '%APPID%' = s 'DeviceEmulator'

+        'DeviceEmulator.EXE'

+        {

+            val AppID = s '%APPID%'

+        }

+    }

+}

+

diff --git a/host/windows/usb/test/device_emulator/LoopbackDevice.cpp b/host/windows/usb/test/device_emulator/LoopbackDevice.cpp
new file mode 100644
index 0000000..64ca8c6
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/LoopbackDevice.cpp
@@ -0,0 +1,796 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file

+  This file consists of implementation of the class CLoopbackDevice:

+    Implements the interface ILoopbackDevice and

+    configures the loopback device to be a valid USB device.

+    The device then processes input to its endpoint in one of 

+    two ways.

+

+    1. By running in polled mode where the data is simply 

+       passed from the OUT Endpoint to the IN Endpoint

+

+       or

+    2. In Event mode where the loopback device receives a 

+       callback to indicate that data needs to be processed,

+       and then processes the data.

+  This project has been created from DDK's SoftUSBLoopback sample project

+  that is located at $(DDK_PATH)\src\Test\DSF\USB\SoftUSBLoopback

+*/

+

+#include "stdafx.h"

+#include <stdio.h>

+#include <conio.h>

+#include <USBProtocolDefs.h>

+#include <dsfif.h>

+#include <softusbif.h>

+#include "android_usb_common_defines.h"

+#include "adb_api_extra.h"

+#include "LoopbackDevice.h"

+#include "DeviceEmulator_i.c"

+

+// These are the indexes of the string descriptors. They are used both

+// as the indexes of the strings with SoftUSBDevice.Strings and as the

+// string descriptor index property values on the various objects (e.g.

+// SoftUSBDevice.Manufacturer = STRING_IDX_MANUFACTURER).

+

+#define STRING_IDX_MANUFACTURER     1

+#define STRING_IDX_PRODUCT_DESC     2

+#define STRING_IDX_SERIAL_NO        3

+#define STRING_IDX_CONFIG           4

+#define STRING_IDX_INTERFACE        5

+

+CLoopbackDevice::CLoopbackDevice() {

+  InitMemberVariables();

+}

+

+CLoopbackDevice::~CLoopbackDevice() {

+  // Release the conneciton point

+  ReleaseConnectionPoint();

+    

+  // Release any interface which the device is holding

+  RELEASE(m_piConnectionPoint);

+  RELEASE(m_piINEndpoint);

+  RELEASE(m_piOUTEndpoint);

+

+  if (NULL != m_piSoftUSBDevice) {

+    (void)m_piSoftUSBDevice->Destroy();

+    RELEASE(m_piSoftUSBDevice);

+  }

+

+  InitMemberVariables();

+}

+

+void CLoopbackDevice::InitMemberVariables() {

+  m_piSoftUSBDevice = NULL;

+  m_piINEndpoint = NULL;

+  m_piOUTEndpoint = NULL;

+  m_piConnectionPoint = NULL;

+  m_iInterfaceString = 0;

+  m_iConfigString = 0;

+  m_dwConnectionCookie = 0;

+}

+

+HRESULT CLoopbackDevice::FinalConstruct() {

+  // Perform tasks which may fail when the class CLoopbackDevice

+  // is finally constructed. This involves creating the USB device 

+  // object and initializing the device so that it is recognized

+  // as a valid USB device by the controller

+  HRESULT hr = S_OK;

+

+  hr = CreateUSBDevice();

+  IfFailHrGo(hr);

+

+  hr = ConfigureDevice();

+  IfFailHrGo(hr);

+

+Exit:

+    return hr;

+}

+

+void CLoopbackDevice::FinalRelease() {

+}

+

+HRESULT CLoopbackDevice::CreateUSBDevice() {

+  // Creates the USB device and initializes the device member variables

+  // and creates and initializes the device qualifier. The device qualifier

+  // is required for USB2.0 devices.

+

+  HRESULT hr = S_OK;

+  ISoftUSBDeviceQualifier* piDeviceQual = NULL;

+  USHORT prod_id = DEVICE_EMULATOR_PROD_ID;

+

+  hr = ::CoCreateInstance(CLSID_SoftUSBDevice, 

+                          NULL,

+                          CLSCTX_INPROC_SERVER,

+                          __uuidof(ISoftUSBDevice),     

+                          reinterpret_cast<void**>(&m_piSoftUSBDevice));

+

+  IfFailHrGo(hr);

+

+  // Create the device qualifer

+  hr = ::CoCreateInstance(CLSID_SoftUSBDeviceQualifier, 

+                          NULL,

+                          CLSCTX_INPROC_SERVER,

+                          __uuidof(ISoftUSBDeviceQualifier),     

+                          reinterpret_cast<void**>(&piDeviceQual));

+

+  IfFailHrGo(hr);

+

+  // Setup the device qualifier

+  // binary coded decimal USB version 2.0

+  IfFailHrGo(piDeviceQual->put_USB(0x0200));

+  // FF=Vendor specfic device class

+  IfFailHrGo(piDeviceQual->put_DeviceClass(0xff)); 

+  // FF = Vendor specific device sub-class

+  IfFailHrGo(piDeviceQual->put_DeviceSubClass(0xff));

+  // FF = Vendor specific device protocol

+  IfFailHrGo(piDeviceQual->put_DeviceProtocol(0xff)); 

+  // Max packet size endpoint 0

+  IfFailHrGo(piDeviceQual->put_MaxPacketSize0(64)); 

+  // Number of configurations

+  IfFailHrGo(piDeviceQual->put_NumConfigurations(1));

+

+  // Setup the device 

+  // binary coded decimal USB version 2.0

+  IfFailHrGo(m_piSoftUSBDevice->put_USB(0x0200));

+  // FF=Vendor specfic device class

+  IfFailHrGo(m_piSoftUSBDevice->put_DeviceClass(0xff));

+  // FF = Vendor specific device sub-class

+  IfFailHrGo(m_piSoftUSBDevice->put_DeviceSubClass(0xff));

+  // FF = Vendor specific device protocol

+  IfFailHrGo(m_piSoftUSBDevice->put_DeviceProtocol(0xff)); 

+  // Max packet size endpoint 0

+  IfFailHrGo(m_piSoftUSBDevice->put_MaxPacketSize0(64)); 

+  // Vendor ID - Google

+  IfFailHrGo(m_piSoftUSBDevice->put_Vendor(DEVICE_VENDOR_ID));

+  // product id - Device Emulator

+  IfFailHrGo(m_piSoftUSBDevice->put_Product(static_cast<SHORT>(prod_id))); 

+  // Binary decimal coded version 1.0

+  IfFailHrGo(m_piSoftUSBDevice->put_Device(0x0100));

+  // Device does not suppport remote wake up

+  IfFailHrGo(m_piSoftUSBDevice->put_RemoteWakeup(VARIANT_FALSE));

+  // Index of the manufacturer string

+  IfFailHrGo(m_piSoftUSBDevice->put_Manufacturer(STRING_IDX_MANUFACTURER));

+  // Index of the product descripton string

+  IfFailHrGo(m_piSoftUSBDevice->put_ProductDesc(STRING_IDX_PRODUCT_DESC)); 

+  // Index of the serial number string

+  IfFailHrGo(m_piSoftUSBDevice->put_SerialNumber(STRING_IDX_SERIAL_NO));

+  // Indicate that the device is self-powered

+  IfFailHrGo(m_piSoftUSBDevice->put_SelfPowered(VARIANT_TRUE));

+  // Indicate that the device has power

+  IfFailHrGo(m_piSoftUSBDevice->put_Powered(VARIANT_TRUE));

+

+  // Create the strings associated with the device

+  IfFailHrGo(CreateStrings());

+

+  // Add the device qualifier

+  IfFailHrGo(m_piSoftUSBDevice->put_DeviceQualifier(piDeviceQual));

+

+Exit:

+  RELEASE(piDeviceQual);

+  return hr;

+}

+

+

+HRESULT CLoopbackDevice::ConfigureConfig(ISoftUSBConfiguration* piConfig) {

+  HRESULT hr = S_OK;

+  // config number passed to SetConfig

+  IfFailHrGo(piConfig->put_ConfigurationValue(1));

+  // Index of string descriptor

+  IfFailHrGo(piConfig->put_Configuration((BYTE)m_iConfigString));

+  // Self powered

+  IfFailHrGo(piConfig->put_Attributes(0x40));

+  // Max power in 2mA units: 50 = 100mA

+  IfFailHrGo(piConfig->put_MaxPower(50));

+

+Exit:

+  return hr;

+}

+

+HRESULT CLoopbackDevice::ConfigureINEndpoint() {

+  HRESULT hr = S_OK;

+

+  if (NULL == m_piINEndpoint) {

+    IfFailHrGo(E_UNEXPECTED);

+  }

+

+  // Endpoint #1 IN 

+  IfFailHrGo(m_piINEndpoint->put_EndpointAddress(0x81));

+  // Bulk data endpoint

+  IfFailHrGo(m_piINEndpoint->put_Attributes(0x02));

+  IfFailHrGo(m_piINEndpoint->put_MaxPacketSize(1024));

+  IfFailHrGo(m_piINEndpoint->put_Interval(0));

+  IfFailHrGo(m_piINEndpoint->put_Halted(FALSE));

+  // back pointer to the device

+  IfFailHrGo(m_piINEndpoint->put_USBDevice(reinterpret_cast<SoftUSBDevice*>(m_piSoftUSBDevice)));

+    

+Exit:    

+  return hr;

+}

+

+HRESULT CLoopbackDevice::ConfigureOUTEndpoint() {

+  HRESULT hr = S_OK;

+

+  if (NULL == m_piOUTEndpoint) {

+    IfFailHrGo(E_UNEXPECTED);

+  }

+

+  // Endpoint #2 OUT

+  IfFailHrGo(m_piOUTEndpoint->put_EndpointAddress(0x02));

+  // Bulk data endpoint

+  IfFailHrGo(m_piOUTEndpoint->put_Attributes(0x02));

+  IfFailHrGo(m_piOUTEndpoint->put_MaxPacketSize(1024));

+  IfFailHrGo(m_piOUTEndpoint->put_Interval(0));

+  IfFailHrGo(m_piOUTEndpoint->put_Halted(FALSE));

+  //back pointer to the device

+  IfFailHrGo(m_piOUTEndpoint->put_USBDevice(reinterpret_cast<SoftUSBDevice*>(m_piSoftUSBDevice)));

+    

+Exit:    

+  return hr;

+}

+

+HRESULT CLoopbackDevice::ConfigureInterface(ISoftUSBInterface* piInterface) {

+  HRESULT hr = S_OK;

+

+  IfFailHrGo(piInterface->put_InterfaceNumber(0));

+  IfFailHrGo(piInterface->put_AlternateSetting(0));

+  // Vendor specific class code

+  IfFailHrGo(piInterface->put_InterfaceClass(0xFF));

+  // Vendor specific sub class code

+  IfFailHrGo(piInterface->put_InterfaceSubClass(0xFF));

+  // Vendor specific protcol

+  IfFailHrGo(piInterface->put_InterfaceProtocol(0xFF));

+  //Index for string describing the interface

+  IfFailHrGo(piInterface->put_Interface((BYTE)m_iInterfaceString));

+

+Exit:

+  return hr;

+}

+

+HRESULT CLoopbackDevice::ConfigureDevice() {

+  HRESULT hr = S_OK;

+  ISoftUSBConfiguration* piConfig = NULL;

+  ISoftUSBInterface* piInterface = NULL;

+  ISoftUSBConfigList* piConfigList = NULL;

+  ISoftUSBInterfaceList* piInterfaceList = NULL;

+  ISoftUSBEndpointList* piEndpointList= NULL; 

+  VARIANT varIndex;

+  VariantInit(&varIndex);

+

+  // All members of the collection will be added at the default locations

+  // so set up the index appropriately

+  varIndex.vt = VT_ERROR;

+  varIndex.scode = DISP_E_PARAMNOTFOUND;

+

+  // Create the IN Endpoint

+  hr = CoCreateInstance(CLSID_SoftUSBEndpoint, 

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBEndpoint),     

+                        reinterpret_cast<void**>(&m_piINEndpoint));

+  IfFailHrGo(hr);

+

+  // Setup the IN Endpoint

+  IfFailHrGo(ConfigureINEndpoint());

+

+  // Create the OUT Endpoint

+  hr = CoCreateInstance(CLSID_SoftUSBEndpoint, 

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBEndpoint),     

+                        reinterpret_cast<void**>(&m_piOUTEndpoint));

+  IfFailHrGo(hr);

+

+  // Setup the OUT Endpoint

+  IfFailHrGo(ConfigureOUTEndpoint());

+

+  // Create the device interface

+  hr = CoCreateInstance(CLSID_SoftUSBInterface, 

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBInterface),     

+                        reinterpret_cast<void**>(&piInterface));

+  IfFailHrGo(hr);

+

+  // Setup the device interface

+  IfFailHrGo(ConfigureInterface(piInterface));

+

+  // Add the Endpoints to the endpoint list

+  IfFailHrGo(piInterface->get_Endpoints(&piEndpointList));

+  IfFailHrGo(piEndpointList->Add(reinterpret_cast<SoftUSBEndpoint*>(m_piINEndpoint), varIndex));

+  IfFailHrGo(piEndpointList->Add(reinterpret_cast<SoftUSBEndpoint*>(m_piOUTEndpoint), varIndex));

+

+  // Create the configuration

+  hr = CoCreateInstance(CLSID_SoftUSBConfiguration, 

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBConfiguration),     

+                        reinterpret_cast<void**>(&piConfig));

+  IfFailHrGo(hr);

+

+  // Set the configuration data up

+  IfFailHrGo(ConfigureConfig(piConfig));

+

+  // Add the interface to the interface collection

+  IfFailHrGo(piConfig->get_Interfaces(&piInterfaceList));

+  IfFailHrGo(piInterfaceList->Add(reinterpret_cast<SoftUSBInterface*>(piInterface), varIndex));

+

+  // Add the configuration to the configuration collection

+  IfFailHrGo(m_piSoftUSBDevice->get_Configurations(&piConfigList));

+  IfFailHrGo(piConfigList->Add(reinterpret_cast<SoftUSBConfiguration*>(piConfig), varIndex));

+

+Exit:

+  RELEASE(piConfig);

+  RELEASE(piInterface);

+  RELEASE(piConfigList);

+  RELEASE(piInterfaceList);

+  RELEASE(piEndpointList);

+  return hr;

+}

+

+HRESULT CLoopbackDevice::CreateStrings() {

+  HRESULT hr = S_OK;

+  ISoftUSBStringList* piStringList = NULL;

+  ISoftUSBString* piStringManufacturer = NULL;

+  ISoftUSBString* piStringProductDesc = NULL;

+  ISoftUSBString* piStringSerialNo = NULL;

+  ISoftUSBString* piStringConfig = NULL;

+  ISoftUSBString* piStringEndpoint = NULL;

+  BSTR bstrManufacturer = ::SysAllocString(L"Google, Inc");

+  BSTR bstrProductDesc = ::SysAllocString(L"USB Emulating Device");

+  BSTR bstrSerialNo = ::SysAllocString(L"123456789ABCDEF");

+  BSTR bstrConfig = ::SysAllocString(L"Configuration with a single interface");

+  BSTR bstrEndpoint = ::SysAllocString(L"Interface with bulk IN endpoint and bulk OUT endpoint");

+  VARIANT varIndex;

+  VariantInit(&varIndex);

+

+  // Check that all BSTR allocations succeeded

+  IfFalseHrGo(0 != ::SysStringLen(bstrManufacturer), E_OUTOFMEMORY);

+  IfFalseHrGo(0 != ::SysStringLen(bstrProductDesc), E_OUTOFMEMORY);

+  IfFalseHrGo(0 != ::SysStringLen(bstrSerialNo), E_OUTOFMEMORY);

+  IfFalseHrGo(0 != ::SysStringLen(bstrConfig), E_OUTOFMEMORY);

+  IfFalseHrGo(0 != ::SysStringLen(bstrEndpoint), E_OUTOFMEMORY);

+

+  //Set up the varaint used as the index

+  varIndex.vt = VT_I4;

+  varIndex.lVal = STRING_IDX_MANUFACTURER;

+

+  //Create and initialize the string descriptors. Also create a string 

+  //descriptor index for each. This index is used both to set the string's

+  //descriptors position in the m_piSoftUSBDevice.Strings and is the index value 

+  //the GetDescriptors request from the host. Note that we don't use 

+  //string descriptor index zero because that is a reserved value for a 

+  //device's language ID descriptor.

+

+  //Get the string list from the device

+  hr = m_piSoftUSBDevice->get_Strings(&piStringList);

+  IfFailHrGo(hr);

+

+  hr = CoCreateInstance(CLSID_SoftUSBString,

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBString),     

+                        reinterpret_cast<void**>(&piStringManufacturer));

+  IfFailHrGo(hr);

+

+  IfFailHrGo(piStringManufacturer->put_Value(bstrManufacturer));

+  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringManufacturer), varIndex));

+    

+  hr = CoCreateInstance(CLSID_SoftUSBString,

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBString),     

+                        reinterpret_cast<void**>(&piStringProductDesc));

+

+  IfFailHrGo(hr);

+  IfFailHrGo(piStringProductDesc->put_Value(bstrProductDesc));

+  varIndex.lVal = STRING_IDX_PRODUCT_DESC;

+  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringProductDesc), varIndex));

+

+  hr = CoCreateInstance(CLSID_SoftUSBString,

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBString),     

+                        reinterpret_cast<void**>(&piStringSerialNo));

+  IfFailHrGo(hr);

+  IfFailHrGo(piStringSerialNo->put_Value(bstrSerialNo));

+  varIndex.lVal = STRING_IDX_SERIAL_NO;

+  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringSerialNo), varIndex));

+

+  hr = CoCreateInstance(CLSID_SoftUSBString,

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBString),     

+                        reinterpret_cast<void**>(&piStringConfig));

+  IfFailHrGo(hr);

+  IfFailHrGo(piStringConfig->put_Value(bstrConfig));

+  varIndex.lVal = STRING_IDX_CONFIG;

+  m_iConfigString = varIndex.lVal;

+  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringConfig), varIndex));

+

+  hr = CoCreateInstance(CLSID_SoftUSBString,

+                        NULL,

+                        CLSCTX_INPROC_SERVER,

+                        __uuidof(ISoftUSBString),     

+                        reinterpret_cast<void**>(&piStringEndpoint));

+  IfFailHrGo(hr);

+  IfFailHrGo(piStringEndpoint->put_Value(bstrEndpoint));

+  varIndex.lVal = STRING_IDX_INTERFACE;

+  m_iInterfaceString = varIndex.lVal;

+  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringEndpoint), varIndex));

+

+Exit:

+  RELEASE(piStringList);

+  RELEASE(piStringManufacturer);

+  RELEASE(piStringProductDesc);

+  RELEASE(piStringSerialNo);

+  RELEASE(piStringConfig);

+  RELEASE(piStringEndpoint);

+  ::SysFreeString(bstrManufacturer);

+  ::SysFreeString(bstrProductDesc);

+  ::SysFreeString(bstrSerialNo);

+  ::SysFreeString(bstrConfig);

+  ::SysFreeString(bstrEndpoint);

+

+  return hr;

+}

+

+HRESULT CLoopbackDevice::ReleaseConnectionPoint() {

+  HRESULT hr = S_OK;

+    

+  if (NULL != m_piConnectionPoint) {

+    m_piConnectionPoint->Unadvise(m_dwConnectionCookie);

+    m_dwConnectionCookie = 0;

+  }

+

+  RELEASE(m_piConnectionPoint);

+

+  return hr;

+}

+

+

+HRESULT CLoopbackDevice::SetupConnectionPoint(IUnknown* punkObject,

+                                              REFIID iidConnectionPoint) {

+  HRESULT hr = S_OK;

+  IConnectionPointContainer* piConnectionPointContainer = NULL;

+  IUnknown* punkSink = NULL;

+

+  //If there is already connection point enabled, disable it

+  if(NULL != m_piConnectionPoint) {

+    IfFailHrGo(ReleaseConnectionPoint());

+  }

+        

+  IfFailHrGo(punkObject->QueryInterface(IID_IConnectionPointContainer,

+                                        reinterpret_cast<void **>(&piConnectionPointContainer)));

+

+  IfFailHrGo(piConnectionPointContainer->FindConnectionPoint(iidConnectionPoint,

+                                                             &m_piConnectionPoint));

+

+  // Get the IUknown of this interface as this is the event sink

+  punkSink = (this)->GetUnknown(); 

+

+  if(NULL == punkSink) {

+    IfFailHrGo(E_UNEXPECTED);

+  }

+

+  IfFailHrGo(m_piConnectionPoint->Advise(punkSink, &m_dwConnectionCookie));

+

+

+Exit:

+  return hr;

+}

+

+STDMETHODIMP CLoopbackDevice::get_DSFDevice(DSFDevice** ppDSFDevice) {

+  HRESULT hr = S_OK;

+  DSFDevice* pDSFDevice = NULL;

+

+  //Validate the the UDB device exists else this is an

+  //internal error

+  if (NULL == m_piSoftUSBDevice) {

+    IfFailHrGo(E_UNEXPECTED);

+  }    

+

+  if (NULL == ppDSFDevice) {

+    IfFailHrGo(E_POINTER);

+  }

+

+  IfFailHrGo(m_piSoftUSBDevice->get_DSFDevice(&pDSFDevice));

+  IfFailHrGo(reinterpret_cast<IDSFDevice *>(pDSFDevice)->QueryInterface(__uuidof(IDispatch), reinterpret_cast<void **>(ppDSFDevice)));

+

+Exit:

+  if (NULL != pDSFDevice)

+    reinterpret_cast<IDSFDevice *>(pDSFDevice)->Release();

+

+  return hr;

+}

+

+

+STDMETHODIMP CLoopbackDevice::DoPolledLoopback(long lTimeInterval) {

+/*

+   Demonstrates how to use the drain OUT queue and queue IN data

+   methods to communicate with the host controller. 

+

+   The code checks to see if there is any data in the OUT, if no 

+   data is present an event is fired to indicate if the function 

+   should exit. If the function should not exit then the function 

+   sleeps for the time interval before re-checking the queue.

+

+   If there is data then the function reads the data and passes the

+   data to the IN queue. This simply provides a loopback mechanism

+   to the host controller.

+*/

+  HRESULT hr = S_OK;

+  BOOL fKeepLooping = TRUE;

+  // Number of items currently in the queue

+  ULONG ulNoOfQueuedItems = 0;

+  // Only going to read one transfer at a time

+  ULONG ulTransfers = 1;

+  SOFTUSB_OUT_TRANSFER* pOUTTransfer = NULL;

+  // Copied the message status

+  BYTE bStatus = 0;

+  // Copied the message data

+  BYTE* pDataBuffer = NULL;

+  // Holds the size of the data buffer

+  ULONG cbDataBuffer      = 0;

+  VARIANT_BOOL fvarContinue = VARIANT_TRUE;

+

+  if (NULL == m_piINEndpoint || NULL == m_piOUTEndpoint) {

+    IfFailHrGo(E_UNEXPECTED);

+  }

+

+  while (fKeepLooping) {

+    // Reset the number of queued items

+    ulNoOfQueuedItems = 0;

+        

+    // Check to see if there is any data in the out queue

+    IfFailHrGo(m_piOUTEndpoint->DrainOUTQueue(0, &ulNoOfQueuedItems, NULL));

+

+    if (0 == ulNoOfQueuedItems) {

+      // There is no data in the list so we need to check

+      // If we should continue to loop

+      // Fire Event to check if more processing is required

+      IfFailHrGo(Fire_ContinueToPoll(&fvarContinue));

+

+      // Check to see if the return value is VARIANT_FALSE

+      if (VARIANT_FALSE == fvarContinue)

+        fKeepLooping = FALSE;

+            

+      if (fKeepLooping)

+        ::Sleep(lTimeInterval);

+    } else {

+      // There is data to read, loop until we have moved all 

+      // the data from the OUT queue to the IN queue moving

+      // one data item at a time

+      do {

+        // Get the OUT data

+        IfFailHrGo(m_piOUTEndpoint->DrainOUTQueue(ulTransfers, 

+                                                  &ulNoOfQueuedItems, 

+                                                  &pOUTTransfer));

+

+        // Setup the IN data

+        bStatus= pOUTTransfer->bStatus;

+        cbDataBuffer = pOUTTransfer->cbData;

+        pDataBuffer =&pOUTTransfer->Data[0];

+                

+        // Send the data to the out queue

+        IfFailHrGo(m_piINEndpoint->QueueINData(pDataBuffer,

+                                               cbDataBuffer,

+                                               bStatus,

+                                               SOFTUSB_FOREVER));

+

+        // Free the memory used by pOUTTransfer   

+        m_piOUTEndpoint->FreeOUTQueue(pOUTTransfer);

+        pOUTTransfer = NULL;

+

+        // Force a context switch 

+        ::Sleep(1);

+      } while (0 != ulNoOfQueuedItems);

+    }

+  }

+

+Exit:

+  // If one of the calls failed pOUTTransfer will be NON-NULL 

+  // And needs to be freed

+  if (NULL != pOUTTransfer) {

+    // Free the memory used by pOUTTransfer   

+    m_piOUTEndpoint->FreeOUTQueue(pOUTTransfer);

+    pOUTTransfer = NULL;

+  }

+

+  return hr;

+}

+

+STDMETHODIMP CLoopbackDevice::StartEventProcessing() {

+/*

+   Demonstrates how to setup event sinks so that the 

+   event mechanism can be used to control data flow to and

+   from the USB controller. In this example an event sink

+   is installed on the OUT USB endpoint, when the controller

+   has data to send to the device the OnWriteTransfer event

+   will fire, this will occur on an arbitrary thread. The 

+   device then simply copies this data and passes it the

+   IN queue of the IN Endpoint.

+*/

+  HRESULT               hr                = S_OK;

+  BOOL                  fKeepLooping      = TRUE;

+  VARIANT_BOOL          fvarContinue      = VARIANT_TRUE;

+

+  // Set up event sink on the OUT endpoint

+  IfFailHrGo(SetupConnectionPoint(m_piOUTEndpoint, __uuidof(ISoftUSBEndpointEvents)));

+

+  // Loop waiting for Events to be fired

+  while (TRUE == fKeepLooping) {

+    // Context switch to allow other threads to process

+    ::Sleep(1);

+

+    // Fire Event to check if the caller want to continue processing

+    IfFailHrGo(Fire_ContinueEventProcessing(&fvarContinue));

+

+    // Check to see if the return value is VARIANT_FALSE

+    if (VARIANT_FALSE == fvarContinue)

+      fKeepLooping = FALSE;

+  }

+

+  // Remove the event sink from the OUT endpoint

+  IfFailHrGo(ReleaseConnectionPoint());

+    

+Exit:

+  return hr;

+}

+

+STDMETHODIMP CLoopbackDevice::StartAsyncEventProcessing() {

+/*

+   Demonstrates how to setup event sinks so that the event mechanism can

+   be used to control data flow to and from the USB controller. In this

+   example an event sink is installed on the OUT USB endpoint, when the

+   controller has data to send to the device the OnWriteTransfer event

+   will fire, this will occur on an arbitrary thread. The device then

+   simply copies this data and passes it the IN queue of the IN

+   Endpoint. Control returns to the caller and event processing

+   continues in an arbitrary thread. To terminate event processing call

+   StopAsyncEventProcessing.

+*/

+  HRESULT hr = S_OK;

+

+  // Set up event sink on the OUT endpoint

+  IfFailHrGo(SetupConnectionPoint(m_piOUTEndpoint, __uuidof(ISoftUSBEndpointEvents)));

+

+Exit:

+  return hr;

+}

+

+STDMETHODIMP CLoopbackDevice::StopAsyncEventProcessing() {

+  HRESULT hr = S_OK;

+  // Remove the event sink on the OUT endpoint

+  IfFailHrGo(ReleaseConnectionPoint());

+

+Exit:

+  return hr;

+}

+

+

+

+STDMETHODIMP CLoopbackDevice::AreKeystrokesWaiting(

+    VARIANT_BOOL* pfvarKeyWaiting) {

+/*

+   Implements IDeviceEmulator::AreKeystrokesWaiting. It calls the low level 

+   IO function _kbhit to see if the keyboard has been struck. If the Keyboard

+   has been hit the function return VARIANT_TRUE otherwise it returns VARIANT_FALSE

+*/

+  HRESULT hr = S_OK;

+  int iKeyHit = 0;

+

+  if (NULL == pfvarKeyWaiting) {

+    IfFailHrGo(E_POINTER);

+  }

+    

+  *pfvarKeyWaiting = VARIANT_FALSE;

+

+  iKeyHit = _kbhit();

+

+  if (0 != iKeyHit)

+    *pfvarKeyWaiting = VARIANT_TRUE;

+

+Exit:

+  return hr;

+}

+

+//ISoftUSBEndpointEvents

+

+STDMETHODIMP CLoopbackDevice::OnSetupTransfer(BYTE DataToggle,

+                                              BYTE* pbDataBuffer,

+                                              ULONG cbDataBuffer,

+                                              BYTE *pbStatus) {

+  HRESULT hr = E_NOTIMPL;

+  UNREFERENCED_PARAMETER(DataToggle);

+  UNREFERENCED_PARAMETER(pbDataBuffer);

+  UNREFERENCED_PARAMETER(cbDataBuffer);

+  UNREFERENCED_PARAMETER(pbStatus);

+  return hr;

+}

+

+STDMETHODIMP CLoopbackDevice::OnWriteTransfer(BYTE DataToggle,

+                                              BYTE* pbDataBuffer,

+                                              ULONG cbDataBuffer,

+                                              BYTE * pbStatus) {

+    

+  HRESULT hr = S_OK;

+  BYTE bINStatus = USB_ACK;

+  UNREFERENCED_PARAMETER(DataToggle);

+

+  // Check that the IN endpoint is valid

+  if (NULL == m_piINEndpoint) {

+    IfFailHrGo(E_UNEXPECTED);

+  }

+

+  // Send the data to the IN Endpoint

+  IfFailHrGo(m_piINEndpoint->QueueINData(pbDataBuffer,

+                                         cbDataBuffer,

+                                         bINStatus,

+                                         SOFTUSB_FOREVER));

+

+  // ACK the status as the data was successfully sent to the IN endpoint

+  *pbStatus = USB_ACK;

+

+Exit:

+  if (FAILED(hr))

+    *pbStatus = USB_STALL;

+

+  return hr;

+}

+

+STDMETHODIMP CLoopbackDevice::OnReadTransfer(BYTE DataToggle,

+                                             BYTE* pbDataBuffer,

+                                             ULONG cbDataBuffer,

+                                             ULONG* cbDataWritten,

+                                             BYTE* pbStatus) {

+  HRESULT hr = E_NOTIMPL;

+  UNREFERENCED_PARAMETER(DataToggle);

+  UNREFERENCED_PARAMETER(pbDataBuffer);

+  UNREFERENCED_PARAMETER(cbDataBuffer);

+  UNREFERENCED_PARAMETER(cbDataWritten);

+  UNREFERENCED_PARAMETER(pbStatus);

+  return hr;

+}

+

+STDMETHODIMP CLoopbackDevice::OnDeviceRequest(USBSETUPREQUEST *pSetupRequest,

+                                              ULONG_PTR* RequestHandle,

+                                              BYTE* pbHostData,

+                                              ULONG cbHostData,

+                                              BYTE** ppbResponseData,

+                                              ULONG* pcbResponseData,

+                                              BYTE* pbSetupStatus) {

+  HRESULT hr = E_NOTIMPL;

+  UNREFERENCED_PARAMETER(pSetupRequest);

+  UNREFERENCED_PARAMETER(RequestHandle);

+  UNREFERENCED_PARAMETER(pbHostData);

+  UNREFERENCED_PARAMETER(cbHostData);

+  UNREFERENCED_PARAMETER(ppbResponseData);

+  UNREFERENCED_PARAMETER(pcbResponseData);

+  UNREFERENCED_PARAMETER(pbSetupStatus);

+  return hr;

+}

+

+STDMETHODIMP CLoopbackDevice::OnDeviceRequestComplete(

+    ULONG_PTR RequestHandle,

+    BYTE* pbFinalRequestStatus) {

+  HRESULT hr = E_NOTIMPL;

+  UNREFERENCED_PARAMETER(RequestHandle);

+  UNREFERENCED_PARAMETER(pbFinalRequestStatus);

+  return hr;

+}

diff --git a/host/windows/usb/test/device_emulator/LoopbackDevice.h b/host/windows/usb/test/device_emulator/LoopbackDevice.h
new file mode 100644
index 0000000..0df3fba
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/LoopbackDevice.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file

+  This file consists of definition of the class CLoopbackDevice

+  This project has been created from DDK's SoftUSBLoopback sample project

+  that is located at $(DDK_PATH)\src\Test\DSF\USB\SoftUSBLoopback

+*/

+

+#pragma once

+#include "resource.h"

+

+#include "DeviceEmulator.h"

+#include "LoopbackDeviceEvents.h"

+

+

+//Release and Add ref macros

+#define ADDREF(punk) { \

+  if ((punk) != NULL) { \

+    (punk)->AddRef(); \

+  } \

+}

+

+

+#define RELEASE(punk) { \

+  if ((punk) != NULL) { \

+    IUnknown *_punkXxx = (punk); \

+    (punk) = NULL; \

+    _punkXxx->Release(); \

+  } \

+}

+

+//HR check

+#define IfFailHrGo(EXPR) { hr = (EXPR); if(FAILED(hr)) goto Exit; }

+#define IfFalseHrGo(EXPR, HR) { if(!(EXPR)) { hr = (HR); goto Exit; } }

+

+#pragma warning(disable: 4995) //Pragma deprecated

+

+class ATL_NO_VTABLE CLoopbackDevice : 

+    public CComObjectRootEx<CComSingleThreadModel>,

+    public CComCoClass<CLoopbackDevice, &CLSID_LoopbackDevice>,

+    public IConnectionPointContainerImpl<CLoopbackDevice>,

+    public CProxy_ILoopbackDeviceEvents<CLoopbackDevice>, 

+    public ISoftUSBEndpointEvents,

+    public IDispatchImpl<ILoopbackDevice, &IID_ILoopbackDevice,

+                         &LIBID_DeviceEmulatorLib,

+                         /*wMajor =*/ 1, /*wMinor =*/ 0> {

+ public:

+    CLoopbackDevice();

+    virtual ~CLoopbackDevice();

+DECLARE_REGISTRY_RESOURCEID(IDR_LOOPBACKDEVICE)

+

+

+BEGIN_COM_MAP(CLoopbackDevice)

+    COM_INTERFACE_ENTRY(ILoopbackDevice)

+    COM_INTERFACE_ENTRY(IDispatch)

+    COM_INTERFACE_ENTRY(ISoftUSBEndpointEvents)

+    COM_INTERFACE_ENTRY(IConnectionPointContainer)

+END_COM_MAP()

+

+BEGIN_CONNECTION_POINT_MAP(CLoopbackDevice)

+    CONNECTION_POINT_ENTRY(__uuidof(ILoopbackDeviceEvents))

+END_CONNECTION_POINT_MAP()

+

+

+  DECLARE_PROTECT_FINAL_CONSTRUCT()

+

+  HRESULT FinalConstruct();

+    

+  void FinalRelease();

+

+ private:

+  void InitMemberVariables();

+

+   HRESULT CreateUSBDevice();

+   HRESULT CreateStrings();

+   HRESULT ConfigureDevice();

+   HRESULT ConfigureOUTEndpoint();

+   HRESULT ConfigureINEndpoint();

+   HRESULT ConfigureInterface(ISoftUSBInterface* piInterface);

+   HRESULT ConfigureConfig(ISoftUSBConfiguration* piConfig);

+

+   HRESULT SetupConnectionPoint(IUnknown* punkObject,

+                                REFIID iidConnectionPoint);

+   HRESULT ReleaseConnectionPoint();

+

+   // Underlying SoftUSBDevice object

+   ISoftUSBDevice          *m_piSoftUSBDevice;

+   // IN Endpoint

+   ISoftUSBEndpoint        *m_piINEndpoint;

+   // OUT Endpoint

+   ISoftUSBEndpoint        *m_piOUTEndpoint;

+   // Connection point interface

+   IConnectionPoint        *m_piConnectionPoint;

+   // Connection point cookie.

+   DWORD                    m_dwConnectionCookie;

+   // Index of interface identifier string

+   int                      m_iInterfaceString;

+   // Index of config identifier string

+   int                      m_iConfigString;

+     

+ public:

+  //ILoopbackDevice

+  STDMETHOD(get_DSFDevice)(DSFDevice** ppDSFDevice);

+  STDMETHOD(DoPolledLoopback)(long lTimeInterval);

+  STDMETHOD(StartEventProcessing)();

+  STDMETHOD(StartAsyncEventProcessing)();

+  STDMETHOD(StopAsyncEventProcessing)();

+  STDMETHOD(AreKeystrokesWaiting)(VARIANT_BOOL* pfvarKeyWaiting);

+

+  //ISoftUSBEndpointEvents

+  STDMETHOD(OnSetupTransfer)(BYTE DataToggle, BYTE* pbDataBuffer,

+                             ULONG cbDataBuffer, BYTE* pbStatus);

+

+  STDMETHOD(OnWriteTransfer)(BYTE DataToggle, BYTE* pbDataBuffer,

+                             ULONG cbDataBuffer, BYTE* pbStatus);

+

+  STDMETHOD(OnReadTransfer)(BYTE DataToggle, BYTE* pbDataBuffer,

+                            ULONG cbDataBuffer,ULONG* cbDataWritten,

+                            BYTE* pbStatus);       

+

+  STDMETHOD(OnDeviceRequest)(USBSETUPREQUEST* pSetupRequest,

+                             ULONG_PTR* RequestHandle, 

+                             BYTE* pbHostData, ULONG cbHostData,

+                             BYTE** ppbResponseData,

+                             ULONG* pcbResponseData,BYTE* pbSetupStatus);

+

+  STDMETHOD(OnDeviceRequestComplete)(ULONG_PTR RequestHandle,

+                                     BYTE* pbFinalRequestStatus);

+};

+

+OBJECT_ENTRY_AUTO(__uuidof(LoopbackDevice), CLoopbackDevice)

diff --git a/host/windows/usb/test/device_emulator/LoopbackDevice.rgs b/host/windows/usb/test/device_emulator/LoopbackDevice.rgs
new file mode 100644
index 0000000..422f654
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/LoopbackDevice.rgs
@@ -0,0 +1,27 @@
+HKCR

+{

+    DeviceEmulator.LoopbackDevice.1 = s 'LoopbackDevice Class'

+    {

+        CLSID = s '{9A0BD4A6-E346-4668-A89C-ACA546212CD4}'

+    }

+    DeviceEmulator.LoopbackDevice = s 'LoopbackDevice Class'

+    {

+        CLSID = s '{9A0BD4A6-E346-4668-A89C-ACA546212CD4}'

+        CurVer = s 'DeviceEmulator.LoopbackDevice.1'

+    }

+    NoRemove CLSID

+    {

+        ForceRemove {9A0BD4A6-E346-4668-A89C-ACA546212CD4} = s 'LoopbackDevice Class'

+        {

+            ProgID = s 'DeviceEmulator.LoopbackDevice.1'

+            VersionIndependentProgID = s 'DeviceEmulator.LoopbackDevice'

+            ForceRemove 'Programmable'

+            InprocServer32 = s '%MODULE%'

+            {

+                val ThreadingModel = s 'Apartment'

+            }

+            'TypeLib' = s '{0C206596-5CC2-4d16-898D-4D1699BB6282}'

+        }

+    }

+}

+

diff --git a/host/windows/usb/test/device_emulator/LoopbackDeviceEvents.h b/host/windows/usb/test/device_emulator/LoopbackDeviceEvents.h
new file mode 100644
index 0000000..9bde9e0
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/LoopbackDeviceEvents.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file

+  This file consists of definition of the template class which implements the

+  event interface ILoopbackDeviceEvents.

+  This project has been created from DDK's SoftUSBLoopback sample project

+  that is located at $(DDK_PATH)\src\Test\DSF\USB\SoftUSBLoopback

+*/

+

+template<class T>

+class CProxy_ILoopbackDeviceEvents :

+    public IConnectionPointImpl<T, &__uuidof(ILoopbackDeviceEvents)> {

+ public:

+  HRESULT _stdcall Fire_ContinueToPoll(VARIANT_BOOL *pfvarContinue) {

+    HRESULT hr = S_OK;

+    T* pThis = static_cast<T *>(this);

+    int cConnections = m_vec.GetSize();

+

+    for (int iConnection = 0; iConnection < cConnections; iConnection++) {

+      pThis->Lock();

+      CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);

+      pThis->Unlock();

+

+      IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

+

+      if (pConnection) {

+        CComVariant varResult;

+

+        DISPPARAMS params = { NULL, NULL, 0, 0 };

+        hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT,

+                                 DISPATCH_METHOD, &params, &varResult,

+                                 NULL, NULL);

+

+        //Set the return parameter

+        *pfvarContinue  = varResult.boolVal;

+      }

+    }

+    return hr;

+  }

+

+  HRESULT _stdcall Fire_ContinueEventProcessing(VARIANT_BOOL *pfvarContinue) {

+    HRESULT hr = S_OK;

+    T * pThis = static_cast<T *>(this);

+    int cConnections = m_vec.GetSize();

+

+    for (int iConnection = 0; iConnection < cConnections; iConnection++) {

+      pThis->Lock();

+      CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);

+      pThis->Unlock();

+

+      IDispatch * pConnection = static_cast<IDispatch *>(punkConnection.p);

+

+      if (pConnection) {

+        CComVariant varResult;

+

+        DISPPARAMS params = { NULL, NULL, 0, 0 };

+        hr = pConnection->Invoke(2, IID_NULL, LOCALE_USER_DEFAULT,

+                                 DISPATCH_METHOD, &params, &varResult,

+                                 NULL, NULL);

+

+        //Set the return parameter

+        *pfvarContinue  = varResult.boolVal;

+      }

+    }

+    return hr;

+  }

+};

+

diff --git a/host/windows/usb/test/device_emulator/device_emulator.sln b/host/windows/usb/test/device_emulator/device_emulator.sln
new file mode 100644
index 0000000..3fff7ca
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/device_emulator.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "device_emulator", "device_emulator.vcproj", "{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}"

+	ProjectSection(ProjectDependencies) = postProject

+	EndProjectSection

+EndProject

+Global

+	GlobalSection(SolutionConfiguration) = preSolution

+		Debug = Debug

+		Release = Release

+	EndGlobalSection

+	GlobalSection(ProjectConfiguration) = postSolution

+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}.Debug.ActiveCfg = Debug|Win32

+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}.Debug.Build.0 = Debug|Win32

+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}.Release.ActiveCfg = Release|Win32

+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}.Release.Build.0 = Release|Win32

+	EndGlobalSection

+	GlobalSection(ExtensibilityGlobals) = postSolution

+	EndGlobalSection

+	GlobalSection(ExtensibilityAddIns) = postSolution

+	EndGlobalSection

+EndGlobal

diff --git a/host/windows/usb/test/device_emulator/device_emulator.vcproj b/host/windows/usb/test/device_emulator/device_emulator.vcproj
new file mode 100644
index 0000000..34a66c3
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/device_emulator.vcproj
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="Windows-1252"?>

+<VisualStudioProject

+	ProjectType="Visual C++"

+	Version="7.10"

+	Name="device_emulator"

+	ProjectGUID="{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}"

+	Keyword="MakeFileProj">

+	<Platforms>

+		<Platform

+			Name="Win32"/>

+	</Platforms>

+	<Configurations>

+		<Configuration

+			Name="Debug|Win32"

+			OutputDirectory="Debug"

+			IntermediateDirectory="Debug"

+			ConfigurationType="0">

+			<Tool

+				Name="VCNMakeTool"

+				BuildCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ chk WXP

+set PROJECTDIR=$(ProjectDir)

+set DRIVE=%PROJECTDIR:~0,2%

+%DRIVE%

+cd %PROJECTDIR%

+build -beEIFZ

+"

+				ReBuildCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ chk WXP

+set PROJECTDIR=$(ProjectDir)

+set DRIVE=%PROJECTDIR:~0,2%

+%DRIVE%

+cd %PROJECTDIR%

+build -cbeEIFZ

+"

+				CleanCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ chk WXP

+set PROJECTDIR=$(ProjectDir)

+set DRIVE=%PROJECTDIR:~0,2%

+%DRIVE%

+cd %PROJECTDIR%

+build -c0

+"/>

+		</Configuration>

+		<Configuration

+			Name="Release|Win32"

+			OutputDirectory="Release"

+			IntermediateDirectory="Release"

+			ConfigurationType="0">

+			<Tool

+				Name="VCNMakeTool"

+				BuildCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ free WXP

+set PROJECTDIR=$(ProjectDir)

+set DRIVE=%PROJECTDIR:~0,2%

+%DRIVE%

+cd %PROJECTDIR%

+build -beEIFZ"

+				ReBuildCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ free WXP

+set PROJECTDIR=$(ProjectDir)

+set DRIVE=%PROJECTDIR:~0,2%

+%DRIVE%

+cd %PROJECTDIR%

+build -cbeEIFZ"

+				CleanCommandLine="call c:\winddk\6000\bin\setenv.bat c:\winddk\6000\ free WXP

+set PROJECTDIR=$(ProjectDir)

+set DRIVE=%PROJECTDIR:~0,2%

+%DRIVE%

+cd %PROJECTDIR%

+build -c0

+"

+				Output="device_emulator.dll"/>

+		</Configuration>

+	</Configurations>

+	<References>

+	</References>

+	<Files>

+		<Filter

+			Name="Source Files"

+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"

+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">

+			<File

+				RelativePath=".\LoopbackDevice.cpp">

+			</File>

+			<File

+				RelativePath=".\DeviceEmulator.cpp">

+			</File>

+			<File

+				RelativePath=".\DeviceEmulator.idl">

+			</File>

+			<File

+				RelativePath=".\stdafx.cpp">

+			</File>

+		</Filter>

+		<Filter

+			Name="Header Files"

+			Filter="h;hpp;hxx;hm;inl;inc;xsd"

+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">

+			<File

+				RelativePath=".\LoopbackDevice.h">

+			</File>

+			<File

+				RelativePath=".\LoopbackDeviceEvents.h">

+			</File>

+			<File

+				RelativePath=".\resource.h">

+			</File>

+			<File

+				RelativePath=".\stdafx.h">

+			</File>

+			<Filter

+				Name="common"

+				Filter="">

+				<File

+					RelativePath="..\..\common\android_usb_common_defines.h">

+				</File>

+			</Filter>

+		</Filter>

+		<Filter

+			Name="Resource Files"

+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"

+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">

+			<File

+				RelativePath=".\LoopbackDevice.rgs">

+			</File>

+			<File

+				RelativePath=".\DeviceEmulator.rc">

+			</File>

+			<File

+				RelativePath=".\DeviceEmulator.rgs">

+			</File>

+		</Filter>

+		<File

+			RelativePath=".\makefile">

+		</File>

+		<File

+			RelativePath=".\RunDeviceLoopbackSample.wsf">

+		</File>

+		<File

+			RelativePath=".\DeviceEmulator.def">

+		</File>

+		<File

+			RelativePath=".\sources">

+		</File>

+	</Files>

+	<Globals>

+	</Globals>

+</VisualStudioProject>

diff --git a/host/windows/usb/test/device_emulator/makefile b/host/windows/usb/test/device_emulator/makefile
new file mode 100644
index 0000000..66f1c8e
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/makefile
@@ -0,0 +1,8 @@
+#

+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source

+# file to this component.  This file merely indirects to the real make file

+# that is shared by all the driver components of the Windows NT DDK

+#

+

+!INCLUDE $(NTMAKEENV)\makefile.def

+

diff --git a/host/windows/usb/test/device_emulator/resource.h b/host/windows/usb/test/device_emulator/resource.h
new file mode 100644
index 0000000..6e5e435
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/resource.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** \file

+  This file defines resources used by Emulator.rc

+  This project has been created from DDK's SoftUSBLoopback sample project

+  that is located at $(DDK_PATH)\src\Test\DSF\USB\SoftUSBLoopback

+*/

+

+#define IDS_PROJNAME                    100

+#define IDR_DEVICEEMULATOR              101

+#define IDR_LOOPBACKDEVICE              102

+

+// Next default values for new objects

+// 

+#ifdef APSTUDIO_INVOKED

+#ifndef APSTUDIO_READONLY_SYMBOLS

+#define _APS_NEXT_RESOURCE_VALUE        201

+#define _APS_NEXT_COMMAND_VALUE         32768

+#define _APS_NEXT_CONTROL_VALUE         201

+#define _APS_NEXT_SYMED_VALUE           103

+#endif

+#endif

+

diff --git a/host/windows/usb/test/device_emulator/sources b/host/windows/usb/test/device_emulator/sources
new file mode 100644
index 0000000..b65a1d8
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/sources
@@ -0,0 +1,56 @@
+TARGETNAME= DeviceEmulator

+TARGETTYPE=DYNLINK

+

+DLLENTRY=_DllMainCRTStartup

+

+DLLDEF=DeviceEmulator.def

+

+USE_NATIVE_EH=ASYNC

+

+MUI = 0

+MUI_COMMENT=TEST_TOOL, Device Simulation Framework

+

+PRECOMPILED_CXX = 1

+

+MSC_WARNING_LEVEL=/W4 /WX

+

+USE_ATL = 1

+ATL_VER = 70

+

+USE_MSVCRT = 1

+USE_OBJECT_ROOT=1

+

+!IF "$(DDKBUILDENV)"=="chk"
+TARGETPATH=..\..\build\Debug
+!ELSE
+TARGETPATH=..\..\build\Release
+!ENDIF
+

+

+C_DEFINES = $(C_DEFINES) -DDSF_USER_MODE -DUNICODE

+

+PRECOMPILED_CXX=1

+

+TARGETLIBS= \

+           $(SDK_LIB_PATH)\kernel32.lib \

+           $(SDK_LIB_PATH)\user32.lib \

+           $(SDK_LIB_PATH)\advapi32.lib \

+           $(SDK_LIB_PATH)\ole32.lib \

+           $(SDK_LIB_PATH)\oleaut32.lib \

+           $(SDK_LIB_PATH)\uuid.lib \

+           $(SDK_LIB_PATH)\shlwapi.lib \

+           $(DDK_LIB_PATH)\SoftUSBIf.lib \

+

+

+INCLUDES=\

+    ..\..\api; \

+    ..\..\common; \

+    $(DDK_LIB_DEST)\$(TARGET_DIRECTORY); \

+    $(DDK_INC_PATH); \

+    

+SOURCES= \

+    DeviceEmulator.idl \

+    LoopbackDevice.cpp \

+    DeviceEmulator.cpp \

+    DeviceEmulator.rc \

+

diff --git a/host/windows/usb/test/device_emulator/stdafx.cpp b/host/windows/usb/test/device_emulator/stdafx.cpp
new file mode 100644
index 0000000..5e452ed
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/stdafx.cpp
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"

+

diff --git a/host/windows/usb/test/device_emulator/stdafx.h b/host/windows/usb/test/device_emulator/stdafx.h
new file mode 100644
index 0000000..8651cd0
--- /dev/null
+++ b/host/windows/usb/test/device_emulator/stdafx.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once

+

+#ifndef STRICT

+#define STRICT

+#endif

+

+// Modify the following defines if you have to target a platform prior to the ones specified below.

+// Refer to MSDN for the latest info on corresponding values for different platforms.

+#ifndef WINVER              // Allow use of features specific to Windows 95 and Windows NT 4 or later.

+#define WINVER 0x0500       // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.

+#endif

+

+#ifndef _WIN32_WINNT        // Allow use of features specific to Windows NT 4 or later.

+#define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target Windows 2000 or later.

+#endif                      

+

+#ifndef _WIN32_WINDOWS      // Allow use of features specific to Windows 98 or later.

+#define _WIN32_WINDOWS 0x0500 // Change this to the appropriate value to target Windows Me or later.

+#endif

+

+#ifndef _WIN32_IE           // Allow use of features specific to IE 4.0 or later.

+#define _WIN32_IE 0x0501    // Change this to the appropriate value to target IE 5.0 or later.

+#endif

+

+#define _ATL_APARTMENT_THREADED

+#define _ATL_NO_AUTOMATIC_NAMESPACE

+

+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS  // some CString constructors will be explicit

+

+// turns off ATL's hiding of some common and often safely ignored warning messages

+#define _ATL_ALL_WARNINGS

+

+

+#include "resource.h"

+#include <atlbase.h>

+#include <atlcom.h>

+

+using namespace ATL;

+

diff --git a/host/windows/usb/usb_windows.sln b/host/windows/usb/usb_windows.sln
new file mode 100644
index 0000000..7dfff9b
--- /dev/null
+++ b/host/windows/usb/usb_windows.sln
@@ -0,0 +1,53 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android_usb", "driver\android_usb.vcproj", "{D980BE56-A7AB-4E05-919B-677FB7716307}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdbWinApi", "api\AdbWinApi.vcproj", "{C0A471E9-6892-4270-96DE-DB5F8D526FB1}"
+	ProjectSection(ProjectDependencies) = postProject
+		{D980BE56-A7AB-4E05-919B-677FB7716307} = {D980BE56-A7AB-4E05-919B-677FB7716307}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "device_emulator", "test\device_emulator\device_emulator.vcproj", "{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}"
+	ProjectSection(ProjectDependencies) = postProject
+		{D980BE56-A7AB-4E05-919B-677FB7716307} = {D980BE56-A7AB-4E05-919B-677FB7716307}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "android_usb_test", "test\android_usb_test\android_usb_test.vcproj", "{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}"
+	ProjectSection(ProjectDependencies) = postProject
+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59} = {EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}
+		{D980BE56-A7AB-4E05-919B-677FB7716307} = {D980BE56-A7AB-4E05-919B-677FB7716307}
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1} = {C0A471E9-6892-4270-96DE-DB5F8D526FB1}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{D980BE56-A7AB-4E05-919B-677FB7716307}.Debug.ActiveCfg = Debug|Win32
+		{D980BE56-A7AB-4E05-919B-677FB7716307}.Debug.Build.0 = Debug|Win32
+		{D980BE56-A7AB-4E05-919B-677FB7716307}.Release.ActiveCfg = Release|Win32
+		{D980BE56-A7AB-4E05-919B-677FB7716307}.Release.Build.0 = Release|Win32
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Debug.ActiveCfg = Debug|Win32
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Debug.Build.0 = Debug|Win32
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Release.ActiveCfg = Release|Win32
+		{C0A471E9-6892-4270-96DE-DB5F8D526FB1}.Release.Build.0 = Release|Win32
+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}.Debug.ActiveCfg = Debug|Win32
+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}.Debug.Build.0 = Debug|Win32
+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}.Release.ActiveCfg = Release|Win32
+		{EAB61831-9DDA-40AA-A5EF-2D9E8F9A5C59}.Release.Build.0 = Release|Win32
+		{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}.Debug.ActiveCfg = Debug|Win32
+		{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}.Debug.Build.0 = Debug|Win32
+		{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}.Release.ActiveCfg = Release|Win32
+		{9C6DBEED-9D2C-4FD8-B83D-88254035F78B}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionItems) = postSolution
+		usb_windows.c = usb_windows.c
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal