diff options
| author | J M Rossy <[email protected]> | 2015-07-29 15:40:09 -0700 |
|---|---|---|
| committer | J M Rossy <[email protected]> | 2015-07-29 16:34:40 -0700 |
| commit | 5d61a4a79a1e96dc5d9af1e5e712c84507307544 (patch) | |
| tree | 49ed270893578cd18758b74ffcca16dc7ab948d6 /input | |
| parent | 5d41613e26e147d2300c786bb2b34cb4b4067a25 (diff) | |
Samples update for public Windows 10 release
Fix #2 Enabling WPP Recorder in Sensors Samples causes errors
Fix #4 Add back fixed KMDOD sample
Add new BarcodeScanner sample in pos folder
Add new MagneticStripeReader sample in pos folder
Add new SynpaticsTouch sample in input folder
Add new Power Engine Plugin sample in pofx folder
Add new DeviceMft sample in avstream folder
Add new AvsCamera sample in root
Add new SimBatt sample in root
Add other pre-existing samples not yet released for Win10
Diffstat (limited to 'input')
50 files changed, 12507 insertions, 0 deletions
diff --git a/input/hiddigi/SynapticsTouch/SynapticsTouch.inx b/input/hiddigi/SynapticsTouch/SynapticsTouch.inx new file mode 100644 index 00000000..680ba592 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/SynapticsTouch.inx @@ -0,0 +1,199 @@ +; SynapticsTouch.INF +; Copyright (c) 2000,2011 Microsoft Corporation +; +; Sample code. Dealpoint ID #843729. +; + +[Version] +Signature = "$WINDOWS NT$" +Class = HIDClass +ClassGUID = {745A17A0-74D3-11D0-B6FE-00A0C90F57DA} +Provider = %Provider_Name% +DriverVer = 08/01/2011,1.0 +; Uncomment the following line when you have a valid catalog file. +; If you use bogus catalog file installation will fail. +CatalogFile=KmdfSamples.cat + +[DestinationDirs] +DefaultDestDir = 12 + +[SourceDisksNames] +1 = %Installation_Disk%,,,"" + +[SourceDisksFiles] +SynapticsTouch.sys = 1,, + +[Manufacturer] +%Manufacturer_Name% = Standard,NTARM + +[Standard.NTARM] +%TchDriver_Device_Desc% = TchDriver_Device.NT, ACPI\OEM_TOUCH + +;***************************************** +; TchDriver client driver Install Section +;***************************************** + +[TchDriver_Device.NT] +CopyFiles = TchDriver_Device.NT.CopyFiles + +[TchDriver_Device.NT.CopyFiles] +SynapticsTouch.sys + +[TchDriver_Device.NT.HW] +AddReg = FilterInst.NT.HW.AddReg +AddReg = CapButtons.NT.HW.AddReg +AddReg = PowerConfig.NT.HW.AddReg +AddReg = Configuration.NT.HW.AddReg +AddReg = Resolutions.NT.HW.AddReg +AddReg = DisplaySize.NT.HW.AddReg +AddReg = ButtonBacklights.NT.HW.AddReg +AddReg = LegacyTouchScaling.NT.HW.AddReg + +[FilterInst.NT.HW.AddReg] +HKR,,"UpperFilters", %REG_MULTI_SZ%, mshidkmdf +HKR,,"MultiportDevice", %REG_DWORD%, 0 + +[CapButtons.NT.HW.AddReg] +HKLM,"SYSTEM\TOUCH\BUTTONS", "Area", %REG_SZ%, "0,1280 768,1390" +HKLM,"SYSTEM\TOUCH\BUTTONS", "Count", %REG_DWORD%, 0x3 +HKLM,"SYSTEM\TOUCH\BUTTONS", "Vibrate", %REG_DWORD%, 0x1 +HKLM,"SYSTEM\TOUCH\BUTTONS", "Duration", %REG_DWORD%, 0x19 +HKLM,"SYSTEM\TOUCH\BUTTONS", "Intensity",%REG_DWORD%, 0x32 +HKLM,"SYSTEM\TOUCH\BUTTONS\0", "Area", %REG_SZ%, "0,1295 236,1390" +HKLM,"SYSTEM\TOUCH\BUTTONS\0", "Name", %REG_SZ% "Back" +HKLM,"SYSTEM\TOUCH\BUTTONS\0", "VKey", %REG_DWORD%, 0x1B +HKLM,"SYSTEM\TOUCH\BUTTONS\1", "Area", %REG_SZ%, "277,1295 492,1390" +HKLM,"SYSTEM\TOUCH\BUTTONS\1", "Name", %REG_SZ%, "Start" +HKLM,"SYSTEM\TOUCH\BUTTONS\1", "VKey", %REG_DWORD%, 0x71 +HKLM,"SYSTEM\TOUCH\BUTTONS\2", "Area", %REG_SZ%, "533,1295 768,1390" +HKLM,"SYSTEM\TOUCH\BUTTONS\2", "Name", %REG_SZ%, "Search" +HKLM,"SYSTEM\TOUCH\BUTTONS\2", "VKey", %REG_DWORD%, 0x72 + +[PowerConfig.NT.HW.AddReg] +HKR,,"EnhancedPowerManagementEnabled", %REG_DWORD%, 1 +HKR,,"EnhancedPowerManagementUseMonitor", %REG_DWORD%, 1 + +[Configuration.NT.HW.AddReg] +HKR,%Configuration%, "PepRemovesVoltageInD3", %REG_DWORD%, 0x0 +HKR,%Configuration%, "SleepMode", %REG_DWORD%, 0x0 +HKR,%Configuration%, "NoSleep", %REG_DWORD%, 0x1 +HKR,%Configuration%, "ReportRate", %REG_DWORD%, 0x0 +HKR,%Configuration%, "Configured", %REG_DWORD%, 0x1 +HKR,%Configuration%, "InterruptEnable", %REG_DWORD%, 0xf +HKR,%Configuration%, "DozeInterval", %REG_DWORD%, 0x3 +HKR,%Configuration%, "DozeThreshold", %REG_DWORD%, 0x1e +HKR,%Configuration%, "DozeHoldoff", %REG_DWORD%, 0x5 +HKR,%Configuration%, "ReportingMode", %REG_DWORD%, 0x1 +HKR,%Configuration%, "AbsPosFilt", %REG_DWORD%, 0x1 +HKR,%Configuration%, "RelPosFilt", %REG_DWORD%, 0x0 +HKR,%Configuration%, "RelBallistics", %REG_DWORD%, 0x0 +HKR,%Configuration%, "Dribble", %REG_DWORD%, 0x0 +HKR,%Configuration%, "PalmDetectThreshold", %REG_DWORD%, 0xb +HKR,%Configuration%, "MotionSensitivity", %REG_DWORD%, 0x0 +HKR,%Configuration%, "ManTrackEn", %REG_DWORD%, 0x0 +HKR,%Configuration%, "ManTrackedFinger", %REG_DWORD%, 0x0 +HKR,%Configuration%, "DeltaXPosThreshold", %REG_DWORD%, 0x0 +HKR,%Configuration%, "DeltaYPosThreshold", %REG_DWORD%, 0x0 +HKR,%Configuration%, "Velocity", %REG_DWORD%, 0x0 +HKR,%Configuration%, "Acceleration", %REG_DWORD%, 0x0 +HKR,%Configuration%, "SensorMaxXPos", %REG_DWORD%, 0x330 +HKR,%Configuration%, "SensorMaxYPos", %REG_DWORD%, 0x572 +HKR,%Configuration%, "ZTouchThreshold", %REG_DWORD%, 0x1e +HKR,%Configuration%, "ZHysteresis", %REG_DWORD%, 0x5 +HKR,%Configuration%, "SmallZThreshold", %REG_DWORD%, 0x28 +HKR,%Configuration%, "SmallZScaleFactor", %REG_DWORD%, 0x28f5 +HKR,%Configuration%, "LargeZScaleFactor", %REG_DWORD%, 0x051e +HKR,%Configuration%, "AlgorithmSelection", %REG_DWORD%, 0x1 +HKR,%Configuration%, "WxScaleFactor", %REG_DWORD%, 0x30 +HKR,%Configuration%, "WxOffset", %REG_DWORD%, 0x0 +HKR,%Configuration%, "WyScaleFactor", %REG_DWORD%, 0x30 +HKR,%Configuration%, "WyOffset", %REG_DWORD%, 0x0 +HKR,%Configuration%, "XPitch", %REG_DWORD%, 0x4800 +HKR,%Configuration%, "YPitch", %REG_DWORD%, 0x4800 +HKR,%Configuration%, "FingerWidthX", %REG_DWORD%, 0xea4f +HKR,%Configuration%, "FingerWidthY", %REG_DWORD%, 0xdf6c +HKR,%Configuration%, "ReportMeasuredSize", %REG_DWORD%, 0x0 +HKR,%Configuration%, "SegmentationSensitivity", %REG_DWORD%, 0x70 +HKR,%Configuration%, "XClipLo", %REG_DWORD%, 0x0 +HKR,%Configuration%, "XClipHi", %REG_DWORD%, 0x0 +HKR,%Configuration%, "YClipLo", %REG_DWORD%, 0x0 +HKR,%Configuration%, "YClipHi", %REG_DWORD%, 0x0 +HKR,%Configuration%, "MinFingerSeparation", %REG_DWORD%, 0xa +HKR,%Configuration%, "MaxFingerMovement", %REG_DWORD%, 0x4 + +[Resolutions.NT.HW.AddReg] +HKLM,%ScreenProps%,"TouchSwapAxes", %REG_DWORD%, 0x0 +HKLM,%ScreenProps%,"TouchInvertXAxis", %REG_DWORD%, 0x0 +HKLM,%ScreenProps%,"TouchInvertYAxis", %REG_DWORD%, 0x1 +HKLM,%ScreenProps%,"TouchPhysicalWidth", %REG_DWORD%, 0x330 +HKLM,%ScreenProps%,"TouchPhysicalHeight", %REG_DWORD%, 0x572 +HKLM,%ScreenProps%,"TouchPhysicalButtonHeight", %REG_DWORD%, 0x6E +HKLM,%ScreenProps%,"TouchPillarBoxWidthLeft", %REG_DWORD%, 0x8 +HKLM,%ScreenProps%,"TouchPillarBoxWidthRight", %REG_DWORD%, 0x8 +HKLM,%ScreenProps%,"TouchLetterBoxHeightTop", %REG_DWORD%, 0x4 +HKLM,%ScreenProps%,"TouchLetterBoxHeightBottom", %REG_DWORD%, 0x0 +HKLM,%ScreenProps%,"DisplayPhysicalWidth", %REG_DWORD%, 0x320 +HKLM,%ScreenProps%,"DisplayPhysicalHeight", %REG_DWORD%, 0x500 +HKLM,%ScreenProps%,"DisplayPillarBoxWidthLeft", %REG_DWORD%, 0x10 +HKLM,%ScreenProps%,"DisplayPillarBoxWidthRight", %REG_DWORD%, 0x10 +HKLM,%ScreenProps%,"DisplayLetterBoxHeightTop", %REG_DWORD%, 0x0 +HKLM,%ScreenProps%,"DisplayLetterBoxHeightBottom", %REG_DWORD%, 0x0 +HKLM,%ScreenProps%,"DisplayViewableWidth", %REG_DWORD%, 0x1e0 +HKLM,%ScreenProps%,"DisplayViewableHeight", %REG_DWORD%, 0x320 + +[DisplaySize.NT.HW.AddReg] +; The following values will be used to convert mm to display pixels. +; These are the dimensions of the Lumia 920, please remove this line +; when you've updated the dimensions to match your windows phone. +HKLM,%DisplaySize%,"DisplayHeight10um", %REG_DWORD%, 0x25E4 ; 97 mm +HKLM,%DisplaySize%,"DisplayWidth10um", %REG_DWORD%, 0x1702 ; 58.9 mm + +[ButtonBacklights.NT.HW.AddReg] +HKLM,"SYSTEM\TOUCH\BUTTONS\BACKLIGHT", "LedCount", %REG_DWORD%, 0x3 +HKLM,"SYSTEM\TOUCH\BUTTONS\BACKLIGHT", "LedIndexList", %REG_MULTI_SZ%, "0","1","2" +HKLM,"SYSTEM\TOUCH\BUTTONS\BACKLIGHT", "InactivityTimeout", %REG_DWORD%, 0 ; No timeout (msec) + +[LegacyTouchScaling.NT.HW.AddReg] +; This implies that the correct physical/logical min/max/unit/exp +; values for X/Y in the HID descriptor are being used -- don't just +; report pixels +HKR,,"LegacyTouchScaling", %REG_DWORD%, 0x0 + +;-------------- Service installation +[TchDriver_Device.NT.Services] +AddService = SynapticsTouch, %SPSVCINST_ASSOCSERVICE%, TchDriver_Service_Inst + +; ------------- TchDriver driver install section +[TchDriver_Service_Inst] +DisplayName = %TchDriver_Service_Desc% +ServiceType = %SERVICE_KERNEL_DRIVER% +StartType = %SERVICE_DEMAND_START% +ErrorControl = %SERVICE_ERROR_NORMAL% +ServiceBinary = %12%\SynapticsTouch.sys +LoadOrderGroup = Base + +; ------------- Strings section +[Strings] +Provider_Name = "TODO-Set-Provider" +Manufacturer_Name = "Synaptics" +Installation_Disk = "Touch Driver Installation Disk" +TchDriver_Device_Desc = "Touch Driver" +TchDriver_Service_Desc = "Synaptics Touch Driver Service" + +; ------------- non-localizable strings +Configuration = "Settings" +ScreenProps = "SYSTEM\TOUCH\SCREENPROPERTIES" +DisplaySize = "SYSTEM\TOUCH\DISPLAYPROPERTIES" +SPSVCINST_ASSOCSERVICE = 0x00000002 +SERVICE_KERNEL_DRIVER = 1 +SERVICE_BOOT_START = 0 +SERVICE_SYSTEM_START = 1 +SERVICE_DEMAND_START = 3 +SERVICE_ERROR_NORMAL = 1 +SERVICE_ERROR_IGNORE = 0 +SERVICE_ERROR_CRITICAL = 3 +REG_EXPAND_SZ = 0x00020000 +REG_MULTI_SZ = 0x00010000 +REG_DWORD = 0x00010001 +REG_SZ = 0x00000000 + diff --git a/input/hiddigi/SynapticsTouch/SynapticsTouch.sln b/input/hiddigi/SynapticsTouch/SynapticsTouch.sln new file mode 100644 index 00000000..d0bb5610 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/SynapticsTouch.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SynapticsTouch", "SynapticsTouch.vcxproj", "{B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}.Debug|Win32.ActiveCfg = Debug|Win32 + {B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}.Debug|Win32.Build.0 = Debug|Win32 + {B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}.Release|Win32.ActiveCfg = Release|Win32 + {B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}.Release|Win32.Build.0 = Release|Win32 + {B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}.Debug|x64.ActiveCfg = Debug|x64 + {B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}.Debug|x64.Build.0 = Debug|x64 + {B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}.Release|x64.ActiveCfg = Release|x64 + {B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/input/hiddigi/SynapticsTouch/SynapticsTouch.vcxproj b/input/hiddigi/SynapticsTouch/SynapticsTouch.vcxproj new file mode 100644 index 00000000..924a97e2 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/SynapticsTouch.vcxproj @@ -0,0 +1,200 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B07A4DCF-0F5D-4F7A-9C90-C972527A69CD}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{6FA87448-3C43-47E0-8863-483C7DA26875}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems"> + <ClCompile Include="device.c; driver.c; hid.c; idle.c; init.c; power.c; queue.c; report.c; resolutions.c; registry.c; spb.c"> + <WppEnabled>true</WppEnabled> + <WppKernelMode>true</WppKernelMode> + <WppTraceFunction>Trace(LEVEL,FLAGS,MSG,...)</WppTraceFunction> + <WppScanConfigurationData>trace.h</WppScanConfigurationData> + </ClCompile> + <Inf Include=".\SynapticsTouch.inx"> + <Architecture>$(InfArch)</Architecture> + <SpecifyArchitecture>true</SpecifyArchitecture> + <CopyOutput>.\$(IntDir)\SynapticsTouch.inf</CopyOutput> + </Inf> + </ItemGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>SynapticsTouch</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>SynapticsTouch</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>SynapticsTouch</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>SynapticsTouch</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\HidClass.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\HidClass.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\HidClass.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);DRIVER;_WIN32_WINNT=0x602;_WINNT_;_SAMPLE_DESCRIPTOR_</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);.;$(DDK_INC_PATH);$(DDK_INC_PATH)\wdm\</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\HidClass.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/input/hiddigi/SynapticsTouch/SynapticsTouch.vcxproj.Filters b/input/hiddigi/SynapticsTouch/SynapticsTouch.vcxproj.Filters new file mode 100644 index 00000000..fa3943ae --- /dev/null +++ b/input/hiddigi/SynapticsTouch/SynapticsTouch.vcxproj.Filters @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{FFD83EEB-ECDA-42ED-9B34-C8F74E64369E}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{1DCE09F2-2C5B-42B6-9AB0-8995F5C04B01}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{99D0F0CC-6C33-4FEB-969F-839D0D2D8B45}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{6CA5C1EB-79DF-4295-B67B-20594E06BE0B}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="device.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="driver.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="hid.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="idle.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="init.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="power.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="queue.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="registry.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="report.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="resolutions.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="spb.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <Inf Include=".\SynapticsTouch.inx"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/input/hiddigi/SynapticsTouch/controller.h b/input/hiddigi/SynapticsTouch/controller.h new file mode 100644 index 00000000..c3fdde1f --- /dev/null +++ b/input/hiddigi/SynapticsTouch/controller.h @@ -0,0 +1,203 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + controller.h + + Abstract: + + This module contains touch driver public definitions. + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + +#include <wdm.h> +#include <wdf.h> +#include <hidport.h> +#define RESHUB_USE_HELPER_ROUTINES +#include <reshub.h> +#include <kbdmou.h> +#include "trace.h" +#include "spb.h" + +#define TOUCH_POOL_TAG (ULONG)'cuoT' + +// +// Device descriptions +// + +#define OEM_MAX_TOUCHES 10 + +// +// Constants +// +#define MODE_MOUSE 0x00 +#define MODE_SINGLE_TOUCH 0x01 +#define MODE_MULTI_TOUCH 0x02 + +#define MAX_MOUSE_COORD 0x7FFF +#define MAX_TOUCH_COORD 0x0FFF + +#define MOUSE_LEFT_BUTTON_DOWN 0x0001 +#define MOUSE_LEFT_BUTTON_UP 0x0002 +#define MOUSE_MOVE_TOUCH_ABSOLUTE 0x8000 + +#define FINGER_STATUS 0x01 // finger down +#define RANGE_STATUS 0x02 // in range +#define RANGE_FINGER_STATUS 0x03 // finger down (range + finger) + +#define KEY_DOWN_START (1 << 0) +#define KEY_DOWN_SEARCH (1 << 1) +#define KEY_DOWN_BACK (1 << 2) + +#define REPORTID_MTOUCH 1 +#define REPORTID_MOUSE 3 +#define REPORTID_FEATURE 7 +#define REPORTID_MAX_COUNT 8 +#define REPORTID_CAPKEY 9 + +// +// Type defintions +// + +#pragma warning(push) +#pragma warning(disable:4201) // (nameless struct/union) +#include <pshpack1.h> + +typedef struct _HID_TOUCH_REPORT +{ + union + { + struct + { + UCHAR bStatus; + UCHAR ContactId; + USHORT wXData; + USHORT wYData; + UCHAR bStatus2; + UCHAR ContactId2; + USHORT wXData2; + USHORT wYData2; + UCHAR ActualCount; + } InputReport; + UCHAR RawInput[13]; + }; +} HID_TOUCH_REPORT, *PHID_TOUCH_REPORT; + +typedef struct _HID_MOUSE_REPORT { + union + { + struct + { + UCHAR bButtons; + USHORT wXData; + USHORT wYData; + USHORT wReserved; + }InputReport; + UCHAR RawInput[7]; + }; +} HID_MOUSE_REPORT, *PHID_MOUSE_REPORT; + +typedef struct _HID_KEY_REPORT { + union + { + struct + { + UCHAR bKeys; + UCHAR bReserved; + USHORT wReserved; + }InputReport; + UCHAR RawInput[4]; + }; +} HID_KEY_REPORT, *PHID_KEY_REPORT; + + +typedef struct _HID_FEATURE_REPORT +{ + UCHAR ReportID; + UCHAR InputMode; + UCHAR DeviceIndex; +} HID_FEATURE_REPORT, *PHID_FEATURE_REPORT; + +typedef struct _HID_MAX_COUNT_REPORT +{ + UCHAR ReportID; + UCHAR MaxCount; +}HID_MAX_COUNT_REPORT, *PHID_MAX_COUNT_REPORT; + +typedef struct _HID_INPUT_REPORT +{ + UCHAR ReportID; + union + { + HID_TOUCH_REPORT TouchReport; + HID_MOUSE_REPORT MouseReport; + HID_KEY_REPORT KeyReport; + }; +#ifdef _TIMESTAMP_ + LARGE_INTEGER TimeStamp; +#endif +} HID_INPUT_REPORT, *PHID_INPUT_REPORT; + +#include <poppack.h> +#pragma warning(pop) + +NTSTATUS +TchAllocateContext( + OUT VOID **ControllerContext, + IN WDFDEVICE FxDevice + ); + +NTSTATUS +TchFreeContext( + IN VOID *ControllerContext + ); + +NTSTATUS +TchStartDevice( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext + ); + +NTSTATUS +TchStopDevice( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext + ); + +NTSTATUS +TchStandbyDevice( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext + ); + +NTSTATUS +TchWakeDevice( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext + ); + +NTSTATUS +TchRegistryGetControllerSettings( + IN VOID *ControllerContext, + IN WDFDEVICE FxDevice + ); + +NTSTATUS +TchServiceInterrupts( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext, + IN PHID_INPUT_REPORT HidReport, + IN UCHAR InputMode, + OUT BOOLEAN *ServicingComplete + ); + diff --git a/input/hiddigi/SynapticsTouch/device.c b/input/hiddigi/SynapticsTouch/device.c new file mode 100644 index 00000000..dad83df9 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/device.c @@ -0,0 +1,480 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + device.c + + Abstract: + + Code for handling WDF device-specific requests + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "internal.h" +#include "controller.h" +#include "device.h" +#include "spb.h" +#include "idle.h" +#include "device.tmh" + +#ifdef ALLOC_PRAGMA + #pragma alloc_text(PAGE, OnD0Exit) +#endif + +BOOLEAN +OnInterruptIsr( + IN WDFINTERRUPT Interrupt, + IN ULONG MessageID + ) +/*++ + + Routine Description: + + This routine responds to interrupts generated by the + controller. If one is recognized, it queues a DPC for + processing. + + This is a PASSIVE_LEVEL ISR. ACPI should specify + level-triggered interrupts when using Synaptics 3202. + + Arguments: + + Interrupt - a handle to a framework interrupt object + MessageID - message number identifying the device's + hardware interrupt message (if using MSI) + + Return Value: + + TRUE if interrupt recognized. + +--*/ +{ + PDEVICE_EXTENSION devContext; + NTSTATUS status; + WDFREQUEST request; + BOOLEAN servicingComplete; + HID_INPUT_REPORT hidReportFromDriver; + PHID_INPUT_REPORT hidReportRequestBuffer; + size_t hidReportRequestBufferLength; + + UNREFERENCED_PARAMETER(MessageID); + + status = STATUS_SUCCESS; + servicingComplete = FALSE; + devContext = GetDeviceContext(WdfInterruptGetDevice(Interrupt)); + request = NULL; + + + // + // If we're in diagnostic mode, let the diagnostic application handle + // interrupt servicing + // + if (devContext->DiagnosticMode != FALSE) + { + goto exit; + } + + + // + // Service the device interrupt + // + while (servicingComplete == FALSE) + { + // + // Service touch interrupts. Success indicates we have a report + // to complete to Hid. ServicingComplete indicates another report + // is required to continue servicing this interrupt. + // + if (!NT_SUCCESS(TchServiceInterrupts( + devContext->TouchContext, + &devContext->I2CContext, + &hidReportFromDriver, + devContext->InputMode, + &servicingComplete))) + { + // + // hidReportFromDriver was not filled + // + continue; + } + + // + // Complete a HIDClass request if one is available + // + status = WdfIoQueueRetrieveNextRequest( + devContext->PingPongQueue, + &request); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_REPORTING, + "No request pending from HIDClass, ignoring report - %!STATUS!", + status); + + continue; + } + + // + // Validate an output buffer was provided + // + status = WdfRequestRetrieveOutputBuffer( + request, + sizeof(HID_INPUT_REPORT), + &hidReportRequestBuffer, + &hidReportRequestBufferLength); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_VERBOSE, + TRACE_FLAG_SAMPLES, + "Error retrieving HID read request output buffer - %!STATUS!", + status); + } + else + { + // + // Validate the size of the output buffer + // + if (hidReportRequestBufferLength < sizeof(HID_INPUT_REPORT)) + { + status = STATUS_BUFFER_TOO_SMALL; + + Trace( + TRACE_LEVEL_VERBOSE, + TRACE_FLAG_SAMPLES, + "Error HID read request buffer is too small (%I64x bytes) - %!STATUS!", + hidReportRequestBufferLength, + status); + } + else + { + RtlCopyMemory( + hidReportRequestBuffer, + &hidReportFromDriver, + sizeof(HID_INPUT_REPORT)); + + WdfRequestSetInformation(request, sizeof(HID_INPUT_REPORT)); + } + } + + WdfRequestComplete(request, status); + } + +exit: + return TRUE; +} + +NTSTATUS +OnD0Entry( + IN WDFDEVICE Device, + IN WDF_POWER_DEVICE_STATE PreviousState + ) +/*++ + +Routine Description: + + This routine will power on the hardware + +Arguments: + + Device - WDF device to power on + PreviousState - Prior power state + +Return Value: + + NTSTATUS indicating success or failure + +*/ +{ + NTSTATUS status; + PDEVICE_EXTENSION devContext; + + devContext = GetDeviceContext(Device); + + UNREFERENCED_PARAMETER(PreviousState); + + status = TchWakeDevice(devContext->TouchContext, &devContext->I2CContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_POWER, + "Error setting device to D0 - %!STATUS!", + status); + } + + // + // N.B. This RMI chip's IRQ is level-triggered, but cannot be enabled in + // ACPI until passive-level interrupt handling is added to the driver. + // Service chip in case we missed an edge during D3 or boot-up. + // + devContext->ServiceInterruptsAfterD0Entry = TRUE; + + // + // Complete any pending Idle IRPs + // + TchCompleteIdleIrp(devContext); + + return status; +} + +NTSTATUS +OnD0Exit( + IN WDFDEVICE Device, + IN WDF_POWER_DEVICE_STATE TargetState + ) +/*++ + +Routine Description: + + This routine will power down the hardware + +Arguments: + + Device - WDF device to power off + + PreviousState - Prior power state + +Return Value: + + NTSTATUS indicating success or failure + +*/ +{ + NTSTATUS status; + PDEVICE_EXTENSION devContext; + + PAGED_CODE(); + + devContext = GetDeviceContext(Device); + + UNREFERENCED_PARAMETER(TargetState); + + status = TchStandbyDevice(devContext->TouchContext, &devContext->I2CContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_POWER, + "Error exiting D0 - %!STATUS!", + status); + } + + return status; +} + +NTSTATUS +OnPrepareHardware( + IN WDFDEVICE FxDevice, + IN WDFCMRESLIST FxResourcesRaw, + IN WDFCMRESLIST FxResourcesTranslated + ) +/*++ + + Routine Description: + + This routine is called by the PnP manager and supplies thie device instance + with it's SPB resources (CmResourceTypeConnection) needed to find the I2C + driver. + + Arguments: + + FxDevice - a handle to the framework device object + FxResourcesRaw - list of translated hardware resources that + the PnP manager has assigned to the device + FxResourcesTranslated - list of raw hardware resources that + the PnP manager has assigned to the device + + Return Value: + + NTSTATUS indicating sucess or failure + +--*/ +{ + NTSTATUS status; + PCM_PARTIAL_RESOURCE_DESCRIPTOR res; + PDEVICE_EXTENSION devContext; + ULONG resourceCount; + ULONG i; + + UNREFERENCED_PARAMETER(FxResourcesRaw); + + status = STATUS_INSUFFICIENT_RESOURCES; + devContext = GetDeviceContext(FxDevice); + + // + // Get the resouce hub connection ID for our I2C driver + // + resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); + + for (i=0; i < resourceCount; i++) + { + res = WdfCmResourceListGetDescriptor(FxResourcesTranslated, i); + + if (res->Type == CmResourceTypeConnection && + res->u.Connection.Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && + res->u.Connection.Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) + { + devContext->I2CContext.I2cResHubId.LowPart = + res->u.Connection.IdLowPart; + devContext->I2CContext.I2cResHubId.HighPart = + res->u.Connection.IdHighPart; + + status = STATUS_SUCCESS; + } + } + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error finding CmResourceTypeConnection resource - %!STATUS!", + status); + + goto exit; + } + + // + // Initialize Spb so the driver can issue reads/writes + // + status = SpbTargetInitialize(FxDevice, &devContext->I2CContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error in Spb initialization - %!STATUS!", + status); + + goto exit; + } + + // + // Prepare the hardware for touch scanning + // + status = TchAllocateContext(&devContext->TouchContext, FxDevice); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error allocating touch context - %!STATUS!", + status); + + goto exit; + } + + // + // Fetch controller settings from registry + // + status = TchRegistryGetControllerSettings( + devContext->TouchContext, + devContext->FxDevice); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error retrieving controller settings from registry - %!STATUS!", + status); + + goto exit; + } + + // + // Start the controller + // + status = TchStartDevice(devContext->TouchContext, &devContext->I2CContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error starting touch device - %!STATUS!", + status); + + goto exit; + } + +exit: + + return status; +} + +NTSTATUS +OnReleaseHardware( + IN WDFDEVICE FxDevice, + IN WDFCMRESLIST FxResourcesTranslated + ) +/*++ + + Routine Description: + + This routine cleans up any resources provided. + + Arguments: + + FxDevice - a handle to the framework device object + FxResourcesRaw - list of translated hardware resources that + the PnP manager has assigned to the device + FxResourcesTranslated - list of raw hardware resources that + the PnP manager has assigned to the device + + Return Value: + + NTSTATUS indicating sucesss or failure + +--*/ +{ + NTSTATUS status; + PDEVICE_EXTENSION devContext; + + UNREFERENCED_PARAMETER(FxResourcesTranslated); + + devContext = GetDeviceContext(FxDevice); + + status = TchStopDevice(devContext->TouchContext, &devContext->I2CContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "Error stopping device - %!STATUS!", + status); + } + + status = TchFreeContext(devContext->TouchContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "Error freeing touch context - %!STATUS!", + status); + } + + SpbTargetDeinitialize(FxDevice, &GetDeviceContext(FxDevice)->I2CContext); + + return status; +} + diff --git a/input/hiddigi/SynapticsTouch/device.h b/input/hiddigi/SynapticsTouch/device.h new file mode 100644 index 00000000..c21a409a --- /dev/null +++ b/input/hiddigi/SynapticsTouch/device.h @@ -0,0 +1,32 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + device.h + + Abstract: + + Declarations of WDF device specific entry points + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + + +EVT_WDF_DEVICE_D0_ENTRY OnD0Entry; + +EVT_WDF_DEVICE_D0_EXIT OnD0Exit; + +EVT_WDF_INTERRUPT_ISR OnInterruptIsr; + +EVT_WDF_DEVICE_PREPARE_HARDWARE OnPrepareHardware; + +EVT_WDF_DEVICE_RELEASE_HARDWARE OnReleaseHardware;
\ No newline at end of file diff --git a/input/hiddigi/SynapticsTouch/driver.c b/input/hiddigi/SynapticsTouch/driver.c new file mode 100644 index 00000000..6812fcb3 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/driver.c @@ -0,0 +1,319 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + driver.c + + Abstract: + + Contains driver-specific WDF functions + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "internal.h" +#include "controller.h" +#include "driver.h" +#include "device.h" +#include "hid.h" +#include "queue.h" +#include "driver.tmh" + +#ifdef ALLOC_PRAGMA + #pragma alloc_text(PAGE, OnDeviceAdd) + #pragma alloc_text(PAGE, OnContextCleanup) +#endif + +NTSTATUS +DriverEntry ( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + + Installable driver initialization entry point. + This entry point is called directly by the I/O system. + +Arguments: + + DriverObject - pointer to the driver object + RegistryPath - pointer to a unicode string representing the path, + to driver-specific key in the registry. + +Return Value: + + STATUS_SUCCESS if successful, error code otherwise. + +--*/ +{ + WDF_OBJECT_ATTRIBUTES attributes; + WDF_DRIVER_CONFIG config; + NTSTATUS status; + + // + // Initialize tracing via WPP + // + WPP_INIT_TRACING(DriverObject, RegistryPath); + + // + // Create a framework driver object + // + WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd); + config.DriverPoolTag = TOUCH_POOL_TAG; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.EvtCleanupCallback = OnContextCleanup; + + status = WdfDriverCreate( + DriverObject, + RegistryPath, + &attributes, + &config, + WDF_NO_HANDLE + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error creating WDF driver object - %!STATUS!", + status); + + WPP_CLEANUP(DriverObject); + + goto exit; + } + +exit: + + return status; +} + +NTSTATUS +OnDeviceAdd( + IN WDFDRIVER Driver, + IN PWDFDEVICE_INIT DeviceInit + ) +/*++ + +Routine Description: + + OnDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager when a device is found. We create and + initialize a WDF device object to represent the new instance of + an touch device. Per-device objects are also instantiated. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + WDF_OBJECT_ATTRIBUTES attributes; + PDEVICE_EXTENSION devContext; + WDFDEVICE fxDevice; + WDF_INTERRUPT_CONFIG interruptConfig; + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_IO_QUEUE_CONFIG queueConfig; + NTSTATUS status; + + UNREFERENCED_PARAMETER(Driver); + PAGED_CODE(); + + // + // Relinquish power policy ownership because HIDCLASS acts a power + // policy owner for ther HID stack. + // + WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE); + + // + // This driver handles D0 Entry and Exit to power on and off the + // controller. It also handles prepare/release hardware so that it + // can acquire and free SPB resources needed to communicate with the + // touch controller. + // + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + + pnpPowerCallbacks.EvtDeviceD0Entry = OnD0Entry; + pnpPowerCallbacks.EvtDeviceD0Exit = OnD0Exit; + pnpPowerCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; + + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + // + // Create a framework device object. This call will in turn create + // a WDM device object, attach to the lower stack, and set the + // appropriate flags and attributes. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); + + status = WdfDeviceCreate(&DeviceInit, &attributes, &fxDevice); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "WdfDeviceCreate failed - %!STATUS!", + status); + + goto exit; + } + + devContext = GetDeviceContext(fxDevice); + devContext->FxDevice = fxDevice; + devContext->InputMode = MODE_MULTI_TOUCH; + + // + // Create a parallel dispatch queue to handle requests from HID Class + // + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( + &queueConfig, + WdfIoQueueDispatchParallel); + + queueConfig.EvtIoInternalDeviceControl = OnInternalDeviceControl; + queueConfig.PowerManaged = WdfFalse; + + status = WdfIoQueueCreate( + fxDevice, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &devContext->DefaultQueue); + + if (!NT_SUCCESS (status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error creating WDF default queue - %!STATUS!", + status); + + goto exit; + } + + // + // Register a manual I/O queue for Read Requests. This queue will be used + // for storing HID read requests until touch data is available to + // complete them. + // + WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); + + queueConfig.PowerManaged = WdfFalse; + + status = WdfIoQueueCreate( + fxDevice, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &devContext->PingPongQueue); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error creating WDF read request queue - %!STATUS!", + status); + + goto exit; + } + + // + // Register one last manual I/O queue for parking HIDClass's idle power + // requests. This queue stores idle requests until they're cancelled, + // and could be used to complete a wait/wake request. + // + + WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); + + queueConfig.PowerManaged = WdfFalse; + + status = WdfIoQueueCreate( + fxDevice, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &devContext->IdleQueue + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error creating WDF idle request queue - %!STATUS!", + status); + + goto exit; + } + + // + // Create an interrupt object for hardware notifications + // + WDF_INTERRUPT_CONFIG_INIT( + &interruptConfig, + OnInterruptIsr, + NULL); + interruptConfig.PassiveHandling = TRUE; + + status = WdfInterruptCreate( + fxDevice, + &interruptConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &devContext->InterruptObject); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error creating WDF interrupt object - %!STATUS!", + status); + + goto exit; + } + +exit: + + return status; +} + +VOID +OnContextCleanup( + IN WDFOBJECT Driver + ) +/*++ +Routine Description: + + Free resources allocated in DriverEntry that are not automatically + cleaned up framework. + +Arguments: + + Driver - handle to a WDF Driver object. + +Return Value: + + VOID. + +--*/ +{ + PAGED_CODE(); + + WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver)); +} +
\ No newline at end of file diff --git a/input/hiddigi/SynapticsTouch/driver.h b/input/hiddigi/SynapticsTouch/driver.h new file mode 100644 index 00000000..66036d93 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/driver.h @@ -0,0 +1,29 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + driver.h + + Abstract: + + Contains WDF driver-specific function declarations + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + + +DRIVER_INITIALIZE DriverEntry; + +EVT_WDF_DEVICE_CONTEXT_CLEANUP OnContextCleanup; + +EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd; + diff --git a/input/hiddigi/SynapticsTouch/hid.c b/input/hiddigi/SynapticsTouch/hid.c new file mode 100644 index 00000000..233b6e23 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/hid.c @@ -0,0 +1,769 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + hid.c + + Abstract: + + Code for handling HID related requests + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "internal.h" +#include "controller.h" +#include "hid.h" +#include "hid.tmh" + + +// +// HID Report Descriptor for a touch device +// + +#ifndef _SAMPLE_DESCRIPTOR_ +#error This HID descriptor only works for a touch screen with resolution = 768 x 1280 and dimensions = 2.32" x 3.82" +#endif + +const UCHAR gReportDescriptor[] = { + 0x05, 0x0d, // USAGE_PAGE (Digitizers) + 0x09, 0x04, // USAGE (Touch Screen) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch) + 0x09, 0x22, // USAGE (Finger) + 0xa1, 0x02, // COLLECTION (Logical) + 0x09, 0x42, // USAGE (Tip Switch) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x09, 0x32, // USAGE (In Range) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x06, // REPORT_COUNT (6) + 0x81, 0x03, // INPUT (Cnst,Ary,Abs) + 0x75, 0x08, // REPORT_SIZE (8) + 0x09, 0x51, // USAGE (Contact Identifier) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x05, 0x01, // USAGE_PAGE (Generic Desk.. + 0x26, 0x00, 0x03, // LOGICAL_MAXIMUM (768) NOTE: ADJUST LOGICAL MAXIMUM FOR X BASED ON TOUCH SCREEN RESOLUTION! + 0x75, 0x10, // REPORT_SIZE (16) + 0x55, 0x0e, // UNIT_EXPONENT (-2) + 0x65, 0x13, // UNIT (Inch,EngLinear) + 0x09, 0x30, // USAGE (X) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x46, 0xe8, 0x00, // PHYSICAL_MAXIMUM (232) NOTE: ADJUST PHYSICAL MAXIMUM FOR X BASED ON TOUCH SCREEN DIMENSION (100ths of an inch)! + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x46, 0x7e, 0x01, // PHYSICAL_MAXIMUM (382) NOTE: ADJUST PHYSICAL MAXIMUM FOR Y BASED ON TOUCH SCREEN DIMENSION (100ths of an inch)! + 0x26, 0x00, 0x05, // LOGICAL_MAXIMUM (1280) NOTE: ADJUST LOGICAL MAXIMUM FOR Y BASED ON TOUCH SCREEN RESOLUTION! + 0x09, 0x31, // USAGE (Y) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + 0xa1, 0x02, // COLLECTION (Logical) + 0x05, 0x0d, // USAGE_PAGE (Digitizers) + 0x09, 0x42, // USAGE (Tip Switch) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x09, 0x32, // USAGE (In Range) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x06, // REPORT_COUNT (6) + 0x81, 0x03, // INPUT (Cnst,Ary,Abs) + 0x75, 0x08, // REPORT_SIZE (8) + 0x09, 0x51, // USAGE (Contact Identifier) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x05, 0x01, // USAGE_PAGE (Generic Desk.. + 0x26, 0x00, 0x03, // LOGICAL_MAXIMUM (768) NOTE: ADJUST LOGICAL MAXIMUM FOR X BASED ON TOUCH SCREEN RESOLUTION! + 0x75, 0x10, // REPORT_SIZE (16) + 0x55, 0x0e, // UNIT_EXPONENT (-2) + 0x65, 0x13, // UNIT (Inch,EngLinear) + 0x09, 0x30, // USAGE (X) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x46, 0xe8, 0x00, // PHYSICAL_MAXIMUM (232) NOTE: ADJUST PHYSICAL MAXIMUM FOR X BASED ON TOUCH SCREEN DIMENSION (100ths of an inch)! + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x46, 0x7e, 0x01, // PHYSICAL_MAXIMUM (382) NOTE: ADJUST PHYSICAL MAXIMUM FOR Y BASED ON TOUCH SCREEN DIMENSION (100ths of an inch)! + 0x26, 0x00, 0x05, // LOGICAL_MAXIMUM (1280) NOTE: ADJUST LOGICAL MAXIMUM FOR Y BASED ON TOUCH SCREEN RESOLUTION! + 0x09, 0x31, // USAGE (Y) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + 0x05, 0x0d, // USAGE_PAGE (Digitizers) + 0x09, 0x54, // USAGE (Actual count) + 0x95, 0x01, // REPORT_COUNT (1) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x85, REPORTID_MAX_COUNT, // REPORT_ID (Feature) + 0x09, 0x55, // USAGE(Maximum Count) + 0x25, 0x02, // LOGICAL_MAXIMUM (2) + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + 0xc0, // END_COLLECTION + 0x09, 0x0E, // USAGE (Configuration) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, REPORTID_FEATURE, // REPORT_ID (Feature) + 0x09, 0x22, // USAGE (Finger) + 0xa1, 0x00, // COLLECTION (physical) + 0x09, 0x52, // USAGE (Input Mode) + 0x09, 0x53, // USAGE (Device Index + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x0a, // LOGICAL_MAXIMUM (10) + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) +#ifdef HID_MOUSE_PATH_SUPPORT + 0x09, 0x02, // USAGE (Mouse) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, REPORTID_MOUSE, // REPORT_ID (Mouse) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x02, // USAGE_MAXIMUM (Button 2) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x06, // REPORT_COUNT (6) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x75, 0x10, // REPORT_SIZE (16) + 0x95, 0x02, // REPORT_COUNT (2) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION +#endif + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0xEE, // USAGE (HID_USAGE_KEYBOARD_MOBILE) + 0xa1, 0x01, // COLLECTION (Application) + 0x85, REPORTID_CAPKEY, // REPORT_ID + 0x05, 0x07, // USAGE_PAGE (Key Codes) + 0x09, 0x3B, // USAGE(F2 Key) - Start/Home + 0x09, 0x3C, // USAGE(F3 Key) - Search + 0x09, 0x29, // USAGE(Esc Key) - Back + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x03, // REPORT_COUNT (3) + 0x81, 0x02, // INPUT (Data,Var,Abs) + 0x95, 0x1d, // REPORT_COUNT (29) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + 0xc0, // END_COLLECTION +}; +const ULONG gdwcbReportDescriptor = sizeof(gReportDescriptor); + +// +// HID Descriptor for a touch device +// +const HID_DESCRIPTOR gHidDescriptor = +{ + sizeof(HID_DESCRIPTOR), //bLength + HID_HID_DESCRIPTOR_TYPE, //bDescriptorType + HID_REVISION, //bcdHID + 0, //bCountry - not localized + 1, //bNumDescriptors + { //DescriptorList[0] + HID_REPORT_DESCRIPTOR_TYPE, //bReportType + sizeof(gReportDescriptor) //wReportLength + } +}; + +NTSTATUS +TchReadReport( + IN WDFDEVICE Device, + IN WDFREQUEST Request, + OUT BOOLEAN *Pending + ) +/*++ + +Routine Description: + + Handles read requests from HIDCLASS, by forwarding the request. + +Arguments: + + Device - Handle to WDF Device Object + + Request - Handle to request object + + Pending - flag to monitor if the request was sent down the stack + +Return Value: + + On success, the function returns STATUS_SUCCESS + On failure it passes the relevant error code to the caller. + +--*/ +{ + PDEVICE_EXTENSION devContext; + NTSTATUS status; + + devContext = GetDeviceContext(Device); + + status = WdfRequestForwardToIoQueue( + Request, + devContext->PingPongQueue); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Failed to forward HID request to I/O queue - %!STATUS!", + status); + + goto exit; + } + + if (NULL != Pending) + { + *Pending = TRUE; + } + + // + // Service any interrupt that may have asserted while the framework had + // interrupts disabled, or occurred before a read request was queued. + // + if (devContext->ServiceInterruptsAfterD0Entry == TRUE) + { + HID_INPUT_REPORT hidReport; + BOOLEAN servicingComplete = FALSE; + + while (servicingComplete == FALSE) + { + TchServiceInterrupts( + devContext->TouchContext, + &devContext->I2CContext, + &hidReport, + devContext->InputMode, + &servicingComplete); + } + + devContext->ServiceInterruptsAfterD0Entry = FALSE; + } + +exit: + + return status; +} + +NTSTATUS +TchGetString( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ) +/*++ + +Routine Description: + + Returns string requested by the HIDCLASS driver + +Arguments: + + Device - Handle to WDF Device Object + + Request - Handle to request object + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + PIRP irp; + PIO_STACK_LOCATION irpSp; + ULONG_PTR lenId; + NTSTATUS status; + PWSTR strId; + + UNREFERENCED_PARAMETER(Device); + + status = STATUS_SUCCESS; + + irp = WdfRequestWdmGetIrp(Request); + irpSp = IoGetCurrentIrpStackLocation(irp); + switch ((ULONG_PTR)irpSp->Parameters.DeviceIoControl.Type3InputBuffer & + 0xffff) + { + case HID_STRING_ID_IMANUFACTURER: + strId = gpwstrManufacturerID; + break; + + case HID_STRING_ID_IPRODUCT: + strId = gpwstrProductID; + break; + + case HID_STRING_ID_ISERIALNUMBER: + strId = gpwstrSerialNumber; + break; + + default: + strId = NULL; + break; + } + + lenId = strId ? (wcslen(strId)*sizeof(WCHAR) + sizeof(UNICODE_NULL)) : 0; + if (strId == NULL) + { + status = STATUS_INVALID_PARAMETER; + } + else if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < lenId) + { + status = STATUS_BUFFER_TOO_SMALL; + } + else + { + RtlCopyMemory(irp->UserBuffer, strId, lenId); + irp->IoStatus.Information = lenId; + } + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error getting device string - %!STATUS!", + status); + } + + return status; +} + +NTSTATUS +TchGetHidDescriptor( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ) +/*++ + +Routine Description: + + Finds the HID descriptor and copies it into the buffer provided by the + Request. + +Arguments: + + Device - Handle to WDF Device Object + + Request - Handle to request object + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + WDFMEMORY memory; + NTSTATUS status; + + UNREFERENCED_PARAMETER(Device); + + // + // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory + // will correctly retrieve buffer from Irp->UserBuffer. + // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer + // field irrespective of the ioctl buffer type. However, framework is very + // strict about type checking. You cannot get Irp->UserBuffer by using + // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER + // internal ioctl. + // + status = WdfRequestRetrieveOutputMemory(Request, &memory); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error getting HID descriptor request memory - %!STATUS!", + status); + goto exit; + } + + // + // Use hardcoded global HID Descriptor + // + status = WdfMemoryCopyFromBuffer( + memory, + 0, + (PUCHAR) &gHidDescriptor, + sizeof(gHidDescriptor)); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error copying HID descriptor to request memory - %!STATUS!", + status); + goto exit; + } + + // + // Report how many bytes were copied + // + WdfRequestSetInformation(Request, sizeof(gHidDescriptor)); + +exit: + + return status; +} + +NTSTATUS +TchGetReportDescriptor( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ) +/*++ + +Routine Description: + + Finds the report descriptor and copies it into the buffer provided by the + Request. + +Arguments: + + Device - Handle to WDF Device Object + + Request - Handle to request object + +Return Value: + + NT status code. + success - STATUS_SUCCESS + failure: + STATUS_INVALID_PARAMETER - An invalid parameter was detected. + +--*/ +{ + WDFMEMORY memory; + NTSTATUS status; + + UNREFERENCED_PARAMETER(Device); + + // + // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory + // will correctly retrieve buffer from Irp->UserBuffer. + // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer + // field irrespective of the ioctl buffer type. However, framework is very + // strict about type checking. You cannot get Irp->UserBuffer by using + // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER + // internal ioctl. + // + status = WdfRequestRetrieveOutputMemory(Request, &memory); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error getting HID report descriptor request memory - %!STATUS!", + status); + goto exit; + } + + // + // Use hardcoded Report descriptor + // + status = WdfMemoryCopyFromBuffer( + memory, + 0, + (PUCHAR) gReportDescriptor, + gdwcbReportDescriptor); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error copying HID report descriptor to request memory - %!STATUS!", + status); + goto exit; + } + + // + // Report how many bytes were copied + // + WdfRequestSetInformation(Request, gdwcbReportDescriptor); + +exit: + + return status; +} + +NTSTATUS +TchGetDeviceAttributes( + IN WDFREQUEST Request + ) +/*++ + +Routine Description: + + Fill in the given struct _HID_DEVICE_ATTRIBUTES + +Arguments: + + Request - Pointer to Request object. + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + PHID_DEVICE_ATTRIBUTES deviceAttributes; + NTSTATUS status; + + // + // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory + // will correctly retrieve buffer from Irp->UserBuffer. + // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer + // field irrespective of the ioctl buffer type. However, framework is very + // strict about type checking. You cannot get Irp->UserBuffer by using + // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER + // internal ioctl. + // + status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof (HID_DEVICE_ATTRIBUTES), + &deviceAttributes, + NULL); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error retrieving device attribute output buffer - %!STATUS!", + status); + goto exit; + } + + deviceAttributes->Size = sizeof (HID_DEVICE_ATTRIBUTES); + deviceAttributes->VendorID = gOEMVendorID; + deviceAttributes->ProductID = gOEMProductID; + deviceAttributes->VersionNumber = gOEMVersionID; + + // + // Report how many bytes were copied + // + WdfRequestSetInformation(Request, sizeof (HID_DEVICE_ATTRIBUTES)); + +exit: + + return status; +} + +NTSTATUS +TchSetFeatureReport( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ) +/*++ + +Routine Description: + + Emulates setting a HID Feature report + +Arguments: + + Device - Framework device object + Request - Framework request object + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + PDEVICE_EXTENSION devContext; + PHID_XFER_PACKET featurePacket; + WDF_REQUEST_PARAMETERS params; + NTSTATUS status; + + devContext = GetDeviceContext(Device); + status = STATUS_SUCCESS; + + // + // Validate Request Parameters + // + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + WdfRequestGetParameters(Request, ¶ms); + + if (params.Parameters.DeviceIoControl.InputBufferLength < + sizeof(HID_XFER_PACKET)) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + + featurePacket = + (PHID_XFER_PACKET) WdfRequestWdmGetIrp(Request)->UserBuffer; + + if (featurePacket == NULL) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + // + // Process Request + // + + switch (*(PUCHAR)featurePacket->reportBuffer) + { + case REPORTID_FEATURE: + { + PHID_FEATURE_REPORT inputModeReport = + (PHID_FEATURE_REPORT) featurePacket->reportBuffer; + + if (featurePacket->reportBufferLen < sizeof(HID_FEATURE_REPORT)) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + + if ((inputModeReport->InputMode == MODE_MOUSE) || + (inputModeReport->InputMode == MODE_MULTI_TOUCH)) + { + devContext->InputMode = inputModeReport->InputMode; + } + else + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + + break; + } + + default: + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + } + +exit: + + return status; +} + +NTSTATUS +TchGetFeatureReport( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ) +/*++ + +Routine Description: + + Emulates retrieval of a HID Feature report + +Arguments: + + Device - Framework device object + Request - Framework request object + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + PDEVICE_EXTENSION devContext; + PHID_XFER_PACKET featurePacket; + WDF_REQUEST_PARAMETERS params; + NTSTATUS status; + + devContext = GetDeviceContext(Device); + status = STATUS_SUCCESS; + + // + // Validate Request Parameters + // + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + WdfRequestGetParameters(Request, ¶ms); + + if (params.Parameters.DeviceIoControl.OutputBufferLength < + sizeof(HID_XFER_PACKET)) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + + featurePacket = + (PHID_XFER_PACKET) WdfRequestWdmGetIrp(Request)->UserBuffer; + + if (featurePacket == NULL) + { + status = STATUS_INVALID_DEVICE_REQUEST; + goto exit; + } + + // + // Process Request + // + + switch (*(PUCHAR)featurePacket->reportBuffer) + { + case REPORTID_FEATURE: + { + PHID_FEATURE_REPORT inputModeReport = + (PHID_FEATURE_REPORT) featurePacket->reportBuffer; + + if (featurePacket->reportBufferLen < sizeof(HID_FEATURE_REPORT)) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + + inputModeReport->InputMode = devContext->InputMode; + + break; + } + + case REPORTID_MAX_COUNT: + { + PHID_MAX_COUNT_REPORT maxCountReport = + (PHID_MAX_COUNT_REPORT) featurePacket->reportBuffer; + + if (featurePacket->reportBufferLen < sizeof(HID_MAX_COUNT_REPORT)) + { + status = STATUS_BUFFER_TOO_SMALL; + goto exit; + } + + maxCountReport->MaxCount = OEM_MAX_TOUCHES; + + break; + } + + default: + { + status = STATUS_INVALID_PARAMETER; + goto exit; + } + } + +exit: + + return status; +} diff --git a/input/hiddigi/SynapticsTouch/hid.h b/input/hiddigi/SynapticsTouch/hid.h new file mode 100644 index 00000000..1f0e7912 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/hid.h @@ -0,0 +1,85 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + hid.h + + Abstract: + + HID related function declarations, types, and defines + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + +// +// Global Data Declarations +// +extern const PWSTR gpwstrManufacturerID; +extern const PWSTR gpwstrProductID; +extern const PWSTR gpwstrSerialNumber; +extern const USHORT gOEMVendorID; +extern const USHORT gOEMProductID; +extern const USHORT gOEMVersionID; + +// +// Function prototypes +// + +NTSTATUS +TchGetDeviceAttributes( + IN WDFREQUEST Request + ); + +NTSTATUS +TchGetFeatureReport( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ); + +NTSTATUS +TchGetHidDescriptor( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ); + +NTSTATUS +TchGetReportDescriptor( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ); + +NTSTATUS +TchGetString( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ); + +NTSTATUS +TchProcessIdleRequest( + IN WDFDEVICE Device, + IN WDFREQUEST Request, + OUT BOOLEAN *Pending + ); + +NTSTATUS +TchSetFeatureReport( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ); + +NTSTATUS +TchReadReport( + IN WDFDEVICE Device, + IN WDFREQUEST Request, + OUT BOOLEAN *Pending + ); + diff --git a/input/hiddigi/SynapticsTouch/idle.c b/input/hiddigi/SynapticsTouch/idle.c new file mode 100644 index 00000000..d15b0b98 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/idle.c @@ -0,0 +1,328 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + idle.c + + Abstract: + + This file contains the declarations for Power Idle specific callbacks + and function definitions + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "internal.h" +#include "controller.h" +#include "idle.h" +#include "idle.tmh" + +NTSTATUS +TchProcessIdleRequest( + IN WDFDEVICE Device, + IN WDFREQUEST Request, + OUT BOOLEAN *Pending + ) +/*++ + +Routine Description: + + Handles HIDClass's idle notification request. + + This request is provided to a HID miniport, and provides a callback + routine typically used by HID miniports to self-manage power. + + The callback routine is invoked by the miniport to indicate that all + peripherals are idle, and in response the HID class driver will: + 1) Queue a wait/wake IRP to the device, and + 2) Set the device to D3 + + In the case of this touch miniport, we are using the HID class driver's + enhanced power management functionality, whereby invoking the callback + results in an immediate exit from D0, powering off touch. + + The Request will be completed when either HIDCLASS cancels it or + there is a device wake signal that will cause us to complete it. + +Arguments: + + Device - Handle to WDF Device Object + + Request - Handle to request object + + Pending - flag to monitor if the request was sent down the stack + +Return Value: + + On success, the function returns STATUS_SUCCESS + On failure it passes the relevant error code to the caller. + +--*/ +{ + PDEVICE_EXTENSION devContext; + PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO idleCallbackInfo; + PIRP irp; + PIO_STACK_LOCATION irpSp; + NTSTATUS status; + + devContext = GetDeviceContext(Device); + + NT_ASSERT(Pending != NULL); + *Pending = FALSE; + + // + // Retrieve request parameters and validate + // + irp = WdfRequestWdmGetIrp(Request); + irpSp = IoGetCurrentIrpStackLocation(irp); + + if (irpSp->Parameters.DeviceIoControl.InputBufferLength < + sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO)) + { + status = STATUS_INVALID_BUFFER_SIZE; + + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error: Input buffer is too small to process idle request - %!STATUS!", + status); + + goto exit; + } + + // + // Grab the callback + // + idleCallbackInfo = (PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) + irpSp->Parameters.DeviceIoControl.Type3InputBuffer; + + NT_ASSERT(idleCallbackInfo != NULL); + + if (idleCallbackInfo == NULL || idleCallbackInfo->IdleCallback == NULL) + { + status = STATUS_NO_CALLBACK_ACTIVE; + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error: Idle Notification request %p has no idle callback info - %!STATUS!", + Request, + status); + goto exit; + } + + { + // + // Create a workitem for the idle callback + // + WDF_OBJECT_ATTRIBUTES workItemAttributes; + WDF_WORKITEM_CONFIG workitemConfig; + WDFWORKITEM idleWorkItem; + PIDLE_WORKITEM_CONTEXT idleWorkItemContext; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workItemAttributes, IDLE_WORKITEM_CONTEXT); + workItemAttributes.ParentObject = devContext->FxDevice; + + WDF_WORKITEM_CONFIG_INIT(&workitemConfig, TchIdleIrpWorkitem); + + status = WdfWorkItemCreate( + &workitemConfig, + &workItemAttributes, + &idleWorkItem + ); + + if (!NT_SUCCESS(status)) { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_HID, + "Error creating creating idle work item - %!STATUS!", + status); + goto exit; + } + + // + // Set the workitem context + // + idleWorkItemContext = GetWorkItemContext(idleWorkItem); + idleWorkItemContext->FxDevice = devContext->FxDevice; + idleWorkItemContext->FxRequest = Request; + + // + // Enqueue a workitem for the idle callback + // + WdfWorkItemEnqueue(idleWorkItem); + + // + // Mark the request as pending so that + // we can complete it when we come out of idle + // + *Pending = TRUE; + } + +exit: + + return status; +} + +VOID +TchIdleIrpWorkitem( + IN WDFWORKITEM IdleWorkItem + ) +/*++ + +Routine Description: + + This is a workitem routine that TchProcessIdleRequest queues when + handling the HIDClass's idle notification IRP, so the idle callback can be made in + a different thread context, instead of the Idle Irp's dispatch call. + +Arguments: + + IdleWorkItem - Handle to a WDF workitem object + +Return Value: + + VOID + +--*/ +{ + NTSTATUS status; + PIDLE_WORKITEM_CONTEXT idleWorkItemContext; + PDEVICE_EXTENSION deviceContext; + PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO idleCallbackInfo; + + idleWorkItemContext = GetWorkItemContext(IdleWorkItem); + NT_ASSERT(idleWorkItemContext != NULL); + + deviceContext = GetDeviceContext(idleWorkItemContext->FxDevice); + NT_ASSERT(deviceContext != NULL); + + // + // Get the idle callback info from the workitem context + // + idleCallbackInfo = (PHID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) + IoGetCurrentIrpStackLocation(WdfRequestWdmGetIrp(idleWorkItemContext->FxRequest))->\ + Parameters.DeviceIoControl.Type3InputBuffer; + + // + // idleCallbackInfo is validated already, so invoke idle callback + // + idleCallbackInfo->IdleCallback(idleCallbackInfo->IdleContext); + + // + // Park this request in our IdleQueue and mark it as pending + // This way if the IRP was cancelled, WDF will cancel it for us + // + status = WdfRequestForwardToIoQueue( + idleWorkItemContext->FxRequest, + deviceContext->IdleQueue); + + if (!NT_SUCCESS(status)) + { + // + // IdleQueue is a manual-dispatch, non-power-managed queue. This should + // *never* fail. + // + + NT_ASSERTMSG("WdfRequestForwardToIoQueue to IdleQueue failed!", FALSE); + + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_IDLE, + "Error forwarding idle notification Request:0x%p to IdleQueue:0x%p - %!STATUS!", + idleWorkItemContext->FxRequest, + deviceContext->IdleQueue, + status); + + // + // Complete the request if we couldnt forward to the Idle Queue + // + WdfRequestComplete(idleWorkItemContext->FxRequest, status); + } + else + { + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IDLE, + "Forwarded idle notification Request:0x%p to IdleQueue:0x%p - %!STATUS!", + idleWorkItemContext->FxRequest, + deviceContext->IdleQueue, + status); + } + + // + // Delete the workitem since we're done with it + // + WdfObjectDelete(IdleWorkItem); + + return; +} + + +VOID +TchCompleteIdleIrp( + IN PDEVICE_EXTENSION FxDeviceContext + ) +/*++ + +Routine Description: + + This is invoked when we enter D0. + We simply complete the Idle Irp if it hasn't been cancelled already. + +Arguments: + + FxDeviceContext - Pointer to Device Context for the device + +Return Value: + + + +--*/ +{ + NTSTATUS status; + WDFREQUEST request = NULL; + + // + // Lets try to retrieve the Idle IRP from the Idle queue + // + status = WdfIoQueueRetrieveNextRequest( + FxDeviceContext->IdleQueue, + &request); + + // + // We did not find the Idle IRP, maybe it was cancelled + // + if (!NT_SUCCESS(status) || (request == NULL)) + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_IDLE, + "Error finding idle notification request in IdleQueue:0x%p - %!STATUS!", + FxDeviceContext->IdleQueue, + status); + } + else + { + // + // Complete the Idle IRP + // + WdfRequestComplete(request, status); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IDLE, + "Completed idle notification Request:0x%p from IdleQueue:0x%p - %!STATUS!", + request, + FxDeviceContext->IdleQueue, + status); + } + + return; +}
\ No newline at end of file diff --git a/input/hiddigi/SynapticsTouch/idle.h b/input/hiddigi/SynapticsTouch/idle.h new file mode 100644 index 00000000..1539f88c --- /dev/null +++ b/input/hiddigi/SynapticsTouch/idle.h @@ -0,0 +1,54 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + idle.c + + Abstract: + + This file contains the declarations for Power Idle specific callbacks + and function declarations + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + + +// +// Power Idle Workitem context +// +typedef struct _IDLE_WORKITEM_CONTEXT +{ + // Handle to a WDF device object + WDFDEVICE FxDevice; + + // Handle to a WDF request object + WDFREQUEST FxRequest; + +} IDLE_WORKITEM_CONTEXT, *PIDLE_WORKITEM_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(IDLE_WORKITEM_CONTEXT, GetWorkItemContext) + +NTSTATUS +TchProcessIdleRequest( + IN WDFDEVICE Device, + IN WDFREQUEST Request, + OUT BOOLEAN *Pending + ); + +VOID +TchCompleteIdleIrp( + IN PDEVICE_EXTENSION FxDeviceContext + ); + +EVT_WDF_WORKITEM TchIdleIrpWorkitem; + + diff --git a/input/hiddigi/SynapticsTouch/init.c b/input/hiddigi/SynapticsTouch/init.c new file mode 100644 index 00000000..fa72c9ba --- /dev/null +++ b/input/hiddigi/SynapticsTouch/init.c @@ -0,0 +1,1167 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + init.c + + Abstract: + + Contains Synaptics initialization code + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "rmiinternal.h" +#include "spb.h" +#include "init.tmh" + + +#pragma warning(push) +#pragma warning(disable:4242) // Conversion, possible loss of data + +// +// The logical values come from the registry and are hence DWORDs but the +// physical registers are only 8 bits wide so we use the lower 8 bits of the +// logical value. +// +#define LOGICAL_TO_PHYSICAL(LOGICAL_VALUE) ((LOGICAL_VALUE) & 0xff) + + +NTSTATUS +RmiChangePage( + IN RMI4_CONTROLLER_CONTEXT* ControllerContext, + IN SPB_CONTEXT* SpbContext, + IN int DesiredPage + ) +/*++ + + Routine Description: + + This utility function changes the current register address page. + + Arguments: + + ControllerContext - A pointer to the current touch controller context + SpbContext - A pointer to the current i2c context + DesiredPage - The page the caller expects to be mapped in + + Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + BYTE page; + NTSTATUS status; + + // + // If we're on this page already return success + // + if (ControllerContext->CurrentPage == DesiredPage) + { + status = STATUS_SUCCESS; + } + else + { + page = (BYTE) DesiredPage; + + status = SpbWriteDataSynchronously( + SpbContext, + RMI4_PAGE_SELECT_ADDRESS, + &page, + sizeof(BYTE)); + + if (NT_SUCCESS(status)) + { + ControllerContext->CurrentPage = DesiredPage; + } + } + + return status; +} + +int +RmiGetFunctionIndex( + IN RMI4_FUNCTION_DESCRIPTOR* FunctionDescriptors, + IN int FunctionCount, + IN int FunctionDesired + ) +/*++ + + Routine Description: + + Returns the descriptor table index that corresponds to the + desired RMI function. + + Arguments: + + FunctionDescriptors - A pointer to the touch controllers + full list of function descriptors + + FunctionCount - The count of function descriptors contained + in the above FunctionDescriptors list + + FunctionDesired - The RMI function number (note they are always + in hexadecimal the RMI4 specification) + + Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + UCHAR i; + + for (i=0; i < FunctionCount; i++) + { + // + // Break if we found the index + // + if (FunctionDescriptors[i].Number == FunctionDesired) + { + break; + } + } + + // + // Return the count if the index wasn't found + // + return i; +} + +NTSTATUS +RmiGetFirmwareVersion( + IN RMI4_CONTROLLER_CONTEXT *ControllerContext, + IN SPB_CONTEXT *SpbContext + ) +/*++ + + Routine Description: + + This function queries the firmware version of the current chip for + debugging purposes. + + Arguments: + + ControllerContext - A pointer to the current touch controller context + SpbContext - A pointer to the current i2c context + + Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + int index; + NTSTATUS status; + + // + // Find RMI device control function and configure it + // + index = RmiGetFunctionIndex( + ControllerContext->Descriptors, + ControllerContext->FunctionCount, + RMI4_F01_RMI_DEVICE_CONTROL); + + if (index == ControllerContext->FunctionCount) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Unexpected - RMI Function 01 missing"); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + + status = RmiChangePage( + ControllerContext, + SpbContext, + ControllerContext->FunctionOnPage[index]); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not change register page"); + + goto exit; + } + + // + // Store all F01 query registers, which contain the product ID + // + // TODO: Fix transfer size when SPB can support larger I2C + // transactions + // + status = SpbReadDataSynchronously( + SpbContext, + ControllerContext->Descriptors[index].QueryBase, + &ControllerContext->F01QueryRegisters, + sizeof(BYTE) * FIELD_OFFSET(RMI4_F01_QUERY_REGISTERS, ProductID10)); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error reading RMI F01 Query registers - %!STATUS!", + status); + + goto exit; + } + +exit: + + return status; +} + +VOID +RmiConvertF01ToPhysical( + IN RMI4_F01_CTRL_REGISTERS_LOGICAL* Logical, + IN RMI4_F01_CTRL_REGISTERS* Physical + ) +/*++ + + Routine Description: + + Registry configuration values for F01 must be specified as + 4-byte REG_DWORD values logically, however the chip interprets these + values as bits or bytes physically. This function converts + the registry parameters into a structure that can be programmed + into the controller's memory. + + Arguments: + + Logical - a pointer to the logical settings + + Physical - a pointer to the controller memory-mapped structure + + Return Value: + + None. Function may print warnings in the future when truncating. + +--*/ +{ + RtlZeroMemory(Physical, sizeof(RMI4_F01_CTRL_REGISTERS)); + + // + // Note that truncation of registry values is possible if + // the data was incorrectly provided by the OEM, we may + // print warning messages in the future. + // + + Physical->DeviceControl.SleepMode = LOGICAL_TO_PHYSICAL(Logical->SleepMode); + Physical->DeviceControl.NoSleep = LOGICAL_TO_PHYSICAL(Logical->NoSleep); + Physical->DeviceControl.ReportRate = LOGICAL_TO_PHYSICAL(Logical->ReportRate); + Physical->DeviceControl.Configured = LOGICAL_TO_PHYSICAL(Logical->Configured); + + Physical->InterruptEnable = LOGICAL_TO_PHYSICAL(Logical->InterruptEnable); + Physical->DozeInterval = LOGICAL_TO_PHYSICAL(Logical->DozeInterval); + Physical->DozeThreshold = LOGICAL_TO_PHYSICAL(Logical->DozeThreshold); + Physical->DozeHoldoff = LOGICAL_TO_PHYSICAL(Logical->DozeHoldoff); +} + +VOID +RmiConvertF11ToPhysical( + IN RMI4_F11_CTRL_REGISTERS_LOGICAL* Logical, + IN RMI4_F11_CTRL_REGISTERS* Physical + ) +/*++ + + Routine Description: + + Registry configuration values for F11 must be specified as + 4-byte REG_DWORD values logically, however the chip interprets these + values as bits or bytes physically. This function converts + the registry parameters into a structure that can be programmed + into the controller's memory. + + Arguments: + + Logical - a pointer to the logical settings + + Physical - a pointer to the controller memory-mapped structure + + Return Value: + + None. Function may print warnings in the future when truncating. + +--*/ +{ + RtlZeroMemory(Physical, sizeof(RMI4_F11_CTRL_REGISTERS)); + + // + // Note that truncation of registry values is possible if + // the data was incorrectly provided by the OEM, we may + // print warning messages in the future. + // + + Physical->ReportingMode = LOGICAL_TO_PHYSICAL(Logical->ReportingMode); + Physical->AbsPosFilt = LOGICAL_TO_PHYSICAL(Logical->AbsPosFilt); + Physical->RelPosFilt = LOGICAL_TO_PHYSICAL(Logical->RelPosFilt); + Physical->RelBallistics = LOGICAL_TO_PHYSICAL(Logical->RelBallistics); + Physical->Dribble = LOGICAL_TO_PHYSICAL(Logical->Dribble); + + Physical->PalmDetectThreshold = LOGICAL_TO_PHYSICAL(Logical->PalmDetectThreshold); + Physical->MotionSensitivity = LOGICAL_TO_PHYSICAL(Logical->MotionSensitivity); + Physical->ManTrackEn = LOGICAL_TO_PHYSICAL(Logical->ManTrackEn); + Physical->ManTrackedFinger = LOGICAL_TO_PHYSICAL(Logical->ManTrackedFinger); + + Physical->DeltaXPosThreshold = LOGICAL_TO_PHYSICAL(Logical->DeltaXPosThreshold); + Physical->DeltaYPosThreshold = LOGICAL_TO_PHYSICAL(Logical->DeltaYPosThreshold); + Physical->Velocity = LOGICAL_TO_PHYSICAL(Logical->Velocity); + Physical->Acceleration = LOGICAL_TO_PHYSICAL(Logical->Acceleration); + + Physical->SensorMaxXPosLo = (Logical->SensorMaxXPos & 0xFF) >> 0; + Physical->SensorMaxXPosHi = (Logical->SensorMaxXPos & 0xF00) >> 8; + + Physical->SensorMaxYPosLo = (Logical->SensorMaxYPos & 0xFF) >> 0; + Physical->SensorMaxYPosHi = (Logical->SensorMaxYPos & 0xF00) >> 8; + + Physical->ZTouchThreshold = LOGICAL_TO_PHYSICAL(Logical->ZTouchThreshold); + Physical->ZHysteresis = LOGICAL_TO_PHYSICAL(Logical->ZHysteresis); + Physical->SmallZThreshold = LOGICAL_TO_PHYSICAL(Logical->SmallZThreshold); + + Physical->SmallZScaleFactor[0] = (Logical->SmallZScaleFactor & 0xFF) >> 0; + Physical->SmallZScaleFactor[1] = (Logical->SmallZScaleFactor & 0xFF00) >> 8; + + Physical->LargeZScaleFactor[0] = (Logical->LargeZScaleFactor & 0xFF) >> 0; + Physical->LargeZScaleFactor[1] = (Logical->LargeZScaleFactor & 0xFF00) >> 8; + + Physical->AlgorithmSelection = LOGICAL_TO_PHYSICAL((Logical->AlgorithmSelection)); + Physical->WxScaleFactor = LOGICAL_TO_PHYSICAL((Logical->WxScaleFactor)); + Physical->WxOffset = LOGICAL_TO_PHYSICAL((Logical->WxOffset)); + Physical->WyScaleFactor = LOGICAL_TO_PHYSICAL((Logical->WyScaleFactor)); + Physical->WyOffset = LOGICAL_TO_PHYSICAL((Logical->WyOffset)); + + Physical->XPitch[0] = (Logical->XPitch & 0xFF) >> 0; + Physical->XPitch[1] = (Logical->XPitch & 0xFF00) >> 8; + + Physical->YPitch[0] = (Logical->YPitch & 0xFF) >> 0; + Physical->YPitch[1] = (Logical->YPitch & 0xFF00) >> 8; + + Physical->FingerWidthX[0] = (Logical->FingerWidthX & 0xFF) >> 0; + Physical->FingerWidthX[1] = (Logical->FingerWidthX & 0xFF00) >> 8; + + Physical->FingerWidthY[0] = (Logical->FingerWidthY & 0xFF) >> 0; + Physical->FingerWidthY[1] = (Logical->FingerWidthY & 0xFF00) >> 8; + + Physical->ReportMeasuredSize = LOGICAL_TO_PHYSICAL(Logical->ReportMeasuredSize); + Physical->SegmentationSensitivity = LOGICAL_TO_PHYSICAL(Logical->SegmentationSensitivity); + Physical->XClipLo = LOGICAL_TO_PHYSICAL(Logical->XClipLo); + Physical->XClipHi = LOGICAL_TO_PHYSICAL(Logical->XClipHi); + Physical->YClipLo = LOGICAL_TO_PHYSICAL(Logical->YClipLo); + Physical->YClipHi = LOGICAL_TO_PHYSICAL(Logical->YClipHi); + Physical->MinFingerSeparation = LOGICAL_TO_PHYSICAL(Logical->MinFingerSeparation); + Physical->MaxFingerMovement = LOGICAL_TO_PHYSICAL(Logical->MaxFingerMovement); +} + +NTSTATUS +RmiConfigureFunctions( + IN RMI4_CONTROLLER_CONTEXT *ControllerContext, + IN SPB_CONTEXT *SpbContext + ) +/*++ + + Routine Description: + + RMI4 devices such as this Synaptics touch controller are organized + as collections of logical functions. Discovered functions must be + configured, which is done in this function (things like sleep + timeouts, interrupt enables, report rates, etc.) + + Arguments: + + ControllerContext - A pointer to the current touch controller + context + + SpbContext - A pointer to the current i2c context + + Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + int index; + NTSTATUS status; + + RMI4_F01_CTRL_REGISTERS controlF01 = {0}; + RMI4_F11_CTRL_REGISTERS controlF11 = {0}; + + // + // Find 2D touch sensor function and configure it + // + index = RmiGetFunctionIndex( + ControllerContext->Descriptors, + ControllerContext->FunctionCount, + RMI4_F11_2D_TOUCHPAD_SENSOR); + + if (index == ControllerContext->FunctionCount) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Unexpected - RMI Function 11 missing"); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + + status = RmiChangePage( + ControllerContext, + SpbContext, + ControllerContext->FunctionOnPage[index]); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not change register page"); + + goto exit; + } + + RmiConvertF11ToPhysical( + &ControllerContext->Config.TouchSettings, + &controlF11); + + // + // Write settings to controller + // + status = SpbWriteDataSynchronously( + SpbContext, + ControllerContext->Descriptors[index].ControlBase, + &controlF11, + sizeof(controlF11) + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error writing RMI F11 Ctrl settings - %!STATUS!", + status); + goto exit; + } + + // + // Find 0D capacitive button sensor function and configure it if it exists + // + index = RmiGetFunctionIndex( + ControllerContext->Descriptors, + ControllerContext->FunctionCount, + RMI4_F1A_0D_CAP_BUTTON_SENSOR); + + if (index != ControllerContext->FunctionCount) + { + ControllerContext->HasButtons = TRUE; + + // + // TODO: Get configuration data from registry once Synaptics + // provides sane default values. Until then, assume the + // object is configured for the desired product scenario + // by default. + // + } + + // + // Find RMI device control function and configure it + // + index = RmiGetFunctionIndex( + ControllerContext->Descriptors, + ControllerContext->FunctionCount, + RMI4_F01_RMI_DEVICE_CONTROL); + + if (index == ControllerContext->FunctionCount) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Unexpected - RMI Function 01 missing"); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + + status = RmiChangePage( + ControllerContext, + SpbContext, + ControllerContext->FunctionOnPage[index]); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not change register page"); + + goto exit; + } + + RmiConvertF01ToPhysical( + &ControllerContext->Config.DeviceSettings, + &controlF01); + + // + // Write settings to controller + // + status = SpbWriteDataSynchronously( + SpbContext, + ControllerContext->Descriptors[index].ControlBase, + &controlF01, + sizeof(controlF01) + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error writing RMI F01 Ctrl settings - %!STATUS!", + status); + goto exit; + } + + // + // Note whether the device configuration settings initialized the + // controller in an operating state, to prevent a double-start from + // the D0 entry dispatch routine (TchWakeDevice) + // + if (RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_OPERATING == + controlF01.DeviceControl.SleepMode) + { + ControllerContext->DevicePowerState = PowerDeviceD0; + } + else + { + ControllerContext->DevicePowerState = PowerDeviceD3; + } + +exit: + + return status; +} + +NTSTATUS +RmiBuildFunctionsTable( + IN RMI4_CONTROLLER_CONTEXT *ControllerContext, + IN SPB_CONTEXT *SpbContext + ) +/*++ + + Routine Description: + + RMI4 devices such as this Synaptics touch controller are organized + as collections of logical functions. When initially communicating + with the chip, a driver must build a table of available functions, + as is done in this routine. + + Arguments: + + ControllerContext - A pointer to the current touch controller context + + SpbContext - A pointer to the current i2c context + + Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + UCHAR address; + int function; + int page; + NTSTATUS status; + + + // + // First function is at a fixed address + // + function = 0; + address = RMI4_FIRST_FUNCTION_ADDRESS; + page = 0; + + // + // Discover chip functions one by one + // + do + { + // + // Read function descriptor + // + status = SpbReadDataSynchronously( + SpbContext, + address, + &ControllerContext->Descriptors[function], + sizeof(RMI4_FUNCTION_DESCRIPTOR)); + + if (!(NT_SUCCESS(status))) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error returned from SPB/I2C read attempt %d - %!STATUS!", + function, + status); + goto exit; + } + + // + // Function number 0 implies "last function" on this register page, + // and if this "last function" is the first function on the page, there + // are no more functions to discover. + // + if (ControllerContext->Descriptors[function].Number == 0 && + address == RMI4_FIRST_FUNCTION_ADDRESS) + { + break; + } + // + // If we've exhausted functions on this page, look for more functoins + // on the next register page + // + else if (ControllerContext->Descriptors[function].Number == 0 && + address != RMI4_FIRST_FUNCTION_ADDRESS) + { + page++; + address = RMI4_FIRST_FUNCTION_ADDRESS; + + status = RmiChangePage( + ControllerContext, + SpbContext, + page); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error attempting to change page - %!STATUS!", + status); + goto exit; + } + } + // + // Descriptor stored, look for next or terminator + // + else + { + Trace( + TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "Discovered function $%x", + ControllerContext->Descriptors[function].Number); + + ControllerContext->FunctionOnPage[function] = page; + function++; + address = address - sizeof(RMI4_FUNCTION_DESCRIPTOR); + } + + } while ( + (address > 0) && + (function < RMI4_MAX_FUNCTIONS)); + + // + // If we swept the address space without finding an "end function" + // or maxed-out the total number of functions supported by the + // driver, note the error and exit. + // + if (function >= RMI4_MAX_FUNCTIONS) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error, encountered more than %d functions, must extend driver", + RMI4_MAX_FUNCTIONS); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + if (address <= 0) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Error, did not find terminator function 0, address down to %d", + address); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + + // + // Note the total number of functions that exist + // + ControllerContext->FunctionCount = function; + + Trace( + TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "Discovered %d RMI functions total", + function); + +exit: + + return status; +} + +NTSTATUS +RmiCheckInterrupts( + IN RMI4_CONTROLLER_CONTEXT *ControllerContext, + IN SPB_CONTEXT *SpbContext, + IN ULONG* InterruptStatus + ) +/*++ + + Routine Description: + + This function handles controller interrupts. It currently only + supports valid touch interrupts. Any other interrupt sources (such as + device losing configuration or being reset) are unhandled, but noted + in the controller context. + + Arguments: + + ControllerContext - A pointer to the current touch controller + context + + SpbContext - A pointer to the current i2c context + + Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + RMI4_F01_DATA_REGISTERS data; + int index; + NTSTATUS status; + + RtlZeroMemory(&data, sizeof(data)); + *InterruptStatus = 0; + + // + // Locate RMI data base address + // + index = RmiGetFunctionIndex( + ControllerContext->Descriptors, + ControllerContext->FunctionCount, + RMI4_F01_RMI_DEVICE_CONTROL); + + if (index == ControllerContext->FunctionCount) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Unexpected - RMI Function 01 missing"); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + + status = RmiChangePage( + ControllerContext, + SpbContext, + ControllerContext->FunctionOnPage[index]); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not change register page"); + + goto exit; + } + + // + // Read interrupt status registers + // + status = SpbReadDataSynchronously( + SpbContext, + ControllerContext->Descriptors[index].DataBase, + &data, + sizeof(data)); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error reading interrupt status - %!STATUS!", + status); + + goto exit; + } + + // + // Check for catastrophic failures, simply store in context for + // debugging should these errors occur. + // + switch (data.DeviceStatus.Status) + { + case RMI4_F01_DATA_STATUS_NO_ERROR: + { + break; + } + case RMI4_F01_DATA_STATUS_RESET_OCCURRED: + { + ControllerContext->ResetOccurred = TRUE; + break; + } + case RMI4_F01_DATA_STATUS_INVALID_CONFIG: + { + ControllerContext->InvalidConfiguration = TRUE; + + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Received status code 2 - invalid configuration"); + + break; + } + case RMI4_F01_DATA_STATUS_DEVICE_FAILURE: + { + ControllerContext->DeviceFailure = TRUE; + + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Received status code 4 - device failure"); + + break; + } + default: + { + ControllerContext->UnknownStatus = TRUE; + ControllerContext->UnknownStatusMessage = data.DeviceStatus.Status; + + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Received unknown status code - %d", + ControllerContext->UnknownStatusMessage); + + break; + } + } + + // + // If we're in flash programming mode, report an error + // + if (data.DeviceStatus.FlashProg) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error, device status indicates chip in programming mode"); + + goto exit; + } + + // + // If the chip has lost it's configuration, reconfigure + // + if (data.DeviceStatus.Unconfigured) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error, device status indicates chip is unconfigured"); + + status = RmiConfigureFunctions( + ControllerContext, + SpbContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Could not reconfigure chip - %!STATUS!", + status); + + goto exit; + } + + } + + if (data.InterruptStatus[0]) + { + *InterruptStatus = data.InterruptStatus[0] & 0xFF; + } + else + { + Trace( + TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INTERRUPT, + "Unexpected -- no interrupt status bit set"); + } + +exit: + return status; +} + +NTSTATUS +TchStartDevice( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext + ) +/*++ + + Routine Description: + + This routine is called in response to the KMDF prepare hardware call + to initialize the touch controller for use. + + Arguments: + + ControllerContext - A pointer to the current touch controller + context + + SpbContext - A pointer to the current i2c context + + Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + RMI4_CONTROLLER_CONTEXT* controller; + ULONG interruptStatus; + NTSTATUS status; + + controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext; + interruptStatus = 0; + status = STATUS_SUCCESS; + + // + // Populate context with RMI function descriptors + // + status = RmiBuildFunctionsTable( + ControllerContext, + SpbContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not build table of RMI functions - %!STATUS!", + status); + goto exit; + } + + // + // Initialize RMI function control registers + // + status = RmiConfigureFunctions( + ControllerContext, + SpbContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not configure RMI functions - %!STATUS!", + status); + goto exit; + } + + // + // Read and store the firmware version + // + status = RmiGetFirmwareVersion( + ControllerContext, + SpbContext); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not get RMI firmware version - %!STATUS!", + status); + goto exit; + } + + // + // Clear any pending interrupts + // + status = RmiCheckInterrupts( + ControllerContext, + SpbContext, + &interruptStatus + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not get interrupt status - %!STATUS!%", + status); + } + +exit: + + return status; +} + +NTSTATUS +TchStopDevice( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext + ) +/*++ + +Routine Description: + + This routine cleans up the device that is stopped. + +Argument: + + ControllerContext - Touch controller context + + SpbContext - A pointer to the current i2c context + +Return Value: + + NTSTATUS indicating sucess or failure +--*/ +{ + RMI4_CONTROLLER_CONTEXT* controller; + + UNREFERENCED_PARAMETER(SpbContext); + + controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext; + + return STATUS_SUCCESS; +} + +NTSTATUS +TchAllocateContext( + OUT VOID **ControllerContext, + IN WDFDEVICE FxDevice + ) +/*++ + +Routine Description: + + This routine allocates a controller context. + +Argument: + + ControllerContext - Touch controller context + FxDevice - Framework device object + +Return Value: + + NTSTATUS indicating sucess or failure +--*/ +{ + RMI4_CONTROLLER_CONTEXT* context; + NTSTATUS status; + + context = ExAllocatePoolWithTag( + NonPagedPool, + sizeof(RMI4_CONTROLLER_CONTEXT), + TOUCH_POOL_TAG); + + if (NULL == context) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not allocate controller context!"); + + status = STATUS_UNSUCCESSFUL; + goto exit; + } + + RtlZeroMemory(context, sizeof(RMI4_CONTROLLER_CONTEXT)); + context->FxDevice = FxDevice; + + // + // Get screen properties and populate context + // + TchGetScreenProperties(&context->Props); + + // + // Allocate a WDFWAITLOCK for guarding access to the + // controller HW and driver controller context + // + status = WdfWaitLockCreate( + WDF_NO_OBJECT_ATTRIBUTES, + &context->ControllerLock); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not allocate controller context - %!STATUS!", + status); + + goto exit; + + } + + *ControllerContext = context; + +exit: + + return status; +} + +NTSTATUS +TchFreeContext( + IN VOID *ControllerContext + ) +/*++ + +Routine Description: + + This routine frees a controller context. + +Argument: + + ControllerContext - Touch controller context + +Return Value: + + NTSTATUS indicating sucess or failure +--*/ +{ + RMI4_CONTROLLER_CONTEXT* controller; + + controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext; + + if (controller != NULL) + { + + if (controller->ControllerLock != NULL) + { + WdfObjectDelete(controller->ControllerLock); + } + + ExFreePoolWithTag(controller, TOUCH_POOL_TAG); + } + + return STATUS_SUCCESS; +} + +#pragma warning(pop) diff --git a/input/hiddigi/SynapticsTouch/internal.h b/input/hiddigi/SynapticsTouch/internal.h new file mode 100644 index 00000000..39b8bfdc --- /dev/null +++ b/input/hiddigi/SynapticsTouch/internal.h @@ -0,0 +1,73 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + internal.h + + Abstract: + + Contains common types and defintions used internally + by the multi touch screen driver. + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + +#include "controller.h" + +// +// Device context +// + +typedef struct _DEVICE_EXTENSION +{ + // + // HID Touch input mode (touch vs. mouse) + // + UCHAR InputMode; + + // + // Device related + // + WDFDEVICE FxDevice; + WDFQUEUE DefaultQueue; + WDFQUEUE PingPongQueue; + + // + // Interrupt servicing + // + WDFINTERRUPT InterruptObject; + BOOLEAN ServiceInterruptsAfterD0Entry; + + // + // Spb (I2C) related members used for the lifetime of the device + // + SPB_CONTEXT I2CContext; + + // + // Test related + // + WDFQUEUE TestQueue; + volatile LONG TestSessionRefCnt; + BOOLEAN DiagnosticMode; + + // + // Power related + // + WDFQUEUE IdleQueue; + + // + // Touch related members used for the lifetime of the device + // + VOID *TouchContext; +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, GetDeviceContext) diff --git a/input/hiddigi/SynapticsTouch/power.c b/input/hiddigi/SynapticsTouch/power.c new file mode 100644 index 00000000..b234afb8 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/power.c @@ -0,0 +1,272 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + power.c + + Abstract: + + Contains Synaptics power-on and power-off functionality + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "controller.h" +#include "rmiinternal.h" +#include "spb.h" +#include "power.tmh" + +NTSTATUS +RmiChangeSleepState( + IN RMI4_CONTROLLER_CONTEXT* ControllerContext, + IN SPB_CONTEXT *SpbContext, + IN UCHAR SleepState + ) +/*++ + +Routine Description: + + Changes the SleepMode bits on the controller as specified + +Arguments: + + ControllerContext - Touch controller context + + SpbContext - A pointer to the current i2c context + + SleepState - Either RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_OPERATING + or RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_SLEEPING + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + RMI4_F01_CTRL_REGISTERS* controlF01; + UCHAR deviceControl; + int index; + NTSTATUS status; + + controlF01 = (RMI4_F01_CTRL_REGISTERS*) &deviceControl; + + // + // Find RMI device control function housing sleep settings + // + index = RmiGetFunctionIndex( + ControllerContext->Descriptors, + ControllerContext->FunctionCount, + RMI4_F01_RMI_DEVICE_CONTROL); + + if (index == ControllerContext->FunctionCount) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_POWER, + "Power change failure - RMI Function 01 missing"); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + + status = RmiChangePage( + ControllerContext, + SpbContext, + ControllerContext->FunctionOnPage[index]); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_POWER, + "Could not change register page"); + + goto exit; + } + + // + // Read Device Control register + // + status = SpbReadDataSynchronously( + SpbContext, + ControllerContext->Descriptors[index].ControlBase, + &deviceControl, + sizeof(deviceControl) + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_POWER, + "Could not read sleep register - %!STATUS!", + status); + + goto exit; + } + + // + // Assign new sleep state + // + controlF01->DeviceControl.SleepMode = SleepState; + + // + // Write setting back to the controller + // + status = SpbWriteDataSynchronously( + SpbContext, + ControllerContext->Descriptors[index].ControlBase, + &deviceControl, + sizeof(deviceControl) + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_POWER, + "Could not write sleep register - %X", + status); + + goto exit; + } + +exit: + + return status; +} + +NTSTATUS +TchWakeDevice( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext + ) +/*++ + +Routine Description: + + Enables multi-touch scanning + +Arguments: + + ControllerContext - Touch controller context + + SpbContext - A pointer to the current i2c context + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + RMI4_CONTROLLER_CONTEXT* controller; + NTSTATUS status; + + controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext; + + // + // Check if we were already on + // + if (controller->DevicePowerState == PowerDeviceD0) + { + goto exit; + } + + controller->DevicePowerState = PowerDeviceD0; + + // + // Attempt to put the controller into operating mode + // + status = RmiChangeSleepState( + controller, + SpbContext, + RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_OPERATING); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_POWER, + "Error waking touch controller - %!STATUS!", + status); + } + +exit: + + return STATUS_SUCCESS; +} + +NTSTATUS +TchStandbyDevice( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext + ) +/*++ + +Routine Description: + + Disables multi-touch scanning to conserve power + +Arguments: + + ControllerContext - Touch controller context + + SpbContext - A pointer to the current i2c context + +Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + RMI4_CONTROLLER_CONTEXT* controller; + NTSTATUS status; + + controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext; + + // + // Interrupts are now disabled but the ISR may still be + // executing, so grab the controller lock to ensure ISR + // is finished touching HW and controller state. + // + WdfWaitLockAcquire(controller->ControllerLock, NULL); + + // + // Put the chip in sleep mode + // + status = RmiChangeSleepState( + ControllerContext, + SpbContext, + RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_SLEEPING); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_POWER, + "Error sleeping touch controller - %!STATUS!", + status); + } + + controller->DevicePowerState = PowerDeviceD3; + + // + // Invalidate state + // + controller->TouchesReported = 0; + controller->TouchesTotal = 0; + controller->Cache.FingerSlotValid = 0; + controller->Cache.FingerSlotDirty = 0; + controller->Cache.FingerDownCount = 0; + + WdfWaitLockRelease(controller->ControllerLock); + + return STATUS_SUCCESS; +}
\ No newline at end of file diff --git a/input/hiddigi/SynapticsTouch/queue.c b/input/hiddigi/SynapticsTouch/queue.c new file mode 100644 index 00000000..e765df8b --- /dev/null +++ b/input/hiddigi/SynapticsTouch/queue.c @@ -0,0 +1,180 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + queue.c + + Abstract: + + Contains WDF queue related code, namely the top-level queue + handler for all device IOCTL requests. + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "internal.h" +#include "controller.h" +#include "queue.h" +#include "hid.h" +#include "idle.h" +#include "queue.tmh" + +VOID +OnInternalDeviceControl( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t OutputBufferLength, + IN size_t InputBufferLength, + IN ULONG IoControlCode + ) +/*++ + +Routine Description: + + This event is called when the framework receives + IRP_MJ_INTERNAL DEVICE_CONTROL requests from the system. + +Arguments: + + Queue - Handle to the framework queue object that is associated + with the I/O request. + + Request - Handle to a framework request object. + + OutputBufferLength - length of the request's output buffer, + if an output buffer is available. + + InputBufferLength - length of the request's input buffer, + if an input buffer is available. + + IoControlCode - the driver-defined or system-defined I/O control code + (IOCTL) that is associated with the request. + +Return Value: + + None, status is indicated when completing the request + +--*/ +{ + NTSTATUS status; + PDEVICE_EXTENSION devContext; + WDFDEVICE device; + BOOLEAN requestPending; + + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + device = WdfIoQueueGetDevice(Queue); + devContext = GetDeviceContext(device); + requestPending = FALSE; + + // + // Please note that HIDCLASS provides the buffer in the Irp->UserBuffer + // field irrespective of the ioctl buffer type. However, framework is very + // strict about type checking. You cannot get Irp->UserBuffer by using + // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER + // internal ioctl. So depending on the ioctl code, we will either + // use retreive function or escape to WDM to get the UserBuffer. + // + + switch(IoControlCode) { + + case IOCTL_HID_GET_DEVICE_DESCRIPTOR: + // + // Retrieves master HID descriptor + // + + status = TchGetHidDescriptor(device, Request); + break; + + case IOCTL_HID_GET_DEVICE_ATTRIBUTES: + // + // Retrieves device attributes in a HID_DEVICE_ATTRIBUTES structure + // + + status = TchGetDeviceAttributes(Request); + break; + + case IOCTL_HID_GET_REPORT_DESCRIPTOR: + // + // Obtains the report descriptor for the HID device + // + + status = TchGetReportDescriptor(device, Request); + break; + + case IOCTL_HID_GET_STRING: + // + // Obtains strings associated with the HID device + // + + status = TchGetString(device, Request); + break; + + case IOCTL_HID_READ_REPORT: + // + // Dangling read requests for passing up touch data + // + + status = TchReadReport(device, Request, &requestPending); + break; + + case IOCTL_HID_SET_FEATURE: + // + // This sends a HID class feature report to a top-level collection of + // a HID class device. + // + + status = TchSetFeatureReport(device, Request); + break; + + case IOCTL_HID_GET_FEATURE: + // + // Returns a feature report associated with a top-level collection + // + + status = TchGetFeatureReport(device, Request); + break; + + case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: + // + // Hidclass sends this IOCTL to notify miniports that it wants + // them to go into idle + // + + status = TchProcessIdleRequest(device, Request, &requestPending); + break; + + case IOCTL_HID_WRITE_REPORT: + // + // Transmits a class driver-supplied report to the device. + // + case IOCTL_HID_ACTIVATE_DEVICE: + // + // Makes the device ready for I/O operations. + // + case IOCTL_HID_DEACTIVATE_DEVICE: + // + // Causes the device to cease operations and terminate all outstanding + // I/O requests. + // + + default: + status = STATUS_NOT_SUPPORTED; + break; + } + + if (!requestPending) + { + WdfRequestComplete(Request, status); + } + + return; +} diff --git a/input/hiddigi/SynapticsTouch/queue.h b/input/hiddigi/SynapticsTouch/queue.h new file mode 100644 index 00000000..777ee04c --- /dev/null +++ b/input/hiddigi/SynapticsTouch/queue.h @@ -0,0 +1,24 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + queue.h + + Abstract: + + Contains WDF queue related function declarations + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + + +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL OnInternalDeviceControl; diff --git a/input/hiddigi/SynapticsTouch/readme.md b/input/hiddigi/SynapticsTouch/readme.md new file mode 100644 index 00000000..190da736 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/readme.md @@ -0,0 +1,72 @@ +Synaptics Touch Sample +====================== +The Synaptics Touch (KMDF) sample demonstrates how to write a HID miniport driver for the Synaptics 3202 touch controller. + +## Universal Windows Driver Compliant +This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. + +Related technologies +-------------------- + +[Kernel-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544396) + +[Human Interface Devices](http://msdn.microsoft.com/en-us/library/windows/hardware/jj126202) + +[Windows Pointer Device](http://msdn.microsoft.com/en-us/library/windows/hardware/jj151570) + + +##System requirements +------------------- +**Client:** Windows 10 Technical Preview + +**Server:** Windows 10 Technical Preview + +**Phone:** Windows 10 Technical Preview + + +File Manifest +------------- +#### driver.h, driver.c +DriverEntry and Events on the Driver Object. + +#### device.h, device.c +Events on the Device Object. + +#### queue.h, queue.c +Contains Events on the I/O Queue Objects. + +#### hid.c, hid.h +Contains the HID descriptor and functions to handle to HID requests. + +#### idle.c, idle.h +Contains the declarations for Power Idle specific callbacks and function definitions. + +#### internal.h +Contains common types and defintions used internally by the multi touch screen driver. + +#### spb.c +Contains all I2C-specific functionality. + +#### init.c +Contains Synaptics initialization code. + +#### power.c +Contains Synaptics power-on and power-off functionality. + +#### registry.c +This module retrieves platform-specific controller configuration from the registry, or assigns default values if no registry configuration is present. + +#### report.c +Contains Synaptics specific code for reporting samples. + +#### resolutions.c +Contains resolution translation defines and types. + +#### rmiinternal.h +Contains common types and defintions used internally by the multi touch screen driver. + +#### SynapticsTouch.inx +File that describes the installation of this driver. The build process converts this into an INF file. + + + diff --git a/input/hiddigi/SynapticsTouch/registry.c b/input/hiddigi/SynapticsTouch/registry.c new file mode 100644 index 00000000..29c66be3 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/registry.c @@ -0,0 +1,722 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + registry.c + + Abstract: + + This module retrieves platform-specific controller + configuration from the registry, or assigns default + values if no registry configuration is present. + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "rmiinternal.h" +#include "registry.tmh" + +// +// Default RMI4 configuration values can be changed here. Please refer to the +// RMI4 specification for a full description of the fields and value meanings +// + +static RMI4_CONFIGURATION gDefaultConfiguration = +{ + // + // RMI4 F01 - Device control settings + // + { + 0, // Sleep Mode (normal) + 1, // No Sleep (do sleep) + 0, // Report Rate (standard) + 1, // Configured + 0xf, // Interrupt Enable + RMI4_MILLISECONDS_TO_TENTH_MILLISECONDS(20), // Doze Interval + 10, // Doze Threshold + RMI4_SECONDS_TO_HALF_SECONDS(2) // Doze Holdoff + }, + + // + // RMI4 F11 - 2D Touchpad sensor settings + // + { + 1, // Reporting mode (throttle) + 1, // Abs position filter + 0, // Rel position filter + 0, // Rel ballistics + 0, // Dribble + 0xb, // PalmDetectThreshold + 3, // MotionSensitivity + 0, // ManTrackEn + 0, // ManTrackedFinger + 0, // DeltaXPosThreshold + 0, // DeltaYPosThreshold + 0, // Velocity + 0, // Acceleration + TOUCH_DEVICE_RESOLUTION_X, // Sensor Max X Position + TOUCH_DEVICE_RESOLUTION_Y, // Sensor Max Y Position + 0x1e, // ZTouchThreshold + 0x05, // ZHysteresis + 0x28, // SmallZThreshold + 0x28f5, // SmallZScaleFactor + 0x051e, // LargeZScaleFactor + 0x1, // AlgorithmSelection + 0x30, // WxScaleFactor + 0x0, // WxOffset + 0x30, // WyScaleFactor + 0x0, // WyOffset + 0x4800, // XPitch + 0x4800, // YPitch + 0xea4f, // FingerWidthX + 0xdf6c, // FingerWidthY + 0, // ReportMeasuredSize + 0x70, // SegmentationSensitivity + 0x0, // XClipLo + 0x0, // XClipHi + 0x0, // YClipLo + 0x0, // YClipHi + 0x0a, // MinFingerSeparation + 0x04 // MaxFingerMovement + }, + + // + // Internal driver settings + // + { + 0x0, // Controller stays powered in D3 + }, +}; + +RTL_QUERY_REGISTRY_TABLE gRegistryTable[] = +{ + // + // RMI4 F01 - Device control settings + // + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"SleepMode", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, DeviceSettings) + + FIELD_OFFSET(RMI4_F01_CTRL_REGISTERS_LOGICAL, SleepMode)), + REG_DWORD, + &gDefaultConfiguration.DeviceSettings.SleepMode, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"NoSleep", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, DeviceSettings) + + FIELD_OFFSET(RMI4_F01_CTRL_REGISTERS_LOGICAL, NoSleep)), + REG_DWORD, + &gDefaultConfiguration.DeviceSettings.NoSleep, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"ReportRate", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, DeviceSettings) + + FIELD_OFFSET(RMI4_F01_CTRL_REGISTERS_LOGICAL, ReportRate)), + REG_DWORD, + &gDefaultConfiguration.DeviceSettings.ReportRate, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"Configured", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, DeviceSettings) + + FIELD_OFFSET(RMI4_F01_CTRL_REGISTERS_LOGICAL, Configured)), + REG_DWORD, + &gDefaultConfiguration.DeviceSettings.Configured, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"InterruptEnable", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, DeviceSettings) + + FIELD_OFFSET(RMI4_F01_CTRL_REGISTERS_LOGICAL, InterruptEnable)), + REG_DWORD, + &gDefaultConfiguration.DeviceSettings.InterruptEnable, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DozeInterval", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, DeviceSettings) + + FIELD_OFFSET(RMI4_F01_CTRL_REGISTERS_LOGICAL, DozeInterval)), + REG_DWORD, + &gDefaultConfiguration.DeviceSettings.DozeInterval, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DozeThreshold", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, DeviceSettings) + + FIELD_OFFSET(RMI4_F01_CTRL_REGISTERS_LOGICAL, DozeThreshold)), + REG_DWORD, + &gDefaultConfiguration.DeviceSettings.DozeThreshold, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DozeHoldoff", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, DeviceSettings) + + FIELD_OFFSET(RMI4_F01_CTRL_REGISTERS_LOGICAL, DozeHoldoff)), + REG_DWORD, + &gDefaultConfiguration.DeviceSettings.DozeHoldoff, + sizeof(UINT32) + }, + + // + // RMI4 F11 - 2D Touchpad sensor settings + // + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"ReportingMode", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, ReportingMode)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.ReportingMode, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"AbsPosFilt", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, AbsPosFilt)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.AbsPosFilt, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"RelPosFilt", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, RelPosFilt)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.RelPosFilt, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"RelBallistics", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, RelBallistics)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.RelBallistics, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"Dribble", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, Dribble)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.Dribble, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"PalmDetectThreshold", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, PalmDetectThreshold)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.PalmDetectThreshold, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"MotionSensitivity", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, MotionSensitivity)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.MotionSensitivity, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"ManTrackEn", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, ManTrackEn)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.ManTrackEn, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"ManTrackedFinger", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, ManTrackedFinger)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.ManTrackedFinger, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DeltaXPosThreshold", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, DeltaXPosThreshold)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.DeltaXPosThreshold, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DeltaYPosThreshold", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, DeltaYPosThreshold)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.DeltaYPosThreshold, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"Velocity", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, Velocity)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.Velocity, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"Acceleration", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, Acceleration)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.Acceleration, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"SensorMaxXPos", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, SensorMaxXPos)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.SensorMaxXPos, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"SensorMaxYPos", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, SensorMaxYPos)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.SensorMaxYPos, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"ZTouchThreshold", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, ZTouchThreshold)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.ZTouchThreshold, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"ZHysteresis", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, ZHysteresis)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.ZHysteresis, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"SmallZThreshold", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, SmallZThreshold)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.SmallZThreshold, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"SmallZScaleFactor", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, SmallZScaleFactor)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.SmallZScaleFactor, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"LargeZScaleFactor", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, LargeZScaleFactor)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.LargeZScaleFactor, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"AlgorithmSelection", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, AlgorithmSelection)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.AlgorithmSelection, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"WxScaleFactor", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, WxScaleFactor)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.WxScaleFactor, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"WxOffset", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, WxOffset)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.WxOffset, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"WyScaleFactor", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, WyScaleFactor)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.WyScaleFactor, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"WyOffset", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, WyOffset)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.WyOffset, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"XPitch", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, XPitch)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.XPitch, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"YPitch", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, YPitch)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.YPitch, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"FingerWidthX", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, FingerWidthX)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.FingerWidthX, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"FingerWidthY", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, FingerWidthY)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.FingerWidthY, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"ReportMeasuredSize", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, ReportMeasuredSize)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.ReportMeasuredSize, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"SegmentationSensitivity", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, SegmentationSensitivity)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.SegmentationSensitivity, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"XClipLo", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, XClipLo)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.XClipLo, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"XClipHi", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, XClipHi)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.XClipHi, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"YClipLo", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, YClipLo)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.YClipLo, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"YClipHi", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, YClipHi)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.YClipHi, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"MinFingerSeparation", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, MinFingerSeparation)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.MinFingerSeparation, + sizeof(UINT32) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"MaxFingerMovement", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, TouchSettings) + + FIELD_OFFSET(RMI4_F11_CTRL_REGISTERS_LOGICAL, MaxFingerMovement)), + REG_DWORD, + &gDefaultConfiguration.TouchSettings.MaxFingerMovement, + sizeof(UINT32) + }, + + // + // Add new supported functions here + // + + // + // Internal driver settings + // + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"PepRemovesVoltageInD3", + (PVOID) (FIELD_OFFSET(RMI4_CONFIGURATION, PepRemovesVoltageInD3)), + REG_DWORD, + &gDefaultConfiguration.PepRemovesVoltageInD3, + sizeof(UINT32) + }, + + // + // List Terminator + // + { + NULL, 0, + NULL, + 0, + REG_DWORD, + NULL, + 0 + } +}; +static const ULONG gcbRegistryTable = sizeof(gRegistryTable); +static const ULONG gcRegistryTable = + sizeof(gRegistryTable) / sizeof(gRegistryTable[0]); + + +NTSTATUS +TchRegistryGetControllerSettings( + IN VOID* ControllerContext, + IN WDFDEVICE FxDevice + ) +/*++ + + Routine Description: + + This routine retrieves controller wide settings + from the registry. + + Arguments: + + FxDevice - a handle to the framework device object + Settings - A pointer to the chip settings structure + + Return Value: + + NTSTATUS indicating success or failure + +--*/ +{ + RMI4_CONTROLLER_CONTEXT* controller; + HANDLE hKey; + ULONG i; + WDFKEY key; + PRTL_QUERY_REGISTRY_TABLE regTable; + NTSTATUS status; + WDFKEY subkey; + DECLARE_CONST_UNICODE_STRING(subkeyName, L"Settings"); + + controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext; + + hKey = NULL; + key = NULL; + regTable = NULL; + subkey = NULL; + + // + // Obtain a WDM hkey for RtlQueryRegistryValues + // + + status = WdfDeviceOpenRegistryKey( + FxDevice, + PLUGPLAY_REGKEY_DEVICE, + KEY_READ, + WDF_NO_OBJECT_ATTRIBUTES, + &key); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_REGISTRY, + "Error opening device registry key - %!STATUS!", + status); + + goto exit; + } + + status = WdfRegistryOpenKey( + key, + &subkeyName, + KEY_READ, + WDF_NO_OBJECT_ATTRIBUTES, + &subkey); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_REGISTRY, + "Error opening device registry subkey - %!STATUS!", + status); + + goto exit; + } + + hKey = WdfRegistryWdmGetHandle(subkey); + + if (NULL == hKey) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_REGISTRY, + "Error getting WDM handle to WDF subkey"); + + goto exit; + } + + // + // RtlQueryRegistryValues table must be allocated from NonPagedPool + // + + regTable = ExAllocatePoolWithTag( + NonPagedPool, + gcbRegistryTable, + TOUCH_POOL_TAG); + + RtlCopyMemory( + regTable, + gRegistryTable, + gcbRegistryTable); + + // + // Update offset values with base pointer + // + + for (i=0; i < gcRegistryTable-1; i++) + { + regTable[i].EntryContext = (PVOID) ( + ((SIZE_T) regTable[i].EntryContext) + + ((ULONG_PTR) &controller->Config)); + } + + // + // Populate device context with registry or default configurations + // + + status = RtlQueryRegistryValues( + RTL_REGISTRY_HANDLE, + (PCWSTR) hKey, + regTable, + NULL, + NULL); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_REGISTRY, + "Error retrieving registry configuration - %!STATUS!", + status); + + goto exit; + } + +exit: + + if (!NT_SUCCESS(status)) + { + // + // Revert to default configuration values if there was an + // issue reading configuration data from the registry + // + RtlCopyMemory( + &controller->Config, + &gDefaultConfiguration, + sizeof(RMI4_CONFIGURATION)); + + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_REGISTRY, + "Error reading registry config, using defaults! - %!STATUS!", + status); + + status = STATUS_SUCCESS; + } + + if (subkey != NULL) + { + WdfRegistryClose(subkey); + } + + if (key != NULL) + { + WdfRegistryClose(key); + } + + if (regTable != NULL) + { + ExFreePoolWithTag(regTable, TOUCH_POOL_TAG); + } + + return status; +}
\ No newline at end of file diff --git a/input/hiddigi/SynapticsTouch/report.c b/input/hiddigi/SynapticsTouch/report.c new file mode 100644 index 00000000..e2e58406 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/report.c @@ -0,0 +1,864 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + report.c + + Abstract: + + Contains Synaptics specific code for reporting samples + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "controller.h" +#include "rmiinternal.h" +#include "spb.h" +#include "report.tmh" + +const USHORT gOEMVendorID = 0x7379; // "sy" +const USHORT gOEMProductID = 0x726D; // "rm" +const USHORT gOEMVersionID = 3200; + +const PWSTR gpwstrManufacturerID = L"Synaptics"; +const PWSTR gpwstrProductID = L"3200"; +const PWSTR gpwstrSerialNumber = L"4"; + +NTSTATUS +RmiServiceCapacitiveButtonInterrupt( + IN RMI4_CONTROLLER_CONTEXT* ControllerContext, + IN SPB_CONTEXT* SpbContext, + IN PHID_INPUT_REPORT HidReport + ) +/*++ + +Routine Description: + + This routine services capacitive button (F$1A) interrupts, it reads + button data and fills a HID keyboard report with the relevant information + +Arguments: + + ControllerContext - Touch controller context + SpbContext - A pointer to the current i2c context + HidReport- A HID report buffer to be filled with button data + +Return Value: + + NTSTATUS, where success indicates the request memory was updated with + button press information. + +--*/ +{ + RMI4_F1A_DATA_REGISTERS dataF1A; + PHID_KEY_REPORT hidKeys; + int index; + NTSTATUS status; + + // + // If the controller doesn't support buttons, ignore this interrupt + // + if (ControllerContext->HasButtons == FALSE) + { + status = STATUS_NOT_IMPLEMENTED; + goto exit; + } + + // + // Get the the key press/release information from the controller + // + index = RmiGetFunctionIndex( + ControllerContext->Descriptors, + ControllerContext->FunctionCount, + RMI4_F1A_0D_CAP_BUTTON_SENSOR); + + if (index == ControllerContext->FunctionCount) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Unexpected - RMI Function 1A missing"); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + + status = RmiChangePage( + ControllerContext, + SpbContext, + ControllerContext->FunctionOnPage[index]); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not change register page"); + + goto exit; + } + + // + // Read button press/release data + // + status = SpbReadDataSynchronously( + SpbContext, + ControllerContext->Descriptors[index].DataBase, + &dataF1A, + sizeof(dataF1A)); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error reading finger status data - %!STATUS!", + status); + + goto exit; + } + + RtlZeroMemory(HidReport, sizeof(HID_INPUT_REPORT)); + + // + // Update button states. This mapping should be made registry configurable + // + HidReport->ReportID = REPORTID_CAPKEY; + hidKeys = &(HidReport->KeyReport); + hidKeys->InputReport.bKeys |= (dataF1A.Button0) ? KEY_DOWN_SEARCH : 0; + hidKeys->InputReport.bKeys |= (dataF1A.Button1) ? KEY_DOWN_START : 0; + hidKeys->InputReport.bKeys |= (dataF1A.Button2) ? KEY_DOWN_BACK : 0; + + // + // On return of success, this request will be completed up the stack + // + +exit: + + return status; +} + +NTSTATUS +RmiGetTouchesFromController( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext, + IN RMI4_F11_DATA_REGISTERS *Data + ) +/*++ + +Routine Description: + + This routine reads raw touch messages from hardware. If there is + no touch data available (if a non-touch interrupt fired), the + function will not return success and no touch data was transferred. + +Arguments: + + ControllerContext - Touch controller context + SpbContext - A pointer to the current i2c context + Data - A pointer to any returned F11 touch data + +Return Value: + + NTSTATUS, where only success indicates data was returned + +--*/ +{ + NTSTATUS status; + RMI4_CONTROLLER_CONTEXT* controller; + int index, i; + int fingerStatus[RMI4_MAX_TOUCHES] = {0}; + int highestSlot; + + controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext; + + // + // Locate RMI data base address of 2D touch function + // + index = RmiGetFunctionIndex( + controller->Descriptors, + controller->FunctionCount, + RMI4_F11_2D_TOUCHPAD_SENSOR); + + if (index == controller->FunctionCount) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Unexpected - RMI Function 11 missing"); + + status = STATUS_INVALID_DEVICE_STATE; + goto exit; + } + + status = RmiChangePage( + ControllerContext, + SpbContext, + controller->FunctionOnPage[index]); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "Could not change register page"); + + goto exit; + } + + // + // Read finger statuses first, to determine how much data we need to read + // + status = SpbReadDataSynchronously( + SpbContext, + controller->Descriptors[index].DataBase, + &Data->Status, + sizeof(RMI4_F11_DATA_REGISTERS_STATUS_BLOCK)); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error reading finger status data - %!STATUS!", + status); + + goto exit; + } + + fingerStatus[0] = Data->Status.FingerState0; + fingerStatus[1] = Data->Status.FingerState1; + fingerStatus[2] = Data->Status.FingerState2; + fingerStatus[3] = Data->Status.FingerState3; + fingerStatus[4] = Data->Status.FingerState4; + fingerStatus[5] = Data->Status.FingerState5; + fingerStatus[6] = Data->Status.FingerState6; + fingerStatus[7] = Data->Status.FingerState7; + fingerStatus[8] = Data->Status.FingerState8; + fingerStatus[9] = Data->Status.FingerState9; + + // + // Compute the last slot containing data of interest + // + highestSlot = 0; + + for (i=0; i<RMI4_MAX_TOUCHES; i++) + { + // + // Find the highest slot we know has finger data + // + if (controller->Cache.FingerSlotValid & (1 << i)) + { + highestSlot = i; + } + } + + for (i=highestSlot+1; i<RMI4_MAX_TOUCHES; i++) + { + // + // New fingers in higher slots may need to be read + // + if (fingerStatus[i]) + { + highestSlot = i; + } + } + + // + // Read as much finger position data as we need to + // + status = SpbReadDataSynchronously( + SpbContext, + controller->Descriptors[index].DataBase + + sizeof(RMI4_F11_DATA_REGISTERS_STATUS_BLOCK), + &Data->Finger[0], + sizeof(RMI4_F11_DATA_POSITION) * (highestSlot+1)); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error reading finger status data - %!STATUS!", + status); + + goto exit; + } + +exit: + return status; +} + +VOID +RmiUpdateLocalFingerCache( + IN RMI4_F11_DATA_REGISTERS *Data, + IN RMI4_FINGER_CACHE *Cache + ) +/*++ + +Routine Description: + + This routine takes raw data reported by the Synaptics hardware and + parses it to update a local cache of finger states. This routine manages + removing lifted touches from the cache, and manages a map between the + order of reported touches in hardware, and the order the driver should + use in reporting. + +Arguments: + + Data - A pointer to the new data returned from hardware + Cache - A data structure holding various current finger state info + +Return Value: + + None. + +--*/ +{ + int fingerStatus[RMI4_MAX_TOUCHES] = {0}; + int i, j; + + // + // Unpack the finger statuses into an array to ease dealing with each + // finger uniformly in loops + // + fingerStatus[0] = Data->Status.FingerState0; + fingerStatus[1] = Data->Status.FingerState1; + fingerStatus[2] = Data->Status.FingerState2; + fingerStatus[3] = Data->Status.FingerState3; + fingerStatus[4] = Data->Status.FingerState4; + fingerStatus[5] = Data->Status.FingerState5; + fingerStatus[6] = Data->Status.FingerState6; + fingerStatus[7] = Data->Status.FingerState7; + fingerStatus[8] = Data->Status.FingerState8; + fingerStatus[9] = Data->Status.FingerState9; + + // + // When hardware was last read, if any slots reported as lifted, we + // must clean out the slot and old touch info. There may be new + // finger data using the slot. + // + for (i=0; i<RMI4_MAX_TOUCHES; i++) + { + // + // Sweep for a slot that needs to be cleaned + // + if (!(Cache->FingerSlotDirty & (1 << i))) + { + continue; + } + + NT_ASSERT(Cache->FingerDownCount > 0); + + // + // Find the slot in the reporting list + // + for (j=0; j<RMI4_MAX_TOUCHES; j++) + { + if (Cache->FingerDownOrder[j] == i) + { + break; + } + } + + NT_ASSERT(j != RMI4_MAX_TOUCHES); + + // + // Remove the slot. If the finger lifted was the last in the list, + // we just decrement the list total by one. If it was not last, we + // shift the trailing list items up by one. + // + for (; (j<Cache->FingerDownCount-1) && (j<RMI4_MAX_TOUCHES-1); j++) + { + Cache->FingerDownOrder[j] = Cache->FingerDownOrder[j+1]; + } + Cache->FingerDownCount--; + + // + // Finished, clobber the dirty bit + // + Cache->FingerSlotDirty &= ~(1 << i); + } + + // + // Cache the new set of finger data reported by hardware + // + for (i=0; i<RMI4_MAX_TOUCHES; i++) + { + // + // Take actions when a new contact is first reported as down + // + if ((fingerStatus[i] != RMI4_FINGER_STATE_NOT_PRESENT) && + ((Cache->FingerSlotValid & (1 << i)) == 0) && + (Cache->FingerDownCount < RMI4_MAX_TOUCHES)) + { + Cache->FingerSlotValid |= (1 << i); + Cache->FingerDownOrder[Cache->FingerDownCount++] = i; + } + + // + // Ignore slots with no new information + // + if (!(Cache->FingerSlotValid & (1 << i))) + { + continue; + } + + // + // Update local cache with new information from the controller + // + Cache->FingerSlot[i].fingerStatus = (UCHAR) fingerStatus[i]; + Cache->FingerSlot[i].x = (Data->Finger[i].XPosLo & 0xF) | + ((Data->Finger[i].XPosHi & 0xFF) << 4); + Cache->FingerSlot[i].y = (Data->Finger[i].YPosLo & 0xF) | + ((Data->Finger[i].YPosHi & 0xFF) << 4); + + // + // If a finger lifted, note the slot is now inactive so that any + // cached data is cleaned out before we read hardware again. + // + if (Cache->FingerSlot[i].fingerStatus == RMI4_FINGER_STATE_NOT_PRESENT) + { + Cache->FingerSlotDirty |= (1 << i); + Cache->FingerSlotValid &= ~(1 << i); + } + } +} + +VOID +RmiFillNextHidReportFromCache( + IN PHID_INPUT_REPORT HidReport, + IN RMI4_FINGER_CACHE *Cache, + IN PTOUCH_SCREEN_PROPERTIES Props, + IN int *TouchesReported, + IN int TouchesTotal + ) +/*++ + +Routine Description: + + This routine fills a HID report with the next one or two touch entries in + the local device finger cache. + + The routine also adjusts X/Y coordinates to match the desired display + coordinates. + +Arguments: + + HidReport - pointer to the HID report structure to fill + Cache - pointer to the local device finger cache + Props - information on how to adjust X/Y coordinates to match the display + TouchesReported - On entry, the number of touches (against total) that + have already been reported. As touches are transferred from the local + device cache to a HID report, this number is incremented. + TouchesTotal - total number of touches in the touch cache + +Return Value: + + None. + +--*/ +{ + PHID_TOUCH_REPORT hidTouch = NULL; + int currentlyReporting; + + HidReport->ReportID = REPORTID_MTOUCH; + hidTouch = &(HidReport->TouchReport); + + // + // Report the next available finger + // + currentlyReporting = Cache->FingerDownOrder[*TouchesReported]; + + hidTouch->InputReport.ContactId = (UCHAR) currentlyReporting; + hidTouch->InputReport.wXData = (USHORT) Cache->FingerSlot[currentlyReporting].x; + hidTouch->InputReport.wYData = (USHORT) Cache->FingerSlot[currentlyReporting].y; + + // + // Perform per-platform x/y adjustments to controller coordinates + // + TchTranslateToDisplayCoordinates( + &hidTouch->InputReport.wXData, + &hidTouch->InputReport.wYData, + Props); + + if (Cache->FingerSlot[currentlyReporting].fingerStatus) + { + hidTouch->InputReport.bStatus = RANGE_FINGER_STATUS; + } + + (*TouchesReported)++; + + // + // A single HID report can contain two touches, so see if there's more + // + if (TouchesTotal - *TouchesReported > 0) + { + currentlyReporting = Cache->FingerDownOrder[*TouchesReported]; + + hidTouch->InputReport.ContactId2 = (UCHAR) currentlyReporting; + hidTouch->InputReport.wXData2 = (USHORT) Cache->FingerSlot[currentlyReporting].x; + hidTouch->InputReport.wYData2 = (USHORT) Cache->FingerSlot[currentlyReporting].y; + + // + // Perform per-platform x/y adjustments to controller coordinates + // + TchTranslateToDisplayCoordinates( + &hidTouch->InputReport.wXData2, + &hidTouch->InputReport.wYData2, + Props); + + if (Cache->FingerSlot[currentlyReporting].fingerStatus) + { + hidTouch->InputReport.bStatus2 = RANGE_FINGER_STATUS; + } + + (*TouchesReported)++; + } + + // + // Though a single HID report can contain up to two touches, but more + // can be on the screen, ActualCount reflects the total number + // of touches that will be reported when the first report (of possibly + // many) is sent up + // + if (*TouchesReported == 1 || *TouchesReported == 2) + { + hidTouch->InputReport.ActualCount = (UCHAR) TouchesTotal; + } +} + +NTSTATUS +RmiServiceTouchDataInterrupt( + IN RMI4_CONTROLLER_CONTEXT* ControllerContext, + IN SPB_CONTEXT* SpbContext, + IN PHID_INPUT_REPORT HidReport, + IN UCHAR InputMode, + OUT BOOLEAN* PendingTouches + ) +/*++ + +Routine Description: + + Called when a touch interrupt needs service. Because we fill HID reports + with two touches at a time, if more than two touches were read from + hardware, we may need to complete this request from local cached state. + +Arguments: + + ControllerContext - Touch controller context + SpbContext - A pointer to the current SPB context (I2C, etc) + HidReport- Buffer to fill with a hid report if touch data is available + InputMode - Specifies mouse, single-touch, or multi-touch reporting modes + PendingTouches - Notifies caller if there are more touches to report, to + complete reporting the full state of fingers on the screen + +Return Value: + + NTSTATUS indicating whether or not the current hid report buffer was filled + + PendingTouches also indicates whether the caller should expect more than + one request to be completed to indicate the full state of fingers on + the screen +--*/ +{ + RMI4_F11_DATA_REGISTERS data; + NTSTATUS status; + + status = STATUS_SUCCESS; + RtlZeroMemory(&data, sizeof(data)); + NT_ASSERT(PendingTouches != NULL); + *PendingTouches = FALSE; + + // + // If no touches are unreported in our cache, read the next set of touches + // from hardware. + // + if (ControllerContext->TouchesReported == ControllerContext->TouchesTotal) + { + // + // See if new touch data is available + // + status = RmiGetTouchesFromController( + ControllerContext, + SpbContext, + &data + ); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_VERBOSE, + TRACE_FLAG_SAMPLES, + "No touch data to report - %!STATUS!", + status); + + goto exit; + } + + // + // Process the new touch data by updating our cached state + // + // + RmiUpdateLocalFingerCache( + &data, + &ControllerContext->Cache); + + // + // Prepare to report touches via HID reports + // + ControllerContext->TouchesReported = 0; + ControllerContext->TouchesTotal = + ControllerContext->Cache.FingerDownCount; + + // + // If no touches are present return that no data needed to be reported + // + if (ControllerContext->TouchesTotal == 0) + { + status = STATUS_NO_DATA_DETECTED; + goto exit; + } + } + + RtlZeroMemory(HidReport, sizeof(HID_INPUT_REPORT)); + + // + // Single-finger and HID-mouse input modes not implemented + // + if (MODE_MULTI_TOUCH != InputMode) + { + Trace( + TRACE_LEVEL_VERBOSE, + TRACE_FLAG_SAMPLES, + "Unable to report touches, only multitouch mode is supported"); + + status = STATUS_NOT_IMPLEMENTED; + goto exit; + } + + // + // Fill report with the next (max of two) cached touches + // + RmiFillNextHidReportFromCache( + HidReport, + &ControllerContext->Cache, + &ControllerContext->Props, + &ControllerContext->TouchesReported, + ControllerContext->TouchesTotal + ); + + // + // Update the caller if we still have outstanding touches to report + // + if (ControllerContext->TouchesReported < ControllerContext->TouchesTotal) + { + *PendingTouches = TRUE; + } + else + { + *PendingTouches = FALSE; + } + +exit: + + return status; +} + + +NTSTATUS +TchServiceInterrupts( + IN VOID *ControllerContext, + IN SPB_CONTEXT *SpbContext, + IN PHID_INPUT_REPORT HidReport, + IN UCHAR InputMode, + IN BOOLEAN *ServicingComplete + ) +/*++ + +Routine Description: + + This routine is called in response to an interrupt. The driver will + service chip interrupts, and if data is available to report to HID, + fill the Request object buffer with a HID report. + +Arguments: + + ControllerContext - Touch controller context + SpbContext - A pointer to the current i2c context + HidReport - Pointer to a HID_INPUT_REPORT structure to report to the OS + InputMode - Specifies mouse, single-touch, or multi-touch reporting modes + ServicingComplete - Notifies caller if there are more reports needed to + complete servicing interrupts coming from the hardware. + +Return Value: + + NTSTATUS indicating whether or not the current HidReport has been filled + + ServicingComplete indicates whether or not a new report buffer is required + to complete interrupt processing. +--*/ +{ + NTSTATUS status = STATUS_NO_DATA_DETECTED; + RMI4_CONTROLLER_CONTEXT* controller; + + controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext; + + NT_ASSERT(ServicingComplete != NULL); + + // + // Grab a waitlock to ensure the ISR executes serially and is + // protected against power state transitions + // + WdfWaitLockAcquire(controller->ControllerLock, NULL); + + // + // Check the interrupt source if no interrupts are pending processing + // + if (controller->InterruptStatus == 0) + { + status = RmiCheckInterrupts( + controller, + SpbContext, + &controller->InterruptStatus); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error servicing interrupts - %!STATUS!", + status); + + *ServicingComplete = FALSE; + goto exit; + } + } + + // + // Driver only services 0D cap button and 2D touch messages currently + // + if (controller->InterruptStatus & + ~(RMI4_INTERRUPT_BIT_0D_CAP_BUTTON | RMI4_INTERRUPT_BIT_2D_TOUCH)) + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_INTERRUPT, + "Ignoring following interrupt flags - %!STATUS!", + controller->InterruptStatus & + ~(RMI4_INTERRUPT_BIT_0D_CAP_BUTTON | + RMI4_INTERRUPT_BIT_2D_TOUCH)); + + // + // Mask away flags we don't service + // + controller->InterruptStatus &= + (RMI4_INTERRUPT_BIT_0D_CAP_BUTTON | + RMI4_INTERRUPT_BIT_2D_TOUCH); + } + + // + // RmiServiceXXX routine will change status to STATUS_SUCCESS if there + // is a HID report to process. + // + status = STATUS_UNSUCCESSFUL; + + // + // Service a capacitive button event if indicated by hardware + // + if (controller->InterruptStatus & RMI4_INTERRUPT_BIT_0D_CAP_BUTTON) + { + status = RmiServiceCapacitiveButtonInterrupt( + ControllerContext, + SpbContext, + HidReport); + + controller->InterruptStatus &= ~RMI4_INTERRUPT_BIT_0D_CAP_BUTTON; + + // + // Success indicates the report is ready to be sent, otherwise, + // continue to service interrupts. + // + if (NT_SUCCESS(status)) + { + goto exit; + } + else + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error processing cap button event - %!STATUS!", + status); + } + } + + // + // Service a touch data event if indicated by hardware + // + if (controller->InterruptStatus & RMI4_INTERRUPT_BIT_2D_TOUCH) + { + BOOLEAN pendingTouches = FALSE; + + status = RmiServiceTouchDataInterrupt( + ControllerContext, + SpbContext, + HidReport, + InputMode, + &pendingTouches); + + // + // If there are more touches to report, servicing is incomplete + // + if (pendingTouches == FALSE) + { + controller->InterruptStatus &= ~RMI4_INTERRUPT_BIT_2D_TOUCH; + } + + // + // Success indicates the report is ready to be sent, otherwise, + // continue to service interrupts. + // + if (NT_SUCCESS(status)) + { + goto exit; + } + else + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_INTERRUPT, + "Error processing touch event - %!STATUS!", + status); + } + } + + // + // Add servicing for additional touch interrupts here + // + +exit: + + // + // Indicate whether or not we're done servicing interrupts + // + if (controller->InterruptStatus == 0) + { + *ServicingComplete = TRUE; + } + else + { + *ServicingComplete = FALSE; + } + + WdfWaitLockRelease(controller->ControllerLock); + + return status; +} diff --git a/input/hiddigi/SynapticsTouch/resolutions.c b/input/hiddigi/SynapticsTouch/resolutions.c new file mode 100644 index 00000000..7cd1ea74 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/resolutions.c @@ -0,0 +1,526 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + resolutions.c + + Abstract: + + This module retrieves platform-specific configuration + parameters from the registry, and translates touch + controller pixel units to display pixel units. + + Environment: + + Kernel Mode + + Revision History: + +--*/ + +#include "rmiinternal.h" +#include "resolutions.tmh" + +// +// Registry values explaining the relationship of the touch +// controller coordinates to the physical LCD, as well as +// any differences between the physical LCD dimensons and +// viewable LCD area, are required. If not provided for whatever +// reason, we will assume everything is 480x800 and perfectly +// aligned. +// + +TOUCH_SCREEN_PROPERTIES gDefaultProperties = +{ + 0, + 0, + 0, + TOUCH_DEFAULT_RESOLUTION_X, + TOUCH_DEFAULT_RESOLUTION_Y, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + TOUCH_DEFAULT_RESOLUTION_X, + TOUCH_DEFAULT_RESOLUTION_Y, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + TOUCH_DEFAULT_RESOLUTION_X, + TOUCH_DEFAULT_RESOLUTION_Y +}; + + +RTL_QUERY_REGISTRY_TABLE gResParamsRegTable[] = +{ + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchSwapAxes", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchSwapAxes), + REG_DWORD, + &gDefaultProperties.TouchSwapAxes, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchInvertXAxis", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchInvertXAxis), + REG_DWORD, + &gDefaultProperties.TouchInvertXAxis, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchInvertYAxis", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchInvertYAxis), + REG_DWORD, + &gDefaultProperties.TouchInvertYAxis, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchPhysicalWidth", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchPhysicalWidth), + REG_DWORD, + &gDefaultProperties.TouchPhysicalWidth, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchPhysicalHeight", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchPhysicalHeight), + REG_DWORD, + &gDefaultProperties.TouchPhysicalHeight, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchPhysicalButtonHeight", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchPhysicalButtonHeight), + REG_DWORD, + &gDefaultProperties.TouchPhysicalButtonHeight, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchPillarBoxWidthLeft", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchPillarBoxWidthLeft), + REG_DWORD, + &gDefaultProperties.TouchPillarBoxWidthLeft, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchPillarBoxWidthRight", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchPillarBoxWidthRight), + REG_DWORD, + &gDefaultProperties.TouchPillarBoxWidthRight, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchLetterBoxHeightTop", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchLetterBoxHeightTop), + REG_DWORD, + &gDefaultProperties.TouchLetterBoxHeightTop, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"TouchLetterBoxHeightBottom", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, TouchLetterBoxHeightBottom), + REG_DWORD, + &gDefaultProperties.TouchLetterBoxHeightBottom, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DisplayPhysicalWidth", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, DisplayPhysicalWidth), + REG_DWORD, + &gDefaultProperties.DisplayPhysicalWidth, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DisplayPhysicalHeight", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, DisplayPhysicalHeight), + REG_DWORD, + &gDefaultProperties.DisplayPhysicalHeight, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DisplayViewableWidth", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, DisplayViewableWidth), + REG_DWORD, + &gDefaultProperties.DisplayViewableWidth, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DisplayViewableHeight", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, DisplayViewableHeight), + REG_DWORD, + &gDefaultProperties.DisplayViewableHeight, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DisplayPillarBoxWidthLeft", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, DisplayPillarBoxWidthLeft), + REG_DWORD, + &gDefaultProperties.DisplayPillarBoxWidthLeft, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DisplayPillarBoxWidthRight", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, DisplayPillarBoxWidthRight), + REG_DWORD, + &gDefaultProperties.DisplayPillarBoxWidthRight, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DisplayLetterBoxHeightTop", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, DisplayLetterBoxHeightTop), + REG_DWORD, + &gDefaultProperties.DisplayLetterBoxHeightTop, + sizeof(ULONG) + }, + { + NULL, RTL_QUERY_REGISTRY_DIRECT, + L"DisplayLetterBoxHeightBottom", + (PVOID) FIELD_OFFSET(TOUCH_SCREEN_PROPERTIES, DisplayLetterBoxHeightBottom), + REG_DWORD, + &gDefaultProperties.DisplayLetterBoxHeightBottom, + sizeof(ULONG) + }, + // + // List Terminator - set to NULL to indicate end of table + // + { + NULL, 0, + NULL, + 0, + REG_DWORD, + NULL, + 0 + } +}; + +static const ULONG gcbRegistryTable = sizeof(gResParamsRegTable); +static const ULONG gcRegistryTable = + sizeof(gResParamsRegTable) / sizeof(gResParamsRegTable[0]); + + +VOID +TchTranslateToDisplayCoordinates( + IN PUSHORT PX, + IN PUSHORT PY, + IN PTOUCH_SCREEN_PROPERTIES Props + ) +/*++ + + Routine Description: + + This routine performs translations on touch coordinates + to ensure points reported to the OS match pixels on the + display. + + Arguments: + + X - pointer to the pre-processed X coordinate + Y - pointer the pre-processed Y coordinate + Props - pointer to screen information + + Return Value: + + None. The X/Y values will be modified by this function. + +--*/ +{ + ULONG X; + ULONG Y; + + // + // Avoid overflow + // + X = (ULONG) *PX; + Y = (ULONG) *PY; + + // + // Swap the axes reported by the touch controller if requested + // + if (Props->TouchSwapAxes) + { + ULONG temp = Y; + Y = X; + X = temp; + } + + // + // Invert the coordinates as requested + // + if (Props->TouchInvertXAxis) + { + if (X >= Props->TouchPhysicalWidth) + { + X = Props->TouchPhysicalWidth - 1u; + } + + X = Props->TouchPhysicalWidth - X - 1u; + } + if (Props->TouchInvertYAxis) + { + if (Y >= Props->TouchPhysicalHeight) + { + Y = Props->TouchPhysicalHeight - 1u; + } + + Y = Props->TouchPhysicalHeight - Y - 1u; + } + + // + // Handle touch clipping boundaries so touch matches + // the physical display + // + if (X <= Props->TouchPillarBoxWidthLeft) + { + X = 0; + } + else + { + X -= Props->TouchPillarBoxWidthLeft; + } + if (Y <= Props->TouchLetterBoxHeightTop) + { + Y = 0; + } + else + { + Y -= Props->TouchLetterBoxHeightTop; + } + if (X >= Props->TouchAdjustedWidth) + { + X = Props->TouchAdjustedWidth - 1u; + } + if (Y >= Props->TouchAdjustedHeight) + { + Y = Props->TouchAdjustedHeight - 1u; + } + + // + // Scale the raw touch pixel units into physical display pixels, + // leaving off the capacitive button region. + // + X = X * Props->DisplayPhysicalWidth / Props->TouchAdjustedWidth; + Y = Y * Props->DisplayPhysicalHeight / + (Props->TouchAdjustedHeight - Props->TouchPhysicalButtonHeight); + + // + // If the display is additionally being letterboxed or pillarboxed, make + // further adjustments to the touch coordinates. + // + if (X <= Props->DisplayPillarBoxWidthLeft) + { + X = 0; + } + else + { + X -= Props->DisplayPillarBoxWidthLeft; + } + if (Y <= Props->DisplayLetterBoxHeightTop) + { + Y = 0; + } + else + { + Y -= Props->DisplayLetterBoxHeightTop; + } + if (X >= Props->DisplayAdjustedWidth) + { + X = Props->DisplayAdjustedWidth - 1u; + } + if (Y >= Props->DisplayAdjustedHeight) + { + Y = Props->DisplayAdjustedHeight - 1u; + } + + X = X * Props->DisplayViewableWidth / Props->DisplayAdjustedWidth; + Y = Y * Props->DisplayViewableHeight / + (Props->DisplayAdjustedHeight - Props->DisplayAdjustedButtonHeight); + + Trace( + TRACE_LEVEL_INFORMATION, + TRACE_FLAG_REPORTING, + "In (%d,%d), Out (%d,%d)", + *PX, *PY, X, Y); + + *PX = (USHORT) X; + *PY = (USHORT) Y; +} + +VOID +TchGetScreenProperties( + IN PTOUCH_SCREEN_PROPERTIES Props + ) +/*++ + + Routine Description: + + This routine retrieves coordinate translation settings + from the registry. + + Arguments: + + Props - receives the Props + + Return Value: + + None. On failure, defaults are returned. + +--*/ +{ + ULONG i; + PRTL_QUERY_REGISTRY_TABLE regTable; + NTSTATUS status; + + regTable = NULL; + + // + // Table passed to RtlQueryRegistryValues must be allocated + // from NonPagedPool + // + regTable = ExAllocatePoolWithTag( + NonPagedPool, + gcbRegistryTable, + TOUCH_POOL_TAG); + + RtlCopyMemory( + regTable, + gResParamsRegTable, + gcbRegistryTable); + + // + // Update offset values with base pointer + // + for (i=0; i < gcRegistryTable-1; i++) + { + regTable[i].EntryContext = (PVOID) ( + ((SIZE_T) regTable[i].EntryContext) + + ((ULONG_PTR) Props)); + } + + // + // Start with default values + // + RtlCopyMemory( + Props, + &gDefaultProperties, + sizeof(TOUCH_SCREEN_PROPERTIES)); + + // + // Populate device context with registry overrides (or defaults) + // + status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + TOUCH_SCREEN_PROPERTIES_REG_KEY, + regTable, + NULL, + NULL); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_WARNING, + TRACE_FLAG_REGISTRY, + "Error retrieving registry configuration - %!STATUS!", + status); + } + + // + // Sanity check values provided from the registry + // + + if (Props->TouchPillarBoxWidthLeft + + Props->TouchPillarBoxWidthRight >= + Props->TouchPhysicalWidth) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_REGISTRY, + "Invalid pillar box widths provided (%d,%d for %d)", + Props->TouchPillarBoxWidthLeft, + Props->TouchPillarBoxWidthRight, + Props->TouchPhysicalWidth); + + Props->TouchPillarBoxWidthLeft = + gDefaultProperties.TouchPillarBoxWidthLeft; + Props->TouchPillarBoxWidthRight = + gDefaultProperties.TouchPillarBoxWidthRight; + + } + + if (Props->TouchLetterBoxHeightTop + + Props->TouchLetterBoxHeightBottom >= + Props->TouchPhysicalHeight) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_REGISTRY, + "Invalid letter box heights provided (%d,%d for %d)", + Props->TouchLetterBoxHeightTop, + Props->TouchLetterBoxHeightBottom, + Props->TouchPhysicalHeight); + + Props->TouchLetterBoxHeightTop = + gDefaultProperties.TouchLetterBoxHeightTop; + Props->TouchLetterBoxHeightBottom = + gDefaultProperties.TouchLetterBoxHeightBottom; + } + + // + // Calculate a few parameters for later use + // + Props->TouchAdjustedWidth = + Props->TouchPhysicalWidth - + Props->TouchPillarBoxWidthLeft - + Props->TouchPillarBoxWidthRight; + + Props->TouchAdjustedHeight = + Props->TouchPhysicalHeight - + Props->TouchLetterBoxHeightTop - + Props->TouchLetterBoxHeightBottom; + + Props->DisplayAdjustedWidth = + Props->DisplayPhysicalWidth - + Props->DisplayPillarBoxWidthLeft - + Props->DisplayPillarBoxWidthRight; + + Props->DisplayAdjustedButtonHeight = + Props->TouchPhysicalButtonHeight * + Props->DisplayPhysicalHeight / + (Props->TouchAdjustedHeight - Props->TouchPhysicalButtonHeight); + + Props->DisplayAdjustedHeight = + Props->DisplayPhysicalHeight - + Props->DisplayLetterBoxHeightTop - + Props->DisplayLetterBoxHeightBottom + + Props->DisplayAdjustedButtonHeight; + + if (regTable != NULL) + { + ExFreePoolWithTag(regTable, TOUCH_POOL_TAG); + } +}
\ No newline at end of file diff --git a/input/hiddigi/SynapticsTouch/resolutions.h b/input/hiddigi/SynapticsTouch/resolutions.h new file mode 100644 index 00000000..e6de12c4 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/resolutions.h @@ -0,0 +1,66 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + resolutions.h + + Abstract: + + Contains resolution translation defines and types + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + +#define TOUCH_SCREEN_PROPERTIES_REG_KEY L"\\Registry\\Machine\\System\\TOUCH\\SCREENPROPERTIES" +#define TOUCH_DEFAULT_RESOLUTION_X 480 +#define TOUCH_DEFAULT_RESOLUTION_Y 800 +#define TOUCH_DEVICE_RESOLUTION_X 816 +#define TOUCH_DEVICE_RESOLUTION_Y 1394 + +typedef struct _TOUCH_SCREEN_PROPERTIES +{ + ULONG TouchSwapAxes; + ULONG TouchInvertXAxis; + ULONG TouchInvertYAxis; + ULONG TouchPhysicalWidth; + ULONG TouchPhysicalHeight; + ULONG TouchPhysicalButtonHeight; + ULONG TouchPillarBoxWidthLeft; + ULONG TouchPillarBoxWidthRight; + ULONG TouchLetterBoxHeightTop; + ULONG TouchLetterBoxHeightBottom; + ULONG TouchAdjustedWidth; + ULONG TouchAdjustedHeight; + ULONG DisplayPhysicalWidth; + ULONG DisplayPhysicalHeight; + ULONG DisplayAdjustedButtonHeight; + ULONG DisplayPillarBoxWidthLeft; + ULONG DisplayPillarBoxWidthRight; + ULONG DisplayLetterBoxHeightTop; + ULONG DisplayLetterBoxHeightBottom; + ULONG DisplayAdjustedWidth; + ULONG DisplayAdjustedHeight; + ULONG DisplayViewableWidth; + ULONG DisplayViewableHeight; +} TOUCH_SCREEN_PROPERTIES, *PTOUCH_SCREEN_PROPERTIES; + +VOID +TchGetScreenProperties( + IN PTOUCH_SCREEN_PROPERTIES Props + ); + +VOID +TchTranslateToDisplayCoordinates( + IN PUSHORT X, + IN PUSHORT Y, + IN PTOUCH_SCREEN_PROPERTIES Props + ); diff --git a/input/hiddigi/SynapticsTouch/rmiinternal.h b/input/hiddigi/SynapticsTouch/rmiinternal.h new file mode 100644 index 00000000..ae767e54 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/rmiinternal.h @@ -0,0 +1,579 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + rmiinternal.h + + Abstract: + + Contains common types and defintions used internally + by the multi touch screen driver. + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + +#include <wdm.h> +#include <wdf.h> +#include "controller.h" +#include "resolutions.h" + + +// Ignore warning C4152: nonstandard extension, function/data pointer conversion in expression +#pragma warning (disable : 4152) + +// Ignore warning C4201: nonstandard extension used : nameless struct/union +#pragma warning (disable : 4201) + +// Ignore warning C4201: nonstandard extension used : bit field types other than in +#pragma warning (disable : 4214) + +// Ignore warning C4324: 'xxx' : structure was padded due to __declspec(align()) +#pragma warning (disable : 4324) + + +// +// Defines from Synaptics RMI4 Data Sheet, please refer to +// the spec for details about the fields and values. +// + +#define RMI4_FIRST_FUNCTION_ADDRESS 0xE9 +#define RMI4_PAGE_SELECT_ADDRESS 0xFF + +#define RMI4_F01_RMI_DEVICE_CONTROL 0x01 +#define RMI4_F11_2D_TOUCHPAD_SENSOR 0x11 +#define RMI4_F1A_0D_CAP_BUTTON_SENSOR 0x1A +#define RMI4_F34_FLASH_MEMORY_MANAGEMENT 0x34 +#define RMI4_F54_TEST_REPORTING 0x54 + +#define RMI4_MAX_FUNCTIONS 10 +#define RMI4_MAX_TOUCHES 10 + +typedef struct _RMI4_FUNCTION_DESCRIPTOR +{ + BYTE QueryBase; + BYTE CommandBase; + BYTE ControlBase; + BYTE DataBase; + union + { + BYTE All; + struct + { + BYTE IrqCount : 3; + BYTE Reserved0 : 2; + BYTE FuncVer : 2; + BYTE Reserved1 : 1; + }; + } VersionIrq; + BYTE Number; +} RMI4_FUNCTION_DESCRIPTOR; + +// +// Function $01 - RMI Device Control +// + +typedef struct _RMI4_F01_QUERY_REGISTERS +{ + BYTE ManufacturerID; + union + { + BYTE All; + struct + { + BYTE CustomMap : 1; + BYTE NonCompliant : 1; + BYTE Reserved0 : 1; + BYTE HasSensorID : 1; + BYTE Reserved1 : 1; + BYTE HasAdjDoze : 1; + BYTE HasAdJDozeHold : 1; + BYTE Reserved2 : 1; + }; + } ProductProperties; + BYTE ProductInfo0; + BYTE ProductInfo1; + BYTE Date0; + BYTE Date1; + BYTE WaferLotId0Lo; + BYTE WaferLotId0Hi; + BYTE WaferLotId1Lo; + BYTE WaferLotId1Hi; + BYTE WaferLotId2Lo; + BYTE ProductID1; + BYTE ProductID2; + BYTE ProductID3; + BYTE ProductID4; + BYTE ProductID5; + BYTE ProductID6; + BYTE ProductID7; + BYTE ProductID8; + BYTE ProductID9; + BYTE ProductID10; + BYTE Reserved21; + BYTE SendorID; + BYTE Reserved23; + BYTE Reserved24; + BYTE Reserved25; + BYTE Reserved26; + BYTE Reserved27; + BYTE Reserved28; + BYTE Reserved29; + BYTE Reserved30; + BYTE Reserved31; +} RMI4_F01_QUERY_REGISTERS; + +typedef struct _RMI4_F01_CTRL_REGISTERS +{ + union + { + BYTE All; + struct + { + BYTE SleepMode :2; + BYTE NoSleep :1; + BYTE Reserved0 :3; + BYTE ReportRate :1; + BYTE Configured :1; + }; + } DeviceControl; + BYTE InterruptEnable; + BYTE DozeInterval; + BYTE DozeThreshold; + BYTE DozeHoldoff; +} RMI4_F01_CTRL_REGISTERS; + +#define RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_OPERATING 0 +#define RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_SLEEPING 1 + +// +// Logical structure for getting registry config settings +// +typedef struct _RM4_F01_CTRL_REGISTERS_LOGICAL +{ + UINT32 SleepMode; + UINT32 NoSleep; + UINT32 ReportRate; + UINT32 Configured; + UINT32 InterruptEnable; + UINT32 DozeInterval; + UINT32 DozeThreshold; + UINT32 DozeHoldoff; +} RMI4_F01_CTRL_REGISTERS_LOGICAL; + +#define RMI4_MILLISECONDS_TO_TENTH_MILLISECONDS(n) n/10 +#define RMI4_SECONDS_TO_HALF_SECONDS(n) 2*n + +typedef struct _RMI4_F01_DATA_REGISTERS +{ + union { + BYTE All; + struct + { + BYTE Status : 4; + BYTE Reserved0 : 2; + BYTE FlashProg : 1; + BYTE Unconfigured : 1; + }; + } DeviceStatus; + BYTE InterruptStatus[1]; +} RMI4_F01_DATA_REGISTERS; + +#define RMI4_INTERRUPT_BIT_2D_TOUCH 0x04 +#define RMI4_INTERRUPT_BIT_0D_CAP_BUTTON 0x20 + +#define RMI4_F01_DATA_STATUS_NO_ERROR 0 +#define RMI4_F01_DATA_STATUS_RESET_OCCURRED 1 +#define RMI4_F01_DATA_STATUS_INVALID_CONFIG 2 +#define RMI4_F01_DATA_STATUS_DEVICE_FAILURE 3 +#define RMI4_F01_DATA_STATUS_CONFIG_CRC_FAILURE 4 +#define RMI4_F01_DATA_STATUS_FW_CRC_FAILURE 5 +#define RMI4_F01_DATA_STATUS_CRC_IN_PROGRESS 6 + +typedef struct _RMI4_F01_COMMAND_REGISTERS +{ + BYTE Reset; +} RMI4_F01_COMMAND_REGISTERS; + +// +// Function $11 - 2-D Touch Sensor +// + +typedef struct _RMI4_F11_QUERY_REGISTERS +{ + struct + { + BYTE NumberOfSensors : 3; + BYTE Reserved0 : 1; + BYTE HasQuery11 : 1; + BYTE Reserved1 : 3; + }; + struct + { + BYTE NumberOfFingers : 3; + BYTE HasRelative : 1; + BYTE HasAbsolute : 1; + BYTE HasGestures : 1; + BYTE HasSensitivity : 1; + BYTE Configurable : 1; + }; + BYTE NumXElectrodes; + BYTE NumYElectrodes; + BYTE MaxElectrodes; + struct + { + BYTE AbsDataSize : 2; + BYTE HasAnchoredFin : 1; + BYTE HasAdjHyst : 1; + BYTE HasDribble : 1; + BYTE Reserved2 : 3; + }; + struct + { + BYTE HasZTuning : 1; + BYTE HasAlgoSelect : 1; + BYTE HasWTuning : 1; + BYTE HasPitchInfo : 1; + BYTE HasFingerSize : 1; + BYTE HasObjSensAdj : 1; + BYTE HasXYClip : 1; + BYTE HasDrummingAdj : 1; + }; +} RMI4_F11_QUERY_REGISTERS; + +typedef struct _RMI4_F11_CTRL_REGISTERS +{ + struct + { + BYTE ReportingMode : 3; + BYTE AbsPosFilt : 1; + BYTE RelPosFilt : 1; + BYTE RelBallistics : 1; + BYTE Dribble : 1; + BYTE Reserved0 : 1; + }; + struct + { + BYTE PalmDetectThreshold : 4; + BYTE MotionSensitivity : 2; + BYTE ManTrackEn : 1; + BYTE ManTrackedFinger : 1; + }; + BYTE DeltaXPosThreshold; + BYTE DeltaYPosThreshold; + BYTE Velocity; + BYTE Acceleration; + BYTE SensorMaxXPosLo; + struct + { + BYTE SensorMaxXPosHi : 4; + BYTE Reserved1 : 4; + }; + BYTE SensorMaxYPosLo; + struct + { + BYTE SensorMaxYPosHi : 4; + BYTE Reserved2 : 4; + }; + // + // Note gap in registers on 3200 + // + BYTE ZTouchThreshold; + BYTE ZHysteresis; + BYTE SmallZThreshold; + BYTE SmallZScaleFactor[2]; + BYTE LargeZScaleFactor[2]; + BYTE AlgorithmSelection; + BYTE WxScaleFactor; + BYTE WxOffset; + BYTE WyScaleFactor; + BYTE WyOffset; + BYTE XPitch[2]; + BYTE YPitch[2]; + BYTE FingerWidthX[2]; + BYTE FingerWidthY[2]; + BYTE ReportMeasuredSize; + BYTE SegmentationSensitivity; + BYTE XClipLo; + BYTE XClipHi; + BYTE YClipLo; + BYTE YClipHi; + BYTE MinFingerSeparation; + BYTE MaxFingerMovement; +} RMI4_F11_CTRL_REGISTERS; + +// +// Logical structure for getting registry config settings +// +typedef struct _RMI4_F11_CTRL_REGISTERS_LOGICAL +{ + UINT32 ReportingMode; + UINT32 AbsPosFilt; + UINT32 RelPosFilt; + UINT32 RelBallistics; + UINT32 Dribble; + UINT32 PalmDetectThreshold; + UINT32 MotionSensitivity; + UINT32 ManTrackEn; + UINT32 ManTrackedFinger; + UINT32 DeltaXPosThreshold; + UINT32 DeltaYPosThreshold; + UINT32 Velocity; + UINT32 Acceleration; + UINT32 SensorMaxXPos; + UINT32 SensorMaxYPos; + UINT32 ZTouchThreshold; + UINT32 ZHysteresis; + UINT32 SmallZThreshold; + UINT32 SmallZScaleFactor; + UINT32 LargeZScaleFactor; + UINT32 AlgorithmSelection; + UINT32 WxScaleFactor; + UINT32 WxOffset; + UINT32 WyScaleFactor; + UINT32 WyOffset; + UINT32 XPitch; + UINT32 YPitch; + UINT32 FingerWidthX; + UINT32 FingerWidthY; + UINT32 ReportMeasuredSize; + UINT32 SegmentationSensitivity; + UINT32 XClipLo; + UINT32 XClipHi; + UINT32 YClipLo; + UINT32 YClipHi; + UINT32 MinFingerSeparation; + UINT32 MaxFingerMovement; +} RMI4_F11_CTRL_REGISTERS_LOGICAL; + +typedef struct _RMI4_F11_DATA_POSITION +{ + BYTE XPosHi; + BYTE YPosHi; + struct + { + BYTE XPosLo : 4; + BYTE YPosLo : 4; + }; + struct + { + BYTE XWidth : 4; + BYTE YWidth : 4; + }; + BYTE ZAmplitude; +} RMI4_F11_DATA_POSITION; + +typedef struct _RMI4_F11_DATA_REGISTERS_STATUS_BLOCK +{ + struct + { + BYTE FingerState0 : 2; + BYTE FingerState1 : 2; + BYTE FingerState2 : 2; + BYTE FingerState3 : 2; + }; + struct + { + BYTE FingerState4 : 2; + BYTE FingerState5 : 2; + BYTE FingerState6 : 2; + BYTE FingerState7 : 2; + }; + struct + { + BYTE FingerState8 : 2; + BYTE FingerState9 : 2; + BYTE Reserved0 : 4; + }; +} RMI4_F11_DATA_REGISTERS_STATUS_BLOCK; + +typedef struct _RMI4_F11_DATA_REGISTERS +{ + RMI4_F11_DATA_REGISTERS_STATUS_BLOCK Status; + RMI4_F11_DATA_POSITION Finger[RMI4_MAX_TOUCHES]; +} RMI4_F11_DATA_REGISTERS; + +#define RMI4_FINGER_STATE_NOT_PRESENT 0 +#define RMI4_FINGER_STATE_PRESENT_WITH_ACCURATE_POS 1 +#define RMI4_FINGER_STATE_PRESENT_WITH_INACCURATE_POS 2 +#define RMI4_FINGER_STATE_RESERVED 3 + +// +// Function $1A - 0-D Capacitive Button Sensors +// + +typedef struct _RMI4_F1A_QUERY_REGISTERS +{ + struct + { + BYTE MaxButtonCount : 2; + BYTE Reserved0 : 5; + }; + struct + { + BYTE HasGenControl : 1; + BYTE HasIntEnable : 1; + BYTE HasMultiButSel : 1; + BYTE HasTxRxMapping : 1; + BYTE HasPerButThresh : 1; + BYTE HasRelThresh : 1; + BYTE HasStrongButHyst: 1; + BYTE HasFiltStrength : 1; + }; +} RMI4_F1A_QUERY_REGISTERS; + +typedef struct _RMI4_F1A_CTRL_REGISTERS +{ + struct + { + BYTE MultiButtonRpt : 2; + BYTE FilterMode : 2; + BYTE Reserved0 : 4; + }; + struct + { + BYTE IntEnBtn0 : 1; + BYTE IntEnBtn1 : 1; + BYTE IntEnBtn2 : 1; + BYTE IntEnBtn3 : 1; + BYTE Reserved1 : 4; + }; + struct + { + BYTE MultiBtn0 : 1; + BYTE MultiBtn1 : 1; + BYTE MultiBtn2 : 1; + BYTE MultiBtn3 : 1; + BYTE Reserved2 : 4; + }; + BYTE PhysicalTx0; + BYTE PhysicalRx0; + BYTE PhysicalTx1; + BYTE PhysicalRx1; + BYTE PhysicalTx2; + BYTE PhysicalRx2; + BYTE PhysicalTx3; + BYTE PhysicalRx3; + BYTE Threshold0; + BYTE Threshold1; + BYTE Threshold2; + BYTE Threshold3; + BYTE ReleaseThreshold; + BYTE StrongButtonHyst; + BYTE FilterStrength; +} RMI4_F1A_CTRL_REGISTERS; + +typedef struct _RMI4_F1A_DATA_REGISTERS +{ + struct + { + BYTE Button0 : 1; + BYTE Button1 : 1; + BYTE Button2 : 1; + BYTE Button3 : 1; + BYTE Reserved0 : 4; + }; +} RMI4_F1A_DATA_REGISTERS; + +// +// Function $XX - Add new support functions here +// + + +// +// Driver structures +// + +typedef struct _RMI4_CONFIGURATION +{ + RMI4_F01_CTRL_REGISTERS_LOGICAL DeviceSettings; + RMI4_F11_CTRL_REGISTERS_LOGICAL TouchSettings; + UINT32 PepRemovesVoltageInD3; +} RMI4_CONFIGURATION; + +typedef struct _RMI4_FINGER_INFO +{ + int x; + int y; + UCHAR fingerStatus; +} RMI4_FINGER_INFO; + +typedef struct _RMI4_FINGER_CACHE +{ + RMI4_FINGER_INFO FingerSlot[RMI4_MAX_TOUCHES]; + UINT32 FingerSlotValid; + UINT32 FingerSlotDirty; + int FingerDownOrder[RMI4_MAX_TOUCHES]; + int FingerDownCount; +} RMI4_FINGER_CACHE; + +typedef struct _RMI4_CONTROLLER_CONTEXT +{ + WDFDEVICE FxDevice; + WDFWAITLOCK ControllerLock; + + // + // Controller state + // + int FunctionCount; + RMI4_FUNCTION_DESCRIPTOR Descriptors[RMI4_MAX_FUNCTIONS]; + int FunctionOnPage[RMI4_MAX_FUNCTIONS]; + int CurrentPage; + + ULONG InterruptStatus; + BOOLEAN HasButtons; + BOOLEAN ResetOccurred; + BOOLEAN InvalidConfiguration; + BOOLEAN DeviceFailure; + BOOLEAN UnknownStatus; + BYTE UnknownStatusMessage; + RMI4_F01_QUERY_REGISTERS F01QueryRegisters; + + // + // Power state + // + DEVICE_POWER_STATE DevicePowerState; + + // + // Register configuration programmed to chip + // + TOUCH_SCREEN_PROPERTIES Props; + RMI4_CONFIGURATION Config; + + // + // Current touch state + // + int TouchesReported; + int TouchesTotal; + RMI4_FINGER_CACHE Cache; + +} RMI4_CONTROLLER_CONTEXT; + +NTSTATUS +RmiCheckInterrupts( + IN RMI4_CONTROLLER_CONTEXT *ControllerContext, + IN SPB_CONTEXT *SpbContext, + IN ULONG* InterruptStatus + ); + +int +RmiGetFunctionIndex( + IN RMI4_FUNCTION_DESCRIPTOR* FunctionDescriptors, + IN int FunctionCount, + IN int FunctionDesired + ); + +NTSTATUS +RmiChangePage( + IN RMI4_CONTROLLER_CONTEXT* ControllerContext, + IN SPB_CONTEXT* SpbContext, + IN int DesiredPage + ); diff --git a/input/hiddigi/SynapticsTouch/spb.c b/input/hiddigi/SynapticsTouch/spb.c new file mode 100644 index 00000000..4ec7c179 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/spb.c @@ -0,0 +1,512 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + spb.c + + Abstract: + + Contains all I2C-specific functionality + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#include "internal.h" +#include "controller.h" +#include "spb.tmh" + +NTSTATUS +SpbDoWriteDataSynchronously( + IN SPB_CONTEXT *SpbContext, + IN UCHAR Address, + IN PVOID Data, + IN ULONG Length + ) +/*++ + + Routine Description: + + This helper routine abstracts creating and sending an I/O + request (I2C Write) to the Spb I/O target. + + Arguments: + + SpbContext - Pointer to the current device context + Address - The I2C register address to write to + Data - A buffer to receive the data at at the above address + Length - The amount of data to be read from the above address + + Return Value: + + NTSTATUS Status indicating success or failure + +--*/ +{ + PUCHAR buffer; + ULONG length; + WDFMEMORY memory; + WDF_MEMORY_DESCRIPTOR memoryDescriptor; + NTSTATUS status; + + // + // The address pointer and data buffer must be combined + // into one contiguous buffer representing the write transaction. + // + length = Length + 1; + memory = NULL; + + if (length > DEFAULT_SPB_BUFFER_SIZE) + { + status = WdfMemoryCreate( + WDF_NO_OBJECT_ATTRIBUTES, + NonPagedPool, + TOUCH_POOL_TAG, + length, + &memory, + &buffer); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error allocating memory for Spb write - %!STATUS!", + status); + goto exit; + } + + WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( + &memoryDescriptor, + memory, + NULL); + } + else + { + buffer = (PUCHAR) WdfMemoryGetBuffer(SpbContext->WriteMemory, NULL); + + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( + &memoryDescriptor, + (PVOID) buffer, + length); + } + + // + // Transaction starts by specifying the address bytes + // + RtlCopyMemory(buffer, &Address, sizeof(Address)); + + // + // Address is followed by the data payload + // + RtlCopyMemory((buffer+sizeof(Address)), Data, length-sizeof(Address)); + + status = WdfIoTargetSendWriteSynchronously( + SpbContext->SpbIoTarget, + NULL, + &memoryDescriptor, + NULL, + NULL, + NULL); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error writing to Spb - %!STATUS!", + status); + goto exit; + } + +exit: + + if (NULL != memory) + { + WdfObjectDelete(memory); + } + + return status; +} + +NTSTATUS +SpbWriteDataSynchronously( + IN SPB_CONTEXT *SpbContext, + IN UCHAR Address, + IN PVOID Data, + IN ULONG Length + ) +/*++ + + Routine Description: + + This routine abstracts creating and sending an I/O + request (I2C Write) to the Spb I/O target and utilizes + a helper routine to do work inside of locked code. + + Arguments: + + SpbContext - Pointer to the current device context + Address - The I2C register address to write to + Data - A buffer to receive the data at at the above address + Length - The amount of data to be read from the above address + + Return Value: + + NTSTATUS Status indicating success or failure + +--*/ +{ + NTSTATUS status; + + WdfWaitLockAcquire(SpbContext->SpbLock, NULL); + + status = SpbDoWriteDataSynchronously( + SpbContext, + Address, + Data, + Length); + + WdfWaitLockRelease(SpbContext->SpbLock); + + return status; +} + +NTSTATUS +SpbReadDataSynchronously( + _In_ SPB_CONTEXT *SpbContext, + _In_ UCHAR Address, + _In_reads_bytes_(Length) PVOID Data, + _In_ ULONG Length + ) +/*++ + + Routine Description: + + This helper routine abstracts creating and sending an I/O + request (I2C Read) to the Spb I/O target. + + Arguments: + + SpbContext - Pointer to the current device context + Address - The I2C register address to read from + Data - A buffer to receive the data at at the above address + Length - The amount of data to be read from the above address + + Return Value: + + NTSTATUS Status indicating success or failure + +--*/ +{ + PUCHAR buffer; + WDFMEMORY memory; + WDF_MEMORY_DESCRIPTOR memoryDescriptor; + NTSTATUS status; + ULONG_PTR bytesRead; + + WdfWaitLockAcquire(SpbContext->SpbLock, NULL); + + memory = NULL; + status = STATUS_INVALID_PARAMETER; + bytesRead = 0; + + // + // Read transactions start by writing an address pointer + // + status = SpbDoWriteDataSynchronously( + SpbContext, + Address, + NULL, + 0); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error setting address pointer for Spb read - %!STATUS!", + status); + goto exit; + } + + if (Length > DEFAULT_SPB_BUFFER_SIZE) + { + status = WdfMemoryCreate( + WDF_NO_OBJECT_ATTRIBUTES, + NonPagedPool, + TOUCH_POOL_TAG, + Length, + &memory, + &buffer); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error allocating memory for Spb read - %!STATUS!", + status); + goto exit; + } + + WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( + &memoryDescriptor, + memory, + NULL); + } + else + { + buffer = (PUCHAR) WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); + + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( + &memoryDescriptor, + (PVOID) buffer, + Length); + } + + + status = WdfIoTargetSendReadSynchronously( + SpbContext->SpbIoTarget, + NULL, + &memoryDescriptor, + NULL, + NULL, + &bytesRead); + + if (!NT_SUCCESS(status) || + bytesRead != Length) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error reading from Spb - %!STATUS!", + status); + goto exit; + } + + // + // Copy back to the caller's buffer + // + RtlCopyMemory(Data, buffer, Length); + +exit: + if (NULL != memory) + { + WdfObjectDelete(memory); + } + + WdfWaitLockRelease(SpbContext->SpbLock); + + return status; +} + +VOID +SpbTargetDeinitialize( + IN WDFDEVICE FxDevice, + IN SPB_CONTEXT *SpbContext + ) +/*++ + + Routine Description: + + This helper routine is used to free any members added to the SPB_CONTEXT, + note the SPB I/O target is parented to the device and will be + closed and free'd when the device is removed. + + Arguments: + + FxDevice - Handle to the framework device object + SpbContext - Pointer to the current device context + + Return Value: + + NTSTATUS Status indicating success or failure + +--*/ +{ + UNREFERENCED_PARAMETER(FxDevice); + UNREFERENCED_PARAMETER(SpbContext); + + // + // Free any SPB_CONTEXT allocations here + // + if (SpbContext->SpbLock != NULL) + { + WdfObjectDelete(SpbContext->SpbLock); + } + + if (SpbContext->ReadMemory != NULL) + { + WdfObjectDelete(SpbContext->ReadMemory); + } + + if (SpbContext->WriteMemory != NULL) + { + WdfObjectDelete(SpbContext->WriteMemory); + } +} + +NTSTATUS +SpbTargetInitialize( + IN WDFDEVICE FxDevice, + IN SPB_CONTEXT *SpbContext + ) +/*++ + + Routine Description: + + This helper routine opens the Spb I/O target and + initializes a request object used for the lifetime + of communication between this driver and Spb. + + Arguments: + + FxDevice - Handle to the framework device object + SpbContext - Pointer to the current device context + + Return Value: + + NTSTATUS Status indicating success or failure + +--*/ +{ + WDF_OBJECT_ATTRIBUTES objectAttributes; + WDF_IO_TARGET_OPEN_PARAMS openParams; + UNICODE_STRING spbDeviceName; + WCHAR spbDeviceNameBuffer[RESOURCE_HUB_PATH_SIZE]; + NTSTATUS status; + + WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); + objectAttributes.ParentObject = FxDevice; + + status = WdfIoTargetCreate( + FxDevice, + &objectAttributes, + &SpbContext->SpbIoTarget); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error creating IoTarget object - %!STATUS!", + status); + + WdfObjectDelete(SpbContext->SpbIoTarget); + goto exit; + } + + RtlInitEmptyUnicodeString( + &spbDeviceName, + spbDeviceNameBuffer, + sizeof(spbDeviceNameBuffer)); + + status = RESOURCE_HUB_CREATE_PATH_FROM_ID( + &spbDeviceName, + SpbContext->I2cResHubId.LowPart, + SpbContext->I2cResHubId.HighPart); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error creating Spb resource hub path string - %!STATUS!", + status); + goto exit; + } + + WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( + &openParams, + &spbDeviceName, + (GENERIC_READ | GENERIC_WRITE)); + + openParams.ShareAccess = 0; + openParams.CreateDisposition = FILE_OPEN; + openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; + + status = WdfIoTargetOpen(SpbContext->SpbIoTarget, &openParams); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error opening Spb target for communication - %!STATUS!", + status); + goto exit; + } + + // + // Allocate some fixed-size buffers from NonPagedPool for typical + // Spb transaction sizes to avoid pool fragmentation in most cases + // + status = WdfMemoryCreate( + WDF_NO_OBJECT_ATTRIBUTES, + NonPagedPool, + TOUCH_POOL_TAG, + DEFAULT_SPB_BUFFER_SIZE, + &SpbContext->WriteMemory, + NULL); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error allocating default memory for Spb write - %!STATUS!", + status); + goto exit; + } + + status = WdfMemoryCreate( + WDF_NO_OBJECT_ATTRIBUTES, + NonPagedPool, + TOUCH_POOL_TAG, + DEFAULT_SPB_BUFFER_SIZE, + &SpbContext->ReadMemory, + NULL); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error allocating default memory for Spb read - %!STATUS!", + status); + goto exit; + } + + // + // Allocate a waitlock to guard access to the default buffers + // + status = WdfWaitLockCreate( + WDF_NO_OBJECT_ATTRIBUTES, + &SpbContext->SpbLock); + + if (!NT_SUCCESS(status)) + { + Trace( + TRACE_LEVEL_ERROR, + TRACE_FLAG_SPB, + "Error creating Spb Waitlock - %!STATUS!", + status); + goto exit; + } + +exit: + + if (!NT_SUCCESS(status)) + { + SpbTargetDeinitialize(FxDevice, SpbContext); + } + + return status; +} diff --git a/input/hiddigi/SynapticsTouch/spb.h b/input/hiddigi/SynapticsTouch/spb.h new file mode 100644 index 00000000..15ba8ae6 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/spb.h @@ -0,0 +1,67 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + spb.h + + Abstract: + + This module contains the touch driver I2C helper definitions. + + Environment: + + Kernel Mode + + Revision History: + +--*/ + +#pragma once + +#include <wdm.h> +#include <wdf.h> + +#define DEFAULT_SPB_BUFFER_SIZE 64 + +// +// SPB (I2C) context +// + +typedef struct _SPB_CONTEXT +{ + WDFIOTARGET SpbIoTarget; + LARGE_INTEGER I2cResHubId; + WDFMEMORY WriteMemory; + WDFMEMORY ReadMemory; + WDFWAITLOCK SpbLock; +} SPB_CONTEXT; + +NTSTATUS +SpbReadDataSynchronously( + _In_ SPB_CONTEXT *SpbContext, + _In_ UCHAR Address, + _In_reads_bytes_(Length) PVOID Data, + _In_ ULONG Length + ); + +VOID +SpbTargetDeinitialize( + IN WDFDEVICE FxDevice, + IN SPB_CONTEXT *SpbContext + ); + +NTSTATUS +SpbTargetInitialize( + IN WDFDEVICE FxDevice, + IN SPB_CONTEXT *SpbContext + ); + +NTSTATUS +SpbWriteDataSynchronously( + IN SPB_CONTEXT *SpbContext, + IN UCHAR Address, + IN PVOID Data, + IN ULONG Length + ); diff --git a/input/hiddigi/SynapticsTouch/trace.h b/input/hiddigi/SynapticsTouch/trace.h new file mode 100644 index 00000000..0af97194 --- /dev/null +++ b/input/hiddigi/SynapticsTouch/trace.h @@ -0,0 +1,49 @@ +/*++ + Copyright (c) Microsoft Corporation. All Rights Reserved. + Sample code. Dealpoint ID #843729. + + Module Name: + + trace.h + + Abstract: + + Contains prototypes and definitions related to debugging/tracing + + Environment: + + Kernel mode + + Revision History: + +--*/ + +#pragma once + +// +// Control GUID: +// {64BAF936-E94C-4747-91E3-BB4CB8328E5F} +// + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID( \ + TouchDriverTraceGuid, \ + (64BAF936,E94C,4747,91E3,BB4CB8328E5F), \ + WPP_DEFINE_BIT(TRACE_FLAG_INIT) \ + WPP_DEFINE_BIT(TRACE_FLAG_REGISTRY) \ + WPP_DEFINE_BIT(TRACE_FLAG_HID) \ + WPP_DEFINE_BIT(TRACE_FLAG_PNP) \ + WPP_DEFINE_BIT(TRACE_FLAG_POWER) \ + WPP_DEFINE_BIT(TRACE_FLAG_SPB) \ + WPP_DEFINE_BIT(TRACE_FLAG_CONFIG) \ + WPP_DEFINE_BIT(TRACE_FLAG_REPORTING) \ + WPP_DEFINE_BIT(TRACE_FLAG_INTERRUPT) \ + WPP_DEFINE_BIT(TRACE_FLAG_SAMPLES) \ + WPP_DEFINE_BIT(TRACE_FLAG_OTHER) \ + WPP_DEFINE_BIT(TRACE_FLAG_IDLE) \ + ) + +#define WPP_LEVEL_FLAGS_LOGGER(level,flags) WPP_LEVEL_LOGGER(flags) +#define WPP_LEVEL_FLAGS_ENABLED(level,flags) \ + (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= level) + diff --git a/input/kbfiltr/ReadMe.md b/input/kbfiltr/ReadMe.md new file mode 100644 index 00000000..d902befe --- /dev/null +++ b/input/kbfiltr/ReadMe.md @@ -0,0 +1,119 @@ +Keyboard Input WDF Filter Driver (Kbfiltr) +========================================== + +The Kbdfltr sample is an example of a keyboard input filter driver. + +This sample is WDF version of the original WDM filter driver sample. The WDM version of this sample has been deprecated. + +This is an upper device filter driver sample for PS/2 keyboard. This driver layers in between the KbdClass driver and i8042prt driver and hooks the callback routine that moves keyboard inputs from the port driver to class driver. In its current state, it only hooks into the keyboard packet report chain, the keyboard initialization function, and the keyboard ISR, but does not do any processing of the data that it sees. (The hooking of the initialization function and ISR is only available in the i8042prt stack.) With additions to this current filter-only code base, the filter could conceivably add, remove, or modify input as needed. + +This sample also creates a raw PDO and registers an interface so that applications can talk to the filter driver directly without going through the PS/2 devicestack. The reason for providing this additional interface is because the keyboard device is an exclusive secure device and it's not possible to open the device from usermode and send custom ioctls through it. + +This driver filters input for a particular keyboard on the system. If you want to filter keyboard inputs from all the keyboards plugged into the system, you can install this driver as a class filter below the KbdClass filter driver by adding the service name of this filter driver before the KbdClass filter in the registry at: +`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE10318}\UpperFilters` + +## Universal Windows Driver Compliant +This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. + +Set the hardware ID in the inx file +----------------------------------- + +This step is required for automatic deployment (described later) to work properly. In the kbfiltr.inx file (located with the driver source files), find the [DDK\_Ex.Mfg.NT\$ARCH\$] section. Change the hardware ID in the %DDK\_Ex% entry from the dummy value to the hardware ID of the PS/2 keyboard on the target computer. The following example shows the hardware ID change. + +``` {.syntax xml:space="preserve"} +; For XP and above +[DDK_Ex.Mfg.NT$ARCH$] +;%DDK_Ex% = kbfiltr, *PNP0BAAD +%DDK_Ex% = kbfiltr, ACPI\VEN_PNP&DEV_0303 +``` + +Build the sample using Visual Studio +------------------------------------ + +In Visual Studio, on the **Build** menu, choose **Build Solution**. + +For more information about using Visual Studio to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). + +The test application, *kbftest.exe* is also built as part of the solution under the 'exe' folder. + +Locate the built driver package +------------------------------- + +In File Explorer, navigate to the folder that contains your built driver package. The location of this folder varies depending on what you set for configuration and platform. For example, if your settings are Win7 Debug and x64, the package is your solution folder under x64\\Win7Debug\\Package. + +The package contains these files: + +<table> +<colgroup> +<col width="50%" /> +<col width="50%" /> +</colgroup> +<thead> +<tr class="header"> +<th align="left">File +Description</th> +</tr> +</thead> +<tbody> +<tr class="odd"> +<td align="left">Kmdfsamples.cat +A signed catalog file, which serves as the signature for the entire package.</td> +<td align="left">kbfiltr.inf +An information (INF) file that contains information needed to install the driver.</td> +</tr> +</tbody> +</table> + +Using MSBuild +------------- + +As an alternative to building the Kbfiltr Filter Driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, kbfiltr.sln. Use the [MSBuild](http://go.microsoft.com/fwlink/p/?linkID=262804) command to build the solution. Here are some examples: + +**msbuild /p:configuration=”Win7 Debug” /p:platform=”x64” kbfiltr.sln** + +**msbuild /p:configuration=”Win8 Release” /p:platform=”win32” kbfiltr.sln** + +For more information about using [MSBuild](http://go.microsoft.com/fwlink/p/?linkID=262804) to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). + +Run the sample +-------------- + +The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from where you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*. + +The process of moving the driver package to the target computer and installing the driver is called *deploying the driver*. You can deploy kbfiltr sample driver automatically or manually. + +Automatic deployment +-------------------- + +Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). + +1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**. +2. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Install and Verify**, and choose **Default Driver Package Installation Task** in the list. Click **OK**. +3. On the **Build** menu, choose **Deploy Package** or **Build Solution**. + +Manual deployment +----------------- + +Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](http://msdn.microsoft.com/en-us/library/windows/hardware/dn265571). + +1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\KbfiltrDriverPackage). +2. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the Devcon command with the correct hardware ID, such as: + + **Devcon install kbfiltr.inf ACPI\\VEN\_PNP&DEV\_0303** + + -or- + + Using Device Manager, update the driver for the PS/2 Keyboard by manually selecting kbfiltr.inf from the location where you copied the driver files. + +View the installed driver in Device Manager +------------------------------------------- + +On the target computer, in a Command Prompt window, enter **devmgmt** to open Device Manager. In Device Manager, on the **View** menu, choose **Devices by type**. In the device tree, locate **DDK Example Device that needs filtering** under the **Keyboards** node. + +Testing +------- + +To use the test application provided with the sample, it must be copied to the target computer manually. Save the kbftest.exe file from the folder where the build result is placed (for example, exe\\x64\\Win7Debug). This file is copied somewhere on the target, possibly where the driver package files are located. The test application is the executed on the target computer in a Command Prompt using **kbftest** as the command. + +**Tip** To avoid DLL dependencies for kbftext.exe, and the need to copy additional files, select the statically linked run-time library when building. + diff --git a/input/kbfiltr/exe/kbftest.c b/input/kbfiltr/exe/kbftest.c new file mode 100644 index 00000000..b4c43acb --- /dev/null +++ b/input/kbfiltr/exe/kbftest.c @@ -0,0 +1,239 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + KBFTEST.C + +Abstract: + + +Environment: + + usermode console application + +--*/ + + +#include <basetyps.h> +#include <stdlib.h> +#include <wtypes.h> +#include <initguid.h> +#include <stdio.h> +#include <string.h> +#include <conio.h> +#include <ntddkbd.h> + +#pragma warning(disable:4201) + +#include <setupapi.h> +#include <winioctl.h> + +#pragma warning(default:4201) + +#include "..\sys\public.h" + +//----------------------------------------------------------------------------- +// 4127 -- Conditional Expression is Constant warning +//----------------------------------------------------------------------------- +#define WHILE(constant) \ +__pragma(warning(disable: 4127)) while(constant); __pragma(warning(default: 4127)) + +DEFINE_GUID(GUID_DEVINTERFACE_KBFILTER, +0x3fb7299d, 0x6847, 0x4490, 0xb0, 0xc9, 0x99, 0xe0, 0x98, 0x6a, 0xb8, 0x86); +// {3FB7299D-6847-4490-B0C9-99E0986AB886} + + +int +_cdecl +main( + _In_ int argc, + _In_ char *argv[] + ) +{ + HDEVINFO hardwareDeviceInfo; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = NULL; + ULONG predictedLength = 0; + ULONG requiredLength = 0, bytes=0; + HANDLE file; + ULONG i =0; + KEYBOARD_ATTRIBUTES kbdattrib; + + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + // + // Open a handle to the device interface information set of all + // present toaster class interfaces. + // + + hardwareDeviceInfo = SetupDiGetClassDevs ( + (LPGUID)&GUID_DEVINTERFACE_KBFILTER, + NULL, // Define no enumerator (global) + NULL, // Define no + (DIGCF_PRESENT | // Only Devices present + DIGCF_DEVICEINTERFACE)); // Function class devices. + if(INVALID_HANDLE_VALUE == hardwareDeviceInfo) + { + printf("SetupDiGetClassDevs failed: %x\n", GetLastError()); + return 0; + } + + deviceInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); + + printf("\nList of KBFILTER Device Interfaces\n"); + printf("---------------------------------\n"); + + i = 0; + + // + // Enumerate devices of toaster class + // + + do { + if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo, + 0, // No care about specific PDOs + (LPGUID)&GUID_DEVINTERFACE_KBFILTER, + i, // + &deviceInterfaceData)) { + + if(deviceInterfaceDetailData) { + free (deviceInterfaceDetailData); + deviceInterfaceDetailData = NULL; + } + + // + // Allocate a function class device data structure to + // receive the information about this particular device. + // + + // + // First find out required length of the buffer + // + + if(!SetupDiGetDeviceInterfaceDetail ( + hardwareDeviceInfo, + &deviceInterfaceData, + NULL, // probing so no output buffer yet + 0, // probing so output buffer length of zero + &requiredLength, + NULL)) { // not interested in the specific dev-node + if(ERROR_INSUFFICIENT_BUFFER != GetLastError()) { + printf("SetupDiGetDeviceInterfaceDetail failed %d\n", GetLastError()); + SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); + return FALSE; + } + + } + + predictedLength = requiredLength; + + deviceInterfaceDetailData = malloc (predictedLength); + + if(deviceInterfaceDetailData) { + deviceInterfaceDetailData->cbSize = + sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); + } else { + printf("Couldn't allocate %d bytes for device interface details.\n", predictedLength); + SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); + return FALSE; + } + + + if (! SetupDiGetDeviceInterfaceDetail ( + hardwareDeviceInfo, + &deviceInterfaceData, + deviceInterfaceDetailData, + predictedLength, + &requiredLength, + NULL)) { + printf("Error in SetupDiGetDeviceInterfaceDetail\n"); + SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); + free (deviceInterfaceDetailData); + return FALSE; + } + printf("%d) %s\n", ++i, + deviceInterfaceDetailData->DevicePath); + } + else if (ERROR_NO_MORE_ITEMS != GetLastError()) { + free (deviceInterfaceDetailData); + deviceInterfaceDetailData = NULL; + continue; + } + else + break; + + } WHILE (TRUE); + + + SetupDiDestroyDeviceInfoList (hardwareDeviceInfo); + + if(!deviceInterfaceDetailData) + { + printf("No device interfaces present\n"); + return 0; + } + + // + // Open the last toaster device interface + // + + printf("\nOpening the last interface:\n %s\n", + deviceInterfaceDetailData->DevicePath); + + file = CreateFile ( deviceInterfaceDetailData->DevicePath, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, // no SECURITY_ATTRIBUTES structure + OPEN_EXISTING, // No special create flags + 0, // No special attributes + NULL); + + if (INVALID_HANDLE_VALUE == file) { + printf("Error in CreateFile: %x", GetLastError()); + free (deviceInterfaceDetailData); + return 0; + } + + // + // Send an IOCTL to retrive the keyboard attributes + // These are cached in the kbfiltr + // + + if (!DeviceIoControl (file, + IOCTL_KBFILTR_GET_KEYBOARD_ATTRIBUTES, + NULL, 0, + &kbdattrib, sizeof(kbdattrib), + &bytes, NULL)) { + printf("Retrieve Keyboard Attributes request failed:0x%x\n", GetLastError()); + free (deviceInterfaceDetailData); + CloseHandle(file); + return 0; + } + + printf("\nKeyboard Attributes:\n" + " KeyboardMode: 0x%x\n" + " NumberOfFunctionKeys: 0x%x\n" + " NumberOfIndicators: 0x%x\n" + " NumberOfKeysTotal: 0x%x\n" + " InputDataQueueLength: 0x%x\n", + kbdattrib.KeyboardMode, + kbdattrib.NumberOfFunctionKeys, + kbdattrib.NumberOfIndicators, + kbdattrib.NumberOfKeysTotal, + kbdattrib.InputDataQueueLength); + + free (deviceInterfaceDetailData); + CloseHandle(file); + return 0; +} + + + diff --git a/input/kbfiltr/exe/kbftest.vcxproj b/input/kbfiltr/exe/kbftest.vcxproj new file mode 100644 index 00000000..e51147f8 --- /dev/null +++ b/input/kbfiltr/exe/kbftest.vcxproj @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{4D3A4233-FEF4-479F-9874-8C239D8FF78E}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{6FB0E6F4-D53A-4112-BCA0-F1760AC63AEB}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>kbftest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>kbftest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>kbftest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>kbftest</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="kbftest.c" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/input/kbfiltr/exe/kbftest.vcxproj.Filters b/input/kbfiltr/exe/kbftest.vcxproj.Filters new file mode 100644 index 00000000..2f49b751 --- /dev/null +++ b/input/kbfiltr/exe/kbftest.vcxproj.Filters @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{A3CB6490-2256-4820-8332-9513E8921148}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{6E637087-7080-45AE-889F-39D5089A8A25}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{B1978376-1D0B-4A14-83B0-E6921A530878}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="kbftest.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/input/kbfiltr/kbfiltr.htm b/input/kbfiltr/kbfiltr.htm new file mode 100644 index 00000000..b282cca4 --- /dev/null +++ b/input/kbfiltr/kbfiltr.htm @@ -0,0 +1,465 @@ +<html xmlns:v="urn:schemas-microsoft-com:vml" +xmlns:o="urn:schemas-microsoft-com:office:office" +xmlns:w="urn:schemas-microsoft-com:office:word" +xmlns="http://www.w3.org/TR/REC-html40"> + +<head> +<meta http-equiv=Content-Type content="text/html; charset=windows-1252"> +<meta name=ProgId content=Word.Document> +<meta name=Generator content="Microsoft Word 11"> +<meta name=Originator content="Microsoft Word 11"> +<link rel=File-List href="kbfiltr_files/filelist.xml"> +<title>Kbfiltr</title> +<!--[if gte mso 9]><xml> + <w:WordDocument> + <w:Zoom>110</w:Zoom> + <w:SpellingState>Clean</w:SpellingState> + <w:GrammarState>Clean</w:GrammarState> + <w:ValidateAgainstSchemas/> + <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> + <w:IgnoreMixedContent>false</w:IgnoreMixedContent> + <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> + <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> + </w:WordDocument> +</xml><![endif]--><!--[if gte mso 9]><xml> + <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> + </w:LatentStyles> +</xml><![endif]--> +<style> +<!-- + /* Font Definitions */ + @font-face + {font-family:Verdana; + panose-1:2 11 6 4 3 5 4 4 2 4; + mso-font-charset:0; + mso-generic-font-family:swiss; + mso-font-pitch:variable; + mso-font-signature:536871559 0 0 0 415 0;} +@font-face + {font-family:"MS Sans Serif"; + panose-1:0 0 0 0 0 0 0 0 0 0; + mso-font-alt:"Times New Roman"; + mso-font-charset:0; + mso-generic-font-family:roman; + mso-font-format:other; + mso-font-pitch:auto; + mso-font-signature:0 0 0 0 0 0;} + /* Style Definitions */ + p.MsoNormal, li.MsoNormal, div.MsoNormal + {mso-style-parent:""; + margin:0in; + margin-bottom:.0001pt; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman"; + mso-fareast-font-family:"Times New Roman";} +h2 + {mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:2; + font-size:18.0pt; + font-family:"Times New Roman"; + font-weight:bold;} +h3 + {mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:3; + font-size:13.5pt; + font-family:"Times New Roman"; + font-weight:bold;} +h4 + {mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:4; + font-size:12.0pt; + font-family:"Times New Roman"; + font-weight:bold;} +a:link, span.MsoHyperlink + {color:blue; + text-decoration:underline; + text-underline:single;} +a:visited, span.MsoHyperlinkFollowed + {color:blue; + text-decoration:underline; + text-underline:single;} +p + {mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman"; + mso-fareast-font-family:"Times New Roman";} +pre + {margin:0in; + margin-bottom:.0001pt; + mso-pagination:widow-orphan; + tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt; + font-size:10.0pt; + font-family:"Courier New"; + mso-fareast-font-family:"Times New Roman";} +span.SpellE + {mso-style-name:""; + mso-spl-e:yes;} +span.GramE + {mso-style-name:""; + mso-gram-e:yes;} +@page Section1 + {size:8.5in 11.0in; + margin:1.0in 1.25in 1.0in 1.25in; + mso-header-margin:.5in; + mso-footer-margin:.5in; + mso-paper-source:0;} +div.Section1 + {page:Section1;} + /* List Definitions */ + @list l0 + {mso-list-id:71007566; + mso-list-template-ids:-534640722;} +@list l0:level1 + {mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level2 + {mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level3 + {mso-level-tab-stop:1.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level4 + {mso-level-tab-stop:2.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level5 + {mso-level-tab-stop:2.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level6 + {mso-level-tab-stop:3.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level7 + {mso-level-tab-stop:3.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level8 + {mso-level-tab-stop:4.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level9 + {mso-level-tab-stop:4.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1 + {mso-list-id:681972489; + mso-list-template-ids:-534640722;} +@list l1:level1 + {mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level2 + {mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level3 + {mso-level-tab-stop:1.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level4 + {mso-level-tab-stop:2.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level5 + {mso-level-tab-stop:2.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level6 + {mso-level-tab-stop:3.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level7 + {mso-level-tab-stop:3.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level8 + {mso-level-tab-stop:4.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1:level9 + {mso-level-tab-stop:4.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l2 + {mso-list-id:1281690663; + mso-list-template-ids:-534640722;} +@list l3 + {mso-list-id:1533613307; + mso-list-template-ids:-534640722;} +ol + {margin-bottom:0in;} +ul + {margin-bottom:0in;} +--> +</style> +<!--[if gte mso 10]> +<style> + /* Style Definitions */ + table.MsoNormalTable + {mso-style-name:"Table Normal"; + mso-tstyle-rowband-size:0; + mso-tstyle-colband-size:0; + mso-style-noshow:yes; + mso-style-parent:""; + mso-padding-alt:0in 5.4pt 0in 5.4pt; + mso-para-margin:0in; + mso-para-margin-bottom:.0001pt; + mso-pagination:widow-orphan; + font-size:10.0pt; + font-family:"Times New Roman"; + mso-ansi-language:#0400; + mso-fareast-language:#0400; + mso-bidi-language:#0400;} +</style> +<![endif]--> +</head> + +<body lang=EN-US link=blue vlink=blue style='tab-interval:.5in'> + +<div class=Section1> + +<h2><span class=SpellE><span style='font-family:Verdana'>Kbfiltr</span></span><span +style='font-family:Verdana'><o:p></o:p></span></h2> + +<h3><span style='font-family:Verdana'>SUMMARY<o:p></o:p></span></h3> + +<p><span style='font-size:10.0pt;font-family:Verdana'>This sample is WDF +version of WDM filter driver. The WDM version of this filter has been deprecated. This is an upper device filter driver sample for +PS/2 keyboard. This driver layers in between the <span class=SpellE>KbdClass</span> +driver and i8042prt driver and hooks the callback routine that moves keyboard +inputs from the port driver to class driver. In its current state, it only +hooks into the keyboard packet report chain, the keyboard initialization +function, and the keyboard ISR, but does not do any processing of the data that +it sees. (The hooking of the initialization function and ISR is only available +in the i8042prt stack.) With additions to this current filter-only code base, +the filter could conceivably add, remove, or modify input as needed. <o:p></o:p></span></p> + +<p><span style='font-size:10.0pt;font-family:Verdana'>This sample also creates +a raw PDO and registers an interface so that application can talk to the filter +driver directly without going thru the PS/2 <span class=SpellE>devicestack</span>. +The reason for providing this additional interface is because the keyboard +device is an exclusive secure device and it's not possible to open the device +from <span class=SpellE>usermode</span> and send custom <span class=SpellE>ioctls</span> +through it. <o:p></o:p></span></p> + +<p><span style='font-size:10.0pt;font-family:Verdana'>This driver filters input +for a particular keyboard on the system. If you want to filter keyboard inputs +from all the keyboards plugged into the system then you can install this driver +as a class filter below the <span class=SpellE>kbdclass</span> filter driver by +adding the service name of this filter driver before the <span class=SpellE>kbdclass</span> +filter in the registry at "HKEY_LOCAL_MACHINE\SYSTEM\<span class=SpellE>CurrentControlSet</span>\Control\Class<span +class=GramE>\{</span>4D36E96B-E325-11CE-BFC1-08002BE10318}\<span class=SpellE>UpperFilters</span>". +<o:p></o:p></span></p> + +<h3><span style='font-family:Verdana'>BUILDING THE SAMPLE<o:p></o:p></span></h3> + +<p><span style='font-size:10.0pt;font-family:Verdana'>Click the Free Build +Environment or Checked Build Environment icon under Development Kits program +group to set basic environment variables. <o:p></o:p></span></p> + +<p><span style='font-size:10.0pt;font-family:Verdana'>Change to the directory +containing the device source code, such as CD <span class=SpellE>src\input</span>\kbfiltr. +<o:p></o:p></span></p> + +<p><span style='font-size:10.0pt;font-family:Verdana'>Run <b>build -<span +class=SpellE>ceZ</span>,</b> or use the macro <b>BLD</b>. This command invokes +the Microsoft make routines to build the components. If the build </span>s<span +style='font-size:10.0pt;font-family:Verdana'>ucceeds, you will find the driver, +<span class=SpellE>kbfiltr.sys,</span> +in the binary output directory specified for the build environment. You can get the output path from the buildxxx.log file. If it fails you can find errors and warnings in the <span class=SpellE>buildxxx.err</span> +and <span class=SpellE>buildxxx.wrn</span> respectively, where xxx is <span +class=SpellE>either</span> <span class=SpellE>chk</span> or <span class=SpellE>fre</span> +depending on the build environment. <o:p></o:p></span></p> + +<h3><span style='font-family:Verdana'>INSTALLATION<o:p></o:p></span></h3> + +<p><span style='font-size:10.0pt;font-family:Verdana'> +Copy the KMDF coinstaller (wdfcoinstallerMMmmm.dll), driver binary and the kbfiltr.inf file to a floppy disk or a temp folder. </span></p> + +<p><span style='font-size:10.0pt;font-family:Verdana'>This sample is installed +via an .<span class=SpellE>inf</span> file. The .<span class=SpellE>inf</span> +file included in this sample is designed to filter a PS/2 keyboard. <o:p></o:p></span></p> + +<p><span style='font-size:10.0pt;font-family:Verdana'>Use the following rules +regarding the .<span class=SpellE>inf</span> file that installs the filter +driver.<o:p></o:p></span></p> + +<p class=MsoNormal><span class=GramE><span style='font-size:10.0pt;font-family: +Symbol;mso-ascii-font-family:Verdana'>�</span><span style='font-size:10.0pt; +font-family:Verdana'><span style='mso-spacerun:yes'>� </span>The</span></span><span +style='font-size:10.0pt;font-family:Verdana'> .<span class=SpellE>inf</span> +file must install the class driver (<span class=SpellE>Kbdclass</span>) and the +port driver (i8042prt, <span class=SpellE>Kbdhid</span>, etc.) by using <span +class=SpellE>Keyboard.inf</span> and the INF directives "Needs" and +"Include". <o:p></o:p></span></p> + +<p class=MsoNormal><span class=GramE><span style='font-size:10.0pt;font-family: +Symbol;mso-ascii-font-family:Verdana'>�</span><span style='font-size:10.0pt; +font-family:Verdana'><span style='mso-spacerun:yes'>� </span>The</span></span><span +style='font-size:10.0pt;font-family:Verdana'> .<span class=SpellE>inf</span> +file must add the correct registry values for the class and port driver, as +well as using the new directives. <o:p></o:p></span></p> + +<p><b><span style='font-size:10.0pt;font-family:Verdana'>To +install this filter, follow these steps:</span></b><span style='font-size:10.0pt; +font-family:Verdana'><o:p></o:p></span></p> + +<ol start=1 type=1> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Open the <b>Device Manager</b>. <o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Open the <b>Properties</b> of the PS/2 keyboard + installed on the system.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click the <b>Driver</b> tab, and then click <b>Update + Driver</b>.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click the <b>Browse my computer for drivers software</b></span>.<o:p></o:p></span></li> +<li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click the <b>Let me pick from a list of device drivers on my computer</b></span>.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click <b>Have Disk</b> and point to the location of + the .<span class=SpellE>inf</span> file.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Proceed through the rest of the install. You will + need to reboot the machine if you are filtering a PS/2 device.<o:p></o:p></span></li> +</ol> + +<p><span style='font-size:10.0pt;font-family:Verdana'>To install this driver as +a class filter, you have to use registry APIs to directly update the registry +with an installer and reboot your machine.<o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:Verdana'>Once +built, the sample produces <span class=SpellE>Kbfiltr.sys</span> and <span class=SpellE>Kbftest.exe</span>.<o:p></o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:Verdana'><o:p> </o:p></span></p> + +<p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span +style='font-size:10.0pt;font-family:Verdana'>NULL INF file for Windows 2000:<o:p></o:p></span></b></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:Verdana'><o:p> </o:p></span></p> + +<p class=MsoNormal><span style='font-size:10.0pt;font-family:Verdana'>On +Windows 2000, you have to provide an INF file to install a NULL driver for the +RAW PDO enumerated by the filter driver for sideband communication from <span +class=SpellE>usermode</span>. Without this INF file, the raw PDO wouldn�t get +started. On XP and later <span class=SpellE>OSes</span>, you don�t need to +provide an INF. Here are steps for installing the NULL driver:<o:p></o:p></span></p> + +<ol start=1 type=1> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Open the <span style='mso-bidi-font-weight:bold'>Device + Manager</span>. <o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Select �Show Hidden Devices� in View Menu.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Find the �<span class=SpellE>Keyboard_Filter_nnn</span>� + device with a yellow �!� in �Other� class of devices. �<span class=SpellE><span + class=GramE>nnn</span></span>� stands for the instance number of the + device.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Double click on the device to open the properties.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click the Driver tab, and then click Update Driver.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Follow the wizard's prompts, and when prompted, select + the <span style='mso-bidi-font-weight:bold'>Search for a suitable driver + for my device (recommended)</span> option, and then click <span + class=GramE><span style='mso-bidi-font-weight:bold'>Next</span></span>.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Select <span style='mso-bidi-font-weight:bold'>Specify + a location</span>, clear the other choices, and click <span class=GramE><span + style='mso-bidi-font-weight:bold'>Next</span></span><span + style='mso-bidi-font-weight:bold'>.</span> Point to the location of the <span + class=SpellE>sideband.inf</span> file.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Proceed through the rest of the install. <o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l1 level1 lfo6;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>After install, you should see the Keyboard device + under �Sample Device� class in the device manager.<o:p></o:p></span></li> +</ol> + +<h3><span style='font-family:Verdana'>CODE TOUR<o:p></o:p></span></h3> + +<h4><span style='font-family:Verdana'>File Manifest<o:p></o:p></span></h4> + +<pre><u>File<span style='mso-tab-count:2'>���������� </span>Description<o:p></o:p></u></pre><pre><o:p> </o:p></pre><pre><o:p> </o:p></pre><pre>Kbfiltr.htm<span +style='mso-tab-count:1'>��� </span>The documentation for this sample (this file)</pre><pre><span +class=SpellE>Kbfiltr.c</span><span style='mso-tab-count:1'>����� </span>Hooks into the reporting chain, the initialization of a PS/2 keyboard, and the PS/2 keyboard ISR</pre><pre><span +class=SpellE>Kbfiltr.h</span><span style='mso-tab-count:1'>����� </span>Definitions</pre><pre><span +class=SpellE>public.h</span><span style='mso-tab-count:1'>����� </span>Shared definitions with the exe</pre><pre><span +class=SpellE>Kbfiltr.rc</span><span style='mso-tab-count:1'>���� </span>Resources</pre><pre><span +class=SpellE>Kbfiltr.inx</span><span style='mso-tab-count:1'>��� </span>Sample .<span +class=SpellE>inf</span> file </pre><pre><span +class=SpellE>Sideband.inf</span><span style='mso-spacerun:yes'>�� </span>INF to install a NULL driver for the Raw PDO on Windows 2000</pre><pre><span +class=SpellE>Kbftest.c</span><span style='mso-tab-count:1'>��� </span>Simple test application</pre><pre><span +class=SpellE>Makefile.inc</span><span style='mso-tab-count:1'> </span>A makefile that defines custom build actions. This includes the conversion of the .INX file into a .INF file</pre> +<pre><o:p> </o:p></pre><pre><o:p> </o:p></pre><pre><o:p> </o:p></pre> + +<p align=center style='text-align:center;tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span +style='font-size:10.0pt;font-family:"Courier New"'><a href="#top"><span +style='font-family:Verdana'>Top of page</span></a></span><span +style='font-size:10.0pt;font-family:Verdana;mso-bidi-font-family:"Courier New"'> +<o:p></o:p></span></p> + +<pre><o:p> </o:p></pre> + +<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 width=624 + style='width:6.5in;mso-cellspacing:0in;mso-padding-alt:0in 5.4pt 0in 5.4pt'> + <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes;mso-yfti-lastrow:yes; + height:1.5pt'> + <td style='background:aqua;padding:.75pt .75pt .75pt .75pt;height:1.5pt'> + <p class=MsoNormal><o:p> </o:p></p> + </td> + </tr> +</table> + +<pre><o:p> </o:p></pre><pre><o:p> </o:p></pre> + +<p style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span +style='font-size:7.5pt;font-family:"MS Sans Serif";mso-bidi-font-family:"Courier New"'>� +Microsoft Corporation 1999</span><span style='font-size:10.0pt;font-family: +Verdana;mso-bidi-font-family:"Courier New"'> <o:p></o:p></span></p> + +</div> + +</body> + +</html> diff --git a/input/kbfiltr/kbfiltr.sln b/input/kbfiltr/kbfiltr.sln new file mode 100644 index 00000000..e2138f5d --- /dev/null +++ b/input/kbfiltr/kbfiltr.sln @@ -0,0 +1,46 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Exe", "Exe", "{4A3D2BF5-DE3F-4CA9-95A3-E3FE41000D94}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sys", "Sys", "{75FDC7AD-767A-4C07-975E-332B3D4DD47D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kbftest", "exe\kbftest.vcxproj", "{4D3A4233-FEF4-479F-9874-8C239D8FF78E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kbfiltr", "sys\kbfiltr.vcxproj", "{CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4D3A4233-FEF4-479F-9874-8C239D8FF78E}.Debug|Win32.ActiveCfg = Debug|Win32 + {4D3A4233-FEF4-479F-9874-8C239D8FF78E}.Debug|Win32.Build.0 = Debug|Win32 + {4D3A4233-FEF4-479F-9874-8C239D8FF78E}.Release|Win32.ActiveCfg = Release|Win32 + {4D3A4233-FEF4-479F-9874-8C239D8FF78E}.Release|Win32.Build.0 = Release|Win32 + {4D3A4233-FEF4-479F-9874-8C239D8FF78E}.Debug|x64.ActiveCfg = Debug|x64 + {4D3A4233-FEF4-479F-9874-8C239D8FF78E}.Debug|x64.Build.0 = Debug|x64 + {4D3A4233-FEF4-479F-9874-8C239D8FF78E}.Release|x64.ActiveCfg = Release|x64 + {4D3A4233-FEF4-479F-9874-8C239D8FF78E}.Release|x64.Build.0 = Release|x64 + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}.Debug|Win32.ActiveCfg = Debug|Win32 + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}.Debug|Win32.Build.0 = Debug|Win32 + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}.Release|Win32.ActiveCfg = Release|Win32 + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}.Release|Win32.Build.0 = Release|Win32 + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}.Debug|x64.ActiveCfg = Debug|x64 + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}.Debug|x64.Build.0 = Debug|x64 + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}.Release|x64.ActiveCfg = Release|x64 + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {4D3A4233-FEF4-479F-9874-8C239D8FF78E} = {4A3D2BF5-DE3F-4CA9-95A3-E3FE41000D94} + {CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79} = {75FDC7AD-767A-4C07-975E-332B3D4DD47D} + EndGlobalSection +EndGlobal diff --git a/input/kbfiltr/sys/kbfiltr.c b/input/kbfiltr/sys/kbfiltr.c new file mode 100644 index 00000000..e0009172 --- /dev/null +++ b/input/kbfiltr/sys/kbfiltr.c @@ -0,0 +1,871 @@ +/*-- + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + + +Module Name: + + kbfiltr.c + +Abstract: This is an upper device filter driver sample for PS/2 keyboard. This + driver layers in between the KbdClass driver and i8042prt driver and + hooks the callback routine that moves keyboard inputs from the port + driver to class driver. With this filter, you can remove or insert + additional keys into the stream. This sample also creates a raw + PDO and registers an interface so that application can talk to + the filter driver directly without going thru the PS/2 devicestack. + The reason for providing this additional interface is because the keyboard + device is an exclusive secure device and it's not possible to open the + device from usermode and send custom ioctls. + + If you want to filter keyboard inputs from all the keyboards (ps2, usb) + plugged into the system then you can install this driver as a class filter + and make it sit below the kbdclass filter driver by adding the service + name of this filter driver before the kbdclass filter in the registry at + " HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\ + {4D36E96B-E325-11CE-BFC1-08002BE10318}\UpperFilters" + + +Environment: + + Kernel mode only. + +--*/ + +#include "kbfiltr.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text (INIT, DriverEntry) +#pragma alloc_text (PAGE, KbFilter_EvtDeviceAdd) +#pragma alloc_text (PAGE, KbFilter_EvtIoInternalDeviceControl) +#endif + +ULONG InstanceNo = 0; + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + + Installable driver initialization entry point. + This entry point is called directly by the I/O system. + +Arguments: + + DriverObject - pointer to the driver object + + RegistryPath - pointer to a unicode string representing the path, + to driver-specific key in the registry. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + WDF_DRIVER_CONFIG config; + NTSTATUS status; + + DebugPrint(("Keyboard Filter Driver Sample - Driver Framework Edition.\n")); + DebugPrint(("Built %s %s\n", __DATE__, __TIME__)); + + // + // Initiialize driver config to control the attributes that + // are global to the driver. Note that framework by default + // provides a driver unload routine. If you create any resources + // in the DriverEntry and want to be cleaned in driver unload, + // you can override that by manually setting the EvtDriverUnload in the + // config structure. In general xxx_CONFIG_INIT macros are provided to + // initialize most commonly used members. + // + + WDF_DRIVER_CONFIG_INIT( + &config, + KbFilter_EvtDeviceAdd + ); + + // + // Create a framework driver object to represent our driver. + // + status = WdfDriverCreate(DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, + &config, + WDF_NO_HANDLE); // hDriver optional + if (!NT_SUCCESS(status)) { + DebugPrint(("WdfDriverCreate failed with status 0x%x\n", status)); + } + + return status; +} + +NTSTATUS +KbFilter_EvtDeviceAdd( + IN WDFDRIVER Driver, + IN PWDFDEVICE_INIT DeviceInit + ) +/*++ +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. Here you can query the device properties + using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based + on that, decide to create a filter device object and attach to the + function stack. + + If you are not interested in filtering this particular instance of the + device, you can just return STATUS_SUCCESS without creating a framework + device. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + WDF_OBJECT_ATTRIBUTES deviceAttributes; + NTSTATUS status; + WDFDEVICE hDevice; + WDFQUEUE hQueue; + PDEVICE_EXTENSION filterExt; + WDF_IO_QUEUE_CONFIG ioQueueConfig; + + UNREFERENCED_PARAMETER(Driver); + + PAGED_CODE(); + + DebugPrint(("Enter FilterEvtDeviceAdd \n")); + + // + // Tell the framework that you are filter driver. Framework + // takes care of inherting all the device flags & characterstics + // from the lower device you are attaching to. + // + WdfFdoInitSetFilter(DeviceInit); + + WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_KEYBOARD); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); + + // + // Create a framework device object. This call will in turn create + // a WDM deviceobject, attach to the lower stack and set the + // appropriate flags and attributes. + // + status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice); + if (!NT_SUCCESS(status)) { + DebugPrint(("WdfDeviceCreate failed with status code 0x%x\n", status)); + return status; + } + + filterExt = FilterGetData(hDevice); + + // + // Configure the default queue to be Parallel. Do not use sequential queue + // if this driver is going to be filtering PS2 ports because it can lead to + // deadlock. The PS2 port driver sends a request to the top of the stack when it + // receives an ioctl request and waits for it to be completed. If you use a + // a sequential queue, this request will be stuck in the queue because of the + // outstanding ioctl request sent earlier to the port driver. + // + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, + WdfIoQueueDispatchParallel); + + // + // Framework by default creates non-power managed queues for + // filter drivers. + // + ioQueueConfig.EvtIoInternalDeviceControl = KbFilter_EvtIoInternalDeviceControl; + + status = WdfIoQueueCreate(hDevice, + &ioQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + WDF_NO_HANDLE // pointer to default queue + ); + if (!NT_SUCCESS(status)) { + DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); + return status; + } + + // + // Create a new queue to handle IOCTLs that will be forwarded to us from + // the rawPDO. + // + WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, + WdfIoQueueDispatchParallel); + + // + // Framework by default creates non-power managed queues for + // filter drivers. + // + ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlFromRawPdo; + + status = WdfIoQueueCreate(hDevice, + &ioQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &hQueue + ); + if (!NT_SUCCESS(status)) { + DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); + return status; + } + + filterExt->rawPdoQueue = hQueue; + + // + // Create a RAW pdo so we can provide a sideband communication with + // the application. Please note that not filter drivers desire to + // produce such a communication and not all of them are contrained + // by other filter above which prevent communication thru the device + // interface exposed by the main stack. So use this only if absolutely + // needed. Also look at the toaster filter driver sample for an alternate + // approach to providing sideband communication. + // + status = KbFiltr_CreateRawPdo(hDevice, ++InstanceNo); + + return status; +} + +VOID +KbFilter_EvtIoDeviceControlFromRawPdo( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t OutputBufferLength, + IN size_t InputBufferLength, + IN ULONG IoControlCode + ) +/*++ + +Routine Description: + + This routine is the dispatch routine for device control requests. + +Arguments: + + Queue - Handle to the framework queue object that is associated + with the I/O request. + Request - Handle to a framework request object. + + OutputBufferLength - length of the request's output buffer, + if an output buffer is available. + InputBufferLength - length of the request's input buffer, + if an input buffer is available. + + IoControlCode - the driver-defined or system-defined I/O control code + (IOCTL) that is associated with the request. + +Return Value: + + VOID + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDFDEVICE hDevice; + WDFMEMORY outputMemory; + PDEVICE_EXTENSION devExt; + size_t bytesTransferred = 0; + + UNREFERENCED_PARAMETER(InputBufferLength); + + DebugPrint(("Entered KbFilter_EvtIoInternalDeviceControl\n")); + + hDevice = WdfIoQueueGetDevice(Queue); + devExt = FilterGetData(hDevice); + + // + // Process the ioctl and complete it when you are done. + // + + switch (IoControlCode) { + case IOCTL_KBFILTR_GET_KEYBOARD_ATTRIBUTES: + + // + // Buffer is too small, fail the request + // + if (OutputBufferLength < sizeof(KEYBOARD_ATTRIBUTES)) { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + status = WdfRequestRetrieveOutputMemory(Request, &outputMemory); + + if (!NT_SUCCESS(status)) { + DebugPrint(("WdfRequestRetrieveOutputMemory failed %x\n", status)); + break; + } + + status = WdfMemoryCopyFromBuffer(outputMemory, + 0, + &devExt->KeyboardAttributes, + sizeof(KEYBOARD_ATTRIBUTES)); + + if (!NT_SUCCESS(status)) { + DebugPrint(("WdfMemoryCopyFromBuffer failed %x\n", status)); + break; + } + + bytesTransferred = sizeof(KEYBOARD_ATTRIBUTES); + + break; + default: + status = STATUS_NOT_IMPLEMENTED; + break; + } + + WdfRequestCompleteWithInformation(Request, status, bytesTransferred); + + return; +} + +VOID +KbFilter_EvtIoInternalDeviceControl( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t OutputBufferLength, + IN size_t InputBufferLength, + IN ULONG IoControlCode + ) +/*++ + +Routine Description: + + This routine is the dispatch routine for internal device control requests. + There are two specific control codes that are of interest: + + IOCTL_INTERNAL_KEYBOARD_CONNECT: + Store the old context and function pointer and replace it with our own. + This makes life much simpler than intercepting IRPs sent by the RIT and + modifying them on the way back up. + + IOCTL_INTERNAL_I8042_HOOK_KEYBOARD: + Add in the necessary function pointers and context values so that we can + alter how the ps/2 keyboard is initialized. + + NOTE: Handling IOCTL_INTERNAL_I8042_HOOK_KEYBOARD is *NOT* necessary if + all you want to do is filter KEYBOARD_INPUT_DATAs. You can remove + the handling code and all related device extension fields and + functions to conserve space. + +Arguments: + + Queue - Handle to the framework queue object that is associated + with the I/O request. + Request - Handle to a framework request object. + + OutputBufferLength - length of the request's output buffer, + if an output buffer is available. + InputBufferLength - length of the request's input buffer, + if an input buffer is available. + + IoControlCode - the driver-defined or system-defined I/O control code + (IOCTL) that is associated with the request. + +Return Value: + + VOID + +--*/ +{ + PDEVICE_EXTENSION devExt; + PINTERNAL_I8042_HOOK_KEYBOARD hookKeyboard = NULL; + PCONNECT_DATA connectData = NULL; + NTSTATUS status = STATUS_SUCCESS; + size_t length; + WDFDEVICE hDevice; + BOOLEAN forwardWithCompletionRoutine = FALSE; + BOOLEAN ret = TRUE; + WDFCONTEXT completionContext = WDF_NO_CONTEXT; + WDF_REQUEST_SEND_OPTIONS options; + WDFMEMORY outputMemory; + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + + PAGED_CODE(); + + DebugPrint(("Entered KbFilter_EvtIoInternalDeviceControl\n")); + + hDevice = WdfIoQueueGetDevice(Queue); + devExt = FilterGetData(hDevice); + + switch (IoControlCode) { + + // + // Connect a keyboard class device driver to the port driver. + // + case IOCTL_INTERNAL_KEYBOARD_CONNECT: + // + // Only allow one connection. + // + if (devExt->UpperConnectData.ClassService != NULL) { + status = STATUS_SHARING_VIOLATION; + break; + } + + // + // Get the input buffer from the request + // (Parameters.DeviceIoControl.Type3InputBuffer). + // + status = WdfRequestRetrieveInputBuffer(Request, + sizeof(CONNECT_DATA), + &connectData, + &length); + if(!NT_SUCCESS(status)){ + DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status)); + break; + } + + NT_ASSERT(length == InputBufferLength); + + devExt->UpperConnectData = *connectData; + + // + // Hook into the report chain. Everytime a keyboard packet is reported + // to the system, KbFilter_ServiceCallback will be called + // + + connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice); + +#pragma warning(disable:4152) //nonstandard extension, function/data pointer conversion + + connectData->ClassService = KbFilter_ServiceCallback; + +#pragma warning(default:4152) + + break; + + // + // Disconnect a keyboard class device driver from the port driver. + // + case IOCTL_INTERNAL_KEYBOARD_DISCONNECT: + + // + // Clear the connection parameters in the device extension. + // + // devExt->UpperConnectData.ClassDeviceObject = NULL; + // devExt->UpperConnectData.ClassService = NULL; + + status = STATUS_NOT_IMPLEMENTED; + break; + + // + // Attach this driver to the initialization and byte processing of the + // i8042 (ie PS/2) keyboard. This is only necessary if you want to do PS/2 + // specific functions, otherwise hooking the CONNECT_DATA is sufficient + // + case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD: + + DebugPrint(("hook keyboard received!\n")); + + // + // Get the input buffer from the request + // (Parameters.DeviceIoControl.Type3InputBuffer) + // + status = WdfRequestRetrieveInputBuffer(Request, + sizeof(INTERNAL_I8042_HOOK_KEYBOARD), + &hookKeyboard, + &length); + if(!NT_SUCCESS(status)){ + DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status)); + break; + } + + NT_ASSERT(length == InputBufferLength); + + // + // Enter our own initialization routine and record any Init routine + // that may be above us. Repeat for the isr hook + // + devExt->UpperContext = hookKeyboard->Context; + + // + // replace old Context with our own + // + hookKeyboard->Context = (PVOID) devExt; + + if (hookKeyboard->InitializationRoutine) { + devExt->UpperInitializationRoutine = + hookKeyboard->InitializationRoutine; + } + hookKeyboard->InitializationRoutine = + (PI8042_KEYBOARD_INITIALIZATION_ROUTINE) + KbFilter_InitializationRoutine; + + if (hookKeyboard->IsrRoutine) { + devExt->UpperIsrHook = hookKeyboard->IsrRoutine; + } + hookKeyboard->IsrRoutine = (PI8042_KEYBOARD_ISR) KbFilter_IsrHook; + + // + // Store all of the other important stuff + // + devExt->IsrWritePort = hookKeyboard->IsrWritePort; + devExt->QueueKeyboardPacket = hookKeyboard->QueueKeyboardPacket; + devExt->CallContext = hookKeyboard->CallContext; + + status = STATUS_SUCCESS; + break; + + + case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: + forwardWithCompletionRoutine = TRUE; + completionContext = devExt; + break; + + // + // Might want to capture these in the future. For now, then pass them down + // the stack. These queries must be successful for the RIT to communicate + // with the keyboard. + // + case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: + case IOCTL_KEYBOARD_QUERY_INDICATORS: + case IOCTL_KEYBOARD_SET_INDICATORS: + case IOCTL_KEYBOARD_QUERY_TYPEMATIC: + case IOCTL_KEYBOARD_SET_TYPEMATIC: + break; + } + + if (!NT_SUCCESS(status)) { + WdfRequestComplete(Request, status); + return; + } + + // + // Forward the request down. WdfDeviceGetIoTarget returns + // the default target, which represents the device attached to us below in + // the stack. + // + + if (forwardWithCompletionRoutine) { + + // + // Format the request with the output memory so the completion routine + // can access the return data in order to cache it into the context area + // + + status = WdfRequestRetrieveOutputMemory(Request, &outputMemory); + + if (!NT_SUCCESS(status)) { + DebugPrint(("WdfRequestRetrieveOutputMemory failed: 0x%x\n", status)); + WdfRequestComplete(Request, status); + return; + } + + status = WdfIoTargetFormatRequestForInternalIoctl(WdfDeviceGetIoTarget(hDevice), + Request, + IoControlCode, + NULL, + NULL, + outputMemory, + NULL); + + if (!NT_SUCCESS(status)) { + DebugPrint(("WdfIoTargetFormatRequestForInternalIoctl failed: 0x%x\n", status)); + WdfRequestComplete(Request, status); + return; + } + + // + // Set our completion routine with a context area that we will save + // the output data into + // + WdfRequestSetCompletionRoutine(Request, + KbFilterRequestCompletionRoutine, + completionContext); + + ret = WdfRequestSend(Request, + WdfDeviceGetIoTarget(hDevice), + WDF_NO_SEND_OPTIONS); + + if (ret == FALSE) { + status = WdfRequestGetStatus (Request); + DebugPrint( ("WdfRequestSend failed: 0x%x\n", status)); + WdfRequestComplete(Request, status); + } + + } + else + { + + // + // We are not interested in post processing the IRP so + // fire and forget. + // + WDF_REQUEST_SEND_OPTIONS_INIT(&options, + WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); + + ret = WdfRequestSend(Request, WdfDeviceGetIoTarget(hDevice), &options); + + if (ret == FALSE) { + status = WdfRequestGetStatus (Request); + DebugPrint(("WdfRequestSend failed: 0x%x\n", status)); + WdfRequestComplete(Request, status); + } + + } + + return; +} + +NTSTATUS +KbFilter_InitializationRoutine( + IN PVOID InitializationContext, + IN PVOID SynchFuncContext, + IN PI8042_SYNCH_READ_PORT ReadPort, + IN PI8042_SYNCH_WRITE_PORT WritePort, + OUT PBOOLEAN TurnTranslationOn + ) +/*++ + +Routine Description: + + This routine gets called after the following has been performed on the kb + 1) a reset + 2) set the typematic + 3) set the LEDs + + i8042prt specific code, if you are writing a packet only filter driver, you + can remove this function + +Arguments: + + DeviceObject - Context passed during IOCTL_INTERNAL_I8042_HOOK_KEYBOARD + + SynchFuncContext - Context to pass when calling Read/WritePort + + Read/WritePort - Functions to synchronoulsy read and write to the kb + + TurnTranslationOn - If TRUE when this function returns, i8042prt will not + turn on translation on the keyboard + +Return Value: + + Status is returned. + +--*/ +{ + PDEVICE_EXTENSION devExt; + NTSTATUS status = STATUS_SUCCESS; + + devExt = (PDEVICE_EXTENSION)InitializationContext; + + // + // Do any interesting processing here. We just call any other drivers + // in the chain if they exist. Make sure Translation is turned on as well + // + if (devExt->UpperInitializationRoutine) { + status = (*devExt->UpperInitializationRoutine) ( + devExt->UpperContext, + SynchFuncContext, + ReadPort, + WritePort, + TurnTranslationOn + ); + + if (!NT_SUCCESS(status)) { + return status; + } + } + + *TurnTranslationOn = TRUE; + return status; +} + +BOOLEAN +KbFilter_IsrHook( + PVOID IsrContext, + PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, + PUCHAR DataByte, + PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState + ) +/*++ + +Routine Description: + + This routine gets called at the beginning of processing of the kb interrupt. + + i8042prt specific code, if you are writing a packet only filter driver, you + can remove this function + +Arguments: + + DeviceObject - Our context passed during IOCTL_INTERNAL_I8042_HOOK_KEYBOARD + + CurrentInput - Current input packet being formulated by processing all the + interrupts + + CurrentOutput - Current list of bytes being written to the keyboard or the + i8042 port. + + StatusByte - Byte read from I/O port 60 when the interrupt occurred + + DataByte - Byte read from I/O port 64 when the interrupt occurred. + This value can be modified and i8042prt will use this value + if ContinueProcessing is TRUE + + ContinueProcessing - If TRUE, i8042prt will proceed with normal processing of + the interrupt. If FALSE, i8042prt will return from the + interrupt after this function returns. Also, if FALSE, + it is this functions responsibilityt to report the input + packet via the function provided in the hook IOCTL or via + queueing a DPC within this driver and calling the + service callback function acquired from the connect IOCTL + +Return Value: + + Status is returned. + +--*/ +{ + PDEVICE_EXTENSION devExt; + BOOLEAN retVal = TRUE; + + devExt = (PDEVICE_EXTENSION)IsrContext; + + if (devExt->UpperIsrHook) { + retVal = (*devExt->UpperIsrHook) ( + devExt->UpperContext, + CurrentInput, + CurrentOutput, + StatusByte, + DataByte, + ContinueProcessing, + ScanState + ); + + if (!retVal || !(*ContinueProcessing)) { + return retVal; + } + } + + *ContinueProcessing = TRUE; + return retVal; +} + +VOID +KbFilter_ServiceCallback( + IN PDEVICE_OBJECT DeviceObject, + IN PKEYBOARD_INPUT_DATA InputDataStart, + IN PKEYBOARD_INPUT_DATA InputDataEnd, + IN OUT PULONG InputDataConsumed + ) +/*++ + +Routine Description: + + Called when there are keyboard packets to report to the Win32 subsystem. + You can do anything you like to the packets. For instance: + + o Drop a packet altogether + o Mutate the contents of a packet + o Insert packets into the stream + +Arguments: + + DeviceObject - Context passed during the connect IOCTL + + InputDataStart - First packet to be reported + + InputDataEnd - One past the last packet to be reported. Total number of + packets is equal to InputDataEnd - InputDataStart + + InputDataConsumed - Set to the total number of packets consumed by the RIT + (via the function pointer we replaced in the connect + IOCTL) + +Return Value: + + Status is returned. + +--*/ +{ + PDEVICE_EXTENSION devExt; + WDFDEVICE hDevice; + + hDevice = WdfWdmDeviceGetWdfDeviceHandle(DeviceObject); + + devExt = FilterGetData(hDevice); + + (*(PSERVICE_CALLBACK_ROUTINE)(ULONG_PTR) devExt->UpperConnectData.ClassService)( + devExt->UpperConnectData.ClassDeviceObject, + InputDataStart, + InputDataEnd, + InputDataConsumed); +} + +VOID +KbFilterRequestCompletionRoutine( + WDFREQUEST Request, + WDFIOTARGET Target, + PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, + WDFCONTEXT Context + ) +/*++ + +Routine Description: + + Completion Routine + +Arguments: + + Target - Target handle + Request - Request handle + Params - request completion params + Context - Driver supplied context + + +Return Value: + + VOID + +--*/ +{ + WDFMEMORY buffer = CompletionParams->Parameters.Ioctl.Output.Buffer; + NTSTATUS status = CompletionParams->IoStatus.Status; + + UNREFERENCED_PARAMETER(Target); + + // + // Save the keyboard attributes in our context area so that we can return + // them to the app later. + // + if (NT_SUCCESS(status) && + CompletionParams->Type == WdfRequestTypeDeviceControlInternal && + CompletionParams->Parameters.Ioctl.IoControlCode == IOCTL_KEYBOARD_QUERY_ATTRIBUTES) { + + if( CompletionParams->Parameters.Ioctl.Output.Length >= sizeof(KEYBOARD_ATTRIBUTES)) { + + status = WdfMemoryCopyToBuffer(buffer, + CompletionParams->Parameters.Ioctl.Output.Offset, + &((PDEVICE_EXTENSION)Context)->KeyboardAttributes, + sizeof(KEYBOARD_ATTRIBUTES) + ); + } + } + + WdfRequestComplete(Request, status); + + return; +} + + diff --git a/input/kbfiltr/sys/kbfiltr.h b/input/kbfiltr/sys/kbfiltr.h new file mode 100644 index 00000000..00e149dc --- /dev/null +++ b/input/kbfiltr/sys/kbfiltr.h @@ -0,0 +1,205 @@ +/*++ +Copyright (c) 1997 Microsoft Corporation + +Module Name: + + kbfilter.h + +Abstract: + + This module contains the common private declarations for the keyboard + packet filter + +Environment: + + kernel mode only + +--*/ + +#ifndef KBFILTER_H +#define KBFILTER_H + +#pragma warning(disable:4201) + +#include "ntddk.h" +#include "kbdmou.h" +#include <ntddkbd.h> +#include <ntdd8042.h> + +#pragma warning(default:4201) + +#include <wdf.h> + +#define NTSTRSAFE_LIB +#include <ntstrsafe.h> + +#include <initguid.h> +#include <devguid.h> + +#include "public.h" + +#define KBFILTER_POOL_TAG (ULONG) 'tlfK' + +#if DBG + +#define TRAP() DbgBreakPoint() + +#define DebugPrint(_x_) DbgPrint _x_ + +#else // DBG + +#define TRAP() + +#define DebugPrint(_x_) + +#endif + +#define MIN(_A_,_B_) (((_A_) < (_B_)) ? (_A_) : (_B_)) + +typedef struct _DEVICE_EXTENSION +{ + WDFDEVICE WdfDevice; + + // + // Queue for handling requests that come from the rawPdo + // + WDFQUEUE rawPdoQueue; + + // + // Number of creates sent down + // + LONG EnableCount; + + // + // The real connect data that this driver reports to + // + CONNECT_DATA UpperConnectData; + + // + // Previous initialization and hook routines (and context) + // + PVOID UpperContext; + PI8042_KEYBOARD_INITIALIZATION_ROUTINE UpperInitializationRoutine; + PI8042_KEYBOARD_ISR UpperIsrHook; + + // + // Write function from within KbFilter_IsrHook + // + IN PI8042_ISR_WRITE_PORT IsrWritePort; + + // + // Queue the current packet (ie the one passed into KbFilter_IsrHook) + // + IN PI8042_QUEUE_PACKET QueueKeyboardPacket; + + // + // Context for IsrWritePort, QueueKeyboardPacket + // + IN PVOID CallContext; + + // + // Cached Keyboard Attributes + // + KEYBOARD_ATTRIBUTES KeyboardAttributes; + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, + FilterGetData) + + +typedef struct _WORKER_ITEM_CONTEXT { + + WDFREQUEST Request; + WDFIOTARGET IoTarget; + +} WORKER_ITEM_CONTEXT, *PWORKER_ITEM_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WORKER_ITEM_CONTEXT, GetWorkItemContext) + +// +// Prototypes +// +DRIVER_INITIALIZE DriverEntry; + +EVT_WDF_DRIVER_DEVICE_ADD KbFilter_EvtDeviceAdd; +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL KbFilter_EvtIoDeviceControlForRawPdo; +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL KbFilter_EvtIoDeviceControlFromRawPdo; +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL KbFilter_EvtIoInternalDeviceControl; + +NTSTATUS +KbFilter_InitializationRoutine( + IN PVOID InitializationContext, + IN PVOID SynchFuncContext, + IN PI8042_SYNCH_READ_PORT ReadPort, + IN PI8042_SYNCH_WRITE_PORT WritePort, + OUT PBOOLEAN TurnTranslationOn + ); + +BOOLEAN +KbFilter_IsrHook( + PVOID IsrContext, + PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, + PUCHAR DataByte, + PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState + ); + +VOID +KbFilter_ServiceCallback( + IN PDEVICE_OBJECT DeviceObject, + IN PKEYBOARD_INPUT_DATA InputDataStart, + IN PKEYBOARD_INPUT_DATA InputDataEnd, + IN OUT PULONG InputDataConsumed + ); + +EVT_WDF_REQUEST_COMPLETION_ROUTINE +KbFilterRequestCompletionRoutine; + + +// +// IOCTL Related defintions +// + +// +// Used to identify kbfilter bus. This guid is used as the enumeration string +// for the device id. +DEFINE_GUID(GUID_BUS_KBFILTER, +0xa65c87f9, 0xbe02, 0x4ed9, 0x92, 0xec, 0x1, 0x2d, 0x41, 0x61, 0x69, 0xfa); +// {A65C87F9-BE02-4ed9-92EC-012D416169FA} + +DEFINE_GUID(GUID_DEVINTERFACE_KBFILTER, +0x3fb7299d, 0x6847, 0x4490, 0xb0, 0xc9, 0x99, 0xe0, 0x98, 0x6a, 0xb8, 0x86); +// {3FB7299D-6847-4490-B0C9-99E0986AB886} + + +#define KBFILTR_DEVICE_ID L"{A65C87F9-BE02-4ed9-92EC-012D416169FA}\\KeyboardFilter\0" + + +typedef struct _RPDO_DEVICE_DATA +{ + + ULONG InstanceNo; + + // + // Queue of the parent device we will forward requests to + // + WDFQUEUE ParentQueue; + +} RPDO_DEVICE_DATA, *PRPDO_DEVICE_DATA; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(RPDO_DEVICE_DATA, PdoGetData) + + +NTSTATUS +KbFiltr_CreateRawPdo( + WDFDEVICE Device, + ULONG InstanceNo +); + + + +#endif // KBFILTER_H + diff --git a/input/kbfiltr/sys/kbfiltr.inx b/input/kbfiltr/sys/kbfiltr.inx new file mode 100644 index 00000000..bc9c438a --- /dev/null +++ b/input/kbfiltr/sys/kbfiltr.inx @@ -0,0 +1,139 @@ +; kbfiltr.inf +; +; Installation inf for the Device that needs filtering adapter. +; +; (c) Copyright 1999 Microsoft +; + +[Version] +Signature="$Windows NT$" +Provider=%ProviderName% +ClassGUID={4D36E96B-E325-11CE-BFC1-08002BE10318} +Class=Keyboard +DriverVer=07/20/1999, 1.0.0.0 +; Uncomment the following line when you have a valid catalog file. +; If you use bogus catalog file installation will fail. +CatalogFile=KmdfSamples.cat + +[DestinationDirs] +DefaultDestDir = 12 +kbfiltr_CoInstaller_CopyFiles = 11 + +; +; Driver information +; + +[Manufacturer] +%MfgName% = Standard,NT$ARCH$ + +[Standard.NT$ARCH$] +%kbfiltr.DeviceDesc% = kbfiltr, *PNP0BAAD + +; +; General installation section +; + +[kbfiltr.NT] +; perform port related actions from keyboard.inf +Include=keyboard.inf +Needs=STANDARD_Inst + +; Copy the driver over +CopyFiles=kbfiltr.CopyFiles + + +; +; File sections +; + +[kbfiltr.CopyFiles] +kbfiltr.sys + + +; +; Service Installation +; + +[kbfiltr.NT.Services] +AddService = kbfiltr, , kbfiltr_Service_Inst +; Install the port driver and mouclass from keyboard.inf +Include=keyboard.inf +Needs=STANDARD_Inst.Services + +[kbfiltr_Service_Inst] +DisplayName = %kbfiltr.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 0 ; SERVICE_ERROR_IGNORE +ServiceBinary = %12%\kbfiltr.sys + +[kbfiltr.NT.HW] +; Add the device upper filter +AddReg = kbfiltr.HW.AddReg + +; run the directives need by the port driver +Include=keyboard.inf +Needs=STANDARD_Inst.HW + +[kbfiltr.HW.AddReg] +HKR,,"UpperFilters",0x00010000,"kbfiltr" + + +; +; Source file information +; + + +[SourceDisksNames] +1 = %DiskId1%,,, + +[SourceDisksFiles] +kbfiltr.sys = 1 +WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1 + +; +;--- kbfiltr Coinstaller installation ------ +; + +[kbfiltr.NT.CoInstallers] +AddReg=kbfiltr_CoInstaller_AddReg +CopyFiles=kbfiltr_CoInstaller_CopyFiles + +[kbfiltr_CoInstaller_AddReg] +HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" + +[kbfiltr_CoInstaller_CopyFiles] +WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll + +[kbfiltr.NT.Wdf] +KmdfService = kbfiltr, kbfiltr_wdfsect + +[kbfiltr_wdfsect] +KmdfLibraryVersion = $KMDFVERSION$ + + +[Strings] + +; +; Non-Localizable Strings +; + +REG_SZ = 0x00000000 +REG_MULTI_SZ = 0x00010000 +REG_EXPAND_SZ = 0x00020000 +REG_BINARY = 0x00000001 +REG_DWORD = 0x00010001 + +; +; Localizable Strings +; + +ProviderName = "TODO-Set-Provider" +MfgName = "TODO-Set-Manufacturer" + +kbfiltr.DeviceDesc = "Keyboard Filter Sample Device" + +; Make sure the service description is unique to avoid collision with another INF. +kbfiltr.SvcDesc = "Keyboard Filter Sample Driver" + +DiskId1 = "Keyboard Filter Install Disk" diff --git a/input/kbfiltr/sys/kbfiltr.rc b/input/kbfiltr/sys/kbfiltr.rc new file mode 100644 index 00000000..48695904 --- /dev/null +++ b/input/kbfiltr/sys/kbfiltr.rc @@ -0,0 +1,12 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Example Keyboard Filter Driver" +#define VER_INTERNALNAME_STR "kbfiltr.sys" + +#include "common.ver" + + diff --git a/input/kbfiltr/sys/kbfiltr.vcxproj b/input/kbfiltr/sys/kbfiltr.vcxproj new file mode 100644 index 00000000..3a6ab3aa --- /dev/null +++ b/input/kbfiltr/sys/kbfiltr.vcxproj @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{CABE9083-8EBA-41D4-A0D4-F0E3BFDD9E79}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{05A1F2D0-FD58-49DA-881D-497087488E7D}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems"> + <Inf Include=".\kbfiltr.inx"> + <Architecture>$(InfArch)</Architecture> + <SpecifyArchitecture>true</SpecifyArchitecture> + <CopyOutput>.\$(IntDir)\kbfiltr.inf</CopyOutput> + </Inf> + </ItemGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>kbfiltr</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>kbfiltr</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>kbfiltr</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>kbfiltr</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\wdmsec.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\rtlver.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\wdmsec.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\rtlver.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\wdmsec.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\rtlver.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\wdmsec.lib;$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\rtlver.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="kbfiltr.c" /> + <ClCompile Include="rawpdo.c" /> + <ResourceCompile Include="kbfiltr.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/input/kbfiltr/sys/kbfiltr.vcxproj.Filters b/input/kbfiltr/sys/kbfiltr.vcxproj.Filters new file mode 100644 index 00000000..7e848d3b --- /dev/null +++ b/input/kbfiltr/sys/kbfiltr.vcxproj.Filters @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{BC392AAF-022B-4F26-BED3-9CAECC2514DA}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{EE24B2F3-A2C8-487E-A546-D09434A690B9}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{167CCCE9-D380-4055-A99C-40FBD167AAA4}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{6B67A3D6-3C6D-4A28-9198-2603047EB5E6}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <Inf Include=".\kbfiltr.inx"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ClCompile Include="kbfiltr.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="rawpdo.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="kbfiltr.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/input/kbfiltr/sys/public.h b/input/kbfiltr/sys/public.h new file mode 100644 index 00000000..1119c580 --- /dev/null +++ b/input/kbfiltr/sys/public.h @@ -0,0 +1,11 @@ +#ifndef _PUBLIC_H +#define _PUBLIC_H + +#define IOCTL_INDEX 0x800 + +#define IOCTL_KBFILTR_GET_KEYBOARD_ATTRIBUTES CTL_CODE( FILE_DEVICE_KEYBOARD, \ + IOCTL_INDEX, \ + METHOD_BUFFERED, \ + FILE_READ_DATA) + +#endif diff --git a/input/kbfiltr/sys/rawpdo.c b/input/kbfiltr/sys/rawpdo.c new file mode 100644 index 00000000..e0603211 --- /dev/null +++ b/input/kbfiltr/sys/rawpdo.c @@ -0,0 +1,369 @@ +/*-- + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + + +Module Name: + + RawPdo.c + +Abstract: This module have the code enumerate a raw PDO for every device + the filter attaches to so that it can provide a direct + sideband communication with the usermode application. + + The toaster filter driver sample demonstrates an alternation + approach where you can create one control-device for all the + instances of the filter device. + +Environment: + + Kernel mode only. + +--*/ + +#include "kbfiltr.h" +#include "public.h" + +VOID +KbFilter_EvtIoDeviceControlForRawPdo( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t OutputBufferLength, + IN size_t InputBufferLength, + IN ULONG IoControlCode + ) +/*++ + +Routine Description: + + This routine is the dispatch routine for device control requests. + +Arguments: + + Queue - Handle to the framework queue object that is associated + with the I/O request. + Request - Handle to a framework request object. + + OutputBufferLength - length of the request's output buffer, + if an output buffer is available. + InputBufferLength - length of the request's input buffer, + if an input buffer is available. + + IoControlCode - the driver-defined or system-defined I/O control code + (IOCTL) that is associated with the request. + +Return Value: + + VOID + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + WDFDEVICE parent = WdfIoQueueGetDevice(Queue); + PRPDO_DEVICE_DATA pdoData; + WDF_REQUEST_FORWARD_OPTIONS forwardOptions; + + pdoData = PdoGetData(parent); + + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + DebugPrint(("Entered KbFilter_EvtIoDeviceControlForRawPdo\n")); + + // + // Process the ioctl and complete it when you are done. + // Since the queue is configured for serial dispatch, you will + // not receive another ioctl request until you complete this one. + // + + switch (IoControlCode) { + case IOCTL_KBFILTR_GET_KEYBOARD_ATTRIBUTES: + WDF_REQUEST_FORWARD_OPTIONS_INIT(&forwardOptions); + status = WdfRequestForwardToParentDeviceIoQueue(Request, pdoData->ParentQueue, &forwardOptions); + if (!NT_SUCCESS(status)) { + WdfRequestComplete(Request, status); + } + break; + default: + WdfRequestComplete(Request, status); + break; + } + + return; +} + +#define MAX_ID_LEN 128 + +NTSTATUS +KbFiltr_CreateRawPdo( + WDFDEVICE Device, + ULONG InstanceNo + ) +/*++ + +Routine Description: + + This routine creates and initialize a PDO. + +Arguments: + +Return Value: + + NT Status code. + +--*/ +{ + NTSTATUS status; + PWDFDEVICE_INIT pDeviceInit = NULL; + PRPDO_DEVICE_DATA pdoData = NULL; + WDFDEVICE hChild = NULL; + WDF_OBJECT_ATTRIBUTES pdoAttributes; + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; + WDF_IO_QUEUE_CONFIG ioQueueConfig; + WDFQUEUE queue; + WDF_DEVICE_STATE deviceState; + PDEVICE_EXTENSION devExt; + DECLARE_CONST_UNICODE_STRING(deviceId,KBFILTR_DEVICE_ID ); + DECLARE_CONST_UNICODE_STRING(hardwareId,KBFILTR_DEVICE_ID ); + DECLARE_CONST_UNICODE_STRING(deviceLocation,L"Keyboard Filter\0" ); + DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN); + + DebugPrint(("Entered KbFiltr_CreateRawPdo\n")); + + // + // Allocate a WDFDEVICE_INIT structure and set the properties + // so that we can create a device object for the child. + // + pDeviceInit = WdfPdoInitAllocate(Device); + + if (pDeviceInit == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto Cleanup; + } + + // + // Mark the device RAW so that the child device can be started + // and accessed without requiring a function driver. Since we are + // creating a RAW PDO, we must provide a class guid. + // + status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVCLASS_KEYBOARD); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + // + // Since keyboard is secure device, we must protect ourselves from random + // users sending ioctls and creating trouble. + // + status = WdfDeviceInitAssignSDDLString(pDeviceInit, + &SDDL_DEVOBJ_SYS_ALL_ADM_ALL); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + // + // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID + // + status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + // + // For RAW PDO, there is no need to provide BusQueryHardwareIDs + // and BusQueryCompatibleIDs IDs unless we are running on + // Windows 2000. + // + if (!RtlIsNtDdiVersionAvailable(NTDDI_WINXP)) { + // + // On Win2K, we must provide a HWID for the device to get enumerated. + // Since we are providing a HWID, we will have to provide a NULL inf + // to avoid the "found new device" popup and get the device installed + // silently. + // + status = WdfPdoInitAddHardwareID(pDeviceInit, &hardwareId); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + } + + // + // We could be enumerating more than one children if the filter attaches + // to multiple instances of keyboard, so we must provide a + // BusQueryInstanceID. If we don't, system will throw CA bugcheck. + // + status = RtlUnicodeStringPrintf(&buffer, L"%02d", InstanceNo); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + // + // Provide a description about the device. This text is usually read from + // the device. In the case of USB device, this text comes from the string + // descriptor. This text is displayed momentarily by the PnP manager while + // it's looking for a matching INF. If it finds one, it uses the Device + // Description from the INF file to display in the device manager. + // Since our device is raw device and we don't provide any hardware ID + // to match with an INF, this text will be displayed in the device manager. + // + status = RtlUnicodeStringPrintf(&buffer,L"Keyboard_Filter_%02d", InstanceNo ); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + // + // You can call WdfPdoInitAddDeviceText multiple times, adding device + // text for multiple locales. When the system displays the text, it + // chooses the text that matches the current locale, if available. + // Otherwise it will use the string for the default locale. + // The driver can specify the driver's default locale by calling + // WdfPdoInitSetDefaultLocale. + // + status = WdfPdoInitAddDeviceText(pDeviceInit, + &buffer, + &deviceLocation, + 0x409 + ); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409); + + // + // Initialize the attributes to specify the size of PDO device extension. + // All the state information private to the PDO will be tracked here. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA); + + // + // Set up our queue to allow forwarding of requests to the parent + // This is done so that the cached Keyboard Attributes can be retrieved + // + WdfPdoInitAllowForwardingRequestToParent(pDeviceInit); + + status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + // + // Get the device context. + // + pdoData = PdoGetData(hChild); + + pdoData->InstanceNo = InstanceNo; + + // + // Get the parent queue we will be forwarding to + // + devExt = FilterGetData(Device); + pdoData->ParentQueue = devExt->rawPdoQueue; + + // + // Configure the default queue associated with the control device object + // to be Serial so that request passed to EvtIoDeviceControl are serialized. + // A default queue gets all the requests that are not + // configure-fowarded using WdfDeviceConfigureRequestDispatching. + // + + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, + WdfIoQueueDispatchSequential); + + ioQueueConfig.EvtIoDeviceControl = KbFilter_EvtIoDeviceControlForRawPdo; + + status = WdfIoQueueCreate(hChild, + &ioQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &queue // pointer to default queue + ); + if (!NT_SUCCESS(status)) { + DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); + goto Cleanup; + } + + // + // Set some properties for the child device. + // + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); + + pnpCaps.Removable = WdfTrue; + pnpCaps.SurpriseRemovalOK = WdfTrue; + pnpCaps.NoDisplayInUI = WdfTrue; + + pnpCaps.Address = InstanceNo; + pnpCaps.UINumber = InstanceNo; + + WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); + + // + // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we + // have to do the following to hide the device. Following call + // tells the framework to report the device state in + // IRP_MN_QUERY_DEVICE_STATE request. + // + WDF_DEVICE_STATE_INIT(&deviceState); + deviceState.DontDisplayInUI = WdfTrue; + WdfDeviceSetDeviceState(hChild, &deviceState); + + // + // Tell the Framework that this device will need an interface so that + // application can find our device and talk to it. + // + status = WdfDeviceCreateDeviceInterface( + hChild, + &GUID_DEVINTERFACE_KBFILTER, + NULL + ); + + if (!NT_SUCCESS (status)) { + DebugPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); + goto Cleanup; + } + + // + // Add this device to the FDO's collection of children. + // After the child device is added to the static collection successfully, + // driver must call WdfPdoMarkMissing to get the device deleted. It + // shouldn't delete the child device directly by calling WdfObjectDelete. + // + status = WdfFdoAddStaticChild(Device, hChild); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + // + // pDeviceInit will be freed by WDF. + // + return STATUS_SUCCESS; + +Cleanup: + + DebugPrint(("KbFiltr_CreatePdo failed %x\n", status)); + + // + // Call WdfDeviceInitFree if you encounter an error while initializing + // a new framework device object. If you call WdfDeviceInitFree, + // do not call WdfDeviceCreate. + // + if (pDeviceInit != NULL) { + WdfDeviceInitFree(pDeviceInit); + } + + if(hChild) { + WdfObjectDelete(hChild); + } + + return status; +} + diff --git a/input/moufiltr/Moufiltr.htm b/input/moufiltr/Moufiltr.htm new file mode 100644 index 00000000..85faea72 --- /dev/null +++ b/input/moufiltr/Moufiltr.htm @@ -0,0 +1,699 @@ +<html xmlns:v="urn:schemas-microsoft-com:vml" +xmlns:o="urn:schemas-microsoft-com:office:office" +xmlns:w="urn:schemas-microsoft-com:office:word" +xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" +xmlns="http://www.w3.org/TR/REC-html40"> + +<head> +<meta http-equiv=Content-Type content="text/html; charset=windows-1252"> +<meta name=ProgId content=Word.Document> +<meta name=Generator content="Microsoft Word 12"> +<meta name=Originator content="Microsoft Word 12"> +<link rel=File-List href="Moufiltr_files/filelist.xml"> +<title>Moufiltr</title> +<link rel=themeData href="Moufiltr_files/themedata.thmx"> +<link rel=colorSchemeMapping href="Moufiltr_files/colorschememapping.xml"> +<!--[if gte mso 9]><xml> + <w:WordDocument> + <w:SpellingState>Clean</w:SpellingState> + <w:GrammarState>Clean</w:GrammarState> + <w:TrackMoves>false</w:TrackMoves> + <w:TrackFormatting/> + <w:ValidateAgainstSchemas/> + <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> + <w:IgnoreMixedContent>false</w:IgnoreMixedContent> + <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> + <w:DoNotPromoteQF/> + <w:LidThemeOther>EN-US</w:LidThemeOther> + <w:LidThemeAsian>X-NONE</w:LidThemeAsian> + <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> + <w:Compatibility> + <w:BreakWrappedTables/> + <w:SnapToGridInCell/> + <w:WrapTextWithPunct/> + <w:UseAsianBreakRules/> + <w:DontGrowAutofit/> + <w:SplitPgBreakAndParaMark/> + <w:DontVertAlignCellWithSp/> + <w:DontBreakConstrainedForcedTables/> + <w:DontVertAlignInTxbx/> + <w:Word11KerningPairs/> + <w:CachedColBalance/> + </w:Compatibility> + <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> + <m:mathPr> + <m:mathFont m:val="Cambria Math"/> + <m:brkBin m:val="before"/> + <m:brkBinSub m:val="--"/> + <m:smallFrac m:val="off"/> + <m:dispDef/> + <m:lMargin m:val="0"/> + <m:rMargin m:val="0"/> + <m:defJc m:val="centerGroup"/> + <m:wrapIndent m:val="1440"/> + <m:intLim m:val="subSup"/> + <m:naryLim m:val="undOvr"/> + </m:mathPr></w:WordDocument> +</xml><![endif]--><!--[if gte mso 9]><xml> + <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="false" + DefSemiHidden="false" DefQFormat="false" LatentStyleCount="267"> + <w:LsdException Locked="false" QFormat="true" Name="Normal"/> + <w:LsdException Locked="false" QFormat="true" Name="heading 1"/> + <w:LsdException Locked="false" QFormat="true" Name="heading 2"/> + <w:LsdException Locked="false" QFormat="true" Name="heading 3"/> + <w:LsdException Locked="false" QFormat="true" Name="heading 4"/> + <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" + QFormat="true" Name="heading 5"/> + <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" + QFormat="true" Name="heading 6"/> + <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" + QFormat="true" Name="heading 7"/> + <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" + QFormat="true" Name="heading 8"/> + <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" + QFormat="true" Name="heading 9"/> + <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true" + QFormat="true" Name="caption"/> + <w:LsdException Locked="false" QFormat="true" Name="Title"/> + <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> + <w:LsdException Locked="false" QFormat="true" Name="Subtitle"/> + <w:LsdException Locked="false" QFormat="true" Name="Strong"/> + <w:LsdException Locked="false" QFormat="true" Name="Emphasis"/> + <w:LsdException Locked="false" Priority="99" Name="No List"/> + <w:LsdException Locked="false" Priority="99" SemiHidden="true" + Name="Placeholder Text"/> + <w:LsdException Locked="false" Priority="1" QFormat="true" Name="No Spacing"/> + <w:LsdException Locked="false" Priority="60" Name="Light Shading"/> + <w:LsdException Locked="false" Priority="61" Name="Light List"/> + <w:LsdException Locked="false" Priority="62" Name="Light Grid"/> + <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1"/> + <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2"/> + <w:LsdException Locked="false" Priority="65" Name="Medium List 1"/> + <w:LsdException Locked="false" Priority="66" Name="Medium List 2"/> + <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1"/> + <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2"/> + <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3"/> + <w:LsdException Locked="false" Priority="70" Name="Dark List"/> + <w:LsdException Locked="false" Priority="71" Name="Colorful Shading"/> + <w:LsdException Locked="false" Priority="72" Name="Colorful List"/> + <w:LsdException Locked="false" Priority="73" Name="Colorful Grid"/> + <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 1"/> + <w:LsdException Locked="false" Priority="61" Name="Light List Accent 1"/> + <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 1"/> + <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 1"/> + <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 1"/> + <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 1"/> + <w:LsdException Locked="false" Priority="99" SemiHidden="true" Name="Revision"/> + <w:LsdException Locked="false" Priority="34" QFormat="true" + Name="List Paragraph"/> + <w:LsdException Locked="false" Priority="29" QFormat="true" Name="Quote"/> + <w:LsdException Locked="false" Priority="30" QFormat="true" + Name="Intense Quote"/> + <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 1"/> + <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 1"/> + <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 1"/> + <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 1"/> + <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 1"/> + <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 1"/> + <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 1"/> + <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 1"/> + <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 2"/> + <w:LsdException Locked="false" Priority="61" Name="Light List Accent 2"/> + <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 2"/> + <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 2"/> + <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 2"/> + <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 2"/> + <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 2"/> + <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 2"/> + <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 2"/> + <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 2"/> + <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 2"/> + <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 2"/> + <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 2"/> + <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 2"/> + <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 3"/> + <w:LsdException Locked="false" Priority="61" Name="Light List Accent 3"/> + <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 3"/> + <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 3"/> + <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 3"/> + <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 3"/> + <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 3"/> + <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 3"/> + <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 3"/> + <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 3"/> + <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 3"/> + <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 3"/> + <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 3"/> + <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 3"/> + <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 4"/> + <w:LsdException Locked="false" Priority="61" Name="Light List Accent 4"/> + <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 4"/> + <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 4"/> + <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 4"/> + <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 4"/> + <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 4"/> + <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 4"/> + <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 4"/> + <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 4"/> + <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 4"/> + <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 4"/> + <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 4"/> + <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 4"/> + <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 5"/> + <w:LsdException Locked="false" Priority="61" Name="Light List Accent 5"/> + <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 5"/> + <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 5"/> + <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 5"/> + <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 5"/> + <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 5"/> + <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 5"/> + <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 5"/> + <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 5"/> + <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 5"/> + <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 5"/> + <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 5"/> + <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 5"/> + <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 6"/> + <w:LsdException Locked="false" Priority="61" Name="Light List Accent 6"/> + <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 6"/> + <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 6"/> + <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 6"/> + <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 6"/> + <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 6"/> + <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 6"/> + <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 6"/> + <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 6"/> + <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 6"/> + <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 6"/> + <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 6"/> + <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 6"/> + <w:LsdException Locked="false" Priority="19" QFormat="true" + Name="Subtle Emphasis"/> + <w:LsdException Locked="false" Priority="21" QFormat="true" + Name="Intense Emphasis"/> + <w:LsdException Locked="false" Priority="31" QFormat="true" + Name="Subtle Reference"/> + <w:LsdException Locked="false" Priority="32" QFormat="true" + Name="Intense Reference"/> + <w:LsdException Locked="false" Priority="33" QFormat="true" Name="Book Title"/> + <w:LsdException Locked="false" Priority="37" SemiHidden="true" + UnhideWhenUsed="true" Name="Bibliography"/> + <w:LsdException Locked="false" Priority="39" SemiHidden="true" + UnhideWhenUsed="true" QFormat="true" Name="TOC Heading"/> + </w:LatentStyles> +</xml><![endif]--> +<style> +<!-- + /* Font Definitions */ + @font-face + {font-family:"Cambria Math"; + panose-1:2 4 5 3 5 4 6 3 2 4; + mso-font-charset:0; + mso-generic-font-family:roman; + mso-font-pitch:variable; + mso-font-signature:-1610611985 1107304683 0 0 159 0;} +@font-face + {font-family:Verdana; + panose-1:2 11 6 4 3 5 4 4 2 4; + mso-font-charset:0; + mso-generic-font-family:swiss; + mso-font-pitch:variable; + mso-font-signature:-1593833729 1073750107 16 0 415 0;} +@font-face + {font-family:"MS Sans Serif"; + panose-1:0 0 0 0 0 0 0 0 0 0; + mso-font-alt:"Times New Roman"; + mso-font-charset:0; + mso-generic-font-family:roman; + mso-font-format:other; + mso-font-pitch:auto; + mso-font-signature:0 0 0 0 0 0;} +@font-face + {font-family:Consolas; + panose-1:2 11 6 9 2 2 4 3 2 4; + mso-font-charset:0; + mso-generic-font-family:modern; + mso-font-pitch:fixed; + mso-font-signature:-1610611985 1073750091 0 0 159 0;} + /* Style Definitions */ + p.MsoNormal, li.MsoNormal, div.MsoNormal + {mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-parent:""; + margin:0in; + margin-bottom:.0001pt; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + color:black;} +h2 + {mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 2 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:2; + font-size:18.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +h3 + {mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 3 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:3; + font-size:13.5pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +h4 + {mso-style-unhide:no; + mso-style-qformat:yes; + mso-style-link:"Heading 4 Char"; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + mso-outline-level:4; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:minor-fareast; + color:black; + font-weight:bold;} +a:link, span.MsoHyperlink + {mso-style-unhide:no; + color:blue; + text-decoration:underline; + text-underline:single;} +a:visited, span.MsoHyperlinkFollowed + {mso-style-unhide:no; + color:purple; + text-decoration:underline; + text-underline:single;} +p + {mso-style-unhide:no; + mso-margin-top-alt:auto; + margin-right:0in; + mso-margin-bottom-alt:auto; + margin-left:0in; + mso-pagination:widow-orphan; + font-size:12.0pt; + font-family:"Times New Roman","serif"; + mso-fareast-font-family:"Times New Roman"; + color:black;} +pre + {mso-style-unhide:no; + mso-style-link:"HTML Preformatted Char"; + margin:0in; + margin-bottom:.0001pt; + mso-pagination:widow-orphan; + tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt; + font-size:10.0pt; + font-family:"Courier New"; + mso-fareast-font-family:"Times New Roman"; + color:black;} +span.Heading2Char + {mso-style-name:"Heading 2 Char"; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 2"; + mso-ansi-font-size:13.0pt; + mso-bidi-font-size:13.0pt; + font-family:"Cambria","serif"; + mso-ascii-font-family:Cambria; + mso-ascii-theme-font:major-latin; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:major-fareast; + mso-hansi-font-family:Cambria; + mso-hansi-theme-font:major-latin; + mso-bidi-font-family:"Times New Roman"; + mso-bidi-theme-font:major-bidi; + color:#4F81BD; + mso-themecolor:accent1; + font-weight:bold;} +span.Heading3Char + {mso-style-name:"Heading 3 Char"; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 3"; + mso-ansi-font-size:12.0pt; + mso-bidi-font-size:12.0pt; + font-family:"Cambria","serif"; + mso-ascii-font-family:Cambria; + mso-ascii-theme-font:major-latin; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:major-fareast; + mso-hansi-font-family:Cambria; + mso-hansi-theme-font:major-latin; + mso-bidi-font-family:"Times New Roman"; + mso-bidi-theme-font:major-bidi; + color:#4F81BD; + mso-themecolor:accent1; + font-weight:bold;} +span.Heading4Char + {mso-style-name:"Heading 4 Char"; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"Heading 4"; + mso-ansi-font-size:12.0pt; + mso-bidi-font-size:12.0pt; + font-family:"Cambria","serif"; + mso-ascii-font-family:Cambria; + mso-ascii-theme-font:major-latin; + mso-fareast-font-family:"Times New Roman"; + mso-fareast-theme-font:major-fareast; + mso-hansi-font-family:Cambria; + mso-hansi-theme-font:major-latin; + mso-bidi-font-family:"Times New Roman"; + mso-bidi-theme-font:major-bidi; + color:#4F81BD; + mso-themecolor:accent1; + font-weight:bold; + font-style:italic;} +span.HTMLPreformattedChar + {mso-style-name:"HTML Preformatted Char"; + mso-style-unhide:no; + mso-style-locked:yes; + mso-style-link:"HTML Preformatted"; + font-family:Consolas; + mso-ascii-font-family:Consolas; + mso-hansi-font-family:Consolas; + color:black;} +span.SpellE + {mso-style-name:""; + mso-spl-e:yes;} +span.GramE + {mso-style-name:""; + mso-gram-e:yes;} +.MsoChpDefault + {mso-style-type:export-only; + mso-default-props:yes; + font-size:10.0pt; + mso-ansi-font-size:10.0pt; + mso-bidi-font-size:10.0pt;} +@page Section1 + {size:8.5in 11.0in; + margin:1.0in 1.25in 1.0in 1.25in; + mso-header-margin:.5in; + mso-footer-margin:.5in; + mso-paper-source:0;} +div.Section1 + {page:Section1;} + /* List Definitions */ + @list l0 + {mso-list-id:435291962; + mso-list-template-ids:-741705326;} +@list l0:level1 + {mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level2 + {mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level3 + {mso-level-tab-stop:1.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level4 + {mso-level-tab-stop:2.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level5 + {mso-level-tab-stop:2.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level6 + {mso-level-tab-stop:3.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level7 + {mso-level-tab-stop:3.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level8 + {mso-level-tab-stop:4.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l0:level9 + {mso-level-tab-stop:4.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l1 + {mso-list-id:950281396; + mso-list-template-ids:-189597544;} +@list l1:level1 + {mso-level-number-format:bullet; + mso-level-text:\F0B7; + mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in; + mso-ansi-font-size:10.0pt; + font-family:Symbol;} +@list l2 + {mso-list-id:1292129342; + mso-list-template-ids:97144484;} +@list l3 + {mso-list-id:1686593596; + mso-list-template-ids:1385997532;} +@list l3:level1 + {mso-level-number-format:bullet; + mso-level-text:\F0B7; + mso-level-tab-stop:.5in; + mso-level-number-position:left; + text-indent:-.25in; + mso-ansi-font-size:10.0pt; + font-family:Symbol;} +@list l3:level2 + {mso-level-tab-stop:1.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level3 + {mso-level-tab-stop:1.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level4 + {mso-level-tab-stop:2.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level5 + {mso-level-tab-stop:2.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level6 + {mso-level-tab-stop:3.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level7 + {mso-level-tab-stop:3.5in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level8 + {mso-level-tab-stop:4.0in; + mso-level-number-position:left; + text-indent:-.25in;} +@list l3:level9 + {mso-level-tab-stop:4.5in; + mso-level-number-position:left; + text-indent:-.25in;} +ol + {margin-bottom:0in;} +ul + {margin-bottom:0in;} +--> +</style> +<!--[if gte mso 10]> +<style> + /* Style Definitions */ + table.MsoNormalTable + {mso-style-name:"Table Normal"; + mso-tstyle-rowband-size:0; + mso-tstyle-colband-size:0; + mso-style-noshow:yes; + mso-style-priority:99; + mso-style-qformat:yes; + mso-style-parent:""; + mso-padding-alt:0in 5.4pt 0in 5.4pt; + mso-para-margin:0in; + mso-para-margin-bottom:.0001pt; + mso-pagination:widow-orphan; + font-size:10.0pt; + font-family:"Times New Roman","serif";} +</style> +<![endif]--><!--[if gte mso 9]><xml> + <o:shapedefaults v:ext="edit" spidmax="3074"/> +</xml><![endif]--><!--[if gte mso 9]><xml> + <o:shapelayout v:ext="edit"> + <o:idmap v:ext="edit" data="1"/> + </o:shapelayout></xml><![endif]--> +</head> + +<body bgcolor=white lang=EN-US link=blue vlink=purple style='tab-interval:.5in' +leftmargin=8> + +<div class=Section1> + +<h2><a name=MYSAMPLE></a><span class=SpellE><span style='mso-bookmark:MYSAMPLE'><span +style='font-family:"Verdana","sans-serif";mso-fareast-font-family:"Times New Roman"'>Moufiltr</span></span></span><span +style='mso-bookmark:MYSAMPLE'></span><span style='font-family:"Verdana","sans-serif"; +mso-fareast-font-family:"Times New Roman"'> <o:p></o:p></span></h2> + +<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family: +"Times New Roman"'>SUMMARY<o:p></o:p></span></h3> + +<h3><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +font-weight:normal;mso-bidi-font-weight:bold'>This sample is WDF version of WDM +filter driver sample. The WDM version of this sample has been deprecated.<o:p></o:p></span></h3> + +<h3><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"; +font-weight:normal;mso-bidi-font-weight:bold'>This driver filters input for a +particular mouse on the system. In its current state, it only hooks into the +mouse packet report chain and the mouse ISR, and does not do any processing of +the data that it sees. (The hooking of the ISR is only available in the +i8042prt stack.) With additions to this current filter-only code base, the +filter could conceivably add, remove, or modify input as needed. </span><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-fareast-font-family: +"Times New Roman";font-weight:normal;mso-bidi-font-weight:bold'><o:p></o:p></span></h3> + +<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family: +"Times New Roman"'>BUILDING THE SAMPLE<o:p></o:p></span></h3> + +<p><span style='font-size:10.0pt;font-family:Verdana'>Click the Free Build +Environment or Checked Build Environment icon under Development Kits program +group to set basic environment variables. <o:p></o:p></span></p> + +<p><span style='font-size:10.0pt;font-family:Verdana'>Change to the directory +containing the device source code, such as CD <span class=SpellE>src\input</span>\moufiltr. +<o:p></o:p></span></p> + +<p><span style='font-size:10.0pt;font-family:Verdana'>Run <b>build -<span +class=SpellE>ceZ</span>,</b> or use the macro <b>BLD</b>. This command invokes +the Microsoft make routines to build the components. If the build </span>s<span +style='font-size:10.0pt;font-family:Verdana'>ucceeds, you will find the driver, +<span class=SpellE>moufiltr.sys,</span> +in the binary output directory specified for the build environment. You can get the output path from the buildxxx.log file. If it fails you can find errors and warnings in the <span class=SpellE>buildxxx.err</span> +and <span class=SpellE>buildxxx.wrn</span> respectively, where xxx is <span +class=SpellE>either</span> <span class=SpellE>chk</span> or <span class=SpellE>fre</span> +depending on the build environment. <o:p></o:p></span></p> + +<h3><span style='font-family:Verdana'>INSTALLATION<o:p></o:p></span></h3> + +<p><span style='font-size:10.0pt;font-family:Verdana'> +Copy the KMDF coinstaller (wdfcoinstallerMMmmm.dll), driver binary and the moufiltr.inf file to a floppy disk or a temp folder. </span></p> + +<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>This +sample is installed via an .<span class=SpellE>inf</span> file. The .<span +class=SpellE>inf</span> file included in this sample is designed to filter a +PS/2 mouse. <o:p></o:p></span></p> + +<p><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>Use the +following rules regarding the .<span class=SpellE>inf</span> file that installs +the filter driver.<o:p></o:p></span></p> + +<ul type=disc> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l3 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:"Verdana","sans-serif"'>The .<span class=SpellE>inf</span> file + must install the class driver (<span class=SpellE>Mouclass</span>) and the + port driver (i8042prt, <span class=SpellE>Mouhid</span>, <span + class=SpellE>Sermouse</span>, etc.) by using Msmouse.inf and the INF + directives "Needs" and "Include".<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l3 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:"Verdana","sans-serif"'>The .<span class=SpellE>inf</span> + file must add the correct registry values for the class and port driver, + as well as using the new directives.<o:p></o:p></span></li> +</ul> + +<p><b><span style='font-size:10.0pt;font-family:"Verdana","sans-serif"'>To +install this filter, follow these steps:<o:p></o:p></span></b></p> + +<ol start=1 type=1> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Open the <b>Device Manager</b>. <o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Open the <b>Properties</b> of the PS/2 mouse + installed on the system.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click the <b>Driver</b> tab, and then click <b>Update + Driver</b>.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click the <b>Browse my computer for drivers software</b></span>.<o:p></o:p></span></li> +<li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click the <b>Let me pick from a list of device drivers on my computer</b></span>.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Click <b>Have Disk</b> and point to the location of + the .<span class=SpellE>inf</span> file.<o:p></o:p></span></li> + <li class=MsoNormal style='mso-margin-top-alt:auto;mso-margin-bottom-alt:auto; + mso-list:l0 level1 lfo3;tab-stops:list .5in'><span style='font-size:10.0pt; + font-family:Verdana'>Proceed through the rest of the install. You will + need to reboot the machine if you are filtering a PS/2 device.<o:p></o:p></span></li> +</ol> + +<h3><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family: +"Times New Roman"'>CODE TOUR<o:p></o:p></span></h3> + +<h4><span style='font-family:"Verdana","sans-serif";mso-fareast-font-family: +"Times New Roman"'>File Manifest<o:p></o:p></span></h4> + +<pre><u>File<span style='mso-tab-count:2'>���������� </span>Description<o:p></o:p></u></pre><pre><o:p> </o:p></pre><pre>Moufiltr.htm<span +style='mso-tab-count:1'>�� </span>The documentation for this sample (this file).</pre> +<pre><span class=SpellE>Moufiltr.c</span><span style='mso-tab-count:1'>���� </span>Hooks into the reporting chain, the initialization of a PS/2 mouse, and the PS/2 ISR</pre> +<pre><span class=SpellE>Moufiltr.h</span><span style='mso-tab-count:1'>���� </span>Definitions</pre> +<pre><span class=SpellE>Moufiltr.rc</span><span style='mso-tab-count:1'>��� </span>Resources</pre> +<pre>Moufiltr.inx<span style='mso-tab-count:1'>�� </span>Sample .<span class=SpellE>inx</span> file </pre> +<pre><span class=SpellE>Makefile.inc</span><span style='mso-tab-count:1'> </span>A makefile that defines custom build actions. This includes the conversion of the .INX file into a .INF file</pre> +<pre><o:p> </o:p></pre> + +<p align=center style='text-align:center;tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span +style='font-size:10.0pt;font-family:"Courier New"'><a href="#top"><span +style='font-family:"Verdana","sans-serif"'>Top of page</span></a></span><span +style='font-size:10.0pt;font-family:"Verdana","sans-serif";mso-bidi-font-family: +"Courier New"'> <o:p></o:p></span></p> + +<pre><o:p> </o:p></pre> + +<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 width=624 + style='width:6.5in;mso-cellspacing:0in;mso-yfti-tbllook:1184;mso-padding-alt: + 0in 5.4pt 0in 5.4pt'> + <tr style='mso-yfti-irow:0;mso-yfti-firstrow:yes;mso-yfti-lastrow:yes; + height:1.5pt'> + <td style='background:aqua;padding:.75pt .75pt .75pt .75pt;height:1.5pt'> + <p class=MsoNormal><o:p> </o:p></p> + </td> + </tr> +</table> + +<pre><o:p> </o:p></pre><pre><o:p> </o:p></pre> + +<p style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><span +style='font-size:7.5pt;font-family:"MS Sans Serif","serif";mso-bidi-font-family: +"Courier New"'>� 2004 Microsoft Corporation</span><span style='font-size:10.0pt; +font-family:"Verdana","sans-serif";mso-bidi-font-family:"Courier New"'><o:p></o:p></span></p> + +</div> + +</body> + +</html> diff --git a/input/moufiltr/ReadMe.md b/input/moufiltr/ReadMe.md new file mode 100644 index 00000000..e0cc32c5 --- /dev/null +++ b/input/moufiltr/ReadMe.md @@ -0,0 +1,20 @@ +Mouse Input WDF Filter Driver (Moufiltr) +======================================== +The Moufiltr sample is an example of a mouse input filter driver. + +This sample is WDF version of the original WDM filter driver sample. The WDM version of this sample has been deprecated. + +This driver filters input for a particular mouse on the system. In its current state, it only hooks into the mouse packet report chain and the mouse ISR, and does not do any processing of the data that it sees. (The hooking of the ISR is only available in the i8042prt stack.) With additions to this current filter-only code base, the filter could conceivably add, remove, or modify input as needed. + +## Universal Windows Driver Compliant +This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. + +Installation +------------ + +This sample is installed via an .inf file. The .inf file included in this sample is designed to filter a PS/2 mouse. + +The .inf file must install the class driver (Mouclass) and the port driver (i8042prt, Mouhid, Sermouse, etc.) by using Msmouse.inf and the INF directives "Needs" and "Include". + +The .inf file must add the correct registry values for the class and port driver, as well as using the new directives. + diff --git a/input/moufiltr/moufiltr.c b/input/moufiltr/moufiltr.c new file mode 100644 index 00000000..3e97a7a1 --- /dev/null +++ b/input/moufiltr/moufiltr.c @@ -0,0 +1,504 @@ +/*-- +Copyright (c) 2008 Microsoft Corporation + +Module Name: + + moufiltr.c + +Abstract: + +Environment: + + Kernel mode only- Framework Version + +Notes: + + +--*/ + +#include "moufiltr.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text (INIT, DriverEntry) +#pragma alloc_text (PAGE, MouFilter_EvtDeviceAdd) +#pragma alloc_text (PAGE, MouFilter_EvtIoInternalDeviceControl) +#endif + +#pragma warning(push) +#pragma warning(disable:4055) // type case from PVOID to PSERVICE_CALLBACK_ROUTINE +#pragma warning(disable:4152) // function/data pointer conversion in expression + +NTSTATUS +DriverEntry ( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ +Routine Description: + + Installable driver initialization entry point. + This entry point is called directly by the I/O system. + +--*/ +{ + WDF_DRIVER_CONFIG config; + NTSTATUS status; + + DebugPrint(("Mouse Filter Driver Sample - Driver Framework Edition.\n")); + DebugPrint(("Built %s %s\n", __DATE__, __TIME__)); + + // Initiialize driver config to control the attributes that + // are global to the driver. Note that framework by default + // provides a driver unload routine. If you create any resources + // in the DriverEntry and want to be cleaned in driver unload, + // you can override that by manually setting the EvtDriverUnload in the + // config structure. In general xxx_CONFIG_INIT macros are provided to + // initialize most commonly used members. + + WDF_DRIVER_CONFIG_INIT( + &config, + MouFilter_EvtDeviceAdd + ); + + // + // Create a framework driver object to represent our driver. + // + status = WdfDriverCreate(DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, + &config, + WDF_NO_HANDLE); // hDriver optional + if (!NT_SUCCESS(status)) { + DebugPrint( ("WdfDriverCreate failed with status 0x%x\n", status)); + } + + return status; +} + +NTSTATUS +MouFilter_EvtDeviceAdd( + IN WDFDRIVER Driver, + IN PWDFDEVICE_INIT DeviceInit + ) +/*++ +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. Here you can query the device properties + using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based + on that, decide to create a filter device object and attach to the + function stack. + + If you are not interested in filtering this particular instance of the + device, you can just return STATUS_SUCCESS without creating a framework + device. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + WDF_OBJECT_ATTRIBUTES deviceAttributes; + NTSTATUS status; + WDFDEVICE hDevice; + WDF_IO_QUEUE_CONFIG ioQueueConfig; + + UNREFERENCED_PARAMETER(Driver); + + PAGED_CODE(); + + DebugPrint(("Enter FilterEvtDeviceAdd \n")); + + // + // Tell the framework that you are filter driver. Framework + // takes care of inherting all the device flags & characterstics + // from the lower device you are attaching to. + // + WdfFdoInitSetFilter(DeviceInit); + + WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_MOUSE); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, + DEVICE_EXTENSION); + + + // + // Create a framework device object. This call will in turn create + // a WDM deviceobject, attach to the lower stack and set the + // appropriate flags and attributes. + // + status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &hDevice); + if (!NT_SUCCESS(status)) { + DebugPrint(("WdfDeviceCreate failed with status code 0x%x\n", status)); + return status; + } + + + // + // Configure the default queue to be Parallel. Do not use sequential queue + // if this driver is going to be filtering PS2 ports because it can lead to + // deadlock. The PS2 port driver sends a request to the top of the stack when it + // receives an ioctl request and waits for it to be completed. If you use a + // a sequential queue, this request will be stuck in the queue because of the + // outstanding ioctl request sent earlier to the port driver. + // + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, + WdfIoQueueDispatchParallel); + + // + // Framework by default creates non-power managed queues for + // filter drivers. + // + ioQueueConfig.EvtIoInternalDeviceControl = MouFilter_EvtIoInternalDeviceControl; + + status = WdfIoQueueCreate(hDevice, + &ioQueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + WDF_NO_HANDLE // pointer to default queue + ); + if (!NT_SUCCESS(status)) { + DebugPrint( ("WdfIoQueueCreate failed 0x%x\n", status)); + return status; + } + + return status; +} + + + +VOID +MouFilter_DispatchPassThrough( + _In_ WDFREQUEST Request, + _In_ WDFIOTARGET Target + ) +/*++ +Routine Description: + + Passes a request on to the lower driver. + + +--*/ +{ + // + // Pass the IRP to the target + // + + WDF_REQUEST_SEND_OPTIONS options; + BOOLEAN ret; + NTSTATUS status = STATUS_SUCCESS; + + // + // We are not interested in post processing the IRP so + // fire and forget. + // + WDF_REQUEST_SEND_OPTIONS_INIT(&options, + WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); + + ret = WdfRequestSend(Request, Target, &options); + + if (ret == FALSE) { + status = WdfRequestGetStatus (Request); + DebugPrint( ("WdfRequestSend failed: 0x%x\n", status)); + WdfRequestComplete(Request, status); + } + + return; +} + +VOID +MouFilter_EvtIoInternalDeviceControl( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t OutputBufferLength, + IN size_t InputBufferLength, + IN ULONG IoControlCode + ) +/*++ + +Routine Description: + + This routine is the dispatch routine for internal device control requests. + There are two specific control codes that are of interest: + + IOCTL_INTERNAL_MOUSE_CONNECT: + Store the old context and function pointer and replace it with our own. + This makes life much simpler than intercepting IRPs sent by the RIT and + modifying them on the way back up. + + IOCTL_INTERNAL_I8042_HOOK_MOUSE: + Add in the necessary function pointers and context values so that we can + alter how the ps/2 mouse is initialized. + + NOTE: Handling IOCTL_INTERNAL_I8042_HOOK_MOUSE is *NOT* necessary if + all you want to do is filter MOUSE_INPUT_DATAs. You can remove + the handling code and all related device extension fields and + functions to conserve space. + + +--*/ +{ + + PDEVICE_EXTENSION devExt; + PCONNECT_DATA connectData; + PINTERNAL_I8042_HOOK_MOUSE hookMouse; + NTSTATUS status = STATUS_SUCCESS; + WDFDEVICE hDevice; + size_t length; + + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + PAGED_CODE(); + + hDevice = WdfIoQueueGetDevice(Queue); + devExt = FilterGetData(hDevice); + + switch (IoControlCode) { + + // + // Connect a mouse class device driver to the port driver. + // + case IOCTL_INTERNAL_MOUSE_CONNECT: + // + // Only allow one connection. + // + if (devExt->UpperConnectData.ClassService != NULL) { + status = STATUS_SHARING_VIOLATION; + break; + } + + // + // Copy the connection parameters to the device extension. + // + status = WdfRequestRetrieveInputBuffer(Request, + sizeof(CONNECT_DATA), + &connectData, + &length); + if(!NT_SUCCESS(status)){ + DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status)); + break; + } + + + devExt->UpperConnectData = *connectData; + + // + // Hook into the report chain. Everytime a mouse packet is reported to + // the system, MouFilter_ServiceCallback will be called + // + connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice); + connectData->ClassService = MouFilter_ServiceCallback; + + break; + + // + // Disconnect a mouse class device driver from the port driver. + // + case IOCTL_INTERNAL_MOUSE_DISCONNECT: + + // + // Clear the connection parameters in the device extension. + // + // devExt->UpperConnectData.ClassDeviceObject = NULL; + // devExt->UpperConnectData.ClassService = NULL; + + status = STATUS_NOT_IMPLEMENTED; + break; + + // + // Attach this driver to the initialization and byte processing of the + // i8042 (ie PS/2) mouse. This is only necessary if you want to do PS/2 + // specific functions, otherwise hooking the CONNECT_DATA is sufficient + // + case IOCTL_INTERNAL_I8042_HOOK_MOUSE: + + DebugPrint(("hook mouse received!\n")); + + // Get the input buffer from the request + // (Parameters.DeviceIoControl.Type3InputBuffer) + // + status = WdfRequestRetrieveInputBuffer(Request, + sizeof(INTERNAL_I8042_HOOK_MOUSE), + &hookMouse, + &length); + if(!NT_SUCCESS(status)){ + DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status)); + break; + } + + // + // Set isr routine and context and record any values from above this driver + // + devExt->UpperContext = hookMouse->Context; + hookMouse->Context = (PVOID) devExt; + + if (hookMouse->IsrRoutine) { + devExt->UpperIsrHook = hookMouse->IsrRoutine; + } + hookMouse->IsrRoutine = (PI8042_MOUSE_ISR) MouFilter_IsrHook; + + // + // Store all of the other functions we might need in the future + // + devExt->IsrWritePort = hookMouse->IsrWritePort; + devExt->CallContext = hookMouse->CallContext; + devExt->QueueMousePacket = hookMouse->QueueMousePacket; + + status = STATUS_SUCCESS; + break; + + // + // Might want to capture this in the future. For now, then pass it down + // the stack. These queries must be successful for the RIT to communicate + // with the mouse. + // + case IOCTL_MOUSE_QUERY_ATTRIBUTES: + default: + break; + } + + if (!NT_SUCCESS(status)) { + WdfRequestComplete(Request, status); + return ; + } + + MouFilter_DispatchPassThrough(Request,WdfDeviceGetIoTarget(hDevice)); +} + + +BOOLEAN +MouFilter_IsrHook ( + PVOID DeviceExtension, + PMOUSE_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, + PUCHAR DataByte, + PBOOLEAN ContinueProcessing, + PMOUSE_STATE MouseState, + PMOUSE_RESET_SUBSTATE ResetSubState +) +/*++ + +Remarks: + i8042prt specific code, if you are writing a packet only filter driver, you + can remove this function + +Arguments: + + DeviceExtension - Our context passed during IOCTL_INTERNAL_I8042_HOOK_MOUSE + + CurrentInput - Current input packet being formulated by processing all the + interrupts + + CurrentOutput - Current list of bytes being written to the mouse or the + i8042 port. + + StatusByte - Byte read from I/O port 60 when the interrupt occurred + + DataByte - Byte read from I/O port 64 when the interrupt occurred. + This value can be modified and i8042prt will use this value + if ContinueProcessing is TRUE + + ContinueProcessing - If TRUE, i8042prt will proceed with normal processing of + the interrupt. If FALSE, i8042prt will return from the + interrupt after this function returns. Also, if FALSE, + it is this functions responsibilityt to report the input + packet via the function provided in the hook IOCTL or via + queueing a DPC within this driver and calling the + service callback function acquired from the connect IOCTL + +Return Value: + + Status is returned. + + --+*/ +{ + PDEVICE_EXTENSION devExt; + BOOLEAN retVal = TRUE; + + devExt = DeviceExtension; + + if (devExt->UpperIsrHook) { + retVal = (*devExt->UpperIsrHook) (devExt->UpperContext, + CurrentInput, + CurrentOutput, + StatusByte, + DataByte, + ContinueProcessing, + MouseState, + ResetSubState + ); + + if (!retVal || !(*ContinueProcessing)) { + return retVal; + } + } + + *ContinueProcessing = TRUE; + return retVal; +} + + + +VOID +MouFilter_ServiceCallback( + IN PDEVICE_OBJECT DeviceObject, + IN PMOUSE_INPUT_DATA InputDataStart, + IN PMOUSE_INPUT_DATA InputDataEnd, + IN OUT PULONG InputDataConsumed + ) +/*++ + +Routine Description: + + Called when there are mouse packets to report to the RIT. You can do + anything you like to the packets. For instance: + + o Drop a packet altogether + o Mutate the contents of a packet + o Insert packets into the stream + +Arguments: + + DeviceObject - Context passed during the connect IOCTL + + InputDataStart - First packet to be reported + + InputDataEnd - One past the last packet to be reported. Total number of + packets is equal to InputDataEnd - InputDataStart + + InputDataConsumed - Set to the total number of packets consumed by the RIT + (via the function pointer we replaced in the connect + IOCTL) + +Return Value: + + Status is returned. + +--*/ +{ + PDEVICE_EXTENSION devExt; + WDFDEVICE hDevice; + + hDevice = WdfWdmDeviceGetWdfDeviceHandle(DeviceObject); + + devExt = FilterGetData(hDevice); + // + // UpperConnectData must be called at DISPATCH + // + (*(PSERVICE_CALLBACK_ROUTINE) devExt->UpperConnectData.ClassService)( + devExt->UpperConnectData.ClassDeviceObject, + InputDataStart, + InputDataEnd, + InputDataConsumed + ); +} + +#pragma warning(pop) diff --git a/input/moufiltr/moufiltr.h b/input/moufiltr/moufiltr.h new file mode 100644 index 00000000..f94bc57a --- /dev/null +++ b/input/moufiltr/moufiltr.h @@ -0,0 +1,126 @@ +/*++ +Copyright (c) 2008 Microsoft Corporation + +Module Name: + + moufiltr.h + +Abstract: + + This module contains the common private declarations for the mouse + packet filter + +Environment: + + kernel mode only + +Notes: + + +Revision History: + + +--*/ + +#ifndef MOUFILTER_H +#define MOUFILTER_H + +#include <ntddk.h> +#include <kbdmou.h> +#include <ntddmou.h> +#include <ntdd8042.h> +#include <wdf.h> + + + +#if DBG + +#define TRAP() DbgBreakPoint() + +#define DebugPrint(_x_) DbgPrint _x_ + +#else // DBG + +#define TRAP() + +#define DebugPrint(_x_) + +#endif + + +typedef struct _DEVICE_EXTENSION +{ + + // + // Previous hook routine and context + // + PVOID UpperContext; + + PI8042_MOUSE_ISR UpperIsrHook; + + // + // Write to the mouse in the context of MouFilter_IsrHook + // + IN PI8042_ISR_WRITE_PORT IsrWritePort; + + // + // Context for IsrWritePort, QueueMousePacket + // + IN PVOID CallContext; + + // + // Queue the current packet (ie the one passed into MouFilter_IsrHook) + // to be reported to the class driver + // + IN PI8042_QUEUE_PACKET QueueMousePacket; + + // + // The real connect data that this driver reports to + // + CONNECT_DATA UpperConnectData; + + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, + FilterGetData) + +// +// Prototypes +// +DRIVER_INITIALIZE DriverEntry; + +EVT_WDF_DRIVER_DEVICE_ADD MouFilter_EvtDeviceAdd; +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL MouFilter_EvtIoInternalDeviceControl; + + + +VOID +MouFilter_DispatchPassThrough( + _In_ WDFREQUEST Request, + _In_ WDFIOTARGET Target + ); + +BOOLEAN +MouFilter_IsrHook ( + PVOID DeviceExtension, + PMOUSE_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, + PUCHAR DataByte, + PBOOLEAN ContinueProcessing, + PMOUSE_STATE MouseState, + PMOUSE_RESET_SUBSTATE ResetSubState +); + +VOID +MouFilter_ServiceCallback( + IN PDEVICE_OBJECT DeviceObject, + IN PMOUSE_INPUT_DATA InputDataStart, + IN PMOUSE_INPUT_DATA InputDataEnd, + IN OUT PULONG InputDataConsumed + ); + +#endif // MOUFILTER_H + + diff --git a/input/moufiltr/moufiltr.inx b/input/moufiltr/moufiltr.inx new file mode 100644 index 00000000..50878d68 --- /dev/null +++ b/input/moufiltr/moufiltr.inx @@ -0,0 +1,139 @@ +; moufiltr.inf +; +; Installation inf for the Device that needs filtering adapter. +; +; (c) Copyright 2008 Microsoft +; + +[Version] +Signature="$Windows NT$" +Provider=%ProviderName% +ClassGUID={4D36E96F-E325-11CE-BFC1-08002BE10318} +Class=Mouse +DriverVer=02/05/2008, 1.0.0.0 +; Uncomment the following line when you have a valid catalog file. +; If you use bogus catalog file installation will fail. +CatalogFile=KmdfSamples.cat + +[DestinationDirs] +DefaultDestDir = 12 +moufiltr_CoInstaller_CopyFiles = 11 + +; +; Driver information +; + +[Manufacturer] +%MfgName% = Standard,NT$ARCH$ + +[Standard.NT$ARCH$] +%moufiltr.DeviceDesc% = moufiltr, *PNP0FAKE + +; +; General installation section +; + +[moufiltr.NT] +; perform port related actions from mouse.inf +Include=msmouse.inf +Needs=PS2_Inst + +; Copy the driver over +CopyFiles=moufiltr.CopyFiles + + +; +; File sections +; + +[moufiltr.CopyFiles] +moufiltr.sys + + +; +; Service Installation +; + +[moufiltr.NT.Services] +AddService = moufiltr, , moufiltr_Service_Inst +; Install the port driver and mouclass from msmouse.inf +Include=msmouse.inf +Needs=PS2_Inst.Services + +[moufiltr_Service_Inst] +DisplayName = %moufiltr.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 0 ; SERVICE_ERROR_IGNORE +ServiceBinary = %12%\moufiltr.sys + +[moufiltr.NT.HW] +; Add the device upper filter +AddReg = moufiltr.HW.AddReg + +; run the directives need by the port driver +Include=msmouse.inf +Needs=PS2_Inst.HW + +[moufiltr.HW.AddReg] +HKR,,"UpperFilters",0x00010000,"moufiltr" + + +; +; Source file information +; + + +[SourceDisksNames] +1 = %DiskId1%,,, + +[SourceDisksFiles] +moufiltr.sys = 1 +WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll = 1 + +; +;--- moufiltr Coinstaller installation ------ +; + +[moufiltr.NT.CoInstallers] +AddReg=moufiltr_CoInstaller_AddReg +CopyFiles=moufiltr_CoInstaller_CopyFiles + +[moufiltr_CoInstaller_AddReg] +HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" + +[moufiltr_CoInstaller_CopyFiles] +WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll + +[moufiltr.NT.Wdf] +KmdfService = moufiltr, moufiltr_wdfsect + +[moufiltr_wdfsect] +KmdfLibraryVersion = $KMDFVERSION$ + + +[Strings] + +; +; Non-Localizable Strings +; + +REG_SZ = 0x00000000 +REG_MULTI_SZ = 0x00010000 +REG_EXPAND_SZ = 0x00020000 +REG_BINARY = 0x00000001 +REG_DWORD = 0x00010001 + +; +; Localizable Strings +; + +ProviderName = "TODO-Set-Provider" +MfgName = "TODO-Set-Manufacturer" + +moufiltr.DeviceDesc = "Mouse Filter Sample Device" + +; Make sure the service description is unique to avoid collision with another INF. +moufiltr.SvcDesc = "Mouse Filter Sample Driver" + +DiskId1 = "Mouse Filter Install Disk" diff --git a/input/moufiltr/moufiltr.rc b/input/moufiltr/moufiltr.rc new file mode 100644 index 00000000..af1df62f --- /dev/null +++ b/input/moufiltr/moufiltr.rc @@ -0,0 +1,11 @@ +#include <windows.h> + +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Mouse Filter Driver" +#define VER_INTERNALNAME_STR "moufiltr.sys" + +#include "common.ver" + diff --git a/input/moufiltr/moufiltr.sln b/input/moufiltr/moufiltr.sln new file mode 100644 index 00000000..0f1efdd9 --- /dev/null +++ b/input/moufiltr/moufiltr.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "moufiltr", "moufiltr.vcxproj", "{28C26795-633E-42B3-BAC7-F276679CDF90}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {28C26795-633E-42B3-BAC7-F276679CDF90}.Debug|Win32.ActiveCfg = Debug|Win32 + {28C26795-633E-42B3-BAC7-F276679CDF90}.Debug|Win32.Build.0 = Debug|Win32 + {28C26795-633E-42B3-BAC7-F276679CDF90}.Release|Win32.ActiveCfg = Release|Win32 + {28C26795-633E-42B3-BAC7-F276679CDF90}.Release|Win32.Build.0 = Release|Win32 + {28C26795-633E-42B3-BAC7-F276679CDF90}.Debug|x64.ActiveCfg = Debug|x64 + {28C26795-633E-42B3-BAC7-F276679CDF90}.Debug|x64.Build.0 = Debug|x64 + {28C26795-633E-42B3-BAC7-F276679CDF90}.Release|x64.ActiveCfg = Release|x64 + {28C26795-633E-42B3-BAC7-F276679CDF90}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/input/moufiltr/moufiltr.vcxproj b/input/moufiltr/moufiltr.vcxproj new file mode 100644 index 00000000..9840820e --- /dev/null +++ b/input/moufiltr/moufiltr.vcxproj @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{28C26795-633E-42B3-BAC7-F276679CDF90}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{FFF2D813-0AFF-43E7-9070-27C799AE8C4A}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Universal</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems"> + <Inf Include=".\moufiltr.inx"> + <Architecture>$(InfArch)</Architecture> + <SpecifyArchitecture>true</SpecifyArchitecture> + <CopyOutput>.\$(IntDir)\moufiltr.inf</CopyOutput> + </Inf> + </ItemGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>moufiltr</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>moufiltr</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>moufiltr</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>moufiltr</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="moufiltr.c" /> + <ResourceCompile Include="moufiltr.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/input/moufiltr/moufiltr.vcxproj.Filters b/input/moufiltr/moufiltr.vcxproj.Filters new file mode 100644 index 00000000..100d3c05 --- /dev/null +++ b/input/moufiltr/moufiltr.vcxproj.Filters @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{73708C87-AE82-4681-9C01-042DF504D5E3}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{3531B16D-3C4F-4E1C-ABD4-50E16BFD7670}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{3FD872CD-6DDF-47C5-ADEC-958E7540E672}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{E86BBEC3-C79D-42D9-98BA-B087184AAB24}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <Inf Include=".\moufiltr.inx"> + <Filter>Driver Files</Filter> + </Inf> + </ItemGroup> + <ItemGroup> + <ClCompile Include="moufiltr.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="moufiltr.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file |
