diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
| commit | 5c11852110eeb03dc5a69111354b383f98d15336 (patch) | |
| tree | 7b26fde6effb80c241f28fc3e620016e7f86418e /host | |
Initial Contribution
Diffstat (limited to 'host')
91 files changed, 14391 insertions, 0 deletions
diff --git a/host/Android.mk b/host/Android.mk new file mode 100644 index 000000000..5e318e121 --- /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 Binary files differnew file mode 100644 index 000000000..aa8e9568a --- /dev/null +++ b/host/windows/prebuilt/AdbWinApi.dll diff --git a/host/windows/prebuilt/adb.exe b/host/windows/prebuilt/adb.exe Binary files differnew file mode 100755 index 000000000..4cba503e1 --- /dev/null +++ b/host/windows/prebuilt/adb.exe diff --git a/host/windows/prebuilt/javawrap.exe b/host/windows/prebuilt/javawrap.exe Binary files differnew file mode 100755 index 000000000..d42ac2bd5 --- /dev/null +++ b/host/windows/prebuilt/javawrap.exe diff --git a/host/windows/prebuilt/usb/AdbWinApi.a b/host/windows/prebuilt/usb/AdbWinApi.a Binary files differnew file mode 100644 index 000000000..93ccd663b --- /dev/null +++ b/host/windows/prebuilt/usb/AdbWinApi.a diff --git a/host/windows/prebuilt/usb/AdbWinApi.def b/host/windows/prebuilt/usb/AdbWinApi.def new file mode 100644 index 000000000..18941481b --- /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 Binary files differnew file mode 100755 index 000000000..aa8e9568a --- /dev/null +++ b/host/windows/prebuilt/usb/AdbWinApi.dll diff --git a/host/windows/prebuilt/usb/Android.mk b/host/windows/prebuilt/usb/Android.mk new file mode 100644 index 000000000..180610109 --- /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 Binary files differnew file mode 100644 index 000000000..12d276816 --- /dev/null +++ b/host/windows/prebuilt/usb/driver/WdfCoInstaller01005.dll 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 000000000..69a94911b --- /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 Binary files differnew file mode 100644 index 000000000..ebd01b88d --- /dev/null +++ b/host/windows/prebuilt/usb/driver/androidusb.sys diff --git a/host/windows/usb/api/AdbWinApi.cpp b/host/windows/usb/api/AdbWinApi.cpp new file mode 100644 index 000000000..c7e530393 --- /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 000000000..d55786eed --- /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 000000000..013ea035e --- /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 000000000..f6f4fc047 --- /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 000000000..f9d15e5f6 --- /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 000000000..fd2b2f9e5 --- /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 000000000..50356c794 --- /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 000000000..98a32dcbe --- /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 000000000..cad480dcd --- /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 000000000..4f66b981b --- /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 000000000..9bc80b8bb --- /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 000000000..e1da7fe47 --- /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 000000000..90f698f1d --- /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 000000000..eda8ffafd --- /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 000000000..f2cd93852 --- /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 000000000..18709f045 --- /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 000000000..4f6c801c2 --- /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, + ¶m, 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 000000000..cead45415 --- /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 000000000..6e2808cc8 --- /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 000000000..f46b31b3a --- /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 000000000..02519c910 --- /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 000000000..d29f5e1e4 --- /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 000000000..ea4bc8f72 --- /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 000000000..7161b6749 --- /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 000000000..8c643b446 --- /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 000000000..088971c10 --- /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 000000000..87db2cdb9 --- /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 000000000..f47936f8a --- /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 000000000..abdeba782 --- /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 000000000..69a94911b --- /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 000000000..3b1941617 --- /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 000000000..1c5193e38 --- /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 000000000..5c21aa463 --- /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 000000000..9b3a59c08 --- /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 000000000..8b75eeeeb --- /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 000000000..0655aed93 --- /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 000000000..c40bb5074 --- /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 000000000..b20c1b7b3 --- /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 000000000..5c97e9c7f --- /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 000000000..4fe25d760 --- /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 000000000..d8be50f69 --- /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 000000000..8f68a80d0 --- /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 000000000..e5ce0a26b --- /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 000000000..1dbb92b7b --- /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 000000000..8d697cf1f --- /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 000000000..d6303bbee --- /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 000000000..5bf097beb --- /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 000000000..dc4634df2 --- /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 000000000..08d01654e --- /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 000000000..b0db9a813 --- /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 000000000..708dcb795 --- /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 000000000..68e2f9915 --- /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 000000000..aedd14a1d --- /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 000000000..3c0d3a5b8 --- /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 000000000..1955cef72 --- /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 000000000..97be2a6a6 --- /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 000000000..07fce7eaa --- /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 000000000..5928f73b8 --- /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 000000000..a5c390693 --- /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 000000000..1202096b7 --- /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 000000000..ff93586f7 --- /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=""..\..\build\$(OutDir)\i386""
+ 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=""..\..\build\$(OutDir)\i386""
+ 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 000000000..536a4ef11 --- /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 000000000..ab0e1651c --- /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 000000000..155a6f667 --- /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 000000000..2a7cd7cf9 --- /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 000000000..9b60eb225 --- /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 000000000..89fcd042b --- /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 000000000..a660ea560 --- /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 000000000..64ca8c6ba --- /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 000000000..0df3fbabc --- /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 000000000..422f654d1 --- /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 000000000..9bde9e0d3 --- /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, ¶ms, &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, ¶ms, &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 000000000..3fff7caf1 --- /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 000000000..34a66c31a --- /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 000000000..66f1c8e5c --- /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 000000000..6e5e435ac --- /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 000000000..b65a1d8f2 --- /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 000000000..5e452ed90 --- /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 000000000..8651cd045 --- /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 000000000..7dfff9b31 --- /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 |
