├── crostouchpad ├── stdint.h ├── trace.h ├── spb.h ├── hidcommon.h ├── crostouchpad.vcxproj.user ├── crostouchpad.vcxproj.filters ├── crostouchpad.inf ├── crc.c ├── driver.h ├── crostouchpad.vcxproj ├── spb.c ├── atmel_mxt.h └── atmel.c ├── crostouchpad Package ├── crostouchpad Package.vcxproj.user ├── crostouchpad Package.vcxproj.filters └── crostouchpad Package.vcxproj ├── LICENSE.txt ├── .gitignore └── crostouchpad4.sln /crostouchpad/stdint.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BIT(nr) (1UL << (nr)) -------------------------------------------------------------------------------- /crostouchpad Package/crostouchpad Package.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | DbgengRemoteDebugger 5 | 6 | -------------------------------------------------------------------------------- /crostouchpad Package/crostouchpad Package.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {8E41214B-6785-4CFE-B992-037D68949A14} 6 | inf;inv;inx;mof;mc; 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016 CoolStar 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /crostouchpad/trace.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef _TRACE_H_ 4 | #define _TRACE_H_ 5 | 6 | extern "C" 7 | { 8 | // 9 | // Tracing Definitions: 10 | // 11 | // Control GUID: 12 | // {73e3b785-f5fb-423e-94a9-56627fea9053} 13 | // 14 | 15 | #define WPP_CONTROL_GUIDS \ 16 | WPP_DEFINE_CONTROL_GUID( \ 17 | SpbTestToolTraceGuid, \ 18 | (73e3b785,f5fb,423e,94a9,56627fea9053), \ 19 | WPP_DEFINE_BIT(TRACE_FLAG_WDFLOADING) \ 20 | WPP_DEFINE_BIT(TRACE_FLAG_SPBAPI) \ 21 | WPP_DEFINE_BIT(TRACE_FLAG_OTHER) \ 22 | ) 23 | } 24 | 25 | #define WPP_LEVEL_FLAGS_LOGGER(level,flags) WPP_LEVEL_LOGGER(flags) 26 | #define WPP_LEVEL_FLAGS_ENABLED(level, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= level) 27 | 28 | #define Trace CyapaPrint 29 | #define FuncEntry 30 | #define FuncExit 31 | #define WPP_INIT_TRACING 32 | #define WPP_CLEANUP 33 | #define TRACE_FLAG_SPBAPI 0 34 | #define TRACE_FLAG_WDFLOADING 0 35 | 36 | // begin_wpp config 37 | // FUNC FuncEntry{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 38 | // FUNC FuncExit{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 39 | // USEPREFIX(FuncEntry, "%!STDPREFIX! [%!FUNC!] --> entry"); 40 | // USEPREFIX(FuncExit, "%!STDPREFIX! [%!FUNC!] <--"); 41 | // end_wpp 42 | 43 | #endif _TRACE_H_ 44 | -------------------------------------------------------------------------------- /crostouchpad/spb.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | Copyright (c) Microsoft Corporation. All Rights Reserved. 3 | Sample code. Dealpoint ID #843729. 4 | 5 | Module Name: 6 | 7 | spb.h 8 | 9 | Abstract: 10 | 11 | This module contains the touch driver I2C helper definitions. 12 | 13 | Environment: 14 | 15 | Kernel Mode 16 | 17 | Revision History: 18 | 19 | --*/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | #define DEFAULT_SPB_BUFFER_SIZE 64 27 | #define RESHUB_USE_HELPER_ROUTINES 28 | 29 | // 30 | // SPB (I2C) context 31 | // 32 | 33 | typedef struct _SPB_CONTEXT 34 | { 35 | WDFIOTARGET SpbIoTarget; 36 | LARGE_INTEGER I2cResHubId; 37 | WDFMEMORY WriteMemory; 38 | WDFMEMORY ReadMemory; 39 | WDFWAITLOCK SpbLock; 40 | } SPB_CONTEXT; 41 | 42 | NTSTATUS 43 | SpbReadDataSynchronously( 44 | _In_ SPB_CONTEXT *SpbContext, 45 | _In_ UCHAR Address, 46 | _In_reads_bytes_(Length) PVOID Data, 47 | _In_ ULONG Length 48 | ); 49 | 50 | NTSTATUS 51 | SpbReadDataSynchronously16( 52 | _In_ SPB_CONTEXT *SpbContext, 53 | _In_ UINT16 Address, 54 | _In_reads_bytes_(Length) PVOID Data, 55 | _In_ ULONG Length 56 | ); 57 | 58 | VOID 59 | SpbTargetDeinitialize( 60 | IN WDFDEVICE FxDevice, 61 | IN SPB_CONTEXT *SpbContext 62 | ); 63 | 64 | NTSTATUS 65 | SpbTargetInitialize( 66 | IN WDFDEVICE FxDevice, 67 | IN SPB_CONTEXT *SpbContext 68 | ); 69 | 70 | NTSTATUS 71 | SpbWriteDataSynchronously( 72 | IN SPB_CONTEXT *SpbContext, 73 | IN UCHAR Address, 74 | IN PVOID Data, 75 | IN ULONG Length 76 | ); 77 | 78 | NTSTATUS 79 | SpbWriteDataSynchronously16( 80 | IN SPB_CONTEXT *SpbContext, 81 | IN UINT16 Address, 82 | IN PVOID Data, 83 | IN ULONG Length 84 | ); -------------------------------------------------------------------------------- /crostouchpad/hidcommon.h: -------------------------------------------------------------------------------- 1 | #if !defined(_ATMELTP_COMMON_H_) 2 | #define _ATMELTP_COMMON_H_ 3 | 4 | // 5 | //These are the device attributes returned by vmulti in response 6 | // to IOCTL_HID_GET_DEVICE_ATTRIBUTES. 7 | // 8 | 9 | #define ATMELTP_PID 0xBACC 10 | #define ATMELTP_VID 0x00FF 11 | #define ATMELTP_VERSION 0x0001 12 | 13 | // 14 | // These are the report ids 15 | // 16 | 17 | #define REPORTID_MTOUCH 0x01 18 | #define REPORTID_FEATURE 0x02 19 | #define REPORTID_MOUSE 0x03 20 | #define REPORTID_PTPHQA 0x04 21 | 22 | // 23 | // Multitouch specific report information 24 | // 25 | 26 | #define MULTI_CONFIDENCE_BIT 1 27 | #define MULTI_TIPSWITCH_BIT 2 28 | 29 | #define MULTI_MIN_COORDINATE 0x0000 30 | #define MULTI_MAX_COORDINATE 0x7FFF 31 | 32 | #define MULTI_MAX_COUNT 5 33 | 34 | #pragma pack(1) 35 | typedef struct 36 | { 37 | 38 | BYTE Status; 39 | 40 | BYTE ContactID; 41 | 42 | USHORT XValue; 43 | 44 | USHORT YValue; 45 | 46 | USHORT Pressure; 47 | } 48 | TOUCH, *PTOUCH; 49 | 50 | typedef struct _ATMELTP_MULTITOUCH_REPORT 51 | { 52 | 53 | BYTE ReportID; 54 | 55 | TOUCH Touch[5]; 56 | 57 | USHORT ScanTime; 58 | 59 | BYTE ContactCount; 60 | 61 | BYTE IsDepressed; 62 | } AtmelTPMultiTouchReport; 63 | #pragma pack() 64 | 65 | // 66 | // Feature report infomation 67 | // 68 | 69 | #define DEVICE_MODE_MOUSE 0x00 70 | #define DEVICE_MODE_SINGLE_INPUT 0x01 71 | #define DEVICE_MODE_MULTI_INPUT 0x02 72 | 73 | #pragma pack(1) 74 | typedef struct _ATMELTP_FEATURE_REPORT 75 | { 76 | 77 | BYTE ReportID; 78 | 79 | BYTE DeviceMode; 80 | 81 | BYTE DeviceIdentifier; 82 | 83 | } AtmelTPFeatureReport; 84 | 85 | typedef struct _ATMELTP_MAXCOUNT_REPORT 86 | { 87 | 88 | BYTE ReportID; 89 | 90 | BYTE MaximumCount; 91 | 92 | BYTE PadType; 93 | 94 | } AtmelTPMaxCountReport; 95 | #pragma pack() 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /crostouchpad/crostouchpad.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Off 5 | 6 | 7 | 8 | 9 | 10 | 11 | Off 12 | 13 | 14 | Off 15 | 16 | 17 | Off 18 | 19 | 20 | Off 21 | 22 | 23 | Off 24 | 25 | 26 | Off 27 | 28 | 29 | Off 30 | 31 | 32 | Off 33 | 34 | 35 | Off 36 | 37 | 38 | Off 39 | 40 | 41 | Off 42 | 43 | -------------------------------------------------------------------------------- /crostouchpad/crostouchpad.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | Header Files 27 | 28 | 29 | Header Files 30 | 31 | 32 | Header Files 33 | 34 | 35 | Header Files 36 | 37 | 38 | Header Files 39 | 40 | 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | 53 | 54 | Driver Files 55 | 56 | 57 | -------------------------------------------------------------------------------- /crostouchpad/crostouchpad.inf: -------------------------------------------------------------------------------- 1 | ;/*++ 2 | ; 3 | ;Copyright (c) CoolStar. All rights reserved. 4 | ; 5 | ;Module Name: 6 | ; coolstar.inf 7 | ; 8 | ;Abstract: 9 | ; INF file for installing the Atmel MaxTouch Touchpad Driver 10 | ; 11 | ; 12 | ;--*/ 13 | 14 | [Version] 15 | Signature = "$WINDOWS NT$" 16 | Class = HIDClass 17 | ClassGuid = {745a17a0-74d3-11d0-b6fe-00a0c90f57da} 18 | Provider = CoolStar 19 | DriverVer = 2/15/2022, 4.1.2 20 | CatalogFile = crostouchpad.cat 21 | PnpLockdown = 1 22 | 23 | [DestinationDirs] 24 | DefaultDestDir = 12 25 | 26 | ; ================= Class section ===================== 27 | 28 | [SourceDisksNames] 29 | 1 = %DiskId1%,,,"" 30 | 31 | [SourceDisksFiles] 32 | crostouchpad.sys = 1,, 33 | 34 | ;***************************************** 35 | ; CrosTouchpad Install Section 36 | ;***************************************** 37 | 38 | [Manufacturer] 39 | %StdMfg%=Standard,NT$ARCH$ 40 | 41 | ; Decorated model section take precedence over undecorated 42 | ; ones on XP and later. 43 | [Standard.NT$ARCH$] 44 | %CrosTouchpad.DeviceDesc%=CrosTouchpad_Device, ACPI\ATML0000 45 | 46 | [CrosTouchpad_Device.NT] 47 | CopyFiles=Drivers_Dir 48 | 49 | [CrosTouchpad_Device.NT.HW] 50 | AddReg=CrosTouchpad_AddReg 51 | 52 | [Drivers_Dir] 53 | crostouchpad.sys 54 | 55 | [CrosTouchpad_AddReg] 56 | ; Set to 1 to connect the first interrupt resource found, 0 to leave disconnected 57 | HKR,Settings,"ConnectInterrupt",0x00010001,0 58 | HKR,,"UpperFilters",0x00010000,"mshidkmdf" 59 | 60 | ;-------------- Service installation 61 | [CrosTouchpad_Device.NT.Services] 62 | AddService = CrosTouchpad,%SPSVCINST_ASSOCSERVICE%, CrosTouchpad_Service_Inst 63 | 64 | ; -------------- CrosTouchpad driver install sections 65 | [CrosTouchpad_Service_Inst] 66 | DisplayName = %CrosTouchpad.SVCDESC% 67 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 68 | StartType = 3 ; SERVICE_DEMAND_START 69 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 70 | ServiceBinary = %12%\crostouchpad.sys 71 | LoadOrderGroup = Base 72 | 73 | [Strings] 74 | SPSVCINST_ASSOCSERVICE= 0x00000002 75 | StdMfg = "CoolStar" 76 | DiskId1 = "CrosTouchpad Installation Disk #1" 77 | CrosTouchpad.DeviceDesc = "Chromebook Atmel MaxTouch Touchpad" 78 | CrosTouchpad.SVCDESC = "CrosTouchpad Service" 79 | -------------------------------------------------------------------------------- /crostouchpad/crc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 | * 4 | * This code is derived from software contributed to The DragonFly Project 5 | * by Matthew Dillon 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * 3. Neither the name of The DragonFly Project nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific, prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | *------------------------------------------------------------------------------ 35 | * Copyright 2011 Atmel Corporation. All rights reserved. 36 | * 37 | * Redistribution and use in source and binary forms, with or without 38 | * modification, are permitted provided that the following conditions are met: 39 | * 40 | * 1. Redistributions of source code must retain the above copyright notice, 41 | * this list of conditions and the following disclaimer. 42 | * 43 | * 2. Redistributions in binary form must reproduce the above copyright 44 | * notice, this list of conditions and the following disclaimer in the 45 | * documentation and/or other materials provided with the distribution. 46 | * 47 | * THIS SOFTWARE IS PROVIDED BY ATMEL ''AS IS'' AND ANY EXPRESS OR IMPLIED 48 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 49 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 50 | * EVENT SHALL ATMEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 52 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 53 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 54 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 55 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 56 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | *----------------------------------------------------------------------------- 58 | */ 59 | /* 60 | * This file contains a mix of code taken from the atmel-maxtouch/obp-utils 61 | * github codebase and my own for testing the atmel touchscreen chipset in 62 | * the Acer C720P chromebook. 63 | * 64 | * This code is independent and is used by both kernel AND user mode programs. 65 | */ 66 | 67 | #include 68 | #include "atmel_mxt.h" 69 | 70 | /*! 71 | * @brief Information block checksum return function. 72 | * @return 24-bit checksum value in 32-bit integer. 73 | */ 74 | uint32_t 75 | obp_convert_crc(struct mxt_raw_crc *crc) 76 | { 77 | return ((crc->CRC_hi << 16u) | (crc->CRC)); 78 | } 79 | 80 | /*! 81 | * @brief Information Block Checksum algorithm. 82 | * @return Calculated Information Block Checksum. 83 | */ 84 | static 85 | uint32_t 86 | crc24_2byte(uint32_t crc, uint8_t firstbyte, uint8_t secondbyte) 87 | { 88 | static const uint32_t CRCPOLY = 0x0080001B; 89 | uint32_t result; 90 | uint16_t data_word; 91 | 92 | data_word = (uint16_t)((uint16_t)(secondbyte << 8u) | firstbyte); 93 | result = ((crc << 1u) ^ (uint32_t)data_word); 94 | 95 | /* Check if 25th bit is set, and XOR the result to create 96 | * 24-bit checksum */ 97 | if (result & 0x1000000) { 98 | result ^= CRCPOLY; 99 | } 100 | return result; 101 | } 102 | 103 | /* 104 | * Return 24-bit crc. 105 | */ 106 | uint32_t 107 | obp_crc24(uint8_t *buf, size_t bytes) 108 | { 109 | uint32_t crc; 110 | size_t i; 111 | 112 | crc = 0; 113 | for (i = 0; i < (bytes & ~1); i += 2) { 114 | crc = crc24_2byte(crc, buf[i], buf[i + 1]); 115 | } 116 | if (i < bytes) 117 | crc = crc24_2byte(crc, buf[i], 0); 118 | crc &= 0x00FFFFFF; 119 | 120 | return crc; 121 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015/2017 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # Visual Studio 2017 auto generated files 34 | Generated\ Files/ 35 | 36 | # MSTest test Results 37 | [Tt]est[Rr]esult*/ 38 | [Bb]uild[Ll]og.* 39 | 40 | # NUNIT 41 | *.VisualState.xml 42 | TestResult.xml 43 | 44 | # Build Results of an ATL Project 45 | [Dd]ebugPS/ 46 | [Rr]eleasePS/ 47 | dlldata.c 48 | 49 | # Benchmark Results 50 | BenchmarkDotNet.Artifacts/ 51 | 52 | # .NET Core 53 | project.lock.json 54 | project.fragment.lock.json 55 | artifacts/ 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_h.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *_wpftmp.csproj 81 | *.log 82 | *.vspscc 83 | *.vssscc 84 | .builds 85 | *.pidb 86 | *.svclog 87 | *.scc 88 | 89 | # Chutzpah Test files 90 | _Chutzpah* 91 | 92 | # Visual C++ cache files 93 | ipch/ 94 | *.aps 95 | *.ncb 96 | *.opendb 97 | *.opensdf 98 | *.sdf 99 | *.cachefile 100 | *.VC.db 101 | *.VC.VC.opendb 102 | 103 | # Visual Studio profiler 104 | *.psess 105 | *.vsp 106 | *.vspx 107 | *.sap 108 | 109 | # Visual Studio Trace Files 110 | *.e2e 111 | 112 | # TFS 2012 Local Workspace 113 | $tf/ 114 | 115 | # Guidance Automation Toolkit 116 | *.gpState 117 | 118 | # ReSharper is a .NET coding add-in 119 | _ReSharper*/ 120 | *.[Rr]e[Ss]harper 121 | *.DotSettings.user 122 | 123 | # JustCode is a .NET coding add-in 124 | .JustCode 125 | 126 | # TeamCity is a build add-in 127 | _TeamCity* 128 | 129 | # DotCover is a Code Coverage Tool 130 | *.dotCover 131 | 132 | # AxoCover is a Code Coverage Tool 133 | .axoCover/* 134 | !.axoCover/settings.json 135 | 136 | # Visual Studio code coverage results 137 | *.coverage 138 | *.coveragexml 139 | 140 | # NCrunch 141 | _NCrunch_* 142 | .*crunch*.local.xml 143 | nCrunchTemp_* 144 | 145 | # MightyMoose 146 | *.mm.* 147 | AutoTest.Net/ 148 | 149 | # Web workbench (sass) 150 | .sass-cache/ 151 | 152 | # Installshield output folder 153 | [Ee]xpress/ 154 | 155 | # DocProject is a documentation generator add-in 156 | DocProject/buildhelp/ 157 | DocProject/Help/*.HxT 158 | DocProject/Help/*.HxC 159 | DocProject/Help/*.hhc 160 | DocProject/Help/*.hhk 161 | DocProject/Help/*.hhp 162 | DocProject/Help/Html2 163 | DocProject/Help/html 164 | 165 | # Click-Once directory 166 | publish/ 167 | 168 | # Publish Web Output 169 | *.[Pp]ublish.xml 170 | *.azurePubxml 171 | # Note: Comment the next line if you want to checkin your web deploy settings, 172 | # but database connection strings (with potential passwords) will be unencrypted 173 | *.pubxml 174 | *.publishproj 175 | 176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 177 | # checkin your Azure Web App publish settings, but sensitive information contained 178 | # in these scripts will be unencrypted 179 | PublishScripts/ 180 | 181 | # NuGet Packages 182 | *.nupkg 183 | # The packages folder can be ignored because of Package Restore 184 | **/[Pp]ackages/* 185 | # except build/, which is used as an MSBuild target. 186 | !**/[Pp]ackages/build/ 187 | # Uncomment if necessary however generally it will be regenerated when needed 188 | #!**/[Pp]ackages/repositories.config 189 | # NuGet v3's project.json files produces more ignorable files 190 | *.nuget.props 191 | *.nuget.targets 192 | 193 | # Microsoft Azure Build Output 194 | csx/ 195 | *.build.csdef 196 | 197 | # Microsoft Azure Emulator 198 | ecf/ 199 | rcf/ 200 | 201 | # Windows Store app package directories and files 202 | AppPackages/ 203 | BundleArtifacts/ 204 | Package.StoreAssociation.xml 205 | _pkginfo.txt 206 | *.appx 207 | 208 | # Visual Studio cache files 209 | # files ending in .cache can be ignored 210 | *.[Cc]ache 211 | # but keep track of directories ending in .cache 212 | !*.[Cc]ache/ 213 | 214 | # Others 215 | ClientBin/ 216 | ~$* 217 | *~ 218 | *.dbmdl 219 | *.dbproj.schemaview 220 | *.jfm 221 | *.pfx 222 | *.publishsettings 223 | orleans.codegen.cs 224 | 225 | # Including strong name files can present a security risk 226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 227 | #*.snk 228 | 229 | # Since there are multiple workflows, uncomment next line to ignore bower_components 230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 231 | #bower_components/ 232 | 233 | # RIA/Silverlight projects 234 | Generated_Code/ 235 | 236 | # Backup & report files from converting an old project file 237 | # to a newer Visual Studio version. Backup files are not needed, 238 | # because we have git ;-) 239 | _UpgradeReport_Files/ 240 | Backup*/ 241 | UpgradeLog*.XML 242 | UpgradeLog*.htm 243 | ServiceFabricBackup/ 244 | *.rptproj.bak 245 | 246 | # SQL Server files 247 | *.mdf 248 | *.ldf 249 | *.ndf 250 | 251 | # Business Intelligence projects 252 | *.rdl.data 253 | *.bim.layout 254 | *.bim_*.settings 255 | *.rptproj.rsuser 256 | 257 | # Microsoft Fakes 258 | FakesAssemblies/ 259 | 260 | # GhostDoc plugin setting file 261 | *.GhostDoc.xml 262 | 263 | # Node.js Tools for Visual Studio 264 | .ntvs_analysis.dat 265 | node_modules/ 266 | 267 | # Visual Studio 6 build log 268 | *.plg 269 | 270 | # Visual Studio 6 workspace options file 271 | *.opt 272 | 273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 274 | *.vbw 275 | 276 | # Visual Studio LightSwitch build output 277 | **/*.HTMLClient/GeneratedArtifacts 278 | **/*.DesktopClient/GeneratedArtifacts 279 | **/*.DesktopClient/ModelManifest.xml 280 | **/*.Server/GeneratedArtifacts 281 | **/*.Server/ModelManifest.xml 282 | _Pvt_Extensions 283 | 284 | # Paket dependency manager 285 | .paket/paket.exe 286 | paket-files/ 287 | 288 | # FAKE - F# Make 289 | .fake/ 290 | 291 | # JetBrains Rider 292 | .idea/ 293 | *.sln.iml 294 | 295 | # CodeRush personal settings 296 | .cr/personal 297 | 298 | # Python Tools for Visual Studio (PTVS) 299 | __pycache__/ 300 | *.pyc 301 | 302 | # Cake - Uncomment if you are using it 303 | # tools/** 304 | # !tools/packages.config 305 | 306 | # Tabs Studio 307 | *.tss 308 | 309 | # Telerik's JustMock configuration file 310 | *.jmconfig 311 | 312 | # BizTalk build output 313 | *.btp.cs 314 | *.btm.cs 315 | *.odx.cs 316 | *.xsd.cs 317 | 318 | # OpenCover UI analysis results 319 | OpenCover/ 320 | 321 | # Azure Stream Analytics local run output 322 | ASALocalRun/ 323 | 324 | # MSBuild Binary and Structured Log 325 | *.binlog 326 | 327 | # NVidia Nsight GPU debugger configuration file 328 | *.nvuser 329 | 330 | # MFractors (Xamarin productivity tool) working folder 331 | .mfractor/ 332 | 333 | # Local History for Visual Studio 334 | .localhistory/ 335 | -------------------------------------------------------------------------------- /crostouchpad4.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crostouchpad", "crostouchpad\crostouchpad.vcxproj", "{B3E71397-9BE4-492B-AAED-4D056E59CB1F}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crostouchpad Package", "crostouchpad Package\crostouchpad Package.vcxproj", "{EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F} = {B3E71397-9BE4-492B-AAED-4D056E59CB1F} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Win7 Debug|Win32 = Win7 Debug|Win32 16 | Win7 Debug|x64 = Win7 Debug|x64 17 | Win7 Release|Win32 = Win7 Release|Win32 18 | Win7 Release|x64 = Win7 Release|x64 19 | Win8 Debug|Win32 = Win8 Debug|Win32 20 | Win8 Debug|x64 = Win8 Debug|x64 21 | Win8 Release|Win32 = Win8 Release|Win32 22 | Win8 Release|x64 = Win8 Release|x64 23 | Win8.1 Debug|Win32 = Win8.1 Debug|Win32 24 | Win8.1 Debug|x64 = Win8.1 Debug|x64 25 | Win8.1 Release|Win32 = Win8.1 Release|Win32 26 | Win8.1 Release|x64 = Win8.1 Release|x64 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 30 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 31 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Debug|Win32.Deploy.0 = Win7 Debug|Win32 32 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 33 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 34 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64 35 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 36 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 37 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32 38 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 39 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Release|x64.Build.0 = Win7 Release|x64 40 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win7 Release|x64.Deploy.0 = Win7 Release|x64 41 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 42 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 43 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 44 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 45 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 46 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 47 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 48 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 49 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 50 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 51 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Release|x64.Build.0 = Win8 Release|x64 52 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 53 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 54 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 55 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 56 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 57 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 58 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 59 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 60 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 61 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 62 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 63 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 64 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 65 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 66 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 67 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Debug|Win32.Deploy.0 = Win7 Debug|Win32 68 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 69 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 70 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64 71 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 72 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 73 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32 74 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 75 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Release|x64.Build.0 = Win7 Release|x64 76 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win7 Release|x64.Deploy.0 = Win7 Release|x64 77 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 78 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 79 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 80 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 81 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 82 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 83 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 84 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 85 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 86 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 87 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Release|x64.Build.0 = Win8 Release|x64 88 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 89 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 90 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 91 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 92 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 93 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 94 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 95 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 96 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 97 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 98 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 99 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 100 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 101 | EndGlobalSection 102 | GlobalSection(SolutionProperties) = preSolution 103 | HideSolutionNode = FALSE 104 | EndGlobalSection 105 | EndGlobal 106 | -------------------------------------------------------------------------------- /crostouchpad/driver.h: -------------------------------------------------------------------------------- 1 | #if !defined(_ATMELTP_H_) 2 | #define _ATMELTP_H_ 3 | 4 | #pragma warning(disable:4200) // suppress nameless struct/union warning 5 | #pragma warning(disable:4201) // suppress nameless struct/union warning 6 | #pragma warning(disable:4214) // suppress bit field types other than int warning 7 | #include 8 | #include 9 | 10 | #pragma warning(default:4200) 11 | #pragma warning(default:4201) 12 | #pragma warning(default:4214) 13 | #include 14 | 15 | #pragma warning(disable:4201) // suppress nameless struct/union warning 16 | #pragma warning(disable:4214) // suppress bit field types other than int warning 17 | #include 18 | 19 | #include "hidcommon.h" 20 | #include "spb.h" 21 | #include "atmel_mxt.h" 22 | 23 | // 24 | // String definitions 25 | // 26 | 27 | #define DRIVERNAME "crostouchpad4.sys: " 28 | 29 | #define ATMELTP_POOL_TAG (ULONG) 'aptA' 30 | 31 | #define NTDEVICE_NAME_STRING L"\\Device\\ATML0000" 32 | #define SYMBOLIC_NAME_STRING L"\\DosDevices\\ATML0000" 33 | 34 | #define MT_TOUCH_COLLECTION0 \ 35 | 0xa1, 0x02, /* COLLECTION (Logical) */ \ 36 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ 37 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ 38 | 0x09, 0x47, /* USAGE (Confidence) */ \ 39 | 0x09, 0x42, /* USAGE (Tip switch) */ \ 40 | 0x95, 0x02, /* REPORT_COUNT (2) */ \ 41 | 0x75, 0x01, /* REPORT_SIZE (1) */ \ 42 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 43 | 0x95, 0x06, /* REPORT_COUNT (6) */ \ 44 | 0x81, 0x03, /* INPUT (Cnst,Ary,Abs) */ \ 45 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 46 | 0x75, 0x04, /* REPORT_SIZE (4) */ \ 47 | 0x25, 0x10, /* LOGICAL_MAXIMUM (16) */ \ 48 | 0x09, 0x51, /* USAGE (Contact Identifier)*/ \ 49 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 50 | 0x75, 0x01, /* REPORT_SIZE (1) */ \ 51 | 0x95, 0x04, /* REPORT_COUNT (4) */ \ 52 | 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ 53 | 0x05, 0x01, /* USAGE_PAGE (Generic Desk..*/ \ 54 | 0x75, 0x10, /* REPORT_SIZE (16) */ \ 55 | 0x55, 0x0e, /* UNIT_EXPONENT (-2) */ \ 56 | /*0x65, 0x13, /* UNIT(Inch,EngLinear) */ \ 57 | 0x65, 0x11, /* UNIT(Cm,SiLinear) */ \ 58 | 0x09, 0x30, /* USAGE (X) */ \ 59 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ 60 | 0x35, 0x00, /* PHYSICAL_MINIMUM (0) */ \ 61 | 62 | #define MT_TOUCH_COLLECTION1 \ 63 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 64 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 65 | 66 | #define MT_TOUCH_COLLECTION2 \ 67 | 0x09, 0x31, /* USAGE (Y) */ \ 68 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 69 | 0x05, 0x0d, /* USAGE PAGE (Digitizers) */ \ 70 | 0x09, 0x30, /* USAGE (Tip Pressure) */ \ 71 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 72 | 0xc0, /* END_COLLECTION */ 73 | 74 | #define MT_REF_TOUCH_COLLECTION \ 75 | MT_TOUCH_COLLECTION0 \ 76 | 0x26, 0x66, 0x03, /* LOGICAL_MAXIMUM (870) */ \ 77 | 0x46, 0x8E, 0x03, /* PHYSICAL_MAXIMUM (910) */ \ 78 | MT_TOUCH_COLLECTION1 \ 79 | 0x26, 0xE0, 0x01, /* LOGICAL_MAXIMUM (480) */ \ 80 | 0x46, 0xFE, 0x01, /* PHYSICAL_MAXIMUM (550) */ \ 81 | MT_TOUCH_COLLECTION2 82 | 83 | #define USAGE_PAGES \ 84 | 0x55, 0x0C, /* UNIT_EXPONENT (-4) */ \ 85 | 0x66, 0x01, 0x10, /* UNIT (Seconds) */ \ 86 | 0x47, 0xff, 0xff, 0x00, 0x00, /* PHYSICAL_MAXIMUM (65535) */ \ 87 | 0x27, 0xff, 0xff, 0x00, 0x00, /* LOGICAL_MAXIMUM (65535) */ \ 88 | 0x75, 0x10, /* REPORT_SIZE (16) */ \ 89 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 90 | 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ \ 91 | 0x09, 0x56, /* USAGE (Scan Time) */ \ 92 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 93 | 0x09, 0x54, /* USAGE (Contact count) */ \ 94 | 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ \ 95 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 96 | 0x75, 0x08, /* REPORT_SIZE (8) */ \ 97 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 98 | 0x05, 0x09, /* USAGE_PAGE (Button) */ \ 99 | 0x09, 0x01, /* USAGE_(Button 1) */ \ 100 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ 101 | 0x75, 0x01, /* REPORT_SIZE (1) */ \ 102 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 103 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 104 | 0x95, 0x07, /* REPORT_COUNT (7) */ \ 105 | 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ 106 | 0x05, 0x0d, /* USAGE_PAGE (Digitizer) */ \ 107 | 0x85, REPORTID_MTOUCH, /* REPORT_ID (Feature) */ \ 108 | 0x09, 0x55, /* USAGE (Contact Count Maximum) */ \ 109 | 0x09, 0x59, /* USAGE (Pad TYpe) */ \ 110 | 0x75, 0x08, /* REPORT_SIZE (8) */ \ 111 | 0x95, 0x02, /* REPORT_COUNT (2) */ \ 112 | 0x25, 0x0f, /* LOGICAL_MAXIMUM (15) */ \ 113 | 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ \ 114 | 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ \ 115 | 0x85, REPORTID_PTPHQA, /* Report ID (Certification) */ \ 116 | 0x09, 0xC5, /* Usage (0xC5) */ \ 117 | 0x15, 0x00, /* Logical Minimum (0) */ \ 118 | 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ \ 119 | 0x75, 0x08, /* Report Size (8) */ \ 120 | 0x96, 0x00, 0x01, /* Report Count (256) */ \ 121 | 0xB1, 0x02, /* Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) */ \ 122 | 0xc0, /* END_COLLECTION */ \ 123 | \ 124 | /*MOUSE TLC */ \ 125 | 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ 126 | 0x09, 0x02, /* USAGE (Mouse) */ \ 127 | 0xa1, 0x01, /* COLLECTION (Application) */ \ 128 | 0x85, REPORTID_MOUSE, /* REPORT_ID (Mouse) */ \ 129 | 0x09, 0x01, /* USAGE (Pointer) */ \ 130 | 0xa1, 0x00, /* COLLECTION (Physical) */ \ 131 | 0x05, 0x09, /* USAGE_PAGE (Button) */ \ 132 | 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ 133 | 0x29, 0x02, /* USAGE_MAXIMUM (Button 2) */ \ 134 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ 135 | 0x75, 0x01, /* REPORT_SIZE (1) */ \ 136 | 0x95, 0x02, /* REPORT_COUNT (2) */ \ 137 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 138 | 0x95, 0x06, /* REPORT_COUNT (6) */ \ 139 | 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ 140 | 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ 141 | 0x09, 0x30, /* USAGE (X) */ \ 142 | 0x09, 0x31, /* USAGE (Y) */ \ 143 | 0x75, 0x10, /* REPORT_SIZE (16) */ \ 144 | 0x95, 0x02, /* REPORT_COUNT (2) */ \ 145 | 0x25, 0x0a, /* LOGICAL_MAXIMUM (10) */ \ 146 | 0x81, 0x06, /* INPUT (Data,Var,Rel) */ \ 147 | 0xc0, /* END_COLLECTION */ \ 148 | 0xc0, /*END_COLLECTION */ 149 | // 150 | // This is the default report descriptor for the Hid device provided 151 | // by the mini driver in response to IOCTL_HID_GET_REPORT_DESCRIPTOR. 152 | // 153 | 154 | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR; 155 | 156 | #ifdef DESCRIPTOR_DEF 157 | HID_REPORT_DESCRIPTOR DefaultReportDescriptor[] = { 158 | // 159 | // Multitouch report starts here 160 | // 161 | //TOUCH PAD input TLC 162 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 163 | 0x09, 0x05, // USAGE (Touch Pad) 164 | 0xa1, 0x01, // COLLECTION (Application) 165 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch pad) 166 | 0x09, 0x22, // USAGE (Finger) 167 | MT_REF_TOUCH_COLLECTION 168 | MT_REF_TOUCH_COLLECTION 169 | MT_REF_TOUCH_COLLECTION 170 | MT_REF_TOUCH_COLLECTION 171 | MT_REF_TOUCH_COLLECTION 172 | USAGE_PAGES 173 | }; 174 | 175 | 176 | // 177 | // This is the default HID descriptor returned by the mini driver 178 | // in response to IOCTL_HID_GET_DEVICE_DESCRIPTOR. The size 179 | // of report descriptor is currently the size of DefaultReportDescriptor. 180 | // 181 | 182 | CONST HID_DESCRIPTOR DefaultHidDescriptor = { 183 | 0x09, // length of HID descriptor 184 | 0x21, // descriptor type == HID 0x21 185 | 0x0100, // hid spec release 186 | 0x00, // country code == Not Specified 187 | 0x01, // number of HID class descriptors 188 | { 0x22, // descriptor type 189 | sizeof(DefaultReportDescriptor) } // total length of report descriptor 190 | }; 191 | #endif 192 | 193 | #define true 1 194 | #define false 0 195 | 196 | typedef struct _ATMELTP_CONTEXT 197 | { 198 | 199 | // 200 | // Handle back to the WDFDEVICE 201 | // 202 | 203 | WDFDEVICE FxDevice; 204 | 205 | WDFQUEUE ReportQueue; 206 | 207 | BYTE DeviceMode; 208 | 209 | SPB_CONTEXT I2CContext; 210 | 211 | WDFINTERRUPT Interrupt; 212 | 213 | BOOLEAN ConnectInterrupt; 214 | 215 | BOOLEAN RegsSet; 216 | 217 | BOOLEAN TrackpadBooted; 218 | 219 | mxt_message_t lastmsg; 220 | 221 | struct mxt_rollup core; 222 | 223 | struct mxt_object *msgprocobj; 224 | struct mxt_object *cmdprocobj; 225 | 226 | struct mxt_id_info info; 227 | 228 | UINT32 TouchCount; 229 | 230 | uint8_t Flags[20]; 231 | 232 | USHORT XValue[20]; 233 | 234 | USHORT YValue[20]; 235 | 236 | USHORT AREA[20]; 237 | 238 | BOOLEAN BUTTONPRESSED; 239 | 240 | USHORT TIMEINT; 241 | 242 | LARGE_INTEGER LastTime; 243 | 244 | uint16_t max_x; 245 | uint16_t max_y; 246 | 247 | uint8_t max_x_hid[2]; 248 | uint8_t max_y_hid[2]; 249 | 250 | uint16_t phy_x; 251 | uint16_t phy_y; 252 | 253 | uint8_t phy_x_hid[2]; 254 | uint8_t phy_y_hid[2]; 255 | 256 | uint8_t num_touchids; 257 | uint8_t multitouch; 258 | 259 | struct t7_config t7_cfg; 260 | 261 | uint8_t t100_aux_ampl; 262 | uint8_t t100_aux_area; 263 | uint8_t t100_aux_vect; 264 | 265 | /* Cached parameters from object table */ 266 | uint16_t T5_address; 267 | uint8_t T5_msg_size; 268 | uint8_t T6_reportid; 269 | uint16_t T6_address; 270 | uint16_t T7_address; 271 | uint8_t T9_reportid_min; 272 | uint8_t T9_reportid_max; 273 | uint8_t T19_reportid; 274 | 275 | bool T19_buttonstate; 276 | 277 | uint16_t T44_address; 278 | uint8_t T100_reportid_min; 279 | uint8_t T100_reportid_max; 280 | 281 | uint8_t max_reportid; 282 | 283 | uint8_t last_message_count; 284 | 285 | } ATMELTP_CONTEXT, *PATMELTP_CONTEXT; 286 | 287 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(ATMELTP_CONTEXT, GetDeviceContext) 288 | 289 | // 290 | // Function definitions 291 | // 292 | 293 | DRIVER_INITIALIZE DriverEntry; 294 | 295 | EVT_WDF_DRIVER_UNLOAD AtmelTPDriverUnload; 296 | 297 | EVT_WDF_DRIVER_DEVICE_ADD AtmelTPEvtDeviceAdd; 298 | 299 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL AtmelTPEvtInternalDeviceControl; 300 | 301 | NTSTATUS 302 | AtmelTPGetHidDescriptor( 303 | IN WDFDEVICE Device, 304 | IN WDFREQUEST Request 305 | ); 306 | 307 | NTSTATUS 308 | AtmelTPGetReportDescriptor( 309 | IN WDFDEVICE Device, 310 | IN WDFREQUEST Request, 311 | OUT BOOLEAN* CompleteRequest 312 | ); 313 | 314 | NTSTATUS 315 | AtmelTPGetDeviceAttributes( 316 | IN WDFREQUEST Request 317 | ); 318 | 319 | NTSTATUS 320 | AtmelTPGetString( 321 | IN WDFREQUEST Request 322 | ); 323 | 324 | NTSTATUS 325 | AtmelTPWriteReport( 326 | IN PATMELTP_CONTEXT DevContext, 327 | IN WDFREQUEST Request 328 | ); 329 | 330 | NTSTATUS 331 | AtmelTPProcessVendorReport( 332 | IN PATMELTP_CONTEXT DevContext, 333 | IN PVOID ReportBuffer, 334 | IN ULONG ReportBufferLen, 335 | OUT size_t* BytesWritten 336 | ); 337 | 338 | NTSTATUS 339 | AtmelTPReadReport( 340 | IN PATMELTP_CONTEXT DevContext, 341 | IN WDFREQUEST Request, 342 | OUT BOOLEAN* CompleteRequest 343 | ); 344 | 345 | NTSTATUS 346 | AtmelTPSetFeature( 347 | IN PATMELTP_CONTEXT DevContext, 348 | IN WDFREQUEST Request, 349 | OUT BOOLEAN* CompleteRequest 350 | ); 351 | 352 | NTSTATUS 353 | AtmelTPGetFeature( 354 | IN PATMELTP_CONTEXT DevContext, 355 | IN WDFREQUEST Request, 356 | OUT BOOLEAN* CompleteRequest 357 | ); 358 | 359 | PCHAR 360 | DbgHidInternalIoctlString( 361 | IN ULONG IoControlCode 362 | ); 363 | 364 | // 365 | // Helper macros 366 | // 367 | 368 | #define DEBUG_LEVEL_ERROR 1 369 | #define DEBUG_LEVEL_INFO 2 370 | #define DEBUG_LEVEL_VERBOSE 3 371 | 372 | #define DBG_INIT 1 373 | #define DBG_PNP 2 374 | #define DBG_IOCTL 4 375 | 376 | #if 0 377 | #define AtmelTPPrint(dbglevel, dbgcatagory, fmt, ...) { \ 378 | if (AtmelTPDebugLevel >= dbglevel && \ 379 | (AtmelTPDebugCatagories && dbgcatagory)) \ 380 | { \ 381 | DbgPrint(DRIVERNAME); \ 382 | DbgPrint(fmt, __VA_ARGS__); \ 383 | } \ 384 | } 385 | #else 386 | #define AtmelTPPrint(dbglevel, fmt, ...) { \ 387 | } 388 | #endif 389 | 390 | #endif 391 | -------------------------------------------------------------------------------- /crostouchpad/crostouchpad.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Win8.1 Debug 6 | Win32 7 | 8 | 9 | Win8.1 Release 10 | Win32 11 | 12 | 13 | Win8 Debug 14 | Win32 15 | 16 | 17 | Win8 Release 18 | Win32 19 | 20 | 21 | Win7 Debug 22 | Win32 23 | 24 | 25 | Win7 Release 26 | Win32 27 | 28 | 29 | Win8.1 Debug 30 | x64 31 | 32 | 33 | Win8.1 Release 34 | x64 35 | 36 | 37 | Win8 Debug 38 | x64 39 | 40 | 41 | Win8 Release 42 | x64 43 | 44 | 45 | Win7 Debug 46 | x64 47 | 48 | 49 | Win7 Release 50 | x64 51 | 52 | 53 | 54 | {B3E71397-9BE4-492B-AAED-4D056E59CB1F} 55 | {1bc93793-694f-48fe-9372-81e2b05556fd} 56 | v4.5 57 | 11.0 58 | Win8.1 Debug 59 | Win32 60 | crostouchpad 61 | 10.0.22000.0 62 | crostouchpad 63 | 64 | 65 | 66 | WindowsV6.3 67 | true 68 | WindowsKernelModeDriver10.0 69 | Driver 70 | KMDF 71 | 72 | 73 | WindowsV6.3 74 | false 75 | WindowsKernelModeDriver10.0 76 | Driver 77 | KMDF 78 | 79 | 80 | Windows8 81 | true 82 | WindowsKernelModeDriver10.0 83 | Driver 84 | KMDF 85 | 86 | 87 | Windows8 88 | false 89 | WindowsKernelModeDriver10.0 90 | Driver 91 | KMDF 92 | 93 | 94 | Windows7 95 | true 96 | WindowsKernelModeDriver10.0 97 | Driver 98 | KMDF 99 | 100 | 101 | Windows7 102 | false 103 | WindowsKernelModeDriver10.0 104 | Driver 105 | KMDF 106 | 107 | 108 | WindowsV6.3 109 | true 110 | WindowsKernelModeDriver10.0 111 | Driver 112 | KMDF 113 | 114 | 115 | WindowsV6.3 116 | false 117 | WindowsKernelModeDriver10.0 118 | Driver 119 | KMDF 120 | 121 | 122 | Windows8 123 | true 124 | WindowsKernelModeDriver10.0 125 | Driver 126 | KMDF 127 | 128 | 129 | Windows8 130 | false 131 | WindowsKernelModeDriver10.0 132 | Driver 133 | KMDF 134 | 135 | 136 | Windows7 137 | true 138 | WindowsKernelModeDriver10.0 139 | Driver 140 | KMDF 141 | 142 | 143 | Windows7 144 | false 145 | WindowsKernelModeDriver10.0 146 | Driver 147 | KMDF 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | DbgengKernelDebugger 159 | 160 | 161 | DbgengKernelDebugger 162 | 163 | 164 | DbgengKernelDebugger 165 | 166 | 167 | DbgengKernelDebugger 168 | 169 | 170 | DbgengKernelDebugger 171 | 172 | 173 | DbgengKernelDebugger 174 | 175 | 176 | DbgengKernelDebugger 177 | 178 | 179 | DbgengKernelDebugger 180 | 181 | 182 | DbgengKernelDebugger 183 | 184 | 185 | DbgengKernelDebugger 186 | 187 | 188 | DbgengKernelDebugger 189 | 190 | 191 | DbgengKernelDebugger 192 | 193 | 194 | 195 | true 196 | trace.h 197 | true 198 | false 199 | 200 | 201 | 4.1.3 202 | 203 | 204 | 205 | 206 | true 207 | trace.h 208 | true 209 | false 210 | 211 | 212 | 4.1.3 213 | 214 | 215 | 216 | 217 | true 218 | trace.h 219 | true 220 | false 221 | 222 | 223 | 4.1.3 224 | 225 | 226 | 227 | 228 | true 229 | trace.h 230 | true 231 | false 232 | 233 | 234 | 4.1.3 235 | 236 | 237 | 238 | 239 | true 240 | trace.h 241 | true 242 | false 243 | 244 | 245 | 4.1.3 246 | 247 | 248 | 249 | 250 | true 251 | trace.h 252 | true 253 | false 254 | 255 | 256 | 4.1.3 257 | 258 | 259 | 260 | 261 | true 262 | trace.h 263 | true 264 | false 265 | 266 | 267 | 4.1.3 268 | 269 | 270 | 271 | 272 | true 273 | trace.h 274 | true 275 | false 276 | 277 | 278 | 4.1.3 279 | 280 | 281 | 282 | 283 | true 284 | trace.h 285 | true 286 | false 287 | 288 | 289 | 4.1.3 290 | 291 | 292 | 293 | 294 | true 295 | trace.h 296 | true 297 | false 298 | 299 | 300 | 4.1.3 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | true 310 | trace.h 311 | true 312 | false 313 | 314 | 315 | 4.1.3 316 | 317 | 318 | 319 | 320 | true 321 | trace.h 322 | true 323 | false 324 | 325 | 326 | 4.1.3 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | -------------------------------------------------------------------------------- /crostouchpad/spb.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | Copyright (c) Microsoft Corporation. All Rights Reserved. 3 | Sample code. Dealpoint ID #843729. 4 | 5 | Module Name: 6 | 7 | spb.c 8 | 9 | Abstract: 10 | 11 | Contains all I2C-specific functionality 12 | 13 | Environment: 14 | 15 | Kernel mode 16 | 17 | Revision History: 18 | 19 | --*/ 20 | 21 | #include "driver.h" 22 | #include "spb.h" 23 | #include 24 | 25 | static ULONG AtmelTPDebugLevel = 100; 26 | static ULONG AtmelTPDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 27 | 28 | NTSTATUS 29 | SpbDoWriteDataSynchronously16( 30 | IN SPB_CONTEXT *SpbContext, 31 | IN UINT16 Address, 32 | IN PVOID Data, 33 | IN ULONG Length 34 | ) 35 | /*++ 36 | 37 | Routine Description: 38 | 39 | This helper routine abstracts creating and sending an I/O 40 | request (I2C Write) to the Spb I/O target. 41 | 42 | Arguments: 43 | 44 | SpbContext - Pointer to the current device context 45 | Address - The I2C register address to write to 46 | Data - A buffer to receive the data at at the above address 47 | Length - The amount of data to be read from the above address 48 | 49 | Return Value: 50 | 51 | NTSTATUS Status indicating success or failure 52 | 53 | --*/ 54 | { 55 | PUCHAR buffer; 56 | ULONG length; 57 | WDFMEMORY memory; 58 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 59 | NTSTATUS status; 60 | 61 | // 62 | // The address pointer and data buffer must be combined 63 | // into one contiguous buffer representing the write transaction. 64 | // 65 | length = Length + 2; 66 | memory = NULL; 67 | 68 | if (length > DEFAULT_SPB_BUFFER_SIZE) 69 | { 70 | status = WdfMemoryCreate( 71 | WDF_NO_OBJECT_ATTRIBUTES, 72 | NonPagedPool, 73 | ATMELTP_POOL_TAG, 74 | length, 75 | &memory, 76 | (PVOID *)&buffer); 77 | 78 | if (!NT_SUCCESS(status)) 79 | { 80 | AtmelTPPrint( 81 | DEBUG_LEVEL_ERROR, 82 | DBG_IOCTL, 83 | "Error allocating memory for Spb write - %!STATUS!", 84 | status); 85 | goto exit; 86 | } 87 | 88 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 89 | &memoryDescriptor, 90 | memory, 91 | NULL); 92 | } 93 | else 94 | { 95 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->WriteMemory, NULL); 96 | 97 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 98 | &memoryDescriptor, 99 | (PVOID)buffer, 100 | length); 101 | } 102 | 103 | UINT16 AddressBuffer[] = { 104 | Address 105 | }; 106 | 107 | // 108 | // Transaction starts by specifying the address bytes 109 | // 110 | RtlCopyMemory(buffer, (UCHAR *)&AddressBuffer, sizeof(AddressBuffer)); 111 | 112 | // 113 | // Address is followed by the data payload 114 | // 115 | RtlCopyMemory((buffer + sizeof(AddressBuffer)), Data, length - sizeof(AddressBuffer)); 116 | 117 | status = WdfIoTargetSendWriteSynchronously( 118 | SpbContext->SpbIoTarget, 119 | NULL, 120 | &memoryDescriptor, 121 | NULL, 122 | NULL, 123 | NULL); 124 | 125 | if (!NT_SUCCESS(status)) 126 | { 127 | AtmelTPPrint( 128 | DEBUG_LEVEL_ERROR, 129 | DBG_IOCTL, 130 | "Error writing to Spb - %!STATUS!", 131 | status); 132 | goto exit; 133 | } 134 | 135 | exit: 136 | 137 | if (NULL != memory) 138 | { 139 | WdfObjectDelete(memory); 140 | } 141 | 142 | return status; 143 | } 144 | 145 | NTSTATUS 146 | SpbDoWriteDataSynchronously( 147 | IN SPB_CONTEXT *SpbContext, 148 | IN UCHAR Address, 149 | IN PVOID Data, 150 | IN ULONG Length 151 | ) 152 | /*++ 153 | 154 | Routine Description: 155 | 156 | This helper routine abstracts creating and sending an I/O 157 | request (I2C Write) to the Spb I/O target. 158 | 159 | Arguments: 160 | 161 | SpbContext - Pointer to the current device context 162 | Address - The I2C register address to write to 163 | Data - A buffer to receive the data at at the above address 164 | Length - The amount of data to be read from the above address 165 | 166 | Return Value: 167 | 168 | NTSTATUS Status indicating success or failure 169 | 170 | --*/ 171 | { 172 | PUCHAR buffer; 173 | ULONG length; 174 | WDFMEMORY memory; 175 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 176 | NTSTATUS status; 177 | 178 | // 179 | // The address pointer and data buffer must be combined 180 | // into one contiguous buffer representing the write transaction. 181 | // 182 | length = Length + 1; 183 | memory = NULL; 184 | 185 | if (length > DEFAULT_SPB_BUFFER_SIZE) 186 | { 187 | status = WdfMemoryCreate( 188 | WDF_NO_OBJECT_ATTRIBUTES, 189 | NonPagedPool, 190 | ATMELTP_POOL_TAG, 191 | length, 192 | &memory, 193 | (PVOID *)&buffer); 194 | 195 | if (!NT_SUCCESS(status)) 196 | { 197 | AtmelTPPrint( 198 | DEBUG_LEVEL_ERROR, 199 | DBG_IOCTL, 200 | "Error allocating memory for Spb write - %!STATUS!", 201 | status); 202 | goto exit; 203 | } 204 | 205 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 206 | &memoryDescriptor, 207 | memory, 208 | NULL); 209 | } 210 | else 211 | { 212 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->WriteMemory, NULL); 213 | 214 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 215 | &memoryDescriptor, 216 | (PVOID)buffer, 217 | length); 218 | } 219 | 220 | // 221 | // Transaction starts by specifying the address bytes 222 | // 223 | RtlCopyMemory(buffer, &Address, sizeof(Address)); 224 | 225 | // 226 | // Address is followed by the data payload 227 | // 228 | RtlCopyMemory((buffer + sizeof(Address)), Data, length - sizeof(Address)); 229 | 230 | status = WdfIoTargetSendWriteSynchronously( 231 | SpbContext->SpbIoTarget, 232 | NULL, 233 | &memoryDescriptor, 234 | NULL, 235 | NULL, 236 | NULL); 237 | 238 | if (!NT_SUCCESS(status)) 239 | { 240 | AtmelTPPrint( 241 | DEBUG_LEVEL_ERROR, 242 | DBG_IOCTL, 243 | "Error writing to Spb - %!STATUS!", 244 | status); 245 | goto exit; 246 | } 247 | 248 | exit: 249 | 250 | if (NULL != memory) 251 | { 252 | WdfObjectDelete(memory); 253 | } 254 | 255 | return status; 256 | } 257 | 258 | NTSTATUS 259 | SpbWriteDataSynchronously( 260 | IN SPB_CONTEXT *SpbContext, 261 | IN UCHAR Address, 262 | IN PVOID Data, 263 | IN ULONG Length 264 | ) 265 | /*++ 266 | 267 | Routine Description: 268 | 269 | This routine abstracts creating and sending an I/O 270 | request (I2C Write) to the Spb I/O target and utilizes 271 | a helper routine to do work inside of locked code. 272 | 273 | Arguments: 274 | 275 | SpbContext - Pointer to the current device context 276 | Address - The I2C register address to write to 277 | Data - A buffer to receive the data at at the above address 278 | Length - The amount of data to be read from the above address 279 | 280 | Return Value: 281 | 282 | NTSTATUS Status indicating success or failure 283 | 284 | --*/ 285 | { 286 | NTSTATUS status; 287 | 288 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 289 | 290 | status = SpbDoWriteDataSynchronously( 291 | SpbContext, 292 | Address, 293 | Data, 294 | Length); 295 | 296 | WdfWaitLockRelease(SpbContext->SpbLock); 297 | 298 | return status; 299 | } 300 | 301 | NTSTATUS 302 | SpbWriteDataSynchronously16( 303 | IN SPB_CONTEXT *SpbContext, 304 | IN UINT16 Address, 305 | IN PVOID Data, 306 | IN ULONG Length 307 | ) 308 | /*++ 309 | 310 | Routine Description: 311 | 312 | This routine abstracts creating and sending an I/O 313 | request (I2C Write) to the Spb I/O target and utilizes 314 | a helper routine to do work inside of locked code. 315 | 316 | Arguments: 317 | 318 | SpbContext - Pointer to the current device context 319 | Address - The I2C register address to write to 320 | Data - A buffer to receive the data at at the above address 321 | Length - The amount of data to be read from the above address 322 | 323 | Return Value: 324 | 325 | NTSTATUS Status indicating success or failure 326 | 327 | --*/ 328 | { 329 | NTSTATUS status; 330 | 331 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 332 | 333 | status = SpbDoWriteDataSynchronously16( 334 | SpbContext, 335 | Address, 336 | Data, 337 | Length); 338 | 339 | WdfWaitLockRelease(SpbContext->SpbLock); 340 | 341 | return status; 342 | } 343 | 344 | NTSTATUS 345 | SpbReadDataSynchronously( 346 | _In_ SPB_CONTEXT *SpbContext, 347 | _In_ UCHAR Address, 348 | _In_reads_bytes_(Length) PVOID Data, 349 | _In_ ULONG Length 350 | ) 351 | /*++ 352 | 353 | Routine Description: 354 | 355 | This helper routine abstracts creating and sending an I/O 356 | request (I2C Read) to the Spb I/O target. 357 | 358 | Arguments: 359 | 360 | SpbContext - Pointer to the current device context 361 | Address - The I2C register address to read from 362 | Data - A buffer to receive the data at at the above address 363 | Length - The amount of data to be read from the above address 364 | 365 | Return Value: 366 | 367 | NTSTATUS Status indicating success or failure 368 | 369 | --*/ 370 | { 371 | PUCHAR buffer; 372 | WDFMEMORY memory; 373 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 374 | NTSTATUS status; 375 | ULONG_PTR bytesRead; 376 | 377 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 378 | 379 | memory = NULL; 380 | status = STATUS_INVALID_PARAMETER; 381 | bytesRead = 0; 382 | 383 | // 384 | // Read transactions start by writing an address pointer 385 | // 386 | status = SpbDoWriteDataSynchronously( 387 | SpbContext, 388 | Address, 389 | NULL, 390 | 0); 391 | 392 | if (!NT_SUCCESS(status)) 393 | { 394 | AtmelTPPrint( 395 | DEBUG_LEVEL_ERROR, 396 | DBG_IOCTL, 397 | "Error setting address pointer for Spb read - %!STATUS!", 398 | status); 399 | goto exit; 400 | } 401 | 402 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 403 | { 404 | status = WdfMemoryCreate( 405 | WDF_NO_OBJECT_ATTRIBUTES, 406 | NonPagedPool, 407 | ATMELTP_POOL_TAG, 408 | Length, 409 | &memory, 410 | (PVOID *)&buffer); 411 | 412 | if (!NT_SUCCESS(status)) 413 | { 414 | AtmelTPPrint( 415 | DEBUG_LEVEL_ERROR, 416 | DBG_IOCTL, 417 | "Error allocating memory for Spb read - %!STATUS!", 418 | status); 419 | goto exit; 420 | } 421 | 422 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 423 | &memoryDescriptor, 424 | memory, 425 | NULL); 426 | } 427 | else 428 | { 429 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 430 | 431 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 432 | &memoryDescriptor, 433 | (PVOID)buffer, 434 | Length); 435 | } 436 | 437 | 438 | status = WdfIoTargetSendReadSynchronously( 439 | SpbContext->SpbIoTarget, 440 | NULL, 441 | &memoryDescriptor, 442 | NULL, 443 | NULL, 444 | &bytesRead); 445 | 446 | if (!NT_SUCCESS(status) || 447 | bytesRead != Length) 448 | { 449 | AtmelTPPrint( 450 | DEBUG_LEVEL_ERROR, 451 | DBG_IOCTL, 452 | "Error reading from Spb - %!STATUS!", 453 | status); 454 | goto exit; 455 | } 456 | 457 | // 458 | // Copy back to the caller's buffer 459 | // 460 | RtlCopyMemory(Data, buffer, Length); 461 | 462 | exit: 463 | if (NULL != memory) 464 | { 465 | WdfObjectDelete(memory); 466 | } 467 | 468 | WdfWaitLockRelease(SpbContext->SpbLock); 469 | 470 | return status; 471 | } 472 | 473 | NTSTATUS 474 | SpbReadDataSynchronously16( 475 | _In_ SPB_CONTEXT *SpbContext, 476 | _In_ UINT16 Address, 477 | _In_reads_bytes_(Length) PVOID Data, 478 | _In_ ULONG Length 479 | ) 480 | /*++ 481 | 482 | Routine Description: 483 | 484 | This helper routine abstracts creating and sending an I/O 485 | request (I2C Read) to the Spb I/O target. 486 | 487 | Arguments: 488 | 489 | SpbContext - Pointer to the current device context 490 | Address - The I2C register address to read from 491 | Data - A buffer to receive the data at at the above address 492 | Length - The amount of data to be read from the above address 493 | 494 | Return Value: 495 | 496 | NTSTATUS Status indicating success or failure 497 | 498 | --*/ 499 | { 500 | PUCHAR buffer; 501 | WDFMEMORY memory; 502 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 503 | NTSTATUS status; 504 | ULONG_PTR bytesRead; 505 | 506 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 507 | 508 | memory = NULL; 509 | status = STATUS_INVALID_PARAMETER; 510 | bytesRead = 0; 511 | 512 | // 513 | // Read transactions start by writing an address pointer 514 | // 515 | status = SpbDoWriteDataSynchronously16( 516 | SpbContext, 517 | Address, 518 | NULL, 519 | 0); 520 | 521 | if (!NT_SUCCESS(status)) 522 | { 523 | AtmelTPPrint( 524 | DEBUG_LEVEL_ERROR, 525 | DBG_IOCTL, 526 | "Error setting address pointer for Spb read - %!STATUS!", 527 | status); 528 | goto exit; 529 | } 530 | 531 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 532 | { 533 | status = WdfMemoryCreate( 534 | WDF_NO_OBJECT_ATTRIBUTES, 535 | NonPagedPool, 536 | ATMELTP_POOL_TAG, 537 | Length, 538 | &memory, 539 | (PVOID *)&buffer); 540 | 541 | if (!NT_SUCCESS(status)) 542 | { 543 | AtmelTPPrint( 544 | DEBUG_LEVEL_ERROR, 545 | DBG_IOCTL, 546 | "Error allocating memory for Spb read - %!STATUS!", 547 | status); 548 | goto exit; 549 | } 550 | 551 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 552 | &memoryDescriptor, 553 | memory, 554 | NULL); 555 | } 556 | else 557 | { 558 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 559 | 560 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 561 | &memoryDescriptor, 562 | (PVOID)buffer, 563 | Length); 564 | } 565 | 566 | 567 | status = WdfIoTargetSendReadSynchronously( 568 | SpbContext->SpbIoTarget, 569 | NULL, 570 | &memoryDescriptor, 571 | NULL, 572 | NULL, 573 | &bytesRead); 574 | 575 | if (!NT_SUCCESS(status) || 576 | bytesRead != Length) 577 | { 578 | AtmelTPPrint( 579 | DEBUG_LEVEL_ERROR, 580 | DBG_IOCTL, 581 | "Error reading from Spb - %!STATUS!", 582 | status); 583 | goto exit; 584 | } 585 | 586 | // 587 | // Copy back to the caller's buffer 588 | // 589 | RtlCopyMemory(Data, buffer, Length); 590 | 591 | exit: 592 | if (NULL != memory) 593 | { 594 | WdfObjectDelete(memory); 595 | } 596 | 597 | WdfWaitLockRelease(SpbContext->SpbLock); 598 | 599 | return status; 600 | } 601 | 602 | VOID 603 | SpbTargetDeinitialize( 604 | IN WDFDEVICE FxDevice, 605 | IN SPB_CONTEXT *SpbContext 606 | ) 607 | /*++ 608 | 609 | Routine Description: 610 | 611 | This helper routine is used to free any members added to the SPB_CONTEXT, 612 | note the SPB I/O target is parented to the device and will be 613 | closed and free'd when the device is removed. 614 | 615 | Arguments: 616 | 617 | FxDevice - Handle to the framework device object 618 | SpbContext - Pointer to the current device context 619 | 620 | Return Value: 621 | 622 | NTSTATUS Status indicating success or failure 623 | 624 | --*/ 625 | { 626 | UNREFERENCED_PARAMETER(FxDevice); 627 | UNREFERENCED_PARAMETER(SpbContext); 628 | 629 | // 630 | // Free any SPB_CONTEXT allocations here 631 | // 632 | if (SpbContext->SpbLock != NULL) 633 | { 634 | WdfObjectDelete(SpbContext->SpbLock); 635 | } 636 | 637 | if (SpbContext->ReadMemory != NULL) 638 | { 639 | WdfObjectDelete(SpbContext->ReadMemory); 640 | } 641 | 642 | if (SpbContext->WriteMemory != NULL) 643 | { 644 | WdfObjectDelete(SpbContext->WriteMemory); 645 | } 646 | } 647 | 648 | NTSTATUS 649 | SpbTargetInitialize( 650 | IN WDFDEVICE FxDevice, 651 | IN SPB_CONTEXT *SpbContext 652 | ) 653 | /*++ 654 | 655 | Routine Description: 656 | 657 | This helper routine opens the Spb I/O target and 658 | initializes a request object used for the lifetime 659 | of communication between this driver and Spb. 660 | 661 | Arguments: 662 | 663 | FxDevice - Handle to the framework device object 664 | SpbContext - Pointer to the current device context 665 | 666 | Return Value: 667 | 668 | NTSTATUS Status indicating success or failure 669 | 670 | --*/ 671 | { 672 | WDF_OBJECT_ATTRIBUTES objectAttributes; 673 | WDF_IO_TARGET_OPEN_PARAMS openParams; 674 | UNICODE_STRING spbDeviceName; 675 | WCHAR spbDeviceNameBuffer[RESOURCE_HUB_PATH_SIZE]; 676 | NTSTATUS status; 677 | 678 | WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); 679 | objectAttributes.ParentObject = FxDevice; 680 | 681 | status = WdfIoTargetCreate( 682 | FxDevice, 683 | &objectAttributes, 684 | &SpbContext->SpbIoTarget); 685 | 686 | if (!NT_SUCCESS(status)) 687 | { 688 | AtmelTPPrint( 689 | DEBUG_LEVEL_ERROR, 690 | DBG_IOCTL, 691 | "Error creating IoTarget object - %!STATUS!", 692 | status); 693 | 694 | WdfObjectDelete(SpbContext->SpbIoTarget); 695 | goto exit; 696 | } 697 | 698 | RtlInitEmptyUnicodeString( 699 | &spbDeviceName, 700 | spbDeviceNameBuffer, 701 | sizeof(spbDeviceNameBuffer)); 702 | 703 | status = RESOURCE_HUB_CREATE_PATH_FROM_ID( 704 | &spbDeviceName, 705 | SpbContext->I2cResHubId.LowPart, 706 | SpbContext->I2cResHubId.HighPart); 707 | 708 | if (!NT_SUCCESS(status)) 709 | { 710 | AtmelTPPrint( 711 | DEBUG_LEVEL_ERROR, 712 | DBG_IOCTL, 713 | "Error creating Spb resource hub path string - %!STATUS!", 714 | status); 715 | goto exit; 716 | } 717 | 718 | WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( 719 | &openParams, 720 | &spbDeviceName, 721 | (GENERIC_READ | GENERIC_WRITE)); 722 | 723 | openParams.ShareAccess = 0; 724 | openParams.CreateDisposition = FILE_OPEN; 725 | openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; 726 | 727 | status = WdfIoTargetOpen(SpbContext->SpbIoTarget, &openParams); 728 | 729 | if (!NT_SUCCESS(status)) 730 | { 731 | AtmelTPPrint( 732 | DEBUG_LEVEL_ERROR, 733 | DBG_IOCTL, 734 | "Error opening Spb target for communication - %!STATUS!", 735 | status); 736 | goto exit; 737 | } 738 | 739 | // 740 | // Allocate some fixed-size buffers from NonPagedPool for typical 741 | // Spb transaction sizes to avoid pool fragmentation in most cases 742 | // 743 | status = WdfMemoryCreate( 744 | WDF_NO_OBJECT_ATTRIBUTES, 745 | NonPagedPool, 746 | ATMELTP_POOL_TAG, 747 | DEFAULT_SPB_BUFFER_SIZE, 748 | &SpbContext->WriteMemory, 749 | NULL); 750 | 751 | if (!NT_SUCCESS(status)) 752 | { 753 | AtmelTPPrint( 754 | DEBUG_LEVEL_ERROR, 755 | DBG_IOCTL, 756 | "Error allocating default memory for Spb write - %!STATUS!", 757 | status); 758 | goto exit; 759 | } 760 | 761 | status = WdfMemoryCreate( 762 | WDF_NO_OBJECT_ATTRIBUTES, 763 | NonPagedPool, 764 | ATMELTP_POOL_TAG, 765 | DEFAULT_SPB_BUFFER_SIZE, 766 | &SpbContext->ReadMemory, 767 | NULL); 768 | 769 | if (!NT_SUCCESS(status)) 770 | { 771 | AtmelTPPrint( 772 | DEBUG_LEVEL_ERROR, 773 | DBG_IOCTL, 774 | "Error allocating default memory for Spb read - %!STATUS!", 775 | status); 776 | goto exit; 777 | } 778 | 779 | // 780 | // Allocate a waitlock to guard access to the default buffers 781 | // 782 | status = WdfWaitLockCreate( 783 | WDF_NO_OBJECT_ATTRIBUTES, 784 | &SpbContext->SpbLock); 785 | 786 | if (!NT_SUCCESS(status)) 787 | { 788 | AtmelTPPrint( 789 | DEBUG_LEVEL_ERROR, 790 | DBG_IOCTL, 791 | "Error creating Spb Waitlock - %!STATUS!", 792 | status); 793 | goto exit; 794 | } 795 | 796 | exit: 797 | 798 | if (!NT_SUCCESS(status)) 799 | { 800 | SpbTargetDeinitialize(FxDevice, SpbContext); 801 | } 802 | 803 | return status; 804 | } -------------------------------------------------------------------------------- /crostouchpad Package/crostouchpad Package.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Win8.1 Debug 6 | Win32 7 | 8 | 9 | Win8.1 Release 10 | Win32 11 | 12 | 13 | Win8 Debug 14 | Win32 15 | 16 | 17 | Win8 Release 18 | Win32 19 | 20 | 21 | Win7 Debug 22 | Win32 23 | 24 | 25 | Win7 Release 26 | Win32 27 | 28 | 29 | Win8.1 Debug 30 | x64 31 | 32 | 33 | Win8.1 Release 34 | x64 35 | 36 | 37 | Win8 Debug 38 | x64 39 | 40 | 41 | Win8 Release 42 | x64 43 | 44 | 45 | Win7 Debug 46 | x64 47 | 48 | 49 | Win7 Release 50 | x64 51 | 52 | 53 | 54 | {EA676041-89D8-4ACF-A48B-F11CA9F5DD8B} 55 | {4605da2c-74a5-4865-98e1-152ef136825f} 56 | v4.5 57 | 11.0 58 | Win8.1 Debug 59 | Win32 60 | crostouchpad_Package 61 | 10.0.22000.0 62 | crostouchpad Package 63 | 64 | 65 | 66 | WindowsV6.3 67 | true 68 | WindowsKernelModeDriver10.0 69 | Utility 70 | Package 71 | true 72 | 73 | 74 | WindowsV6.3 75 | false 76 | WindowsKernelModeDriver10.0 77 | Utility 78 | Package 79 | true 80 | 81 | 82 | Windows8 83 | true 84 | WindowsKernelModeDriver10.0 85 | Utility 86 | Package 87 | true 88 | 89 | 90 | Windows8 91 | false 92 | WindowsKernelModeDriver10.0 93 | Utility 94 | Package 95 | true 96 | 97 | 98 | Windows7 99 | true 100 | WindowsKernelModeDriver10.0 101 | Utility 102 | Package 103 | true 104 | 105 | 106 | Windows7 107 | false 108 | WindowsKernelModeDriver10.0 109 | Utility 110 | Package 111 | true 112 | 113 | 114 | WindowsV6.3 115 | true 116 | WindowsKernelModeDriver10.0 117 | Utility 118 | Package 119 | true 120 | 121 | 122 | WindowsV6.3 123 | false 124 | WindowsKernelModeDriver10.0 125 | Utility 126 | Package 127 | true 128 | 129 | 130 | Windows8 131 | true 132 | WindowsKernelModeDriver10.0 133 | Utility 134 | Package 135 | true 136 | 137 | 138 | Windows8 139 | false 140 | WindowsKernelModeDriver10.0 141 | Utility 142 | Package 143 | true 144 | 145 | 146 | Windows7 147 | true 148 | WindowsKernelModeDriver10.0 149 | Utility 150 | Package 151 | true 152 | 153 | 154 | Windows7 155 | false 156 | WindowsKernelModeDriver10.0 157 | Utility 158 | Package 159 | true 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | DbgengKernelDebugger 171 | False 172 | True 173 | 174 | 175 | 176 | False 177 | False 178 | True 179 | 180 | 133563 181 | 182 | 183 | DbgengKernelDebugger 184 | False 185 | True 186 | 187 | 188 | 189 | False 190 | False 191 | True 192 | 193 | 133563 194 | 195 | 196 | DbgengKernelDebugger 197 | False 198 | True 199 | 200 | 201 | 202 | False 203 | False 204 | True 205 | 206 | 133563 207 | 208 | 209 | DbgengKernelDebugger 210 | False 211 | True 212 | 213 | 214 | 215 | False 216 | False 217 | True 218 | 219 | 133563 220 | 221 | 222 | DbgengKernelDebugger 223 | False 224 | True 225 | 226 | 227 | 228 | False 229 | False 230 | True 231 | 232 | 133563 233 | 234 | 235 | DbgengKernelDebugger 236 | False 237 | True 238 | 239 | 240 | 241 | False 242 | False 243 | True 244 | 245 | 133563 246 | 247 | 248 | DbgengKernelDebugger 249 | False 250 | True 251 | 252 | 253 | 254 | False 255 | False 256 | True 257 | 258 | 133563 259 | 260 | 261 | DbgengKernelDebugger 262 | False 263 | True 264 | 265 | 266 | 267 | False 268 | False 269 | True 270 | 271 | 133563 272 | 273 | 274 | DbgengKernelDebugger 275 | False 276 | True 277 | 278 | 279 | 280 | False 281 | False 282 | True 283 | 284 | 133563 285 | 286 | 287 | DbgengKernelDebugger 288 | False 289 | True 290 | 291 | 292 | 293 | False 294 | False 295 | True 296 | 297 | 133563 298 | 299 | 300 | DbgengKernelDebugger 301 | False 302 | True 303 | 304 | 305 | 306 | False 307 | False 308 | True 309 | 310 | 133563 311 | 312 | 313 | DbgengKernelDebugger 314 | False 315 | True 316 | 317 | 318 | 319 | False 320 | False 321 | True 322 | 323 | 133563 324 | 325 | 326 | 327 | SHA256 328 | 329 | 330 | 331 | 332 | SHA256 333 | 334 | 335 | 336 | 337 | SHA256 338 | 339 | 340 | 341 | 342 | SHA256 343 | 344 | 345 | 346 | 347 | SHA256 348 | 349 | 350 | 351 | 352 | SHA256 353 | 354 | 355 | 356 | 357 | SHA256 358 | 359 | 360 | 361 | 362 | SHA256 363 | 364 | 365 | 366 | 367 | SHA256 368 | 369 | 370 | 371 | 372 | SHA256 373 | 374 | 375 | 376 | 377 | SHA256 378 | 379 | 380 | 381 | 382 | SHA256 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | {b3e71397-9be4-492b-aaed-4d056e59cb1f} 391 | 392 | 393 | 394 | 395 | 396 | -------------------------------------------------------------------------------- /crostouchpad/atmel_mxt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 | * 4 | * This code is derived from software contributed to The DragonFly Project 5 | * by Matthew Dillon 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * 3. Neither the name of The DragonFly Project nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific, prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | *------------------------------------------------------------------------------ 35 | * Copyright 2011 Atmel Corporation. All rights reserved. 36 | * 37 | * Redistribution and use in source and binary forms, with or without 38 | * modification, are permitted provided that the following conditions are met: 39 | * 40 | * 1. Redistributions of source code must retain the above copyright notice, 41 | * this list of conditions and the following disclaimer. 42 | * 43 | * 2. Redistributions in binary form must reproduce the above copyright 44 | * notice, this list of conditions and the following disclaimer in the 45 | * documentation and/or other materials provided with the distribution. 46 | * 47 | * THIS SOFTWARE IS PROVIDED BY ATMEL ''AS IS'' AND ANY EXPRESS OR IMPLIED 48 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 49 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 50 | * EVENT SHALL ATMEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 52 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 53 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 54 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 55 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 56 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | *----------------------------------------------------------------------------- 58 | */ 59 | /* 60 | * This file contains a mix of code taken from the atmel-maxtouch/obp-utils 61 | * github codebase and my own for testing the atmel touchscreen chipset in 62 | * the Acer C720P chromebook. 63 | * 64 | * I have rewritten the linux mess for the most part. 65 | */ 66 | 67 | #include "stdint.h" 68 | 69 | #ifndef __packed 70 | #define __packed( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) 71 | #endif 72 | 73 | #ifndef _OBP_UTILS_H_ 74 | #define _OBP_UTILS_H_ 75 | 76 | /* 77 | * CRC structure hangs off the end of the object configuration array and 78 | * is calculated against { mxt_id_info, mxt_object[num_objects] }. 79 | * 80 | * { mxt_id_info, mxt_object[num_objects], mxt_raw_crc } 81 | */ 82 | __packed(struct mxt_raw_crc { 83 | uint16_t CRC; /* low 16 bits */ 84 | uint8_t CRC_hi; /* high 8 bits */ 85 | }); 86 | 87 | /* 88 | * register 0 - Base information structure 89 | */ 90 | __packed(struct mxt_id_info { 91 | uint8_t family; /*!< Device family */ 92 | uint8_t variant; /*!< Device variant */ 93 | 94 | uint8_t version; /*!< Firmware version (Major/minor nibbles) */ 95 | uint8_t build; /*!< Firmware build number */ 96 | 97 | uint8_t matrix_x_size; /*!< Matrix X Size */ 98 | uint8_t matrix_y_size; /*!< Matrix Y Size */ 99 | 100 | /*! Number of elements in the object table. The actual number of 101 | * objects can be different if any object has more than one 102 | * instance. 103 | */ 104 | uint8_t num_objects; 105 | }); 106 | 107 | /* Object types */ 108 | #define MXT_DEBUG_DIAGNOSTIC_T37 37 109 | #define MXT_GEN_MESSAGE_T5 5 110 | #define MXT_GEN_COMMAND_T6 6 111 | #define MXT_GEN_POWER_T7 7 112 | #define MXT_GEN_ACQUIRE_T8 8 113 | #define MXT_GEN_DATASOURCE_T53 53 114 | #define MXT_TOUCH_MULTI_T9 9 115 | #define MXT_TOUCH_KEYARRAY_T15 15 116 | #define MXT_TOUCH_PROXIMITY_T23 23 117 | #define MXT_TOUCH_PROXKEY_T52 52 118 | #define MXT_PROCI_GRIPFACE_T20 20 119 | #define MXT_PROCG_NOISE_T22 22 120 | #define MXT_PROCI_ONETOUCH_T24 24 121 | #define MXT_PROCI_TWOTOUCH_T27 27 122 | #define MXT_PROCI_GRIP_T40 40 123 | #define MXT_PROCI_PALM_T41 41 124 | #define MXT_PROCI_TOUCHSUPPRESSION_T42 42 125 | #define MXT_PROCI_STYLUS_T47 47 126 | #define MXT_PROCG_NOISESUPPRESSION_T48 48 127 | #define MXT_SPT_COMMSCONFIG_T18 18 128 | #define MXT_SPT_GPIOPWM_T19 19 129 | #define MXT_SPT_SELFTEST_T25 25 130 | #define MXT_SPT_CTECONFIG_T28 28 131 | #define MXT_SPT_USERDATA_T38 38 132 | #define MXT_SPT_DIGITIZER_T43 43 133 | #define MXT_SPT_MESSAGECOUNT_T44 44 134 | #define MXT_SPT_CTECONFIG_T46 46 135 | #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 136 | 137 | /* 138 | * register 0 - Object configuration element(s) (occurs after mxt_id_info) 139 | */ 140 | __packed(struct mxt_object { 141 | uint8_t type; /* object type */ 142 | uint16_t start_address; /* start address of config structure */ 143 | //uint8_t start_pos_lsb; /* start address of config structure */ 144 | //uint8_t start_pos_msb; /* start address of config structure */ 145 | uint8_t size_minus_one; /* size of config - 1 */ 146 | uint8_t instances_minus_one; /* #of instances of object - 1 */ 147 | uint8_t num_report_ids; /* max# of touches, sliders, buts, etc*/ 148 | }); 149 | 150 | /* 151 | * message structures (MXT_GEN_MESSAGEPROCESSOR) 152 | */ 153 | __packed(struct mxt_message_any { 154 | uint8_t reportid; 155 | uint8_t data[7]; 156 | }); 157 | 158 | /* MXT_GEN_POWER_T7 field */ 159 | __packed(struct t7_config { 160 | uint8_t idle; 161 | uint8_t active; 162 | }); 163 | 164 | #define MXT_POWER_CFG_RUN 0 165 | #define MXT_POWER_CFG_DEEPSLEEP 1 166 | 167 | __packed(struct mxt_message_touch_t9 { 168 | uint8_t reportid; 169 | uint8_t flags; /* msg[0] */ 170 | uint8_t pos[3]; /* xxxxxxxx(hi) yyyyyyyy(hi) xxxxyyyy(lo) */ 171 | uint8_t area; 172 | uint8_t amplitude; 173 | }); 174 | 175 | /* MXT_TOUCH_MULTI_T9 field */ 176 | #define MXT_T9_CTRL 0 177 | #define MXT_T9_ORIENT 9 178 | #define MXT_T9_RANGE 18 179 | 180 | /* MXT_TOUCH_MULTI_T9 status */ 181 | #define MXT_T9_UNGRIP (1 << 0) 182 | #define MXT_T9_SUPPRESS (1 << 1) 183 | #define MXT_T9_AMP (1 << 2) 184 | #define MXT_T9_VECTOR (1 << 3) 185 | #define MXT_T9_MOVE (1 << 4) 186 | #define MXT_T9_RELEASE (1 << 5) 187 | #define MXT_T9_PRESS (1 << 6) 188 | #define MXT_T9_DETECT (1 << 7) 189 | 190 | __packed(struct t9_range { 191 | uint16_t x; /* x */ 192 | uint16_t y; /* y */ 193 | }); 194 | #define MXT_T9_ORIENT_SWITCH (1 << 0) 195 | 196 | typedef union mxt_message mxt_message_t; 197 | 198 | /* T100 Multiple Touch Touchscreen */ 199 | #define MXT_T100_CTRL 0 200 | #define MXT_T100_CFG1 1 201 | #define MXT_T100_TCHAUX 3 202 | #define MXT_T100_XRANGE 13 203 | #define MXT_T100_YRANGE 24 204 | 205 | #define MXT_T100_CFG_SWITCHXY BIT(5) 206 | 207 | #define MXT_T100_TCHAUX_VECT BIT(0) 208 | #define MXT_T100_TCHAUX_AMPL BIT(1) 209 | #define MXT_T100_TCHAUX_AREA BIT(2) 210 | 211 | #define MXT_T100_DETECT BIT(7) 212 | #define MXT_T100_TYPE_MASK 0x70 213 | 214 | enum t100_type { 215 | MXT_T100_TYPE_FINGER = 1, 216 | MXT_T100_TYPE_PASSIVE_STYLUS = 2, 217 | MXT_T100_TYPE_HOVERING_FINGER = 4, 218 | MXT_T100_TYPE_GLOVE = 5, 219 | MXT_T100_TYPE_LARGE_TOUCH = 6, 220 | }; 221 | 222 | #define MXT_DISTANCE_ACTIVE_TOUCH 0 223 | #define MXT_DISTANCE_HOVERING 1 224 | 225 | #define MXT_TOUCH_MAJOR_DEFAULT 1 226 | #define MXT_PRESSURE_DEFAULT 1 227 | 228 | __packed(struct mxt_message_touch_t100 { 229 | uint8_t reportid; 230 | uint8_t flags; /* msg[0] */ 231 | uint16_t x; 232 | uint16_t y; 233 | uint8_t area; 234 | uint8_t amplitude; 235 | }); 236 | 237 | __packed(union mxt_message { 238 | struct mxt_message_any any; 239 | struct mxt_message_touch_t9 touch_t9; 240 | struct mxt_message_touch_t100 touch_t100; 241 | }); 242 | 243 | /* 244 | * Object types 245 | */ 246 | #define MXT_RESERVED_T0 0 247 | #define MXT_RESERVED_T1 1 248 | #define MXT_DEBUG_DELTAS 2 249 | #define MXT_DEBUG_REFERENCES 3 250 | #define MXT_SIGNALS 4 251 | #define MXT_GEN_MESSAGEPROCESSOR 5 252 | #define MXT_GEN_COMMANDPROCESSOR 6 253 | #define MXT_GEN_POWERCONFIG 7 254 | #define MXT_ACQUISITIONCONFIG 8 255 | #define MXT_TOUCH_MULTITOUCHSCREEN9 9 256 | #define MXT_TOUCH_SINGLETOUCHSCREEN 10 257 | #define MXT_TOUCH_XSLIDER 11 258 | #define MXT_TOUCH_YSLIDER 12 259 | #define MXT_TOUCH_XWHEEL 13 260 | #define MXT_TOUCH_YWHEEL 14 261 | #define MXT_TOUCH_KEYARRAY 15 262 | #define MXT_PROCG_SIGNALFILTER 16 263 | #define MXT_PROCI_LINEARIZATIONTABLE 17 264 | #define MXT_SPT_COMMSCONFIG 18 265 | #define MXT_SPT_GPIOPWM 19 266 | #define MXT_PROCI_GRIPFACESUPPRESSION 20 267 | #define MXT_RESERVED21 21 268 | #define MXT_PROCG_NOISESUPPRESSION22 22 269 | #define MXT_TOUCH_PROXIMITY 23 270 | #define MXT_PROCI_ONETOUCHGESTUREPROCESSOR 24 271 | #define MXT_SPT_SELFTEST 25 272 | #define MXT_DEBUG_CTERANGE 26 273 | #define MXT_PROCI_TWOTOUCHGESTUREPROCESSOR 27 274 | #define MXT_SPT_CTECONFIG28 28 275 | #define MXT_SPT_GPI 29 276 | #define MXT_SPT_GATE 30 277 | #define MXT_TOUCH_KEYSET 31 278 | #define MXT_TOUCH_XSLIDERSET 32 279 | #define MXT_RESERVED33 33 280 | #define MXT_GEN_MESSAGEBLOCK 34 281 | #define MXT_SPT_PROTOTYPE 35 282 | #define MXT_RESERVED36 36 283 | #define MXT_DEBUG_DIAGNOSTIC 37 284 | #define MXT_SPT_USERDATA 38 285 | #define MXT_SPARE39 39 286 | #define MXT_PROCI_GRIPSUPPRESSION 40 287 | #define MXT_PROCI_PALMSUPPRESSION 41 288 | #define MXT_PROCI_TOUCHSUPPRESSION 42 289 | #define MXT_SPT_DIGITIZER 43 290 | #define MXT_SPT_MESSAGECOUNT 44 291 | #define MXT_PROCI_VIRTUALKEY 45 292 | #define MXT_SPT_CTECONFIG46 46 293 | #define MXT_PROCI_STYLUS 47 294 | #define MXT_PROCG_NOISESUPPRESSION48 48 295 | #define MXT_GEN_DUALPULSE 49 296 | #define MXT_SPARE50 50 297 | #define MXT_SPT_SONY_CUSTOM 51 298 | #define MXT_TOUCH_PROXKEY 52 299 | #define MXT_GEN_DATASOURCE 53 300 | #define MXT_PROCG_NOISESUPPRESSION54 54 301 | #define MXT_PROCI_ADAPTIVETHRESHOLD 55 302 | #define MXT_PROCI_SHIELDLESS 56 303 | #define MXT_PROCI_EXTRATOUCHSCREENDATA 57 304 | #define MXT_SPT_EXTRANOISESUPCTRLS 58 305 | #define MXT_SPT_FASTDRIFT 59 306 | #define MXT_SPT_TIMER 61 307 | #define MXT_PROCG_NOISESUPPRESSION62 62 308 | #define MXT_PROCI_ACTIVESTYLUS63 63 309 | #define MXT_SPT_REFERENCERELOAD 64 310 | #define MXT_PROCI_LENSBENDING 65 311 | #define MXT_SPT_GOLDENREFERENCES 66 312 | #define MXT_PROCI_CUSTOMGESTUREPROCESSOR 67 313 | #define MXT_SERIAL_DATA_COMMAND 68 314 | #define MXT_PROCI_PALMGESTUREPROCESSOR 69 315 | #define MXT_SPT_DYNAMICCONFIGURATIONCONTROLLER 70 316 | #define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER 71 317 | #define MXT_PROCG_NOISESUPPRESSION72 72 318 | #define MXT_PROCI_ZONEINDICATION 73 319 | #define MXT_PROCG_SIMPLEGESTUREPROCESSOR 74 320 | #define MXT_MOTION_SENSING_OBJECT 75 321 | #define MXT_PROCI_MOTION_GESTURES 76 322 | #define MXT_SPT_CTESCANCONFIG 77 323 | #define MXT_PROCI_GLOVEDETECTION 78 324 | #define MXT_SPT_TOUCHEVENTTRIGGER 79 325 | #define MXT_PROCI_RETRANSMISSIONCOMPENSATION 80 326 | #define MXT_PROCI_UNLOCKGESTURE 81 327 | #define MXT_SPT_NOISESUPEXTENSION 82 328 | #define MXT_ENVIRO_LIGHTSENSING 83 329 | #define MXT_PROCI_GESTUREPROCESSOR 84 330 | #define MXT_PEN_ACTIVESTYLUSPOWER 85 331 | #define MXT_PROCG_NOISESUPACTIVESTYLUS 86 332 | #define MXT_PEN_ACTIVESTYLUSDATA 87 333 | #define MXT_PEN_ACTIVESTYLUSRECEIVE 88 334 | #define MXT_PEN_ACTIVESTYLUSTRANSMIT 89 335 | #define MXT_PEN_ACTIVESTYLUSWINDOW 90 336 | #define MXT_DEBUG_CUSTOMDATACONFIG 91 337 | #define MXT_PROCI_SYMBOLGESTUREPROCESSOR 92 338 | #define MXT_PROCI_TOUCHSEQUENCELOGGER 93 339 | #define MXT_TOUCH_MULTITOUCHSCREEN 100 340 | #define MXT_SPT_TOUCHSCREENHOVER 101 341 | #define MXT_SPT_SELFCAPHOVERCTECONFIG 102 342 | #define MXT_PROCI_SCHNOISESUPPRESSION 103 343 | #define MXT_SPT_AUXTOUCHCONFIG 104 344 | #define MXT_SPT_DRIVENPLATEHOVERCONFIG 105 345 | #define MXT_SPT_ACTIVESTYLUSMMBCONFIG 106 346 | #define MXT_PROCI_ACTIVESTYLUS107 107 347 | #define MXT_PROCG_NOISESUPSELFCAP 108 348 | #define MXT_SPT_SELFCAPGLOBALCONFIG 109 349 | #define MXT_SPT_SELFCAPTUNINGPARAMS 110 350 | #define MXT_SPT_SELFCAPCONFIG 111 351 | #define MXT_SPT_PROXMEASURECONFIG 113 352 | #define MXT_GEN_INFOBLOCK16BIT 254 353 | #define MXT_RESERVED255 255 354 | 355 | #define MXTSTR(label) #label 356 | 357 | #define MXT_INIT_STRINGS \ 358 | { MXTSTR(MXT_RESERVED_T0), \ 359 | MXT_RESERVED_T0 }, \ 360 | { MXTSTR(MXT_RESERVED_T1), \ 361 | MXT_RESERVED_T1 }, \ 362 | { MXTSTR(MXT_DEBUG_DELTAS), \ 363 | MXT_DEBUG_DELTAS }, \ 364 | { MXTSTR(MXT_DEBUG_REFERENCES), \ 365 | MXT_DEBUG_REFERENCES }, \ 366 | { MXTSTR(MXT_SIGNALS), \ 367 | MXT_SIGNALS }, \ 368 | { MXTSTR(MXT_GEN_MESSAGEPROCESSOR), \ 369 | MXT_GEN_MESSAGEPROCESSOR }, \ 370 | { MXTSTR(MXT_GEN_COMMANDPROCESSOR), \ 371 | MXT_GEN_COMMANDPROCESSOR }, \ 372 | { MXTSTR(MXT_GEN_POWERCONFIG), \ 373 | MXT_GEN_POWERCONFIG }, \ 374 | { MXTSTR(MXT_ACQUISITIONCONFIG), \ 375 | MXT_ACQUISITIONCONFIG }, \ 376 | { MXTSTR(MXT_TOUCH_MULTITOUCHSCREEN), \ 377 | MXT_TOUCH_MULTITOUCHSCREEN }, \ 378 | { MXTSTR(MXT_TOUCH_SINGLETOUCHSCREEN), \ 379 | MXT_TOUCH_SINGLETOUCHSCREEN }, \ 380 | { MXTSTR(MXT_TOUCH_XSLIDER), \ 381 | MXT_TOUCH_XSLIDER }, \ 382 | { MXTSTR(MXT_TOUCH_YSLIDER), \ 383 | MXT_TOUCH_YSLIDER }, \ 384 | { MXTSTR(MXT_TOUCH_XWHEEL), \ 385 | MXT_TOUCH_XWHEEL }, \ 386 | { MXTSTR(MXT_TOUCH_YWHEEL), \ 387 | MXT_TOUCH_YWHEEL }, \ 388 | { MXTSTR(MXT_TOUCH_KEYARRAY), \ 389 | MXT_TOUCH_KEYARRAY }, \ 390 | { MXTSTR(MXT_PROCG_SIGNALFILTER), \ 391 | MXT_PROCG_SIGNALFILTER }, \ 392 | { MXTSTR(MXT_PROCI_LINEARIZATIONTABLE), \ 393 | MXT_PROCI_LINEARIZATIONTABLE }, \ 394 | { MXTSTR(MXT_SPT_COMMSCONFIG), \ 395 | MXT_SPT_COMMSCONFIG }, \ 396 | { MXTSTR(MXT_SPT_GPIOPWM), \ 397 | MXT_SPT_GPIOPWM }, \ 398 | { MXTSTR(MXT_PROCI_GRIPFACESUPPRESSION), \ 399 | MXT_PROCI_GRIPFACESUPPRESSION }, \ 400 | { MXTSTR(MXT_RESERVED21), \ 401 | MXT_RESERVED21 }, \ 402 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION22), \ 403 | MXT_PROCG_NOISESUPPRESSION22 }, \ 404 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION48), \ 405 | MXT_PROCG_NOISESUPPRESSION48 }, \ 406 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION54), \ 407 | MXT_PROCG_NOISESUPPRESSION54 }, \ 408 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION62), \ 409 | MXT_PROCG_NOISESUPPRESSION62 }, \ 410 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION72), \ 411 | MXT_PROCG_NOISESUPPRESSION72 }, \ 412 | { MXTSTR(MXT_TOUCH_PROXIMITY), \ 413 | MXT_TOUCH_PROXIMITY }, \ 414 | { MXTSTR(MXT_PROCI_ONETOUCHGESTUREPROCESSOR), \ 415 | MXT_PROCI_ONETOUCHGESTUREPROCESSOR }, \ 416 | { MXTSTR(MXT_SPT_SELFTEST), \ 417 | MXT_SPT_SELFTEST }, \ 418 | { MXTSTR(MXT_DEBUG_CTERANGE), \ 419 | MXT_DEBUG_CTERANGE }, \ 420 | { MXTSTR(MXT_PROCI_TWOTOUCHGESTUREPROCESSOR), \ 421 | MXT_PROCI_TWOTOUCHGESTUREPROCESSOR }, \ 422 | { MXTSTR(MXT_SPT_CTECONFIG28), \ 423 | MXT_SPT_CTECONFIG28 }, \ 424 | { MXTSTR(MXT_SPT_CTECONFIG46), \ 425 | MXT_SPT_CTECONFIG46 }, \ 426 | { MXTSTR(MXT_SPT_GPI), \ 427 | MXT_SPT_GPI }, \ 428 | { MXTSTR(MXT_SPT_GATE), \ 429 | MXT_SPT_GATE }, \ 430 | { MXTSTR(MXT_TOUCH_KEYSET), \ 431 | MXT_TOUCH_KEYSET }, \ 432 | { MXTSTR(MXT_TOUCH_XSLIDERSET), \ 433 | MXT_TOUCH_XSLIDERSET }, \ 434 | { MXTSTR(MXT_RESERVED33), \ 435 | MXT_RESERVED33 }, \ 436 | { MXTSTR(MXT_GEN_MESSAGEBLOCK), \ 437 | MXT_GEN_MESSAGEBLOCK }, \ 438 | { MXTSTR(MXT_SPT_PROTOTYPE), \ 439 | MXT_SPT_PROTOTYPE }, \ 440 | { MXTSTR(MXT_RESERVED36), \ 441 | MXT_RESERVED36 }, \ 442 | { MXTSTR(MXT_DEBUG_DIAGNOSTIC), \ 443 | MXT_DEBUG_DIAGNOSTIC }, \ 444 | { MXTSTR(MXT_SPT_USERDATA), \ 445 | MXT_SPT_USERDATA }, \ 446 | { MXTSTR(MXT_SPARE39), \ 447 | MXT_SPARE39 }, \ 448 | { MXTSTR(MXT_PROCI_GRIPSUPPRESSION), \ 449 | MXT_PROCI_GRIPSUPPRESSION }, \ 450 | { MXTSTR(MXT_PROCI_PALMSUPPRESSION), \ 451 | MXT_PROCI_PALMSUPPRESSION }, \ 452 | { MXTSTR(MXT_PROCI_TOUCHSUPPRESSION), \ 453 | MXT_PROCI_TOUCHSUPPRESSION }, \ 454 | { MXTSTR(MXT_SPT_DIGITIZER), \ 455 | MXT_SPT_DIGITIZER }, \ 456 | { MXTSTR(MXT_SPT_MESSAGECOUNT), \ 457 | MXT_SPT_MESSAGECOUNT }, \ 458 | { MXTSTR(MXT_PROCI_VIRTUALKEY), \ 459 | MXT_PROCI_VIRTUALKEY }, \ 460 | { MXTSTR(MXT_PROCI_STYLUS), \ 461 | MXT_PROCI_STYLUS }, \ 462 | { MXTSTR(MXT_GEN_DUALPULSE), \ 463 | MXT_GEN_DUALPULSE }, \ 464 | { MXTSTR(MXT_SPARE50), \ 465 | MXT_SPARE50 }, \ 466 | { MXTSTR(MXT_SPT_SONY_CUSTOM), \ 467 | MXT_SPT_SONY_CUSTOM }, \ 468 | { MXTSTR(MXT_TOUCH_PROXKEY), \ 469 | MXT_TOUCH_PROXKEY }, \ 470 | { MXTSTR(MXT_GEN_DATASOURCE), \ 471 | MXT_GEN_DATASOURCE }, \ 472 | { MXTSTR(MXT_PROCI_ADAPTIVETHRESHOLD), \ 473 | MXT_PROCI_ADAPTIVETHRESHOLD }, \ 474 | { MXTSTR(MXT_PROCI_SHIELDLESS), \ 475 | MXT_PROCI_SHIELDLESS }, \ 476 | { MXTSTR(MXT_PROCI_EXTRATOUCHSCREENDATA), \ 477 | MXT_PROCI_EXTRATOUCHSCREENDATA }, \ 478 | { MXTSTR(MXT_SPT_EXTRANOISESUPCTRLS), \ 479 | MXT_SPT_EXTRANOISESUPCTRLS }, \ 480 | { MXTSTR(MXT_SPT_FASTDRIFT), \ 481 | MXT_SPT_FASTDRIFT }, \ 482 | { MXTSTR(MXT_SPT_TIMER), \ 483 | MXT_SPT_TIMER }, \ 484 | { MXTSTR(MXT_PROCI_ACTIVESTYLUS63), \ 485 | MXT_PROCI_ACTIVESTYLUS63 }, \ 486 | { MXTSTR(MXT_PROCI_ACTIVESTYLUS107), \ 487 | MXT_PROCI_ACTIVESTYLUS107 }, \ 488 | { MXTSTR(MXT_SPT_REFERENCERELOAD), \ 489 | MXT_SPT_REFERENCERELOAD }, \ 490 | { MXTSTR(MXT_PROCI_LENSBENDING), \ 491 | MXT_PROCI_LENSBENDING }, \ 492 | { MXTSTR(MXT_SPT_GOLDENREFERENCES), \ 493 | MXT_SPT_GOLDENREFERENCES }, \ 494 | { MXTSTR(MXT_PROCI_CUSTOMGESTUREPROCESSOR), \ 495 | MXT_PROCI_CUSTOMGESTUREPROCESSOR }, \ 496 | { MXTSTR(MXT_SERIAL_DATA_COMMAND), \ 497 | MXT_SERIAL_DATA_COMMAND }, \ 498 | { MXTSTR(MXT_PROCI_PALMGESTUREPROCESSOR), \ 499 | MXT_PROCI_PALMGESTUREPROCESSOR }, \ 500 | { MXTSTR(MXT_SPT_DYNAMICCONFIGURATIONCONTROLLER), \ 501 | MXT_SPT_DYNAMICCONFIGURATIONCONTROLLER }, \ 502 | { MXTSTR(MXT_SPT_DYNAMICCONFIGURATIONCONTAINER), \ 503 | MXT_SPT_DYNAMICCONFIGURATIONCONTAINER }, \ 504 | { MXTSTR(MXT_PROCI_ZONEINDICATION), \ 505 | MXT_PROCI_ZONEINDICATION }, \ 506 | { MXTSTR(MXT_PROCG_SIMPLEGESTUREPROCESSOR), \ 507 | MXT_PROCG_SIMPLEGESTUREPROCESSOR }, \ 508 | { MXTSTR(MXT_MOTION_SENSING_OBJECT), \ 509 | MXT_MOTION_SENSING_OBJECT }, \ 510 | { MXTSTR(MXT_PROCI_MOTION_GESTURES), \ 511 | MXT_PROCI_MOTION_GESTURES }, \ 512 | { MXTSTR(MXT_SPT_CTESCANCONFIG), \ 513 | MXT_SPT_CTESCANCONFIG }, \ 514 | { MXTSTR(MXT_PROCI_GLOVEDETECTION), \ 515 | MXT_PROCI_GLOVEDETECTION }, \ 516 | { MXTSTR(MXT_SPT_TOUCHEVENTTRIGGER), \ 517 | MXT_SPT_TOUCHEVENTTRIGGER }, \ 518 | { MXTSTR(MXT_PROCI_RETRANSMISSIONCOMPENSATION), \ 519 | MXT_PROCI_RETRANSMISSIONCOMPENSATION }, \ 520 | { MXTSTR(MXT_PROCI_UNLOCKGESTURE), \ 521 | MXT_PROCI_UNLOCKGESTURE }, \ 522 | { MXTSTR(MXT_SPT_NOISESUPEXTENSION), \ 523 | MXT_SPT_NOISESUPEXTENSION }, \ 524 | { MXTSTR(MXT_ENVIRO_LIGHTSENSING), \ 525 | MXT_ENVIRO_LIGHTSENSING }, \ 526 | { MXTSTR(MXT_PROCI_GESTUREPROCESSOR), \ 527 | MXT_PROCI_GESTUREPROCESSOR }, \ 528 | { MXTSTR(MXT_PEN_ACTIVESTYLUSPOWER), \ 529 | MXT_PEN_ACTIVESTYLUSPOWER }, \ 530 | { MXTSTR(MXT_PROCG_NOISESUPACTIVESTYLUS), \ 531 | MXT_PROCG_NOISESUPACTIVESTYLUS }, \ 532 | { MXTSTR(MXT_PEN_ACTIVESTYLUSDATA), \ 533 | MXT_PEN_ACTIVESTYLUSDATA }, \ 534 | { MXTSTR(MXT_PEN_ACTIVESTYLUSRECEIVE), \ 535 | MXT_PEN_ACTIVESTYLUSRECEIVE }, \ 536 | { MXTSTR(MXT_PEN_ACTIVESTYLUSTRANSMIT), \ 537 | MXT_PEN_ACTIVESTYLUSTRANSMIT }, \ 538 | { MXTSTR(MXT_PEN_ACTIVESTYLUSWINDOW), \ 539 | MXT_PEN_ACTIVESTYLUSWINDOW }, \ 540 | { MXTSTR(MXT_DEBUG_CUSTOMDATACONFIG), \ 541 | MXT_DEBUG_CUSTOMDATACONFIG }, \ 542 | { MXTSTR(MXT_PROCI_SYMBOLGESTUREPROCESSOR), \ 543 | MXT_PROCI_SYMBOLGESTUREPROCESSOR }, \ 544 | { MXTSTR(MXT_PROCI_TOUCHSEQUENCELOGGER), \ 545 | MXT_PROCI_TOUCHSEQUENCELOGGER }, \ 546 | { MXTSTR(MXT_TOUCH_MULTITOUCHSCREEN), \ 547 | MXT_TOUCH_MULTITOUCHSCREEN }, \ 548 | { MXTSTR(MXT_SPT_TOUCHSCREENHOVER), \ 549 | MXT_SPT_TOUCHSCREENHOVER }, \ 550 | { MXTSTR(MXT_SPT_SELFCAPHOVERCTECONFIG), \ 551 | MXT_SPT_SELFCAPHOVERCTECONFIG }, \ 552 | { MXTSTR(MXT_PROCI_SCHNOISESUPPRESSION), \ 553 | MXT_PROCI_SCHNOISESUPPRESSION }, \ 554 | { MXTSTR(MXT_SPT_AUXTOUCHCONFIG), \ 555 | MXT_SPT_AUXTOUCHCONFIG }, \ 556 | { MXTSTR(MXT_SPT_DRIVENPLATEHOVERCONFIG), \ 557 | MXT_SPT_DRIVENPLATEHOVERCONFIG }, \ 558 | { MXTSTR(MXT_SPT_ACTIVESTYLUSMMBCONFIG), \ 559 | MXT_SPT_ACTIVESTYLUSMMBCONFIG }, \ 560 | { MXTSTR(MXT_PROCG_NOISESUPSELFCAP), \ 561 | MXT_PROCG_NOISESUPSELFCAP }, \ 562 | { MXTSTR(MXT_SPT_SELFCAPGLOBALCONFIG), \ 563 | MXT_SPT_SELFCAPGLOBALCONFIG }, \ 564 | { MXTSTR(MXT_SPT_SELFCAPTUNINGPARAMS), \ 565 | MXT_SPT_SELFCAPTUNINGPARAMS }, \ 566 | { MXTSTR(MXT_SPT_SELFCAPCONFIG), \ 567 | MXT_SPT_SELFCAPCONFIG }, \ 568 | { MXTSTR(MXT_SPT_PROXMEASURECONFIG), \ 569 | MXT_SPT_PROXMEASURECONFIG }, \ 570 | { MXTSTR(MXT_GEN_INFOBLOCK16BIT), \ 571 | MXT_GEN_INFOBLOCK16BIT }, \ 572 | { MXTSTR(MXT_RESERVED255), \ 573 | MXT_RESERVED255 } 574 | 575 | /* 576 | * MXT_GEN_COMMANDPROCESSOR object offsets. 577 | */ 578 | #define MXT_CMDPROC_RESET_OFF 0x00 579 | #define MXT_CMDPROC_BACKUPNV_OFF 0x01 580 | #define MXT_CMDPROC_CALIBRATE_OFF 0x02 581 | #define MXT_CMDPROC_REPORTALL_OFF 0x03 582 | #define MXT_CMDPROC_RESERVED04_OFF 0x04 583 | #define MXT_CMDPROC_DIAGNOSTIC_OFF 0x05 584 | 585 | /* 586 | * device driver helper structures 587 | */ 588 | struct mxt_strinfo { 589 | const char *id; 590 | int type; 591 | }; 592 | 593 | struct mxt_rollup { 594 | struct mxt_id_info info; 595 | struct mxt_object *objs; 596 | int nobjs; 597 | uint8_t *buf; 598 | }; 599 | 600 | struct atmel_softc { 601 | int flags[20]; 602 | int x[20]; 603 | int y[20]; 604 | int p[20]; 605 | int area[20]; 606 | int ampl[20]; 607 | }; 608 | 609 | /* 610 | * Kernel AND user mode support 611 | */ 612 | uint32_t obp_convert_crc(struct mxt_raw_crc *crc); 613 | uint32_t obp_crc24(uint8_t *buf, size_t bytes); 614 | 615 | #endif -------------------------------------------------------------------------------- /crostouchpad/atmel.c: -------------------------------------------------------------------------------- 1 | #define DESCRIPTOR_DEF 2 | #include "driver.h" 3 | 4 | static ULONG AtmelTPDebugLevel = 100; 5 | static ULONG AtmelTPDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 6 | 7 | uint8_t AtmelTPProcessMessagesUntilInvalid(PATMELTP_CONTEXT pDevice); 8 | 9 | NTSTATUS 10 | DriverEntry( 11 | __in PDRIVER_OBJECT DriverObject, 12 | __in PUNICODE_STRING RegistryPath 13 | ) 14 | { 15 | NTSTATUS status = STATUS_SUCCESS; 16 | WDF_DRIVER_CONFIG config; 17 | WDF_OBJECT_ATTRIBUTES attributes; 18 | 19 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_INIT, 20 | "Driver Entry\n"); 21 | 22 | WDF_DRIVER_CONFIG_INIT(&config, AtmelTPEvtDeviceAdd); 23 | 24 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 25 | 26 | // 27 | // Create a framework driver object to represent our driver. 28 | // 29 | 30 | status = WdfDriverCreate(DriverObject, 31 | RegistryPath, 32 | &attributes, 33 | &config, 34 | WDF_NO_HANDLE 35 | ); 36 | 37 | if (!NT_SUCCESS(status)) 38 | { 39 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 40 | "WdfDriverCreate failed with status 0x%x\n", status); 41 | } 42 | 43 | return status; 44 | } 45 | 46 | static uint8_t mxt_obj_size(const struct mxt_object *obj) 47 | { 48 | return obj->size_minus_one + 1; 49 | } 50 | 51 | static uint8_t mxt_obj_instances(const struct mxt_object *obj) 52 | { 53 | return obj->instances_minus_one + 1; 54 | } 55 | 56 | static 57 | struct mxt_object * 58 | mxt_findobject(struct mxt_rollup *core, int type) 59 | { 60 | int i; 61 | 62 | for (i = 0; i < core->nobjs; ++i) { 63 | if (core->objs[i].type == type) 64 | return(&core->objs[i]); 65 | } 66 | return NULL; 67 | } 68 | 69 | static NTSTATUS 70 | mxt_read_reg(PATMELTP_CONTEXT devContext, uint16_t reg, void *rbuf, int bytes) 71 | { 72 | uint8_t wreg[2]; 73 | wreg[0] = reg & 255; 74 | wreg[1] = reg >> 8; 75 | 76 | uint16_t nreg = ((uint16_t *)wreg)[0]; 77 | 78 | NTSTATUS error = SpbReadDataSynchronously16(&devContext->I2CContext, nreg, rbuf, bytes); 79 | 80 | return error; 81 | } 82 | 83 | static NTSTATUS 84 | mxt_write_reg_buf(PATMELTP_CONTEXT devContext, uint16_t reg, void *xbuf, int bytes) 85 | { 86 | uint8_t wreg[2]; 87 | wreg[0] = reg & 255; 88 | wreg[1] = reg >> 8; 89 | 90 | uint16_t nreg = ((uint16_t *)wreg)[0]; 91 | return SpbWriteDataSynchronously16(&devContext->I2CContext, nreg, xbuf, bytes); 92 | } 93 | 94 | static NTSTATUS 95 | mxt_write_reg(PATMELTP_CONTEXT devContext, uint16_t reg, uint8_t val) 96 | { 97 | return mxt_write_reg_buf(devContext, reg, &val, 1); 98 | } 99 | 100 | static NTSTATUS 101 | mxt_write_object_off(PATMELTP_CONTEXT devContext, struct mxt_object *obj, 102 | uint16_t offset, uint8_t val) 103 | { 104 | uint16_t reg = obj->start_address; 105 | 106 | reg += offset; 107 | return mxt_write_reg(devContext, reg, val); 108 | } 109 | 110 | static 111 | NTSTATUS 112 | atmel_reset_device(PATMELTP_CONTEXT devContext) 113 | { 114 | return mxt_write_object_off(devContext, devContext->cmdprocobj, MXT_CMDPROC_RESET_OFF, 1); 115 | } 116 | 117 | static NTSTATUS mxt_read_t9_resolution(PATMELTP_CONTEXT devContext) 118 | { 119 | struct t9_range range; 120 | unsigned char orient; 121 | NTSTATUS status; 122 | 123 | struct mxt_rollup core = devContext->core; 124 | struct mxt_object *resolutionobject = mxt_findobject(&core, MXT_TOUCH_MULTI_T9); 125 | 126 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T9_RANGE, &range, sizeof(range)); 127 | if (!NT_SUCCESS(status)) { 128 | return status; 129 | } 130 | 131 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T9_ORIENT, &orient, 1); 132 | if (!NT_SUCCESS(status)) { 133 | return status; 134 | } 135 | 136 | /* Handle default values */ 137 | if (range.x == 0) 138 | range.x = 1023; 139 | 140 | if (range.y == 0) 141 | range.y = 1023; 142 | 143 | if (orient & MXT_T9_ORIENT_SWITCH) { 144 | devContext->max_x = range.y + 1; 145 | devContext->max_y = range.x + 1; 146 | } 147 | else { 148 | devContext->max_x = range.x + 1; 149 | devContext->max_y = range.y + 1; 150 | } 151 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_PNP, "Screen Size: X: %d Y: %d\n", devContext->max_x, devContext->max_y); 152 | return status; 153 | } 154 | 155 | static NTSTATUS mxt_read_t100_config(PATMELTP_CONTEXT devContext) 156 | { 157 | NTSTATUS status; 158 | uint16_t range_x, range_y; 159 | uint8_t cfg, tchaux; 160 | uint8_t aux; 161 | 162 | struct mxt_rollup core = devContext->core; 163 | struct mxt_object *resolutionobject = mxt_findobject(&core, MXT_TOUCH_MULTITOUCHSCREEN_T100); 164 | 165 | /* read touchscreen dimensions */ 166 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T100_XRANGE, &range_x, sizeof(range_x)); 167 | if (!NT_SUCCESS(status)) { 168 | return status; 169 | } 170 | 171 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T100_YRANGE, &range_y, sizeof(range_y)); 172 | if (!NT_SUCCESS(status)) { 173 | return status; 174 | } 175 | 176 | /* read orientation config */ 177 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T100_CFG1, &cfg, 1); 178 | if (!NT_SUCCESS(status)) { 179 | return status; 180 | } 181 | 182 | if (cfg & MXT_T100_CFG_SWITCHXY) { 183 | devContext->max_x = range_y + 1; 184 | devContext->max_y = range_x + 1; 185 | } 186 | else { 187 | devContext->max_x = range_x + 1; 188 | devContext->max_y = range_y + 1; 189 | } 190 | 191 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T100_TCHAUX, &tchaux, 1); 192 | if (!NT_SUCCESS(status)) { 193 | return status; 194 | } 195 | 196 | aux = 6; 197 | 198 | if (tchaux & MXT_T100_TCHAUX_VECT) 199 | devContext->t100_aux_vect = aux++; 200 | 201 | if (tchaux & MXT_T100_TCHAUX_AMPL) 202 | devContext->t100_aux_ampl = aux++; 203 | 204 | if (tchaux & MXT_T100_TCHAUX_AREA) 205 | devContext->t100_aux_area = aux++; 206 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_PNP, "Screen Size T100: X: %d Y: %d\n", devContext->max_x, devContext->max_y); 207 | return status; 208 | } 209 | 210 | static NTSTATUS mxt_set_t7_power_cfg(PATMELTP_CONTEXT devContext, uint8_t sleep) 211 | { 212 | struct t7_config *new_config; 213 | struct t7_config deepsleep = { .active = 0,.idle = 0 }; 214 | struct t7_config active = { .active = 20,.idle = 100 }; 215 | 216 | if (sleep == MXT_POWER_CFG_DEEPSLEEP) 217 | new_config = &deepsleep; 218 | else { 219 | new_config = &active; 220 | } 221 | 222 | return mxt_write_reg_buf(devContext, devContext->T7_address, 223 | new_config, sizeof(devContext->t7_cfg)); 224 | } 225 | 226 | VOID 227 | AtmelTPBootWorkItem( 228 | IN WDFWORKITEM WorkItem 229 | ) 230 | { 231 | WDFDEVICE Device = (WDFDEVICE)WdfWorkItemGetParentObject(WorkItem); 232 | PATMELTP_CONTEXT pDevice = GetDeviceContext(Device); 233 | 234 | uint8_t test[8]; 235 | mxt_read_reg(pDevice, pDevice->T44_address, test, 0x07); 236 | 237 | WdfObjectDelete(WorkItem); 238 | } 239 | 240 | void AtmelTPBootTimer(_In_ WDFTIMER hTimer) { 241 | WDFDEVICE Device = (WDFDEVICE)WdfTimerGetParentObject(hTimer); 242 | 243 | WDF_OBJECT_ATTRIBUTES attributes; 244 | WDF_WORKITEM_CONFIG workitemConfig; 245 | WDFWORKITEM hWorkItem; 246 | 247 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 248 | WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, ATMELTP_CONTEXT); 249 | attributes.ParentObject = Device; 250 | WDF_WORKITEM_CONFIG_INIT(&workitemConfig, AtmelTPBootWorkItem); 251 | 252 | WdfWorkItemCreate(&workitemConfig, 253 | &attributes, 254 | &hWorkItem); 255 | 256 | WdfWorkItemEnqueue(hWorkItem); 257 | WdfTimerStop(hTimer, FALSE); 258 | } 259 | 260 | NTSTATUS BOOTTRACKPAD( 261 | _In_ PATMELTP_CONTEXT devContext 262 | ) 263 | { 264 | NTSTATUS status = STATUS_SUCCESS; 265 | if (!devContext->TrackpadBooted) { 266 | int blksize; 267 | int totsize; 268 | uint32_t crc; 269 | struct mxt_rollup* core = &devContext->core; 270 | 271 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_PNP, "Initializing Touch Screen.\n"); 272 | 273 | status = mxt_read_reg(devContext, 0, &core->info, sizeof(core->info)); 274 | if (!NT_SUCCESS(status)) { 275 | return status; 276 | } 277 | 278 | core->nobjs = core->info.num_objects; 279 | 280 | if (core->nobjs < 0 || core->nobjs > 1024) { 281 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "init_device nobjs (%d) out of bounds\n", 282 | core.nobjs); 283 | } 284 | 285 | blksize = sizeof(core->info) + 286 | core->nobjs * sizeof(struct mxt_object); 287 | totsize = blksize + sizeof(struct mxt_raw_crc); 288 | 289 | core->buf = (uint8_t*)ExAllocatePoolWithTag(NonPagedPool, totsize, ATMELTP_POOL_TAG); 290 | 291 | status = mxt_read_reg(devContext, 0, core->buf, totsize); 292 | if (!NT_SUCCESS(status)) { 293 | return status; 294 | } 295 | 296 | crc = obp_convert_crc((struct mxt_raw_crc*)((uint8_t*)core->buf + blksize)); 297 | 298 | if (obp_crc24(core->buf, blksize) != crc) { 299 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 300 | "init_device: configuration space " 301 | "crc mismatch %08x/%08x\n", 302 | crc, obp_crc24(core.buf, blksize)); 303 | } 304 | else { 305 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "CRC Matched!\n"); 306 | } 307 | 308 | core->objs = (struct mxt_object *)((uint8_t*)core->buf + 309 | sizeof(core->info)); 310 | 311 | devContext->msgprocobj = mxt_findobject(core, MXT_GEN_MESSAGEPROCESSOR); 312 | devContext->cmdprocobj = mxt_findobject(core, MXT_GEN_COMMANDPROCESSOR); 313 | 314 | uint8_t reportid = 1; 315 | for (int i = 0; i < core->nobjs; i++) { 316 | struct mxt_object* obj = &core->objs[i]; 317 | uint8_t min_id, max_id; 318 | 319 | if (obj->num_report_ids) { 320 | min_id = reportid; 321 | reportid += obj->num_report_ids * 322 | mxt_obj_instances(obj); 323 | max_id = reportid - 1; 324 | } 325 | else { 326 | min_id = 0; 327 | max_id = 0; 328 | } 329 | 330 | switch (obj->type) { 331 | case MXT_GEN_MESSAGE_T5: 332 | if (devContext->info.family == 0x80 && 333 | devContext->info.version < 0x20) { 334 | /* 335 | * On mXT224 firmware versions prior to V2.0 336 | * read and discard unused CRC byte otherwise 337 | * DMA reads are misaligned. 338 | */ 339 | devContext->T5_msg_size = mxt_obj_size(obj); 340 | } 341 | else { 342 | /* CRC not enabled, so skip last byte */ 343 | devContext->T5_msg_size = mxt_obj_size(obj) - 1; 344 | } 345 | devContext->T5_address = obj->start_address; 346 | break; 347 | case MXT_GEN_COMMAND_T6: 348 | devContext->T6_reportid = min_id; 349 | devContext->T6_address = obj->start_address; 350 | break; 351 | case MXT_GEN_POWER_T7: 352 | devContext->T7_address = obj->start_address; 353 | break; 354 | case MXT_TOUCH_MULTI_T9: 355 | devContext->multitouch = MXT_TOUCH_MULTI_T9; 356 | devContext->T9_reportid_min = min_id; 357 | devContext->T9_reportid_max = max_id; 358 | devContext->num_touchids = obj->num_report_ids 359 | * mxt_obj_instances(obj); 360 | break; 361 | case MXT_SPT_MESSAGECOUNT_T44: 362 | devContext->T44_address = obj->start_address; 363 | break; 364 | case MXT_SPT_GPIOPWM_T19: 365 | devContext->T19_reportid = min_id; 366 | break; 367 | case MXT_TOUCH_MULTITOUCHSCREEN_T100: 368 | devContext->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100; 369 | devContext->T100_reportid_min = min_id; 370 | devContext->T100_reportid_max = max_id; 371 | 372 | /* first two report IDs reserved */ 373 | devContext->num_touchids = obj->num_report_ids - 2; 374 | break; 375 | } 376 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_PNP, "Obj Type: %d\n", obj->type); 377 | } 378 | 379 | devContext->max_reportid = reportid; 380 | 381 | AtmelTPProcessMessagesUntilInvalid(devContext); 382 | 383 | if (devContext->multitouch == MXT_TOUCH_MULTI_T9) 384 | mxt_read_t9_resolution(devContext); 385 | else if (devContext->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) 386 | mxt_read_t100_config(devContext); 387 | 388 | if (devContext->multitouch == MXT_TOUCH_MULTI_T9 || devContext->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) { 389 | uint16_t max_x[] = { devContext->max_x }; 390 | uint16_t max_y[] = { devContext->max_y }; 391 | 392 | uint8_t *max_x8bit = (uint8_t *)max_x; 393 | uint8_t *max_y8bit = (uint8_t *)max_y; 394 | 395 | devContext->max_x_hid[0] = max_x8bit[0]; 396 | devContext->max_x_hid[1] = max_x8bit[1]; 397 | 398 | devContext->max_y_hid[0] = max_y8bit[0]; 399 | devContext->max_y_hid[1] = max_y8bit[1]; 400 | 401 | devContext->phy_x = devContext->max_x; 402 | devContext->phy_y = devContext->max_y; 403 | 404 | uint16_t phy_x[] = { devContext->phy_x }; 405 | uint16_t phy_y[] = { devContext->phy_y }; 406 | 407 | uint8_t *phy_x8bit = (uint8_t *)phy_x; 408 | uint8_t *phy_y8bit = (uint8_t *)phy_y; 409 | 410 | devContext->phy_x_hid[0] = phy_x8bit[0]; 411 | devContext->phy_x_hid[1] = phy_x8bit[1]; 412 | 413 | devContext->phy_y_hid[0] = phy_y8bit[0]; 414 | devContext->phy_y_hid[1] = phy_y8bit[1]; 415 | } 416 | 417 | status = atmel_reset_device(devContext); 418 | if (!NT_SUCCESS(status)) { 419 | return status; 420 | } 421 | 422 | WDF_TIMER_CONFIG timerConfig; 423 | WDFTIMER hTimer; 424 | WDF_OBJECT_ATTRIBUTES attributes; 425 | 426 | WDF_TIMER_CONFIG_INIT(&timerConfig, AtmelTPBootTimer); 427 | 428 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 429 | attributes.ParentObject = devContext->FxDevice; 430 | status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); 431 | 432 | WdfTimerStart(hTimer, WDF_REL_TIMEOUT_IN_MS(200)); 433 | 434 | devContext->TrackpadBooted = true; 435 | 436 | return status; 437 | } 438 | else { 439 | if (devContext->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) { 440 | status = mxt_set_t7_power_cfg(devContext, MXT_POWER_CFG_RUN); 441 | if (!NT_SUCCESS(status)) { 442 | return status; 443 | } 444 | } 445 | else { 446 | struct mxt_object* obj = mxt_findobject(&devContext->core, MXT_TOUCH_MULTI_T9); 447 | status = mxt_write_object_off(devContext, obj, MXT_T9_CTRL, 0x83); 448 | if (!NT_SUCCESS(status)) { 449 | return status; 450 | } 451 | } 452 | 453 | status = atmel_reset_device(devContext); 454 | return status; 455 | } 456 | } 457 | 458 | NTSTATUS 459 | OnPrepareHardware( 460 | _In_ WDFDEVICE FxDevice, 461 | _In_ WDFCMRESLIST FxResourcesRaw, 462 | _In_ WDFCMRESLIST FxResourcesTranslated 463 | ) 464 | /*++ 465 | 466 | Routine Description: 467 | 468 | This routine caches the SPB resource connection ID. 469 | 470 | Arguments: 471 | 472 | FxDevice - a handle to the framework device object 473 | FxResourcesRaw - list of translated hardware resources that 474 | the PnP manager has assigned to the device 475 | FxResourcesTranslated - list of raw hardware resources that 476 | the PnP manager has assigned to the device 477 | 478 | Return Value: 479 | 480 | Status 481 | 482 | --*/ 483 | { 484 | PATMELTP_CONTEXT pDevice = GetDeviceContext(FxDevice); 485 | BOOLEAN fSpbResourceFound = FALSE; 486 | NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; 487 | 488 | UNREFERENCED_PARAMETER(FxResourcesRaw); 489 | 490 | // 491 | // Parse the peripheral's resources. 492 | // 493 | 494 | ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); 495 | 496 | for (ULONG i = 0; i < resourceCount; i++) 497 | { 498 | PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 499 | UCHAR Class; 500 | UCHAR Type; 501 | 502 | pDescriptor = WdfCmResourceListGetDescriptor( 503 | FxResourcesTranslated, i); 504 | 505 | switch (pDescriptor->Type) 506 | { 507 | case CmResourceTypeConnection: 508 | // 509 | // Look for I2C or SPI resource and save connection ID. 510 | // 511 | Class = pDescriptor->u.Connection.Class; 512 | Type = pDescriptor->u.Connection.Type; 513 | if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && 514 | Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) 515 | { 516 | if (fSpbResourceFound == FALSE) 517 | { 518 | status = STATUS_SUCCESS; 519 | pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; 520 | pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; 521 | fSpbResourceFound = TRUE; 522 | } 523 | else 524 | { 525 | } 526 | } 527 | break; 528 | default: 529 | // 530 | // Ignoring all other resource types. 531 | // 532 | break; 533 | } 534 | } 535 | 536 | // 537 | // An SPB resource is required. 538 | // 539 | 540 | if (fSpbResourceFound == FALSE) 541 | { 542 | status = STATUS_NOT_FOUND; 543 | } 544 | 545 | status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); 546 | if (!NT_SUCCESS(status)) 547 | { 548 | return status; 549 | } 550 | 551 | status = BOOTTRACKPAD(pDevice); 552 | 553 | if (!NT_SUCCESS(status)) 554 | { 555 | return status; 556 | } 557 | 558 | return status; 559 | } 560 | 561 | NTSTATUS 562 | OnReleaseHardware( 563 | _In_ WDFDEVICE FxDevice, 564 | _In_ WDFCMRESLIST FxResourcesTranslated 565 | ) 566 | /*++ 567 | 568 | Routine Description: 569 | 570 | Arguments: 571 | 572 | FxDevice - a handle to the framework device object 573 | FxResourcesTranslated - list of raw hardware resources that 574 | the PnP manager has assigned to the device 575 | 576 | Return Value: 577 | 578 | Status 579 | 580 | --*/ 581 | { 582 | PATMELTP_CONTEXT pDevice = GetDeviceContext(FxDevice); 583 | NTSTATUS status = STATUS_SUCCESS; 584 | 585 | UNREFERENCED_PARAMETER(FxResourcesTranslated); 586 | 587 | if (pDevice->core.buf != NULL) { 588 | ExFreePoolWithTag(pDevice->core.buf, ATMELTP_POOL_TAG); 589 | } 590 | 591 | pDevice->core.buf = NULL; 592 | 593 | pDevice->msgprocobj = NULL; 594 | pDevice->cmdprocobj = NULL; 595 | 596 | SpbTargetDeinitialize(FxDevice, &pDevice->I2CContext); 597 | 598 | return status; 599 | } 600 | 601 | NTSTATUS 602 | OnD0Entry( 603 | _In_ WDFDEVICE FxDevice, 604 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 605 | ) 606 | /*++ 607 | 608 | Routine Description: 609 | 610 | This routine allocates objects needed by the driver. 611 | 612 | Arguments: 613 | 614 | FxDevice - a handle to the framework device object 615 | FxPreviousState - previous power state 616 | 617 | Return Value: 618 | 619 | Status 620 | 621 | --*/ 622 | { 623 | UNREFERENCED_PARAMETER(FxPreviousState); 624 | 625 | PATMELTP_CONTEXT pDevice = GetDeviceContext(FxDevice); 626 | NTSTATUS status = STATUS_SUCCESS; 627 | 628 | atmel_reset_device(pDevice); 629 | 630 | for (int i = 0; i < 20; i++){ 631 | pDevice->Flags[i] = 0; 632 | } 633 | 634 | pDevice->RegsSet = false; 635 | pDevice->ConnectInterrupt = true; 636 | 637 | return status; 638 | } 639 | 640 | NTSTATUS 641 | OnD0Exit( 642 | _In_ WDFDEVICE FxDevice, 643 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 644 | ) 645 | /*++ 646 | 647 | Routine Description: 648 | 649 | This routine destroys objects needed by the driver. 650 | 651 | Arguments: 652 | 653 | FxDevice - a handle to the framework device object 654 | FxPreviousState - previous power state 655 | 656 | Return Value: 657 | 658 | Status 659 | 660 | --*/ 661 | { 662 | UNREFERENCED_PARAMETER(FxPreviousState); 663 | 664 | PATMELTP_CONTEXT pDevice = GetDeviceContext(FxDevice); 665 | 666 | if (pDevice->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) 667 | mxt_set_t7_power_cfg(pDevice, MXT_POWER_CFG_DEEPSLEEP); 668 | else { 669 | struct mxt_object *obj = mxt_findobject(&pDevice->core, MXT_TOUCH_MULTI_T9); 670 | mxt_write_object_off(pDevice, obj, MXT_T9_CTRL, 0); 671 | } 672 | 673 | pDevice->ConnectInterrupt = false; 674 | 675 | return STATUS_SUCCESS; 676 | } 677 | 678 | int AtmelTPProcessMessage(PATMELTP_CONTEXT pDevice, uint8_t *message) { 679 | static unsigned int t100_touchpad_buttons[] = { 680 | 0, //RESERVED 681 | 0, //RESERVED 682 | 0, //RESERVED 683 | 1 //LEFT 684 | }; 685 | 686 | static unsigned int t9_tp_buttons[] = { 687 | 0, //RESERVED 688 | 0, //RESERVED 689 | 0, //RESERVED 690 | 0, //RESERVED 691 | 0, //RESERVED, 692 | 1 //LEFT 693 | }; 694 | 695 | int t19_num_keys = ARRAYSIZE(t9_tp_buttons); 696 | unsigned int *t19_keymap = t9_tp_buttons; 697 | 698 | if (pDevice->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) { 699 | t19_num_keys = ARRAYSIZE(t100_touchpad_buttons); 700 | t19_keymap = t100_touchpad_buttons; 701 | } 702 | 703 | uint8_t report_id = message[0]; 704 | 705 | if (report_id == 0xff) 706 | return 0; 707 | 708 | if (report_id == pDevice->T6_reportid) { 709 | //uint8_t status = message[1]; 710 | //uint32_t crc = message[2] | (message[3] << 8) | (message[4] << 16); 711 | } 712 | else if (report_id >= pDevice->T9_reportid_min && report_id <= pDevice->T9_reportid_max) { 713 | uint8_t flags = message[1]; 714 | 715 | uint16_t rawx = (message[2] << 4) | ((message[4] >> 4) & 0xf); 716 | uint16_t rawy = (message[3] << 4) | ((message[4] & 0xf)); 717 | 718 | /* Handle 10/12 bit switching */ 719 | if (pDevice->max_x < 1024) 720 | rawx >>= 2; 721 | if (pDevice->max_y < 1024) 722 | rawy >>= 2; 723 | 724 | uint8_t area = message[5]; 725 | //uint8_t ampl = message[6]; 726 | 727 | pDevice->Flags[report_id] = flags; 728 | pDevice->XValue[report_id] = rawx; 729 | pDevice->YValue[report_id] = rawy; 730 | pDevice->AREA[report_id] = area; 731 | } 732 | else if (report_id >= pDevice->T100_reportid_min && report_id <= pDevice->T100_reportid_max) { 733 | int reportid = report_id - pDevice->T100_reportid_min - 2; 734 | 735 | uint8_t flags = message[1]; 736 | 737 | uint8_t t9_flags = 0; //convert T100 flags to T9 738 | if (flags & MXT_T100_DETECT) { 739 | uint8_t type; 740 | type = (flags & MXT_T100_TYPE_MASK) >> 4; 741 | if (type == MXT_T100_TYPE_FINGER || type == MXT_T100_TYPE_GLOVE || type == MXT_T100_TYPE_PASSIVE_STYLUS) 742 | t9_flags += MXT_T9_DETECT; 743 | else if (type == MXT_T100_TYPE_HOVERING_FINGER) { 744 | if (pDevice->Flags[reportid] & MXT_T9_DETECT) 745 | t9_flags += MXT_T9_RELEASE; 746 | else 747 | t9_flags = 0; 748 | } 749 | } 750 | else if (pDevice->Flags[reportid] & MXT_T9_DETECT) 751 | t9_flags += MXT_T9_RELEASE; 752 | 753 | uint16_t rawx = *((uint16_t *)&message[2]); 754 | uint16_t rawy = *((uint16_t *)&message[4]); 755 | 756 | if (reportid >= 0) { 757 | pDevice->Flags[reportid] = t9_flags; 758 | 759 | pDevice->XValue[reportid] = rawx; 760 | pDevice->YValue[reportid] = rawy; 761 | pDevice->AREA[reportid] = 10; 762 | } 763 | } 764 | else if (report_id == pDevice->T19_reportid) { 765 | #define BIT(nr) (1UL << (nr)) 766 | 767 | for (int i = 0; i < t19_num_keys; i++) { 768 | if (t19_keymap[i] == 0) 769 | continue; 770 | 771 | bool buttonClicked = !(message[1] & BIT(i)); 772 | 773 | pDevice->T19_buttonstate = buttonClicked; 774 | } 775 | } 776 | 777 | pDevice->RegsSet = true; 778 | return 1; 779 | } 780 | 781 | uint8_t AtmelReadAndProcessMessages(PATMELTP_CONTEXT pDevice, uint8_t count) { 782 | uint8_t num_valid = 0; 783 | int ret; 784 | if (count > pDevice->max_reportid) 785 | return 0; 786 | 787 | uint8_t *msg_buf = (uint8_t *)ExAllocatePoolWithTag(NonPagedPool, pDevice->max_reportid * pDevice->T5_msg_size, ATMELTP_POOL_TAG); 788 | if (!msg_buf) { 789 | return 0; 790 | } 791 | 792 | for (int i = 0; i < pDevice->max_reportid * pDevice->T5_msg_size; i++) { 793 | msg_buf[i] = 0xff; 794 | } 795 | 796 | NTSTATUS status = mxt_read_reg(pDevice, pDevice->T5_address, msg_buf, pDevice->T5_msg_size * count); 797 | if (!NT_SUCCESS(status)) { 798 | ExFreePoolWithTag(msg_buf, ATMELTP_POOL_TAG); 799 | return 0; 800 | } 801 | 802 | for (uint8_t i = 0; i < count; i++) { 803 | ret = AtmelTPProcessMessage(pDevice, 804 | msg_buf + pDevice->T5_msg_size * i); 805 | 806 | if (ret == 1) 807 | num_valid++; 808 | } 809 | 810 | ExFreePoolWithTag(msg_buf, ATMELTP_POOL_TAG); 811 | 812 | /* return number of messages read */ 813 | return num_valid; 814 | } 815 | 816 | uint8_t AtmelTPProcessMessagesUntilInvalid(PATMELTP_CONTEXT pDevice) { 817 | uint8_t count, read; 818 | uint8_t tries = 2; 819 | 820 | count = pDevice->max_reportid; 821 | do { 822 | read = AtmelReadAndProcessMessages(pDevice, count); 823 | if (read < count) 824 | return 0; 825 | } while (--tries); 826 | return 0; 827 | } 828 | 829 | bool AtmelTPDeviceReadT44(PATMELTP_CONTEXT pDevice) { 830 | NTSTATUS status, ret; 831 | uint8_t count, num_left; 832 | 833 | uint8_t *msg_buf = (uint8_t *)ExAllocatePoolWithTag(NonPagedPool, pDevice->T5_msg_size + 1, ATMELTP_POOL_TAG); 834 | if (!msg_buf) { 835 | return false; 836 | } 837 | 838 | /* Read T44 and T5 together */ 839 | status = mxt_read_reg(pDevice, pDevice->T44_address, msg_buf, pDevice->T5_msg_size); 840 | if (!NT_SUCCESS(status)) { 841 | goto end; 842 | } 843 | 844 | count = msg_buf[0]; 845 | 846 | if (count == 0) 847 | goto end; 848 | 849 | if (count > pDevice->max_reportid) { 850 | count = pDevice->max_reportid; 851 | } 852 | 853 | ret = AtmelTPProcessMessage(pDevice, msg_buf + 1); 854 | if (ret < 0) { 855 | goto end; 856 | } 857 | 858 | num_left = count - 1; 859 | 860 | if (num_left) { 861 | ret = AtmelReadAndProcessMessages(pDevice, num_left); 862 | if (ret < 0) 863 | goto end; 864 | //else if (ret != num_left) 865 | /// DbgPrint("T44: Unexpected invalid message!\n"); 866 | } 867 | 868 | end: 869 | ExFreePoolWithTag(msg_buf, ATMELTP_POOL_TAG); 870 | return true; 871 | } 872 | 873 | bool AtmelTPDeviceRead(PATMELTP_CONTEXT pDevice) { 874 | uint8_t total_handled, num_handled; 875 | uint8_t count = pDevice->last_message_count; 876 | 877 | if (count < 1 || count > pDevice->max_reportid) 878 | count = 1; 879 | 880 | /* include final invalid message */ 881 | total_handled = AtmelReadAndProcessMessages(pDevice, count + 1); 882 | if (total_handled < 0) 883 | return false; 884 | else if (total_handled <= count) 885 | goto update_count; 886 | 887 | /* keep reading two msgs until one is invalid or reportid limit */ 888 | do { 889 | num_handled = AtmelReadAndProcessMessages(pDevice, 2); 890 | if (num_handled < 0) 891 | return false; 892 | 893 | total_handled += num_handled; 894 | 895 | if (num_handled < 2) 896 | break; 897 | } while (total_handled < pDevice->num_touchids); 898 | 899 | update_count: 900 | pDevice->last_message_count = total_handled; 901 | 902 | return true; 903 | } 904 | 905 | void AtmelTpProcessInput(PATMELTP_CONTEXT pDevice) { 906 | LARGE_INTEGER CurrentTime; 907 | 908 | KeQuerySystemTime(&CurrentTime); 909 | 910 | LARGE_INTEGER DIFF; 911 | 912 | DIFF.QuadPart = 0; 913 | 914 | if (pDevice->LastTime.QuadPart != 0) 915 | DIFF.QuadPart = (CurrentTime.QuadPart - pDevice->LastTime.QuadPart) / 1000; 916 | 917 | struct _ATMELTP_MULTITOUCH_REPORT report; 918 | report.ReportID = REPORTID_MTOUCH; 919 | 920 | pDevice->BUTTONPRESSED = pDevice->T19_buttonstate; 921 | 922 | pDevice->TIMEINT += (USHORT)DIFF.QuadPart; 923 | 924 | pDevice->LastTime = CurrentTime; 925 | 926 | BYTE count = 0, i = 0; 927 | while (count < 5 && i < 20) { 928 | if (pDevice->Flags[i] != 0) { 929 | report.Touch[count].ContactID = i; 930 | 931 | report.Touch[count].XValue = pDevice->XValue[i]; 932 | report.Touch[count].YValue = pDevice->YValue[i]; 933 | report.Touch[count].Pressure = 10; 934 | 935 | uint8_t flags = pDevice->Flags[i]; 936 | if (flags & MXT_T9_DETECT) { 937 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 938 | } 939 | else if (flags & MXT_T9_PRESS) { 940 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 941 | } 942 | else if (flags & MXT_T9_RELEASE) { 943 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT; 944 | pDevice->Flags[i] = 0; 945 | } 946 | else 947 | report.Touch[count].Status = 0; 948 | 949 | count++; 950 | } 951 | i++; 952 | } 953 | 954 | report.ScanTime = pDevice->TIMEINT; 955 | report.IsDepressed = pDevice->BUTTONPRESSED; 956 | 957 | report.ContactCount = count; 958 | 959 | size_t bytesWritten; 960 | AtmelTPProcessVendorReport(pDevice, &report, sizeof(report), &bytesWritten); 961 | } 962 | 963 | BOOLEAN OnInterruptIsr( 964 | WDFINTERRUPT Interrupt, 965 | ULONG MessageID) { 966 | UNREFERENCED_PARAMETER(MessageID); 967 | 968 | WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); 969 | PATMELTP_CONTEXT pDevice = GetDeviceContext(Device); 970 | 971 | if (!pDevice->TrackpadBooted) 972 | return false; 973 | if (!pDevice->ConnectInterrupt) 974 | return false; 975 | 976 | bool ret = true; 977 | 978 | if (pDevice->T44_address) 979 | ret = AtmelTPDeviceReadT44(pDevice); 980 | else 981 | ret = AtmelTPDeviceRead(pDevice); 982 | 983 | AtmelTpProcessInput(pDevice); 984 | 985 | return ret; 986 | } 987 | 988 | NTSTATUS 989 | AtmelTPEvtDeviceAdd( 990 | IN WDFDRIVER Driver, 991 | IN PWDFDEVICE_INIT DeviceInit 992 | ) 993 | { 994 | NTSTATUS status = STATUS_SUCCESS; 995 | WDF_IO_QUEUE_CONFIG queueConfig; 996 | WDF_OBJECT_ATTRIBUTES attributes; 997 | WDFDEVICE device; 998 | WDF_INTERRUPT_CONFIG interruptConfig; 999 | WDFQUEUE queue; 1000 | PATMELTP_CONTEXT devContext; 1001 | 1002 | UNREFERENCED_PARAMETER(Driver); 1003 | 1004 | PAGED_CODE(); 1005 | 1006 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_PNP, 1007 | "AtmelTPEvtDeviceAdd called\n"); 1008 | 1009 | // 1010 | // Tell framework this is a filter driver. Filter drivers by default are 1011 | // not power policy owners. This works well for this driver because 1012 | // HIDclass driver is the power policy owner for HID minidrivers. 1013 | // 1014 | 1015 | WdfFdoInitSetFilter(DeviceInit); 1016 | 1017 | { 1018 | WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; 1019 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); 1020 | 1021 | pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; 1022 | pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; 1023 | pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; 1024 | pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; 1025 | 1026 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); 1027 | } 1028 | 1029 | // 1030 | // Setup the device context 1031 | // 1032 | 1033 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, ATMELTP_CONTEXT); 1034 | 1035 | // 1036 | // Create a framework device object.This call will in turn create 1037 | // a WDM device object, attach to the lower stack, and set the 1038 | // appropriate flags and attributes. 1039 | // 1040 | 1041 | status = WdfDeviceCreate(&DeviceInit, &attributes, &device); 1042 | 1043 | if (!NT_SUCCESS(status)) 1044 | { 1045 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1046 | "WdfDeviceCreate failed with status code 0x%x\n", status); 1047 | 1048 | return status; 1049 | } 1050 | 1051 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); 1052 | 1053 | queueConfig.EvtIoInternalDeviceControl = AtmelTPEvtInternalDeviceControl; 1054 | 1055 | status = WdfIoQueueCreate(device, 1056 | &queueConfig, 1057 | WDF_NO_OBJECT_ATTRIBUTES, 1058 | &queue 1059 | ); 1060 | 1061 | if (!NT_SUCCESS(status)) 1062 | { 1063 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1064 | "WdfIoQueueCreate failed 0x%x\n", status); 1065 | 1066 | return status; 1067 | } 1068 | 1069 | // 1070 | // Create manual I/O queue to take care of hid report read requests 1071 | // 1072 | 1073 | devContext = GetDeviceContext(device); 1074 | 1075 | devContext->TrackpadBooted = false; 1076 | devContext->FxDevice = device; 1077 | 1078 | WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); 1079 | 1080 | queueConfig.PowerManaged = WdfFalse; 1081 | 1082 | status = WdfIoQueueCreate(device, 1083 | &queueConfig, 1084 | WDF_NO_OBJECT_ATTRIBUTES, 1085 | &devContext->ReportQueue 1086 | ); 1087 | 1088 | if (!NT_SUCCESS(status)) 1089 | { 1090 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1091 | "WdfIoQueueCreate failed 0x%x\n", status); 1092 | 1093 | return status; 1094 | } 1095 | 1096 | // 1097 | // Create an interrupt object for hardware notifications 1098 | // 1099 | WDF_INTERRUPT_CONFIG_INIT( 1100 | &interruptConfig, 1101 | OnInterruptIsr, 1102 | NULL); 1103 | interruptConfig.PassiveHandling = TRUE; 1104 | 1105 | status = WdfInterruptCreate( 1106 | device, 1107 | &interruptConfig, 1108 | WDF_NO_OBJECT_ATTRIBUTES, 1109 | &devContext->Interrupt); 1110 | 1111 | if (!NT_SUCCESS(status)) 1112 | { 1113 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1114 | "Error creating WDF interrupt object - %!STATUS!", 1115 | status); 1116 | 1117 | return status; 1118 | } 1119 | 1120 | // 1121 | // Initialize DeviceMode 1122 | // 1123 | 1124 | devContext->DeviceMode = DEVICE_MODE_MOUSE; 1125 | 1126 | return status; 1127 | } 1128 | 1129 | VOID 1130 | AtmelTPEvtInternalDeviceControl( 1131 | IN WDFQUEUE Queue, 1132 | IN WDFREQUEST Request, 1133 | IN size_t OutputBufferLength, 1134 | IN size_t InputBufferLength, 1135 | IN ULONG IoControlCode 1136 | ) 1137 | { 1138 | NTSTATUS status = STATUS_SUCCESS; 1139 | WDFDEVICE device; 1140 | PATMELTP_CONTEXT devContext; 1141 | BOOLEAN completeRequest = TRUE; 1142 | 1143 | UNREFERENCED_PARAMETER(OutputBufferLength); 1144 | UNREFERENCED_PARAMETER(InputBufferLength); 1145 | 1146 | device = WdfIoQueueGetDevice(Queue); 1147 | devContext = GetDeviceContext(device); 1148 | 1149 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1150 | "%s, Queue:0x%p, Request:0x%p\n", 1151 | DbgHidInternalIoctlString(IoControlCode), 1152 | Queue, 1153 | Request 1154 | ); 1155 | 1156 | // 1157 | // Please note that HIDCLASS provides the buffer in the Irp->UserBuffer 1158 | // field irrespective of the ioctl buffer type. However, framework is very 1159 | // strict about type checking. You cannot get Irp->UserBuffer by using 1160 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1161 | // internal ioctl. So depending on the ioctl code, we will either 1162 | // use retreive function or escape to WDM to get the UserBuffer. 1163 | // 1164 | 1165 | switch (IoControlCode) 1166 | { 1167 | 1168 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 1169 | // 1170 | // Retrieves the device's HID descriptor. 1171 | // 1172 | status = AtmelTPGetHidDescriptor(device, Request); 1173 | break; 1174 | 1175 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 1176 | // 1177 | //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure. 1178 | // 1179 | status = AtmelTPGetDeviceAttributes(Request); 1180 | break; 1181 | 1182 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 1183 | // 1184 | //Obtains the report descriptor for the HID device. 1185 | // 1186 | status = AtmelTPGetReportDescriptor(device, Request, &completeRequest); 1187 | break; 1188 | 1189 | case IOCTL_HID_GET_STRING: 1190 | // 1191 | // Requests that the HID minidriver retrieve a human-readable string 1192 | // for either the manufacturer ID, the product ID, or the serial number 1193 | // from the string descriptor of the device. The minidriver must send 1194 | // a Get String Descriptor request to the device, in order to retrieve 1195 | // the string descriptor, then it must extract the string at the 1196 | // appropriate index from the string descriptor and return it in the 1197 | // output buffer indicated by the IRP. Before sending the Get String 1198 | // Descriptor request, the minidriver must retrieve the appropriate 1199 | // index for the manufacturer ID, the product ID or the serial number 1200 | // from the device extension of a top level collection associated with 1201 | // the device. 1202 | // 1203 | status = AtmelTPGetString(Request); 1204 | break; 1205 | 1206 | case IOCTL_HID_WRITE_REPORT: 1207 | case IOCTL_HID_SET_OUTPUT_REPORT: 1208 | // 1209 | //Transmits a class driver-supplied report to the device. 1210 | // 1211 | status = AtmelTPWriteReport(devContext, Request); 1212 | break; 1213 | 1214 | case IOCTL_HID_READ_REPORT: 1215 | case IOCTL_HID_GET_INPUT_REPORT: 1216 | // 1217 | // Returns a report from the device into a class driver-supplied buffer. 1218 | // 1219 | status = AtmelTPReadReport(devContext, Request, &completeRequest); 1220 | break; 1221 | 1222 | case IOCTL_HID_SET_FEATURE: 1223 | // 1224 | // This sends a HID class feature report to a top-level collection of 1225 | // a HID class device. 1226 | // 1227 | status = AtmelTPSetFeature(devContext, Request, &completeRequest); 1228 | break; 1229 | 1230 | case IOCTL_HID_GET_FEATURE: 1231 | // 1232 | // returns a feature report associated with a top-level collection 1233 | // 1234 | status = AtmelTPGetFeature(devContext, Request, &completeRequest); 1235 | break; 1236 | 1237 | case IOCTL_HID_ACTIVATE_DEVICE: 1238 | // 1239 | // Makes the device ready for I/O operations. 1240 | // 1241 | case IOCTL_HID_DEACTIVATE_DEVICE: 1242 | // 1243 | // Causes the device to cease operations and terminate all outstanding 1244 | // I/O requests. 1245 | // 1246 | default: 1247 | status = STATUS_NOT_SUPPORTED; 1248 | break; 1249 | } 1250 | 1251 | if (completeRequest) 1252 | { 1253 | WdfRequestComplete(Request, status); 1254 | 1255 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1256 | "%s completed, Queue:0x%p, Request:0x%p\n", 1257 | DbgHidInternalIoctlString(IoControlCode), 1258 | Queue, 1259 | Request 1260 | ); 1261 | } 1262 | else 1263 | { 1264 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1265 | "%s deferred, Queue:0x%p, Request:0x%p\n", 1266 | DbgHidInternalIoctlString(IoControlCode), 1267 | Queue, 1268 | Request 1269 | ); 1270 | } 1271 | 1272 | return; 1273 | } 1274 | 1275 | NTSTATUS 1276 | AtmelTPGetHidDescriptor( 1277 | IN WDFDEVICE Device, 1278 | IN WDFREQUEST Request 1279 | ) 1280 | { 1281 | NTSTATUS status = STATUS_SUCCESS; 1282 | size_t bytesToCopy = 0; 1283 | WDFMEMORY memory; 1284 | 1285 | UNREFERENCED_PARAMETER(Device); 1286 | 1287 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1288 | "AtmelTPGetHidDescriptor Entry\n"); 1289 | 1290 | // 1291 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1292 | // will correctly retrieve buffer from Irp->UserBuffer. 1293 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1294 | // field irrespective of the ioctl buffer type. However, framework is very 1295 | // strict about type checking. You cannot get Irp->UserBuffer by using 1296 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1297 | // internal ioctl. 1298 | // 1299 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 1300 | 1301 | if (!NT_SUCCESS(status)) 1302 | { 1303 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1304 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 1305 | 1306 | return status; 1307 | } 1308 | 1309 | // 1310 | // Use hardcoded "HID Descriptor" 1311 | // 1312 | bytesToCopy = DefaultHidDescriptor.bLength; 1313 | 1314 | if (bytesToCopy == 0) 1315 | { 1316 | status = STATUS_INVALID_DEVICE_STATE; 1317 | 1318 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1319 | "DefaultHidDescriptor is zero, 0x%x\n", status); 1320 | 1321 | return status; 1322 | } 1323 | 1324 | status = WdfMemoryCopyFromBuffer(memory, 1325 | 0, // Offset 1326 | (PVOID)&DefaultHidDescriptor, 1327 | bytesToCopy); 1328 | 1329 | if (!NT_SUCCESS(status)) 1330 | { 1331 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1332 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1333 | 1334 | return status; 1335 | } 1336 | 1337 | // 1338 | // Report how many bytes were copied 1339 | // 1340 | WdfRequestSetInformation(Request, bytesToCopy); 1341 | 1342 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1343 | "AtmelTPGetHidDescriptor Exit = 0x%x\n", status); 1344 | 1345 | return status; 1346 | } 1347 | 1348 | NTSTATUS 1349 | AtmelTPGetReportDescriptor( 1350 | IN WDFDEVICE Device, 1351 | IN WDFREQUEST Request, 1352 | OUT BOOLEAN* CompleteRequest 1353 | ) 1354 | { 1355 | UNREFERENCED_PARAMETER(CompleteRequest); 1356 | 1357 | NTSTATUS status = STATUS_SUCCESS; 1358 | ULONG_PTR bytesToCopy; 1359 | WDFMEMORY memory; 1360 | 1361 | PATMELTP_CONTEXT devContext = GetDeviceContext(Device); 1362 | 1363 | UNREFERENCED_PARAMETER(Device); 1364 | 1365 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1366 | "AtmelTPGetReportDescriptor Entry\n"); 1367 | 1368 | #define MT_TOUCH_COLLECTION \ 1369 | MT_TOUCH_COLLECTION0 \ 1370 | 0x26, devContext->max_x_hid[0], devContext->max_x_hid[1], /* LOGICAL_MAXIMUM (WIDTH) */ \ 1371 | 0x46, devContext->phy_x_hid[0], devContext->phy_x_hid[1], /* PHYSICAL_MAXIMUM (WIDTH) */ \ 1372 | MT_TOUCH_COLLECTION1 \ 1373 | 0x26, devContext->max_y_hid[0], devContext->max_y_hid[1], /* LOGICAL_MAXIMUM (HEIGHT) */ \ 1374 | 0x46, devContext->phy_y_hid[0], devContext->phy_y_hid[1], /* PHYSICAL_MAXIMUM (HEIGHT) */ \ 1375 | MT_TOUCH_COLLECTION2 1376 | 1377 | HID_REPORT_DESCRIPTOR ReportDescriptor[] = { 1378 | // 1379 | // Multitouch report starts here 1380 | // 1381 | //TOUCH PAD input TLC 1382 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 1383 | 0x09, 0x05, // USAGE (Touch Pad) 1384 | 0xa1, 0x01, // COLLECTION (Application) 1385 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch pad) 1386 | 0x09, 0x22, // USAGE (Finger) 1387 | MT_TOUCH_COLLECTION 1388 | MT_TOUCH_COLLECTION 1389 | MT_TOUCH_COLLECTION 1390 | MT_TOUCH_COLLECTION 1391 | MT_TOUCH_COLLECTION 1392 | USAGE_PAGES 1393 | }; 1394 | 1395 | // 1396 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1397 | // will correctly retrieve buffer from Irp->UserBuffer. 1398 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1399 | // field irrespective of the ioctl buffer type. However, framework is very 1400 | // strict about type checking. You cannot get Irp->UserBuffer by using 1401 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1402 | // internal ioctl. 1403 | // 1404 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 1405 | if (!NT_SUCCESS(status)) 1406 | { 1407 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1408 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 1409 | 1410 | return status; 1411 | } 1412 | 1413 | // 1414 | // Use hardcoded Report descriptor 1415 | // 1416 | bytesToCopy = DefaultHidDescriptor.DescriptorList[0].wReportLength; 1417 | 1418 | if (bytesToCopy == 0) 1419 | { 1420 | status = STATUS_INVALID_DEVICE_STATE; 1421 | 1422 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1423 | "DefaultHidDescriptor's reportLength is zero, 0x%x\n", status); 1424 | 1425 | return status; 1426 | } 1427 | 1428 | status = WdfMemoryCopyFromBuffer(memory, 1429 | 0, 1430 | (PVOID)ReportDescriptor, 1431 | bytesToCopy); 1432 | if (!NT_SUCCESS(status)) 1433 | { 1434 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1435 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1436 | 1437 | return status; 1438 | } 1439 | 1440 | // 1441 | // Report how many bytes were copied 1442 | // 1443 | WdfRequestSetInformation(Request, bytesToCopy); 1444 | 1445 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1446 | "AtmelTPGetReportDescriptor Exit = 0x%x\n", status); 1447 | 1448 | return status; 1449 | } 1450 | 1451 | 1452 | NTSTATUS 1453 | AtmelTPGetDeviceAttributes( 1454 | IN WDFREQUEST Request 1455 | ) 1456 | { 1457 | NTSTATUS status = STATUS_SUCCESS; 1458 | PHID_DEVICE_ATTRIBUTES deviceAttributes = NULL; 1459 | 1460 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1461 | "AtmelTPGetDeviceAttributes Entry\n"); 1462 | 1463 | // 1464 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1465 | // will correctly retrieve buffer from Irp->UserBuffer. 1466 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1467 | // field irrespective of the ioctl buffer type. However, framework is very 1468 | // strict about type checking. You cannot get Irp->UserBuffer by using 1469 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1470 | // internal ioctl. 1471 | // 1472 | status = WdfRequestRetrieveOutputBuffer(Request, 1473 | sizeof(HID_DEVICE_ATTRIBUTES), 1474 | &deviceAttributes, 1475 | NULL); 1476 | if (!NT_SUCCESS(status)) 1477 | { 1478 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1479 | "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); 1480 | 1481 | return status; 1482 | } 1483 | 1484 | // 1485 | // Set USB device descriptor 1486 | // 1487 | 1488 | deviceAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES); 1489 | deviceAttributes->VendorID = ATMELTP_VID; 1490 | deviceAttributes->ProductID = ATMELTP_PID; 1491 | deviceAttributes->VersionNumber = ATMELTP_VERSION; 1492 | 1493 | // 1494 | // Report how many bytes were copied 1495 | // 1496 | WdfRequestSetInformation(Request, sizeof(HID_DEVICE_ATTRIBUTES)); 1497 | 1498 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1499 | "AtmelTPGetDeviceAttributes Exit = 0x%x\n", status); 1500 | 1501 | return status; 1502 | } 1503 | 1504 | NTSTATUS 1505 | AtmelTPGetString( 1506 | IN WDFREQUEST Request 1507 | ) 1508 | { 1509 | 1510 | NTSTATUS status = STATUS_SUCCESS; 1511 | PWSTR pwstrID; 1512 | size_t lenID; 1513 | WDF_REQUEST_PARAMETERS params; 1514 | void *pStringBuffer = NULL; 1515 | 1516 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1517 | "AtmelTPGetString Entry\n"); 1518 | 1519 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1520 | WdfRequestGetParameters(Request, ¶ms); 1521 | 1522 | switch ((ULONG_PTR)params.Parameters.DeviceIoControl.Type3InputBuffer & 0xFFFF) 1523 | { 1524 | case HID_STRING_ID_IMANUFACTURER: 1525 | pwstrID = L"AtmelTP.\0"; 1526 | break; 1527 | 1528 | case HID_STRING_ID_IPRODUCT: 1529 | pwstrID = L"MaxTouch Touch Screen\0"; 1530 | break; 1531 | 1532 | case HID_STRING_ID_ISERIALNUMBER: 1533 | pwstrID = L"123123123\0"; 1534 | break; 1535 | 1536 | default: 1537 | pwstrID = NULL; 1538 | break; 1539 | } 1540 | 1541 | lenID = pwstrID ? wcslen(pwstrID)*sizeof(WCHAR) + sizeof(UNICODE_NULL) : 0; 1542 | 1543 | if (pwstrID == NULL) 1544 | { 1545 | 1546 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1547 | "AtmelTPGetString Invalid request type\n"); 1548 | 1549 | status = STATUS_INVALID_PARAMETER; 1550 | 1551 | return status; 1552 | } 1553 | 1554 | status = WdfRequestRetrieveOutputBuffer(Request, 1555 | lenID, 1556 | &pStringBuffer, 1557 | &lenID); 1558 | 1559 | if (!NT_SUCCESS(status)) 1560 | { 1561 | 1562 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1563 | "AtmelTPGetString WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1564 | 1565 | return status; 1566 | } 1567 | 1568 | RtlCopyMemory(pStringBuffer, pwstrID, lenID); 1569 | 1570 | WdfRequestSetInformation(Request, lenID); 1571 | 1572 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1573 | "AtmelTPGetString Exit = 0x%x\n", status); 1574 | 1575 | return status; 1576 | } 1577 | 1578 | NTSTATUS 1579 | AtmelTPWriteReport( 1580 | IN PATMELTP_CONTEXT DevContext, 1581 | IN WDFREQUEST Request 1582 | ) 1583 | { 1584 | UNREFERENCED_PARAMETER(DevContext); 1585 | 1586 | NTSTATUS status = STATUS_SUCCESS; 1587 | WDF_REQUEST_PARAMETERS params; 1588 | PHID_XFER_PACKET transferPacket = NULL; 1589 | 1590 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1591 | "AtmelTPWriteReport Entry\n"); 1592 | 1593 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1594 | WdfRequestGetParameters(Request, ¶ms); 1595 | 1596 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1597 | { 1598 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1599 | "AtmelTPWriteReport Xfer packet too small\n"); 1600 | 1601 | status = STATUS_BUFFER_TOO_SMALL; 1602 | } 1603 | else 1604 | { 1605 | 1606 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1607 | 1608 | if (transferPacket == NULL) 1609 | { 1610 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1611 | "AtmelTPWriteReport No xfer packet\n"); 1612 | 1613 | status = STATUS_INVALID_DEVICE_REQUEST; 1614 | } 1615 | else 1616 | { 1617 | // 1618 | // switch on the report id 1619 | // 1620 | 1621 | switch (transferPacket->reportId) 1622 | { 1623 | default: 1624 | 1625 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1626 | "AtmelTPWriteReport Unhandled report type %d\n", transferPacket->reportId); 1627 | 1628 | status = STATUS_INVALID_PARAMETER; 1629 | 1630 | break; 1631 | } 1632 | } 1633 | } 1634 | 1635 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1636 | "AtmelTPWriteReport Exit = 0x%x\n", status); 1637 | 1638 | return status; 1639 | 1640 | } 1641 | 1642 | NTSTATUS 1643 | AtmelTPProcessVendorReport( 1644 | IN PATMELTP_CONTEXT DevContext, 1645 | IN PVOID ReportBuffer, 1646 | IN ULONG ReportBufferLen, 1647 | OUT size_t* BytesWritten 1648 | ) 1649 | { 1650 | NTSTATUS status = STATUS_SUCCESS; 1651 | WDFREQUEST reqRead; 1652 | PVOID pReadReport = NULL; 1653 | size_t bytesReturned = 0; 1654 | 1655 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1656 | "AtmelTPProcessVendorReport Entry\n"); 1657 | 1658 | status = WdfIoQueueRetrieveNextRequest(DevContext->ReportQueue, 1659 | &reqRead); 1660 | 1661 | if (NT_SUCCESS(status)) 1662 | { 1663 | status = WdfRequestRetrieveOutputBuffer(reqRead, 1664 | ReportBufferLen, 1665 | &pReadReport, 1666 | &bytesReturned); 1667 | 1668 | if (NT_SUCCESS(status)) 1669 | { 1670 | // 1671 | // Copy ReportBuffer into read request 1672 | // 1673 | 1674 | if (bytesReturned > ReportBufferLen) 1675 | { 1676 | bytesReturned = ReportBufferLen; 1677 | } 1678 | 1679 | RtlCopyMemory(pReadReport, 1680 | ReportBuffer, 1681 | bytesReturned); 1682 | 1683 | // 1684 | // Complete read with the number of bytes returned as info 1685 | // 1686 | 1687 | WdfRequestCompleteWithInformation(reqRead, 1688 | status, 1689 | bytesReturned); 1690 | 1691 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1692 | "AtmelTPProcessVendorReport %d bytes returned\n", bytesReturned); 1693 | 1694 | // 1695 | // Return the number of bytes written for the write request completion 1696 | // 1697 | 1698 | *BytesWritten = bytesReturned; 1699 | 1700 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1701 | "%s completed, Queue:0x%p, Request:0x%p\n", 1702 | DbgHidInternalIoctlString(IOCTL_HID_READ_REPORT), 1703 | DevContext->ReportQueue, 1704 | reqRead); 1705 | } 1706 | else 1707 | { 1708 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1709 | "WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1710 | } 1711 | } 1712 | else 1713 | { 1714 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1715 | "WdfIoQueueRetrieveNextRequest failed Status 0x%x\n", status); 1716 | } 1717 | 1718 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1719 | "AtmelTPProcessVendorReport Exit = 0x%x\n", status); 1720 | 1721 | return status; 1722 | } 1723 | 1724 | NTSTATUS 1725 | AtmelTPReadReport( 1726 | IN PATMELTP_CONTEXT DevContext, 1727 | IN WDFREQUEST Request, 1728 | OUT BOOLEAN* CompleteRequest 1729 | ) 1730 | { 1731 | NTSTATUS status = STATUS_SUCCESS; 1732 | 1733 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1734 | "AtmelTPReadReport Entry\n"); 1735 | 1736 | // 1737 | // Forward this read request to our manual queue 1738 | // (in other words, we are going to defer this request 1739 | // until we have a corresponding write request to 1740 | // match it with) 1741 | // 1742 | 1743 | status = WdfRequestForwardToIoQueue(Request, DevContext->ReportQueue); 1744 | 1745 | if (!NT_SUCCESS(status)) 1746 | { 1747 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1748 | "WdfRequestForwardToIoQueue failed Status 0x%x\n", status); 1749 | } 1750 | else 1751 | { 1752 | *CompleteRequest = FALSE; 1753 | } 1754 | 1755 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1756 | "AtmelTPReadReport Exit = 0x%x\n", status); 1757 | 1758 | return status; 1759 | } 1760 | 1761 | NTSTATUS 1762 | AtmelTPSetFeature( 1763 | IN PATMELTP_CONTEXT DevContext, 1764 | IN WDFREQUEST Request, 1765 | OUT BOOLEAN* CompleteRequest 1766 | ) 1767 | { 1768 | UNREFERENCED_PARAMETER(CompleteRequest); 1769 | 1770 | NTSTATUS status = STATUS_SUCCESS; 1771 | WDF_REQUEST_PARAMETERS params; 1772 | PHID_XFER_PACKET transferPacket = NULL; 1773 | AtmelTPFeatureReport* pReport = NULL; 1774 | 1775 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1776 | "AtmelTPSetFeature Entry\n"); 1777 | 1778 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1779 | WdfRequestGetParameters(Request, ¶ms); 1780 | 1781 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1782 | { 1783 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1784 | "AtmelTPSetFeature Xfer packet too small\n"); 1785 | 1786 | status = STATUS_BUFFER_TOO_SMALL; 1787 | } 1788 | else 1789 | { 1790 | 1791 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1792 | 1793 | if (transferPacket == NULL) 1794 | { 1795 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1796 | "AtmelTPWriteReport No xfer packet\n"); 1797 | 1798 | status = STATUS_INVALID_DEVICE_REQUEST; 1799 | } 1800 | else 1801 | { 1802 | // 1803 | // switch on the report id 1804 | // 1805 | 1806 | switch (transferPacket->reportId) 1807 | { 1808 | case REPORTID_FEATURE: 1809 | 1810 | if (transferPacket->reportBufferLen == sizeof(AtmelTPFeatureReport)) 1811 | { 1812 | pReport = (AtmelTPFeatureReport*)transferPacket->reportBuffer; 1813 | 1814 | DevContext->DeviceMode = pReport->DeviceMode; 1815 | 1816 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1817 | "AtmelTPSetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1818 | } 1819 | else 1820 | { 1821 | status = STATUS_INVALID_PARAMETER; 1822 | 1823 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1824 | "AtmelTPSetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(AtmelTPFeatureReport) (%d)\n", 1825 | transferPacket->reportBufferLen, 1826 | sizeof(AtmelTPFeatureReport)); 1827 | } 1828 | 1829 | break; 1830 | 1831 | default: 1832 | 1833 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1834 | "AtmelTPSetFeature Unhandled report type %d\n", transferPacket->reportId); 1835 | 1836 | status = STATUS_INVALID_PARAMETER; 1837 | 1838 | break; 1839 | } 1840 | } 1841 | } 1842 | 1843 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1844 | "AtmelTPSetFeature Exit = 0x%x\n", status); 1845 | 1846 | return status; 1847 | } 1848 | 1849 | NTSTATUS 1850 | AtmelTPGetFeature( 1851 | IN PATMELTP_CONTEXT DevContext, 1852 | IN WDFREQUEST Request, 1853 | OUT BOOLEAN* CompleteRequest 1854 | ) 1855 | { 1856 | UNREFERENCED_PARAMETER(CompleteRequest); 1857 | 1858 | NTSTATUS status = STATUS_SUCCESS; 1859 | WDF_REQUEST_PARAMETERS params; 1860 | PHID_XFER_PACKET transferPacket = NULL; 1861 | 1862 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1863 | "AtmelTPGetFeature Entry\n"); 1864 | 1865 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1866 | WdfRequestGetParameters(Request, ¶ms); 1867 | 1868 | if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) 1869 | { 1870 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1871 | "AtmelTPGetFeature Xfer packet too small\n"); 1872 | 1873 | status = STATUS_BUFFER_TOO_SMALL; 1874 | } 1875 | else 1876 | { 1877 | 1878 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1879 | 1880 | if (transferPacket == NULL) 1881 | { 1882 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1883 | "AtmelTPGetFeature No xfer packet\n"); 1884 | 1885 | status = STATUS_INVALID_DEVICE_REQUEST; 1886 | } 1887 | else 1888 | { 1889 | // 1890 | // switch on the report id 1891 | // 1892 | 1893 | switch (transferPacket->reportId) 1894 | { 1895 | case REPORTID_MTOUCH: 1896 | { 1897 | 1898 | AtmelTPMaxCountReport* pReport = NULL; 1899 | 1900 | if (transferPacket->reportBufferLen >= sizeof(AtmelTPMaxCountReport)) 1901 | { 1902 | pReport = (AtmelTPMaxCountReport*)transferPacket->reportBuffer; 1903 | 1904 | pReport->MaximumCount = MULTI_MAX_COUNT; 1905 | 1906 | pReport->PadType = 0; 1907 | 1908 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1909 | "AtmelTPGetFeature MaximumCount = 0x%x\n", MULTI_MAX_COUNT); 1910 | } 1911 | else 1912 | { 1913 | status = STATUS_INVALID_PARAMETER; 1914 | 1915 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1916 | "AtmelTPGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(AtmelTPMaxCountReport) (%d)\n", 1917 | transferPacket->reportBufferLen, 1918 | sizeof(AtmelTPMaxCountReport)); 1919 | } 1920 | 1921 | break; 1922 | } 1923 | 1924 | case REPORTID_FEATURE: 1925 | { 1926 | 1927 | AtmelTPFeatureReport* pReport = NULL; 1928 | 1929 | if (transferPacket->reportBufferLen >= sizeof(AtmelTPFeatureReport)) 1930 | { 1931 | pReport = (AtmelTPFeatureReport*)transferPacket->reportBuffer; 1932 | 1933 | pReport->DeviceMode = DevContext->DeviceMode; 1934 | 1935 | pReport->DeviceIdentifier = 0; 1936 | 1937 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1938 | "AtmelTPGetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1939 | } 1940 | else 1941 | { 1942 | status = STATUS_INVALID_PARAMETER; 1943 | 1944 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1945 | "AtmelTPGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(AtmelTPFeatureReport) (%d)\n", 1946 | transferPacket->reportBufferLen, 1947 | sizeof(AtmelTPFeatureReport)); 1948 | } 1949 | 1950 | break; 1951 | } 1952 | 1953 | case REPORTID_PTPHQA: 1954 | { 1955 | uint8_t PTPHQA_BLOB[] = { REPORTID_PTPHQA, 0xfc, 0x28, 0xfe, 0x84, 0x40, 0xcb, 0x9a, 0x87, 0x0d, 0xbe, 0x57, 0x3c, 0xb6, 0x70, 0x09, 0x88, 0x07,\ 1956 | 0x97, 0x2d, 0x2b, 0xe3, 0x38, 0x34, 0xb6, 0x6c, 0xed, 0xb0, 0xf7, 0xe5, 0x9c, 0xf6, 0xc2, 0x2e, 0x84,\ 1957 | 0x1b, 0xe8, 0xb4, 0x51, 0x78, 0x43, 0x1f, 0x28, 0x4b, 0x7c, 0x2d, 0x53, 0xaf, 0xfc, 0x47, 0x70, 0x1b,\ 1958 | 0x59, 0x6f, 0x74, 0x43, 0xc4, 0xf3, 0x47, 0x18, 0x53, 0x1a, 0xa2, 0xa1, 0x71, 0xc7, 0x95, 0x0e, 0x31,\ 1959 | 0x55, 0x21, 0xd3, 0xb5, 0x1e, 0xe9, 0x0c, 0xba, 0xec, 0xb8, 0x89, 0x19, 0x3e, 0xb3, 0xaf, 0x75, 0x81,\ 1960 | 0x9d, 0x53, 0xb9, 0x41, 0x57, 0xf4, 0x6d, 0x39, 0x25, 0x29, 0x7c, 0x87, 0xd9, 0xb4, 0x98, 0x45, 0x7d,\ 1961 | 0xa7, 0x26, 0x9c, 0x65, 0x3b, 0x85, 0x68, 0x89, 0xd7, 0x3b, 0xbd, 0xff, 0x14, 0x67, 0xf2, 0x2b, 0xf0,\ 1962 | 0x2a, 0x41, 0x54, 0xf0, 0xfd, 0x2c, 0x66, 0x7c, 0xf8, 0xc0, 0x8f, 0x33, 0x13, 0x03, 0xf1, 0xd3, 0xc1, 0x0b,\ 1963 | 0x89, 0xd9, 0x1b, 0x62, 0xcd, 0x51, 0xb7, 0x80, 0xb8, 0xaf, 0x3a, 0x10, 0xc1, 0x8a, 0x5b, 0xe8, 0x8a,\ 1964 | 0x56, 0xf0, 0x8c, 0xaa, 0xfa, 0x35, 0xe9, 0x42, 0xc4, 0xd8, 0x55, 0xc3, 0x38, 0xcc, 0x2b, 0x53, 0x5c,\ 1965 | 0x69, 0x52, 0xd5, 0xc8, 0x73, 0x02, 0x38, 0x7c, 0x73, 0xb6, 0x41, 0xe7, 0xff, 0x05, 0xd8, 0x2b, 0x79,\ 1966 | 0x9a, 0xe2, 0x34, 0x60, 0x8f, 0xa3, 0x32, 0x1f, 0x09, 0x78, 0x62, 0xbc, 0x80, 0xe3, 0x0f, 0xbd, 0x65,\ 1967 | 0x20, 0x08, 0x13, 0xc1, 0xe2, 0xee, 0x53, 0x2d, 0x86, 0x7e, 0xa7, 0x5a, 0xc5, 0xd3, 0x7d, 0x98, 0xbe,\ 1968 | 0x31, 0x48, 0x1f, 0xfb, 0xda, 0xaf, 0xa2, 0xa8, 0x6a, 0x89, 0xd6, 0xbf, 0xf2, 0xd3, 0x32, 0x2a, 0x9a,\ 1969 | 0xe4, 0xcf, 0x17, 0xb7, 0xb8, 0xf4, 0xe1, 0x33, 0x08, 0x24, 0x8b, 0xc4, 0x43, 0xa5, 0xe5, 0x24, 0xc2 }; 1970 | if (transferPacket->reportBufferLen >= sizeof(PTPHQA_BLOB)) 1971 | { 1972 | uint8_t *blobBuffer = (uint8_t*)transferPacket->reportBuffer; 1973 | for (int i = 0; i < sizeof(PTPHQA_BLOB); i++) { 1974 | blobBuffer[i] = PTPHQA_BLOB[i]; 1975 | } 1976 | AtmelTPPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1977 | "AtmelTPGetFeature PHPHQA\n"); 1978 | } 1979 | else 1980 | { 1981 | status = STATUS_INVALID_PARAMETER; 1982 | 1983 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1984 | "AtmelTPGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(PTPHEQ_BLOB) (%d)\n", 1985 | transferPacket->reportBufferLen, 1986 | sizeof(AtmelTPFeatureReport)); 1987 | } 1988 | break; 1989 | } 1990 | 1991 | default: 1992 | 1993 | AtmelTPPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1994 | "AtmelTPGetFeature Unhandled report type %d\n", transferPacket->reportId); 1995 | 1996 | status = STATUS_INVALID_PARAMETER; 1997 | 1998 | break; 1999 | } 2000 | } 2001 | } 2002 | 2003 | AtmelTPPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 2004 | "AtmelTPGetFeature Exit = 0x%x\n", status); 2005 | 2006 | return status; 2007 | } 2008 | 2009 | PCHAR 2010 | DbgHidInternalIoctlString( 2011 | IN ULONG IoControlCode 2012 | ) 2013 | { 2014 | switch (IoControlCode) 2015 | { 2016 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 2017 | return "IOCTL_HID_GET_DEVICE_DESCRIPTOR"; 2018 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 2019 | return "IOCTL_HID_GET_REPORT_DESCRIPTOR"; 2020 | case IOCTL_HID_READ_REPORT: 2021 | return "IOCTL_HID_READ_REPORT"; 2022 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 2023 | return "IOCTL_HID_GET_DEVICE_ATTRIBUTES"; 2024 | case IOCTL_HID_WRITE_REPORT: 2025 | return "IOCTL_HID_WRITE_REPORT"; 2026 | case IOCTL_HID_SET_FEATURE: 2027 | return "IOCTL_HID_SET_FEATURE"; 2028 | case IOCTL_HID_GET_FEATURE: 2029 | return "IOCTL_HID_GET_FEATURE"; 2030 | case IOCTL_HID_GET_STRING: 2031 | return "IOCTL_HID_GET_STRING"; 2032 | case IOCTL_HID_ACTIVATE_DEVICE: 2033 | return "IOCTL_HID_ACTIVATE_DEVICE"; 2034 | case IOCTL_HID_DEACTIVATE_DEVICE: 2035 | return "IOCTL_HID_DEACTIVATE_DEVICE"; 2036 | case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: 2037 | return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST"; 2038 | case IOCTL_HID_SET_OUTPUT_REPORT: 2039 | return "IOCTL_HID_SET_OUTPUT_REPORT"; 2040 | case IOCTL_HID_GET_INPUT_REPORT: 2041 | return "IOCTL_HID_GET_INPUT_REPORT"; 2042 | default: 2043 | return "Unknown IOCTL"; 2044 | } 2045 | } 2046 | --------------------------------------------------------------------------------