├── crostouchpad ├── stdint.h ├── spb.h ├── trace.h ├── hidcommon.h ├── crostouchpad.vcxproj.user ├── crostouchpad.vcxproj.filters ├── crostouchpad.inf ├── cyapa.h ├── spb.c ├── driver.h ├── crostouchpad.vcxproj └── cyapa.c ├── crostouchpad Package ├── crostouchpad Package.vcxproj.user ├── crostouchpad Package.vcxproj.filters └── crostouchpad Package.vcxproj ├── LICENSE.txt ├── .gitignore └── crostouchpad4.sln /crostouchpad/stdint.h: -------------------------------------------------------------------------------- 1 | typedef signed char int8_t; 2 | typedef signed short int16_t; 3 | typedef signed int int32_t; 4 | typedef unsigned char uint8_t; 5 | typedef unsigned short uint16_t; 6 | typedef unsigned int uint32_t; -------------------------------------------------------------------------------- /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/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 | VOID 51 | SpbTargetDeinitialize( 52 | IN WDFDEVICE FxDevice, 53 | IN SPB_CONTEXT *SpbContext 54 | ); 55 | 56 | NTSTATUS 57 | SpbTargetInitialize( 58 | IN WDFDEVICE FxDevice, 59 | IN SPB_CONTEXT *SpbContext 60 | ); 61 | 62 | NTSTATUS 63 | SpbWriteDataSynchronously( 64 | IN SPB_CONTEXT *SpbContext, 65 | IN UCHAR Address, 66 | IN PVOID Data, 67 | IN ULONG Length 68 | ); -------------------------------------------------------------------------------- /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/hidcommon.h: -------------------------------------------------------------------------------- 1 | #if !defined(_CYAPA_COMMON_H_) 2 | #define _CYAPA_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 CYAPA_PID 0xBACC 10 | #define CYAPA_VID 0x00FF 11 | #define CYAPA_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 _CYAPA_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 | } CyapaMultiTouchReport; 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 _CYAPA_FEATURE_REPORT 75 | { 76 | 77 | BYTE ReportID; 78 | 79 | BYTE DeviceMode; 80 | 81 | BYTE DeviceIdentifier; 82 | 83 | } CyapaFeatureReport; 84 | 85 | typedef struct _CYAPA_MAXCOUNT_REPORT 86 | { 87 | 88 | BYTE ReportID; 89 | 90 | BYTE MaximumCount; 91 | 92 | BYTE PadType; 93 | 94 | } CyapaMaxCountReport; 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 | 50 | 51 | Driver Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /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 Cypress v3 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\CYAP0000 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 Cypress v3 Touchpad" 78 | CrosTouchpad.SVCDESC = "CrosTouchpad Service" 79 | -------------------------------------------------------------------------------- /crostouchpad/cyapa.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 | #include "stdint.h" 36 | 37 | #ifndef __packed 38 | #define __packed( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) 39 | #endif 40 | 41 | #ifndef _SYS_DEV_SMBUS_CYAPA_CYAPA_H_ 42 | #define _SYS_DEV_SMBUS_CYAPA_CYAPA_H_ 43 | 44 | #define CYAPA_MAX_MT 5 45 | 46 | /* 47 | * Boot-time registers. This is the device map 48 | * if (stat & CYAPA_STAT_RUNNING) is 0. 49 | */ 50 | __packed(struct cyapa_boot_regs{ 51 | uint8_t stat; /* CYAPA_STAT_xxx */ 52 | uint8_t boot; /* CYAPA_BOOT_xxx */ 53 | uint8_t error; 54 | }); 55 | 56 | #define CYAPA_BOOT_BUSY 0x80 57 | #define CYAPA_BOOT_RUNNING 0x10 58 | #define CYAPA_BOOT_DATA_VALID 0x08 59 | #define CYAPA_BOOT_CSUM_VALID 0x01 60 | 61 | #define CYAPA_ERROR_INVALID 0x80 62 | #define CYAPA_ERROR_INVALID_KEY 0x40 63 | #define CYAPA_ERROR_BOOTLOADER 0x20 64 | #define CYAPA_ERROR_CMD_CSUM 0x10 65 | #define CYAPA_ERROR_FLASH_PROT 0x08 66 | #define CYAPA_ERROR_FLASH_CSUM 0x04 67 | 68 | /* 69 | * Gen3 Operational Device Status Register 70 | * 71 | * bit 7: Valid interrupt source 72 | * bit 6 - 4: Reserved 73 | * bit 3 - 2: Power status 74 | * bit 1 - 0: Device status 75 | */ 76 | #define REG_OP_STATUS 0x00 77 | #define OP_STATUS_SRC 0x80 78 | #define OP_STATUS_POWER 0x0c 79 | #define OP_STATUS_DEV 0x03 80 | #define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) 81 | 82 | /* 83 | * Operational Finger Count/Button Flags Register 84 | * 85 | * bit 7 - 4: Number of touched finger 86 | * bit 3: Valid data 87 | * bit 2: Middle Physical Button 88 | * bit 1: Right Physical Button 89 | * bit 0: Left physical Button 90 | */ 91 | #define REG_OP_DATA1 0x01 92 | #define OP_DATA_VALID 0x08 93 | #define OP_DATA_MIDDLE_BTN 0x04 94 | #define OP_DATA_RIGHT_BTN 0x02 95 | #define OP_DATA_LEFT_BTN 0x01 96 | #define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ 97 | OP_DATA_LEFT_BTN) 98 | 99 | __packed(struct cyapa_regs{ 100 | uint8_t stat; 101 | uint8_t fngr; 102 | 103 | struct { 104 | uint8_t xy_high; /* 7:4 high 4 bits of x */ 105 | uint8_t x_low; /* 3:0 high 4 bits of y */ 106 | uint8_t y_low; 107 | uint8_t pressure; 108 | uint8_t id; /* 1-15 incremented each touch */ 109 | } touch[CYAPA_MAX_MT]; 110 | }); 111 | 112 | __packed(struct cyapa_cap{ 113 | uint8_t prod_ida[5]; /* 0x00 - 0x04 */ 114 | uint8_t prod_idb[6]; /* 0x05 - 0x0A */ 115 | uint8_t prod_idc[2]; /* 0x0B - 0x0C */ 116 | uint8_t reserved[6]; /* 0x0D - 0x12 */ 117 | uint8_t buttons; /* 0x13 */ 118 | uint8_t gen; /* 0x14, low 4 bits */ 119 | uint8_t max_abs_xy_high;/* 0x15 7:4 high x bits, 3:0 high y bits */ 120 | uint8_t max_abs_x_low; /* 0x16 */ 121 | uint8_t max_abs_y_low; /* 0x17 */ 122 | uint8_t phy_siz_xy_high;/* 0x18 7:4 high x bits, 3:0 high y bits */ 123 | uint8_t phy_siz_x_low; /* 0x19 */ 124 | uint8_t phy_siz_y_low; /* 0x1A */ 125 | }); 126 | 127 | #define CYAPA_STAT_RUNNING 0x80 128 | #define CYAPA_STAT_PWR_MASK 0x0C 129 | #define CYAPA_PWR_OFF 0x00 130 | #define CYAPA_PWR_IDLE 0x08 131 | #define CYAPA_PWR_ACTIVE 0x0C 132 | 133 | #define CYAPA_STAT_DEV_MASK 0x03 134 | #define CYAPA_DEV_NORMAL 0x03 135 | #define CYAPA_DEV_BUSY 0x01 136 | 137 | #define CYAPA_FNGR_DATA_VALID 0x08 138 | #define CYAPA_FNGR_MIDDLE 0x04 139 | #define CYAPA_FNGR_RIGHT 0x02 140 | #define CYAPA_FNGR_LEFT 0x01 141 | #define CYAPA_FNGR_NUMFINGERS(c) (((c) >> 4) & 0x0F) 142 | 143 | #define CYAPA_TOUCH_X(regs, i) ((((regs)->touch[i].xy_high << 4) & 0x0F00) | \ 144 | (regs)->touch[i].x_low) 145 | #define CYAPA_TOUCH_Y(regs, i) ((((regs)->touch[i].xy_high << 8) & 0x0F00) | \ 146 | (regs)->touch[i].y_low) 147 | #define CYAPA_TOUCH_P(regs, i) ((regs)->touch[i].pressure) 148 | 149 | #define CMD_BOOT_STATUS 0x00 /* only if in boot state */ 150 | #define CMD_DEV_STATUS 0x00 /* only if in operational state */ 151 | #define CMD_SOFT_RESET 0x28 152 | #define CMD_POWER_MODE 0x29 153 | #define CMD_POWER_MODE_OFF (0x00 << 2) 154 | #define CMD_POWER_MODE_IDLE (0x03 << 2) 155 | #define CMD_POWER_MODE_FULL (0x3f << 2) 156 | #define CMD_QUERY_CAPABILITIES 0x2A 157 | 158 | 159 | /*struct cyapa_softc { 160 | uint32_t x; 161 | uint32_t y; 162 | bool mousedown; 163 | int mousebutton; 164 | int lastnfingers; 165 | int lastid = -1; 166 | bool mousedownfromtap; 167 | int tick = 0; 168 | int tickssincelastclick = 0; 169 | 170 | int multitaskinggesturetick = 0; 171 | int multitaskingx; 172 | int multitaskingy; 173 | bool multitaskingdone; 174 | bool hasmoved; 175 | 176 | int scrollratelimit = 0; 177 | };*/ 178 | 179 | static int cyapa_minpressure = 16; 180 | static int cyapa_norm_freq = 100; 181 | 182 | #define ZSCALE 10 183 | #define SIMULATE_BUT4 0x0100 184 | #define SIMULATE_BUT5 0x0200 185 | #define SIMULATE_LOCK 0x8000 186 | 187 | #define MXT_T9_RELEASE (1 << 5) 188 | #define MXT_T9_PRESS (1 << 6) 189 | #define MXT_T9_DETECT (1 << 7) 190 | 191 | #endif -------------------------------------------------------------------------------- /.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/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 CyapaDebugLevel = 100; 26 | static ULONG CyapaDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 27 | 28 | NTSTATUS 29 | SpbDoWriteDataSynchronously( 30 | IN SPB_CONTEXT *SpbContext, 31 | IN UCHAR 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 + 1; 66 | memory = NULL; 67 | 68 | if (length > DEFAULT_SPB_BUFFER_SIZE) 69 | { 70 | status = WdfMemoryCreate( 71 | WDF_NO_OBJECT_ATTRIBUTES, 72 | NonPagedPool, 73 | CYAPA_POOL_TAG, 74 | length, 75 | &memory, 76 | (PVOID *)&buffer); 77 | 78 | if (!NT_SUCCESS(status)) 79 | { 80 | CyapaPrint( 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 | // 104 | // Transaction starts by specifying the address bytes 105 | // 106 | RtlCopyMemory(buffer, &Address, sizeof(Address)); 107 | 108 | // 109 | // Address is followed by the data payload 110 | // 111 | RtlCopyMemory((buffer + sizeof(Address)), Data, length - sizeof(Address)); 112 | 113 | status = WdfIoTargetSendWriteSynchronously( 114 | SpbContext->SpbIoTarget, 115 | NULL, 116 | &memoryDescriptor, 117 | NULL, 118 | NULL, 119 | NULL); 120 | 121 | if (!NT_SUCCESS(status)) 122 | { 123 | CyapaPrint( 124 | DEBUG_LEVEL_ERROR, 125 | DBG_IOCTL, 126 | "Error writing to Spb - %!STATUS!", 127 | status); 128 | goto exit; 129 | } 130 | 131 | exit: 132 | 133 | if (NULL != memory) 134 | { 135 | WdfObjectDelete(memory); 136 | } 137 | 138 | return status; 139 | } 140 | 141 | NTSTATUS 142 | SpbWriteDataSynchronously( 143 | IN SPB_CONTEXT *SpbContext, 144 | IN UCHAR Address, 145 | IN PVOID Data, 146 | IN ULONG Length 147 | ) 148 | /*++ 149 | 150 | Routine Description: 151 | 152 | This routine abstracts creating and sending an I/O 153 | request (I2C Write) to the Spb I/O target and utilizes 154 | a helper routine to do work inside of locked code. 155 | 156 | Arguments: 157 | 158 | SpbContext - Pointer to the current device context 159 | Address - The I2C register address to write to 160 | Data - A buffer to receive the data at at the above address 161 | Length - The amount of data to be read from the above address 162 | 163 | Return Value: 164 | 165 | NTSTATUS Status indicating success or failure 166 | 167 | --*/ 168 | { 169 | NTSTATUS status; 170 | 171 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 172 | 173 | status = SpbDoWriteDataSynchronously( 174 | SpbContext, 175 | Address, 176 | Data, 177 | Length); 178 | 179 | WdfWaitLockRelease(SpbContext->SpbLock); 180 | 181 | return status; 182 | } 183 | 184 | NTSTATUS 185 | SpbReadDataSynchronously( 186 | _In_ SPB_CONTEXT *SpbContext, 187 | _In_ UCHAR Address, 188 | _In_reads_bytes_(Length) PVOID Data, 189 | _In_ ULONG Length 190 | ) 191 | /*++ 192 | 193 | Routine Description: 194 | 195 | This helper routine abstracts creating and sending an I/O 196 | request (I2C Read) to the Spb I/O target. 197 | 198 | Arguments: 199 | 200 | SpbContext - Pointer to the current device context 201 | Address - The I2C register address to read from 202 | Data - A buffer to receive the data at at the above address 203 | Length - The amount of data to be read from the above address 204 | 205 | Return Value: 206 | 207 | NTSTATUS Status indicating success or failure 208 | 209 | --*/ 210 | { 211 | PUCHAR buffer; 212 | WDFMEMORY memory; 213 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 214 | NTSTATUS status; 215 | ULONG_PTR bytesRead; 216 | 217 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 218 | 219 | memory = NULL; 220 | status = STATUS_INVALID_PARAMETER; 221 | bytesRead = 0; 222 | 223 | // 224 | // Read transactions start by writing an address pointer 225 | // 226 | status = SpbDoWriteDataSynchronously( 227 | SpbContext, 228 | Address, 229 | NULL, 230 | 0); 231 | 232 | if (!NT_SUCCESS(status)) 233 | { 234 | CyapaPrint( 235 | DEBUG_LEVEL_ERROR, 236 | DBG_IOCTL, 237 | "Error setting address pointer for Spb read - %!STATUS!", 238 | status); 239 | goto exit; 240 | } 241 | 242 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 243 | { 244 | status = WdfMemoryCreate( 245 | WDF_NO_OBJECT_ATTRIBUTES, 246 | NonPagedPool, 247 | CYAPA_POOL_TAG, 248 | Length, 249 | &memory, 250 | (PVOID *)&buffer); 251 | 252 | if (!NT_SUCCESS(status)) 253 | { 254 | CyapaPrint( 255 | DEBUG_LEVEL_ERROR, 256 | DBG_IOCTL, 257 | "Error allocating memory for Spb read - %!STATUS!", 258 | status); 259 | goto exit; 260 | } 261 | 262 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 263 | &memoryDescriptor, 264 | memory, 265 | NULL); 266 | } 267 | else 268 | { 269 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 270 | 271 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 272 | &memoryDescriptor, 273 | (PVOID)buffer, 274 | Length); 275 | } 276 | 277 | 278 | status = WdfIoTargetSendReadSynchronously( 279 | SpbContext->SpbIoTarget, 280 | NULL, 281 | &memoryDescriptor, 282 | NULL, 283 | NULL, 284 | &bytesRead); 285 | 286 | if (!NT_SUCCESS(status) || 287 | bytesRead != Length) 288 | { 289 | CyapaPrint( 290 | DEBUG_LEVEL_ERROR, 291 | DBG_IOCTL, 292 | "Error reading from Spb - %!STATUS!", 293 | status); 294 | goto exit; 295 | } 296 | 297 | // 298 | // Copy back to the caller's buffer 299 | // 300 | RtlCopyMemory(Data, buffer, Length); 301 | 302 | exit: 303 | if (NULL != memory) 304 | { 305 | WdfObjectDelete(memory); 306 | } 307 | 308 | WdfWaitLockRelease(SpbContext->SpbLock); 309 | 310 | return status; 311 | } 312 | 313 | VOID 314 | SpbTargetDeinitialize( 315 | IN WDFDEVICE FxDevice, 316 | IN SPB_CONTEXT *SpbContext 317 | ) 318 | /*++ 319 | 320 | Routine Description: 321 | 322 | This helper routine is used to free any members added to the SPB_CONTEXT, 323 | note the SPB I/O target is parented to the device and will be 324 | closed and free'd when the device is removed. 325 | 326 | Arguments: 327 | 328 | FxDevice - Handle to the framework device object 329 | SpbContext - Pointer to the current device context 330 | 331 | Return Value: 332 | 333 | NTSTATUS Status indicating success or failure 334 | 335 | --*/ 336 | { 337 | UNREFERENCED_PARAMETER(FxDevice); 338 | UNREFERENCED_PARAMETER(SpbContext); 339 | 340 | // 341 | // Free any SPB_CONTEXT allocations here 342 | // 343 | if (SpbContext->SpbLock != NULL) 344 | { 345 | WdfObjectDelete(SpbContext->SpbLock); 346 | } 347 | 348 | if (SpbContext->ReadMemory != NULL) 349 | { 350 | WdfObjectDelete(SpbContext->ReadMemory); 351 | } 352 | 353 | if (SpbContext->WriteMemory != NULL) 354 | { 355 | WdfObjectDelete(SpbContext->WriteMemory); 356 | } 357 | } 358 | 359 | NTSTATUS 360 | SpbTargetInitialize( 361 | IN WDFDEVICE FxDevice, 362 | IN SPB_CONTEXT *SpbContext 363 | ) 364 | /*++ 365 | 366 | Routine Description: 367 | 368 | This helper routine opens the Spb I/O target and 369 | initializes a request object used for the lifetime 370 | of communication between this driver and Spb. 371 | 372 | Arguments: 373 | 374 | FxDevice - Handle to the framework device object 375 | SpbContext - Pointer to the current device context 376 | 377 | Return Value: 378 | 379 | NTSTATUS Status indicating success or failure 380 | 381 | --*/ 382 | { 383 | WDF_OBJECT_ATTRIBUTES objectAttributes; 384 | WDF_IO_TARGET_OPEN_PARAMS openParams; 385 | UNICODE_STRING spbDeviceName; 386 | WCHAR spbDeviceNameBuffer[RESOURCE_HUB_PATH_SIZE]; 387 | NTSTATUS status; 388 | 389 | WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); 390 | objectAttributes.ParentObject = FxDevice; 391 | 392 | status = WdfIoTargetCreate( 393 | FxDevice, 394 | &objectAttributes, 395 | &SpbContext->SpbIoTarget); 396 | 397 | if (!NT_SUCCESS(status)) 398 | { 399 | CyapaPrint( 400 | DEBUG_LEVEL_ERROR, 401 | DBG_IOCTL, 402 | "Error creating IoTarget object - %!STATUS!", 403 | status); 404 | 405 | WdfObjectDelete(SpbContext->SpbIoTarget); 406 | goto exit; 407 | } 408 | 409 | RtlInitEmptyUnicodeString( 410 | &spbDeviceName, 411 | spbDeviceNameBuffer, 412 | sizeof(spbDeviceNameBuffer)); 413 | 414 | status = RESOURCE_HUB_CREATE_PATH_FROM_ID( 415 | &spbDeviceName, 416 | SpbContext->I2cResHubId.LowPart, 417 | SpbContext->I2cResHubId.HighPart); 418 | 419 | if (!NT_SUCCESS(status)) 420 | { 421 | CyapaPrint( 422 | DEBUG_LEVEL_ERROR, 423 | DBG_IOCTL, 424 | "Error creating Spb resource hub path string - %!STATUS!", 425 | status); 426 | goto exit; 427 | } 428 | 429 | WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( 430 | &openParams, 431 | &spbDeviceName, 432 | (GENERIC_READ | GENERIC_WRITE)); 433 | 434 | openParams.ShareAccess = 0; 435 | openParams.CreateDisposition = FILE_OPEN; 436 | openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; 437 | 438 | status = WdfIoTargetOpen(SpbContext->SpbIoTarget, &openParams); 439 | 440 | if (!NT_SUCCESS(status)) 441 | { 442 | CyapaPrint( 443 | DEBUG_LEVEL_ERROR, 444 | DBG_IOCTL, 445 | "Error opening Spb target for communication - %!STATUS!", 446 | status); 447 | goto exit; 448 | } 449 | 450 | // 451 | // Allocate some fixed-size buffers from NonPagedPool for typical 452 | // Spb transaction sizes to avoid pool fragmentation in most cases 453 | // 454 | status = WdfMemoryCreate( 455 | WDF_NO_OBJECT_ATTRIBUTES, 456 | NonPagedPool, 457 | CYAPA_POOL_TAG, 458 | DEFAULT_SPB_BUFFER_SIZE, 459 | &SpbContext->WriteMemory, 460 | NULL); 461 | 462 | if (!NT_SUCCESS(status)) 463 | { 464 | CyapaPrint( 465 | DEBUG_LEVEL_ERROR, 466 | DBG_IOCTL, 467 | "Error allocating default memory for Spb write - %!STATUS!", 468 | status); 469 | goto exit; 470 | } 471 | 472 | status = WdfMemoryCreate( 473 | WDF_NO_OBJECT_ATTRIBUTES, 474 | NonPagedPool, 475 | CYAPA_POOL_TAG, 476 | DEFAULT_SPB_BUFFER_SIZE, 477 | &SpbContext->ReadMemory, 478 | NULL); 479 | 480 | if (!NT_SUCCESS(status)) 481 | { 482 | CyapaPrint( 483 | DEBUG_LEVEL_ERROR, 484 | DBG_IOCTL, 485 | "Error allocating default memory for Spb read - %!STATUS!", 486 | status); 487 | goto exit; 488 | } 489 | 490 | // 491 | // Allocate a waitlock to guard access to the default buffers 492 | // 493 | status = WdfWaitLockCreate( 494 | WDF_NO_OBJECT_ATTRIBUTES, 495 | &SpbContext->SpbLock); 496 | 497 | if (!NT_SUCCESS(status)) 498 | { 499 | CyapaPrint( 500 | DEBUG_LEVEL_ERROR, 501 | DBG_IOCTL, 502 | "Error creating Spb Waitlock - %!STATUS!", 503 | status); 504 | goto exit; 505 | } 506 | 507 | exit: 508 | 509 | if (!NT_SUCCESS(status)) 510 | { 511 | SpbTargetDeinitialize(FxDevice, SpbContext); 512 | } 513 | 514 | return status; 515 | } -------------------------------------------------------------------------------- /crostouchpad/driver.h: -------------------------------------------------------------------------------- 1 | #if !defined(_CYAPA_H_) 2 | #define _CYAPA_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 "cyapa.h" 22 | 23 | // 24 | // String definitions 25 | // 26 | 27 | #define DRIVERNAME "crostouchpad4.sys: " 28 | 29 | #define CYAPA_POOL_TAG (ULONG) 'payC' 30 | 31 | #define NTDEVICE_NAME_STRING L"\\Device\\CYAP0000" 32 | #define SYMBOLIC_NAME_STRING L"\\DosDevices\\CYAP0000" 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 | 0x25, 0x28, /* LOGICAL_MAXIMUM (40) */ \ 71 | 0x09, 0x30, /* USAGE (Tip Pressure) */ \ 72 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 73 | 0xc0, /* END_COLLECTION */ 74 | 75 | #define MT_REF_TOUCH_COLLECTION \ 76 | MT_TOUCH_COLLECTION0 \ 77 | 0x26, 0x66, 0x03, /* LOGICAL_MAXIMUM (870) */ \ 78 | 0x46, 0x8E, 0x03, /* PHYSICAL_MAXIMUM (910) */ \ 79 | MT_TOUCH_COLLECTION1 \ 80 | 0x26, 0xE0, 0x01, /* LOGICAL_MAXIMUM (480) */ \ 81 | 0x46, 0xFE, 0x01, /* PHYSICAL_MAXIMUM (550) */ \ 82 | MT_TOUCH_COLLECTION2 83 | 84 | #define USAGE_PAGES \ 85 | 0x55, 0x0C, /* UNIT_EXPONENT (-4) */ \ 86 | 0x66, 0x01, 0x10, /* UNIT (Seconds) */ \ 87 | 0x47, 0xff, 0xff, 0x00, 0x00, /* PHYSICAL_MAXIMUM (65535) */ \ 88 | 0x27, 0xff, 0xff, 0x00, 0x00, /* LOGICAL_MAXIMUM (65535) */ \ 89 | 0x75, 0x10, /* REPORT_SIZE (16) */ \ 90 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 91 | 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ \ 92 | 0x09, 0x56, /* USAGE (Scan Time) */ \ 93 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 94 | 0x09, 0x54, /* USAGE (Contact count) */ \ 95 | 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ \ 96 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 97 | 0x75, 0x08, /* REPORT_SIZE (8) */ \ 98 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 99 | 0x05, 0x09, /* USAGE_PAGE (Button) */ \ 100 | 0x09, 0x01, /* USAGE_(Button 1) */ \ 101 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ 102 | 0x75, 0x01, /* REPORT_SIZE (1) */ \ 103 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 104 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 105 | 0x95, 0x07, /* REPORT_COUNT (7) */ \ 106 | 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ 107 | 0x05, 0x0d, /* USAGE_PAGE (Digitizer) */ \ 108 | 0x85, REPORTID_MTOUCH, /* REPORT_ID (Feature) */ \ 109 | 0x09, 0x55, /* USAGE (Contact Count Maximum) */ \ 110 | 0x09, 0x59, /* USAGE (Pad TYpe) */ \ 111 | 0x75, 0x08, /* REPORT_SIZE (8) */ \ 112 | 0x95, 0x02, /* REPORT_COUNT (2) */ \ 113 | 0x25, 0x0f, /* LOGICAL_MAXIMUM (15) */ \ 114 | 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ \ 115 | 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ \ 116 | 0x85, REPORTID_PTPHQA, /* Report ID (Certification) */ \ 117 | 0x09, 0xC5, /* Usage (0xC5) */ \ 118 | 0x15, 0x00, /* Logical Minimum (0) */ \ 119 | 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ \ 120 | 0x75, 0x08, /* Report Size (8) */ \ 121 | 0x96, 0x00, 0x01, /* Report Count (256) */ \ 122 | 0xB1, 0x02, /* Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) */ \ 123 | 0xc0, /* END_COLLECTION */ \ 124 | \ 125 | /*MOUSE TLC */ \ 126 | 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ 127 | 0x09, 0x02, /* USAGE (Mouse) */ \ 128 | 0xa1, 0x01, /* COLLECTION (Application) */ \ 129 | 0x85, REPORTID_MOUSE, /* REPORT_ID (Mouse) */ \ 130 | 0x09, 0x01, /* USAGE (Pointer) */ \ 131 | 0xa1, 0x00, /* COLLECTION (Physical) */ \ 132 | 0x05, 0x09, /* USAGE_PAGE (Button) */ \ 133 | 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ \ 134 | 0x29, 0x02, /* USAGE_MAXIMUM (Button 2) */ \ 135 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ 136 | 0x75, 0x01, /* REPORT_SIZE (1) */ \ 137 | 0x95, 0x02, /* REPORT_COUNT (2) */ \ 138 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 139 | 0x95, 0x06, /* REPORT_COUNT (6) */ \ 140 | 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ \ 141 | 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ \ 142 | 0x09, 0x30, /* USAGE (X) */ \ 143 | 0x09, 0x31, /* USAGE (Y) */ \ 144 | 0x75, 0x10, /* REPORT_SIZE (16) */ \ 145 | 0x95, 0x02, /* REPORT_COUNT (2) */ \ 146 | 0x25, 0x0a, /* LOGICAL_MAXIMUM (10) */ \ 147 | 0x81, 0x06, /* INPUT (Data,Var,Rel) */ \ 148 | 0xc0, /* END_COLLECTION */ \ 149 | 0xc0, /*END_COLLECTION */ 150 | // 151 | // This is the default report descriptor for the Hid device provided 152 | // by the mini driver in response to IOCTL_HID_GET_REPORT_DESCRIPTOR. 153 | // 154 | 155 | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR; 156 | 157 | #ifdef DESCRIPTOR_DEF 158 | HID_REPORT_DESCRIPTOR DefaultReportDescriptor[] = { 159 | // 160 | // Multitouch report starts here 161 | // 162 | //TOUCH PAD input TLC 163 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 164 | 0x09, 0x05, // USAGE (Touch Pad) 165 | 0xa1, 0x01, // COLLECTION (Application) 166 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch pad) 167 | 0x09, 0x22, // USAGE (Finger) 168 | MT_REF_TOUCH_COLLECTION 169 | MT_REF_TOUCH_COLLECTION 170 | MT_REF_TOUCH_COLLECTION 171 | MT_REF_TOUCH_COLLECTION 172 | MT_REF_TOUCH_COLLECTION 173 | USAGE_PAGES 174 | }; 175 | 176 | 177 | // 178 | // This is the default HID descriptor returned by the mini driver 179 | // in response to IOCTL_HID_GET_DEVICE_DESCRIPTOR. The size 180 | // of report descriptor is currently the size of DefaultReportDescriptor. 181 | // 182 | 183 | CONST HID_DESCRIPTOR DefaultHidDescriptor = { 184 | 0x09, // length of HID descriptor 185 | 0x21, // descriptor type == HID 0x21 186 | 0x0100, // hid spec release 187 | 0x00, // country code == Not Specified 188 | 0x01, // number of HID class descriptors 189 | { 0x22, // descriptor type 190 | sizeof(DefaultReportDescriptor) } // total length of report descriptor 191 | }; 192 | #endif 193 | 194 | #define true 1 195 | #define false 0 196 | 197 | typedef struct _CYAPA_CONTEXT 198 | { 199 | 200 | // 201 | // Handle back to the WDFDEVICE 202 | // 203 | 204 | WDFDEVICE FxDevice; 205 | 206 | WDFQUEUE ReportQueue; 207 | 208 | BYTE DeviceMode; 209 | 210 | SPB_CONTEXT I2CContext; 211 | 212 | WDFINTERRUPT Interrupt; 213 | 214 | BOOLEAN ConnectInterrupt; 215 | 216 | BOOLEAN RegsSet; 217 | 218 | uint8_t Flags[15]; 219 | 220 | USHORT XValue[15]; 221 | 222 | USHORT YValue[15]; 223 | 224 | USHORT PValue[15]; 225 | 226 | BOOLEAN BUTTONPRESSED; 227 | 228 | USHORT TIMEINT; 229 | 230 | LARGE_INTEGER LastTime; 231 | 232 | uint16_t max_x; 233 | uint16_t max_y; 234 | 235 | uint8_t max_x_hid[2]; 236 | uint8_t max_y_hid[2]; 237 | 238 | uint16_t phy_x; 239 | uint16_t phy_y; 240 | 241 | uint8_t phy_x_hid[2]; 242 | uint8_t phy_y_hid[2]; 243 | 244 | WDFREQUEST lastRequest; 245 | 246 | } CYAPA_CONTEXT, *PCYAPA_CONTEXT; 247 | 248 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CYAPA_CONTEXT, GetDeviceContext) 249 | 250 | // 251 | // Function definitions 252 | // 253 | 254 | DRIVER_INITIALIZE DriverEntry; 255 | 256 | EVT_WDF_DRIVER_UNLOAD CyapaDriverUnload; 257 | 258 | EVT_WDF_DRIVER_DEVICE_ADD CyapaEvtDeviceAdd; 259 | 260 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL CyapaEvtInternalDeviceControl; 261 | 262 | NTSTATUS 263 | CyapaGetHidDescriptor( 264 | IN WDFDEVICE Device, 265 | IN WDFREQUEST Request 266 | ); 267 | 268 | NTSTATUS 269 | CyapaGetReportDescriptor( 270 | IN WDFDEVICE Device, 271 | IN WDFREQUEST Request, 272 | IN BOOLEAN Retried, 273 | OUT BOOLEAN* CompleteRequest 274 | ); 275 | 276 | NTSTATUS 277 | CyapaGetDeviceAttributes( 278 | IN WDFREQUEST Request 279 | ); 280 | 281 | NTSTATUS 282 | CyapaGetString( 283 | IN WDFREQUEST Request 284 | ); 285 | 286 | NTSTATUS 287 | CyapaWriteReport( 288 | IN PCYAPA_CONTEXT DevContext, 289 | IN WDFREQUEST Request 290 | ); 291 | 292 | NTSTATUS 293 | CyapaProcessVendorReport( 294 | IN PCYAPA_CONTEXT DevContext, 295 | IN PVOID ReportBuffer, 296 | IN ULONG ReportBufferLen, 297 | OUT size_t* BytesWritten 298 | ); 299 | 300 | NTSTATUS 301 | CyapaReadReport( 302 | IN PCYAPA_CONTEXT DevContext, 303 | IN WDFREQUEST Request, 304 | OUT BOOLEAN* CompleteRequest 305 | ); 306 | 307 | NTSTATUS 308 | CyapaSetFeature( 309 | IN PCYAPA_CONTEXT DevContext, 310 | IN WDFREQUEST Request, 311 | OUT BOOLEAN* CompleteRequest 312 | ); 313 | 314 | NTSTATUS 315 | CyapaGetFeature( 316 | IN PCYAPA_CONTEXT DevContext, 317 | IN WDFREQUEST Request, 318 | OUT BOOLEAN* CompleteRequest 319 | ); 320 | 321 | PCHAR 322 | DbgHidInternalIoctlString( 323 | IN ULONG IoControlCode 324 | ); 325 | 326 | // 327 | // Helper macros 328 | // 329 | 330 | #define DEBUG_LEVEL_ERROR 1 331 | #define DEBUG_LEVEL_INFO 2 332 | #define DEBUG_LEVEL_VERBOSE 3 333 | 334 | #define DBG_INIT 1 335 | #define DBG_PNP 2 336 | #define DBG_IOCTL 4 337 | 338 | #if 0 339 | #define CyapaPrint(dbglevel, dbgcatagory, fmt, ...) { \ 340 | if (CyapaDebugLevel >= dbglevel && \ 341 | (CyapaDebugCatagories && dbgcatagory)) \ 342 | { \ 343 | DbgPrint(DRIVERNAME); \ 344 | DbgPrint(fmt, __VA_ARGS__); \ 345 | } \ 346 | } 347 | #else 348 | #define CyapaPrint(dbglevel, fmt, ...) { \ 349 | } 350 | #endif 351 | 352 | #endif 353 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/cyapa.c: -------------------------------------------------------------------------------- 1 | #define DESCRIPTOR_DEF 2 | #include "driver.h" 3 | 4 | #define bool int 5 | 6 | static ULONG CyapaDebugLevel = 100; 7 | static ULONG CyapaDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 8 | 9 | static bool deviceLoaded = false; 10 | 11 | static int sqr(int num) { 12 | return num * num; 13 | } 14 | 15 | static int diffsig(int x, int y, int lastx, int lasty) { 16 | uint32_t distsq = sqr(x - lastx) + sqr(y - lasty); 17 | if (distsq < 4) 18 | return 0; 19 | return 1; 20 | } 21 | 22 | NTSTATUS 23 | DriverEntry( 24 | __in PDRIVER_OBJECT DriverObject, 25 | __in PUNICODE_STRING RegistryPath 26 | ) 27 | { 28 | NTSTATUS status = STATUS_SUCCESS; 29 | WDF_DRIVER_CONFIG config; 30 | WDF_OBJECT_ATTRIBUTES attributes; 31 | 32 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_INIT, 33 | "Driver Entry\n"); 34 | 35 | WDF_DRIVER_CONFIG_INIT(&config, CyapaEvtDeviceAdd); 36 | 37 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 38 | 39 | // 40 | // Create a framework driver object to represent our driver. 41 | // 42 | 43 | status = WdfDriverCreate(DriverObject, 44 | RegistryPath, 45 | &attributes, 46 | &config, 47 | WDF_NO_HANDLE 48 | ); 49 | 50 | if (!NT_SUCCESS(status)) 51 | { 52 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 53 | "WdfDriverCreate failed with status 0x%x\n", status); 54 | } 55 | 56 | return status; 57 | } 58 | 59 | NTSTATUS cyapa_set_power_mode(_In_ PCYAPA_CONTEXT pDevice, _In_ uint8_t power_mode) 60 | { 61 | NTSTATUS status; 62 | uint8_t ret = 0; 63 | uint8_t power; 64 | 65 | status = SpbReadDataSynchronously(&pDevice->I2CContext, CMD_POWER_MODE, &ret, 1); 66 | if (!NT_SUCCESS(status)) { 67 | return status; 68 | } 69 | if (ret < 0) 70 | return STATUS_INVALID_DEVICE_STATE; 71 | 72 | power = (ret & ~0xFC); 73 | power |= power_mode & 0xFc; 74 | 75 | status = SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_POWER_MODE, &power, 1); 76 | return status; 77 | } 78 | 79 | VOID 80 | CyapaBootWorkItem( 81 | IN WDFWORKITEM WorkItem 82 | ) 83 | { 84 | NTSTATUS status; 85 | WDFDEVICE Device = (WDFDEVICE)WdfWorkItemGetParentObject(WorkItem); 86 | PCYAPA_CONTEXT pDevice = GetDeviceContext(Device); 87 | 88 | struct cyapa_cap cap = { 0 }; 89 | status = SpbReadDataSynchronously(&pDevice->I2CContext, CMD_QUERY_CAPABILITIES, &cap, sizeof(cap)); 90 | if (!NT_SUCCESS(status)) { 91 | WdfObjectDelete(WorkItem); 92 | return; 93 | } 94 | if (strncmp((const char *)cap.prod_ida, "CYTRA", 5) != 0) { 95 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "[cyapainit] Product ID \"%5.5s\" mismatch\n", 96 | cap.prod_ida); 97 | status = SpbReadDataSynchronously(&pDevice->I2CContext, CMD_QUERY_CAPABILITIES, &cap, sizeof(cap)); 98 | if (!NT_SUCCESS(status)) { 99 | WdfObjectDelete(WorkItem); 100 | return; 101 | } 102 | } 103 | 104 | pDevice->max_x = ((cap.max_abs_xy_high << 4) & 0x0F00) | 105 | cap.max_abs_x_low; 106 | pDevice->max_y = ((cap.max_abs_xy_high << 8) & 0x0F00) | 107 | cap.max_abs_y_low; 108 | 109 | pDevice->phy_x = ((cap.phy_siz_xy_high << 4) & 0x0F00) | 110 | cap.phy_siz_x_low; 111 | pDevice->phy_y = ((cap.phy_siz_xy_high << 8) & 0x0F00) | 112 | cap.phy_siz_y_low; 113 | 114 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_PNP, "[cyapainit] %5.5s-%6.6s-%2.2s buttons=%c%c%c res=%dx%d\n", 115 | cap.prod_ida, cap.prod_idb, cap.prod_idc, 116 | ((cap.buttons & CYAPA_FNGR_LEFT) ? 'L' : '-'), 117 | ((cap.buttons & CYAPA_FNGR_MIDDLE) ? 'M' : '-'), 118 | ((cap.buttons & CYAPA_FNGR_RIGHT) ? 'R' : '-'), 119 | pDevice->max_x, 120 | pDevice->max_y); 121 | 122 | uint16_t max_x[] = { pDevice->max_x }; 123 | uint16_t max_y[] = { pDevice->max_y }; 124 | 125 | uint8_t *max_x8bit = (uint8_t *)max_x; 126 | uint8_t *max_y8bit = (uint8_t *)max_y; 127 | 128 | pDevice->max_x_hid[0] = max_x8bit[0]; 129 | pDevice->max_x_hid[1] = max_x8bit[1]; 130 | 131 | pDevice->max_y_hid[0] = max_y8bit[0]; 132 | pDevice->max_y_hid[1] = max_y8bit[1]; 133 | 134 | 135 | uint16_t phy_x[] = { pDevice->phy_x * 10 }; 136 | uint16_t phy_y[] = { pDevice->phy_y * 10 }; 137 | 138 | uint8_t *phy_x8bit = (uint8_t *)phy_x; 139 | uint8_t *phy_y8bit = (uint8_t *)phy_y; 140 | 141 | pDevice->phy_x_hid[0] = phy_x8bit[0]; 142 | pDevice->phy_x_hid[1] = phy_x8bit[1]; 143 | 144 | pDevice->phy_y_hid[0] = phy_y8bit[0]; 145 | pDevice->phy_y_hid[1] = phy_y8bit[1]; 146 | 147 | cyapa_set_power_mode(pDevice, CMD_POWER_MODE_FULL); 148 | 149 | pDevice->ConnectInterrupt = true; 150 | WdfObjectDelete(WorkItem); 151 | } 152 | 153 | void CyapaBootTimer(_In_ WDFTIMER hTimer) { 154 | WDFDEVICE Device = (WDFDEVICE)WdfTimerGetParentObject(hTimer); 155 | 156 | WDF_OBJECT_ATTRIBUTES attributes; 157 | WDF_WORKITEM_CONFIG workitemConfig; 158 | WDFWORKITEM hWorkItem; 159 | 160 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 161 | WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, CYAPA_CONTEXT); 162 | attributes.ParentObject = Device; 163 | WDF_WORKITEM_CONFIG_INIT(&workitemConfig, CyapaBootWorkItem); 164 | 165 | WdfWorkItemCreate(&workitemConfig, 166 | &attributes, 167 | &hWorkItem); 168 | 169 | WdfWorkItemEnqueue(hWorkItem); 170 | WdfTimerStop(hTimer, FALSE); 171 | } 172 | 173 | NTSTATUS BOOTTRACKPAD( 174 | _In_ PCYAPA_CONTEXT pDevice 175 | ) 176 | { 177 | NTSTATUS status; 178 | 179 | static char bl_exit[] = { 180 | 0x00, 0xff, 0xa5, 0x00, 0x01, 181 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; 182 | 183 | static char bl_deactivate[] = { 184 | 0x00, 0xff, 0x3b, 0x00, 0x01, 185 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; 186 | 187 | struct cyapa_boot_regs boot = { 0 }; 188 | 189 | status = SpbReadDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, &boot, sizeof(boot)); 190 | if (!NT_SUCCESS(status)) { 191 | return status; 192 | } 193 | 194 | if ((boot.stat & CYAPA_STAT_RUNNING) == 0) { 195 | if (boot.error & CYAPA_ERROR_BOOTLOADER) 196 | status = SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, bl_deactivate, sizeof(bl_deactivate)); 197 | else 198 | status = SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, bl_exit, sizeof(bl_exit)); 199 | 200 | if (!NT_SUCCESS(status)) { 201 | return status; 202 | } 203 | } 204 | 205 | WDF_TIMER_CONFIG timerConfig; 206 | WDFTIMER hTimer; 207 | WDF_OBJECT_ATTRIBUTES attributes; 208 | 209 | WDF_TIMER_CONFIG_INIT(&timerConfig, CyapaBootTimer); 210 | 211 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 212 | attributes.ParentObject = pDevice->FxDevice; 213 | status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); 214 | 215 | WdfTimerStart(hTimer, WDF_REL_TIMEOUT_IN_MS(75)); 216 | 217 | return status; 218 | } 219 | 220 | NTSTATUS 221 | OnPrepareHardware( 222 | _In_ WDFDEVICE FxDevice, 223 | _In_ WDFCMRESLIST FxResourcesRaw, 224 | _In_ WDFCMRESLIST FxResourcesTranslated 225 | ) 226 | /*++ 227 | 228 | Routine Description: 229 | 230 | This routine caches the SPB resource connection ID. 231 | 232 | Arguments: 233 | 234 | FxDevice - a handle to the framework device object 235 | FxResourcesRaw - list of translated hardware resources that 236 | the PnP manager has assigned to the device 237 | FxResourcesTranslated - list of raw hardware resources that 238 | the PnP manager has assigned to the device 239 | 240 | Return Value: 241 | 242 | Status 243 | 244 | --*/ 245 | { 246 | PCYAPA_CONTEXT pDevice = GetDeviceContext(FxDevice); 247 | BOOLEAN fSpbResourceFound = FALSE; 248 | NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; 249 | 250 | UNREFERENCED_PARAMETER(FxResourcesRaw); 251 | 252 | // 253 | // Parse the peripheral's resources. 254 | // 255 | 256 | ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); 257 | 258 | for (ULONG i = 0; i < resourceCount; i++) 259 | { 260 | PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 261 | UCHAR Class; 262 | UCHAR Type; 263 | 264 | pDescriptor = WdfCmResourceListGetDescriptor( 265 | FxResourcesTranslated, i); 266 | 267 | switch (pDescriptor->Type) 268 | { 269 | case CmResourceTypeConnection: 270 | // 271 | // Look for I2C or SPI resource and save connection ID. 272 | // 273 | Class = pDescriptor->u.Connection.Class; 274 | Type = pDescriptor->u.Connection.Type; 275 | if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && 276 | Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) 277 | { 278 | if (fSpbResourceFound == FALSE) 279 | { 280 | status = STATUS_SUCCESS; 281 | pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; 282 | pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; 283 | fSpbResourceFound = TRUE; 284 | } 285 | else 286 | { 287 | } 288 | } 289 | break; 290 | default: 291 | // 292 | // Ignoring all other resource types. 293 | // 294 | break; 295 | } 296 | } 297 | 298 | // 299 | // An SPB resource is required. 300 | // 301 | 302 | if (fSpbResourceFound == FALSE) 303 | { 304 | status = STATUS_NOT_FOUND; 305 | } 306 | 307 | status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); 308 | if (!NT_SUCCESS(status)) 309 | { 310 | return status; 311 | } 312 | 313 | struct cyapa_boot_regs boot = { 0 }; 314 | 315 | status = SpbReadDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, &boot, sizeof(boot)); 316 | if (!NT_SUCCESS(status)) { 317 | return status; 318 | } 319 | 320 | return status; 321 | } 322 | 323 | NTSTATUS 324 | OnReleaseHardware( 325 | _In_ WDFDEVICE FxDevice, 326 | _In_ WDFCMRESLIST FxResourcesTranslated 327 | ) 328 | /*++ 329 | 330 | Routine Description: 331 | 332 | Arguments: 333 | 334 | FxDevice - a handle to the framework device object 335 | FxResourcesTranslated - list of raw hardware resources that 336 | the PnP manager has assigned to the device 337 | 338 | Return Value: 339 | 340 | Status 341 | 342 | --*/ 343 | { 344 | PCYAPA_CONTEXT pDevice = GetDeviceContext(FxDevice); 345 | NTSTATUS status = STATUS_SUCCESS; 346 | 347 | UNREFERENCED_PARAMETER(FxResourcesTranslated); 348 | 349 | SpbTargetDeinitialize(FxDevice, &pDevice->I2CContext); 350 | 351 | return status; 352 | } 353 | 354 | NTSTATUS 355 | OnD0Entry( 356 | _In_ WDFDEVICE FxDevice, 357 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 358 | ) 359 | /*++ 360 | 361 | Routine Description: 362 | 363 | This routine allocates objects needed by the driver. 364 | 365 | Arguments: 366 | 367 | FxDevice - a handle to the framework device object 368 | FxPreviousState - previous power state 369 | 370 | Return Value: 371 | 372 | Status 373 | 374 | --*/ 375 | { 376 | UNREFERENCED_PARAMETER(FxPreviousState); 377 | 378 | PCYAPA_CONTEXT pDevice = GetDeviceContext(FxDevice); 379 | NTSTATUS status = STATUS_SUCCESS; 380 | 381 | for (int i = 0; i < 15; i++){ 382 | pDevice->Flags[i] = 0; 383 | } 384 | 385 | pDevice->RegsSet = false; 386 | 387 | BOOTTRACKPAD(pDevice); 388 | 389 | return status; 390 | } 391 | 392 | NTSTATUS 393 | OnD0Exit( 394 | _In_ WDFDEVICE FxDevice, 395 | _In_ WDF_POWER_DEVICE_STATE FxTargetState 396 | ) 397 | /*++ 398 | 399 | Routine Description: 400 | 401 | This routine destroys objects needed by the driver. 402 | 403 | Arguments: 404 | 405 | FxDevice - a handle to the framework device object 406 | FxTargetState - the target power state 407 | 408 | Return Value: 409 | 410 | Status 411 | 412 | --*/ 413 | { 414 | UNREFERENCED_PARAMETER(FxTargetState); 415 | 416 | PCYAPA_CONTEXT pDevice = GetDeviceContext(FxDevice); 417 | 418 | pDevice->ConnectInterrupt = false; 419 | 420 | return STATUS_SUCCESS; 421 | } 422 | 423 | BOOLEAN OnInterruptIsr( 424 | WDFINTERRUPT Interrupt, 425 | ULONG MessageID){ 426 | UNREFERENCED_PARAMETER(MessageID); 427 | 428 | WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); 429 | PCYAPA_CONTEXT pDevice = GetDeviceContext(Device); 430 | 431 | if (!pDevice->ConnectInterrupt) 432 | return false; 433 | 434 | LARGE_INTEGER CurrentTime; 435 | 436 | KeQuerySystemTime(&CurrentTime); 437 | 438 | LARGE_INTEGER DIFF; 439 | 440 | DIFF.QuadPart = 0; 441 | 442 | if (pDevice->LastTime.QuadPart != 0) 443 | DIFF.QuadPart = (CurrentTime.QuadPart - pDevice->LastTime.QuadPart) / 1000; 444 | 445 | struct cyapa_regs rawregs = { 0 }; 446 | if (!NT_SUCCESS(SpbReadDataSynchronously(&pDevice->I2CContext, 0, &rawregs, sizeof(rawregs)))) { 447 | return false; 448 | } 449 | struct cyapa_regs *regs = &rawregs; 450 | 451 | struct _CYAPA_MULTITOUCH_REPORT report; 452 | report.ReportID = REPORTID_MTOUCH; 453 | 454 | int nfingers; 455 | 456 | nfingers = CYAPA_FNGR_NUMFINGERS(regs->fngr); 457 | 458 | int x[15]; 459 | int y[15]; 460 | int p[15]; 461 | for (int i = 0; i < 15; i++) { 462 | x[i] = -1; 463 | y[i] = -1; 464 | p[i] = -1; 465 | } 466 | for (int i = 0; i < nfingers; i++) { 467 | int a = regs->touch[i].id; 468 | int rawx = CYAPA_TOUCH_X(regs, i); 469 | int rawy = CYAPA_TOUCH_Y(regs, i); 470 | int rawp = CYAPA_TOUCH_P(regs, i); 471 | x[a] = rawx; 472 | y[a] = rawy; 473 | p[a] = rawp; 474 | } 475 | for (int i = 0; i < 15; i++) { 476 | if (pDevice->Flags[i] == MXT_T9_DETECT && x[i] == -1) { 477 | pDevice->Flags[i] = MXT_T9_RELEASE; 478 | } 479 | if (x[i] != -1) { 480 | bool updateValues = false; 481 | 482 | if (pDevice->Flags[i] == 0 || pDevice->Flags[i] == MXT_T9_RELEASE) 483 | updateValues = true; 484 | 485 | pDevice->Flags[i] = MXT_T9_DETECT; 486 | 487 | if (diffsig(x[i], y[i], pDevice->XValue[i], pDevice->YValue[i]) == 1) 488 | updateValues = true; 489 | 490 | if (updateValues) { 491 | pDevice->XValue[i] = (USHORT)x[i]; 492 | pDevice->YValue[i] = (USHORT)y[i]; 493 | pDevice->PValue[i] = (USHORT)p[i]; 494 | } 495 | } 496 | } 497 | 498 | pDevice->BUTTONPRESSED = ((regs->fngr & CYAPA_FNGR_LEFT) != 0); 499 | 500 | pDevice->TIMEINT += (USHORT)DIFF.QuadPart; 501 | 502 | pDevice->LastTime = CurrentTime; 503 | 504 | BYTE count = 0, i = 0; 505 | while (count < 5 && i < 15) { 506 | if (pDevice->Flags[i] != 0) { 507 | report.Touch[count].ContactID = i; 508 | 509 | report.Touch[count].XValue = pDevice->XValue[i]; 510 | report.Touch[count].YValue = pDevice->YValue[i]; 511 | report.Touch[count].Pressure = pDevice->PValue[i]; 512 | 513 | uint8_t flags = pDevice->Flags[i]; 514 | if (flags & MXT_T9_DETECT) { 515 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 516 | } 517 | else if (flags & MXT_T9_PRESS) { 518 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 519 | } 520 | else if (flags & MXT_T9_RELEASE) { 521 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT; 522 | pDevice->Flags[i] = 0; 523 | } 524 | else 525 | report.Touch[count].Status = 0; 526 | 527 | count++; 528 | } 529 | i++; 530 | } 531 | 532 | report.ScanTime = pDevice->TIMEINT; 533 | report.IsDepressed = pDevice->BUTTONPRESSED; 534 | 535 | report.ContactCount = count; 536 | 537 | size_t bytesWritten; 538 | CyapaProcessVendorReport(pDevice, &report, sizeof(report), &bytesWritten); 539 | 540 | pDevice->RegsSet = true; 541 | return true; 542 | } 543 | 544 | NTSTATUS 545 | CyapaEvtDeviceAdd( 546 | IN WDFDRIVER Driver, 547 | IN PWDFDEVICE_INIT DeviceInit 548 | ) 549 | { 550 | NTSTATUS status = STATUS_SUCCESS; 551 | WDF_IO_QUEUE_CONFIG queueConfig; 552 | WDF_OBJECT_ATTRIBUTES attributes; 553 | WDFDEVICE device; 554 | WDF_INTERRUPT_CONFIG interruptConfig; 555 | WDFQUEUE queue; 556 | PCYAPA_CONTEXT devContext; 557 | 558 | UNREFERENCED_PARAMETER(Driver); 559 | 560 | PAGED_CODE(); 561 | 562 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_PNP, 563 | "CyapaEvtDeviceAdd called\n"); 564 | 565 | // 566 | // Tell framework this is a filter driver. Filter drivers by default are 567 | // not power policy owners. This works well for this driver because 568 | // HIDclass driver is the power policy owner for HID minidrivers. 569 | // 570 | 571 | WdfFdoInitSetFilter(DeviceInit); 572 | 573 | { 574 | WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; 575 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); 576 | 577 | pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; 578 | pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; 579 | pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; 580 | pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; 581 | 582 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); 583 | } 584 | 585 | // 586 | // Setup the device context 587 | // 588 | 589 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CYAPA_CONTEXT); 590 | 591 | // 592 | // Create a framework device object.This call will in turn create 593 | // a WDM device object, attach to the lower stack, and set the 594 | // appropriate flags and attributes. 595 | // 596 | 597 | status = WdfDeviceCreate(&DeviceInit, &attributes, &device); 598 | 599 | if (!NT_SUCCESS(status)) 600 | { 601 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 602 | "WdfDeviceCreate failed with status code 0x%x\n", status); 603 | 604 | return status; 605 | } 606 | 607 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); 608 | 609 | queueConfig.EvtIoInternalDeviceControl = CyapaEvtInternalDeviceControl; 610 | 611 | status = WdfIoQueueCreate(device, 612 | &queueConfig, 613 | WDF_NO_OBJECT_ATTRIBUTES, 614 | &queue 615 | ); 616 | 617 | if (!NT_SUCCESS(status)) 618 | { 619 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 620 | "WdfIoQueueCreate failed 0x%x\n", status); 621 | 622 | return status; 623 | } 624 | 625 | // 626 | // Create manual I/O queue to take care of hid report read requests 627 | // 628 | 629 | devContext = GetDeviceContext(device); 630 | 631 | devContext->FxDevice = device; 632 | devContext->ConnectInterrupt = false; 633 | 634 | WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); 635 | 636 | queueConfig.PowerManaged = WdfFalse; 637 | 638 | status = WdfIoQueueCreate(device, 639 | &queueConfig, 640 | WDF_NO_OBJECT_ATTRIBUTES, 641 | &devContext->ReportQueue 642 | ); 643 | 644 | if (!NT_SUCCESS(status)) 645 | { 646 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 647 | "WdfIoQueueCreate failed 0x%x\n", status); 648 | 649 | return status; 650 | } 651 | 652 | // 653 | // Create an interrupt object for hardware notifications 654 | // 655 | WDF_INTERRUPT_CONFIG_INIT( 656 | &interruptConfig, 657 | OnInterruptIsr, 658 | NULL); 659 | interruptConfig.PassiveHandling = TRUE; 660 | 661 | status = WdfInterruptCreate( 662 | device, 663 | &interruptConfig, 664 | WDF_NO_OBJECT_ATTRIBUTES, 665 | &devContext->Interrupt); 666 | 667 | if (!NT_SUCCESS(status)) 668 | { 669 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 670 | "Error creating WDF interrupt object - %!STATUS!", 671 | status); 672 | 673 | return status; 674 | } 675 | 676 | // 677 | // Initialize DeviceMode 678 | // 679 | 680 | devContext->DeviceMode = DEVICE_MODE_MOUSE; 681 | 682 | return status; 683 | } 684 | 685 | VOID 686 | CyapaEvtInternalDeviceControl( 687 | IN WDFQUEUE Queue, 688 | IN WDFREQUEST Request, 689 | IN size_t OutputBufferLength, 690 | IN size_t InputBufferLength, 691 | IN ULONG IoControlCode 692 | ) 693 | { 694 | NTSTATUS status = STATUS_SUCCESS; 695 | WDFDEVICE device; 696 | PCYAPA_CONTEXT devContext; 697 | BOOLEAN completeRequest = TRUE; 698 | 699 | UNREFERENCED_PARAMETER(OutputBufferLength); 700 | UNREFERENCED_PARAMETER(InputBufferLength); 701 | 702 | device = WdfIoQueueGetDevice(Queue); 703 | devContext = GetDeviceContext(device); 704 | 705 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 706 | "%s, Queue:0x%p, Request:0x%p\n", 707 | DbgHidInternalIoctlString(IoControlCode), 708 | Queue, 709 | Request 710 | ); 711 | 712 | // 713 | // Please note that HIDCLASS provides the buffer in the Irp->UserBuffer 714 | // field irrespective of the ioctl buffer type. However, framework is very 715 | // strict about type checking. You cannot get Irp->UserBuffer by using 716 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 717 | // internal ioctl. So depending on the ioctl code, we will either 718 | // use retreive function or escape to WDM to get the UserBuffer. 719 | // 720 | 721 | switch (IoControlCode) 722 | { 723 | 724 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 725 | // 726 | // Retrieves the device's HID descriptor. 727 | // 728 | status = CyapaGetHidDescriptor(device, Request); 729 | break; 730 | 731 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 732 | // 733 | //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure. 734 | // 735 | status = CyapaGetDeviceAttributes(Request); 736 | break; 737 | 738 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 739 | // 740 | //Obtains the report descriptor for the HID device. 741 | // 742 | status = CyapaGetReportDescriptor(device, Request, FALSE, &completeRequest); 743 | break; 744 | 745 | case IOCTL_HID_GET_STRING: 746 | // 747 | // Requests that the HID minidriver retrieve a human-readable string 748 | // for either the manufacturer ID, the product ID, or the serial number 749 | // from the string descriptor of the device. The minidriver must send 750 | // a Get String Descriptor request to the device, in order to retrieve 751 | // the string descriptor, then it must extract the string at the 752 | // appropriate index from the string descriptor and return it in the 753 | // output buffer indicated by the IRP. Before sending the Get String 754 | // Descriptor request, the minidriver must retrieve the appropriate 755 | // index for the manufacturer ID, the product ID or the serial number 756 | // from the device extension of a top level collection associated with 757 | // the device. 758 | // 759 | status = CyapaGetString(Request); 760 | break; 761 | 762 | case IOCTL_HID_WRITE_REPORT: 763 | case IOCTL_HID_SET_OUTPUT_REPORT: 764 | // 765 | //Transmits a class driver-supplied report to the device. 766 | // 767 | status = CyapaWriteReport(devContext, Request); 768 | break; 769 | 770 | case IOCTL_HID_READ_REPORT: 771 | case IOCTL_HID_GET_INPUT_REPORT: 772 | // 773 | // Returns a report from the device into a class driver-supplied buffer. 774 | // 775 | status = CyapaReadReport(devContext, Request, &completeRequest); 776 | break; 777 | 778 | case IOCTL_HID_SET_FEATURE: 779 | // 780 | // This sends a HID class feature report to a top-level collection of 781 | // a HID class device. 782 | // 783 | status = CyapaSetFeature(devContext, Request, &completeRequest); 784 | break; 785 | 786 | case IOCTL_HID_GET_FEATURE: 787 | // 788 | // returns a feature report associated with a top-level collection 789 | // 790 | status = CyapaGetFeature(devContext, Request, &completeRequest); 791 | break; 792 | 793 | case IOCTL_HID_ACTIVATE_DEVICE: 794 | // 795 | // Makes the device ready for I/O operations. 796 | // 797 | case IOCTL_HID_DEACTIVATE_DEVICE: 798 | // 799 | // Causes the device to cease operations and terminate all outstanding 800 | // I/O requests. 801 | // 802 | default: 803 | status = STATUS_NOT_SUPPORTED; 804 | break; 805 | } 806 | 807 | if (completeRequest) 808 | { 809 | WdfRequestComplete(Request, status); 810 | 811 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 812 | "%s completed, Queue:0x%p, Request:0x%p\n", 813 | DbgHidInternalIoctlString(IoControlCode), 814 | Queue, 815 | Request 816 | ); 817 | } 818 | else 819 | { 820 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 821 | "%s deferred, Queue:0x%p, Request:0x%p\n", 822 | DbgHidInternalIoctlString(IoControlCode), 823 | Queue, 824 | Request 825 | ); 826 | } 827 | 828 | return; 829 | } 830 | 831 | NTSTATUS 832 | CyapaGetHidDescriptor( 833 | IN WDFDEVICE Device, 834 | IN WDFREQUEST Request 835 | ) 836 | { 837 | NTSTATUS status = STATUS_SUCCESS; 838 | size_t bytesToCopy = 0; 839 | WDFMEMORY memory; 840 | 841 | UNREFERENCED_PARAMETER(Device); 842 | 843 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 844 | "CyapaGetHidDescriptor Entry\n"); 845 | 846 | // 847 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 848 | // will correctly retrieve buffer from Irp->UserBuffer. 849 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 850 | // field irrespective of the ioctl buffer type. However, framework is very 851 | // strict about type checking. You cannot get Irp->UserBuffer by using 852 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 853 | // internal ioctl. 854 | // 855 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 856 | 857 | if (!NT_SUCCESS(status)) 858 | { 859 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 860 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 861 | 862 | return status; 863 | } 864 | 865 | // 866 | // Use hardcoded "HID Descriptor" 867 | // 868 | bytesToCopy = DefaultHidDescriptor.bLength; 869 | 870 | if (bytesToCopy == 0) 871 | { 872 | status = STATUS_INVALID_DEVICE_STATE; 873 | 874 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 875 | "DefaultHidDescriptor is zero, 0x%x\n", status); 876 | 877 | return status; 878 | } 879 | 880 | status = WdfMemoryCopyFromBuffer(memory, 881 | 0, // Offset 882 | (PVOID)&DefaultHidDescriptor, 883 | bytesToCopy); 884 | 885 | if (!NT_SUCCESS(status)) 886 | { 887 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 888 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 889 | 890 | return status; 891 | } 892 | 893 | // 894 | // Report how many bytes were copied 895 | // 896 | WdfRequestSetInformation(Request, bytesToCopy); 897 | 898 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 899 | "CyapaGetHidDescriptor Exit = 0x%x\n", status); 900 | 901 | return status; 902 | } 903 | 904 | void CyapaDescriptorTimer(_In_ WDFTIMER hTimer) { 905 | WDFDEVICE Device = (WDFDEVICE)WdfTimerGetParentObject(hTimer); 906 | PCYAPA_CONTEXT pDevice = GetDeviceContext(Device); 907 | 908 | WdfRequestForwardToIoQueue(pDevice->lastRequest, pDevice->ReportQueue); 909 | 910 | pDevice->lastRequest = NULL; 911 | 912 | WdfTimerStop(hTimer, FALSE); 913 | } 914 | 915 | NTSTATUS 916 | CyapaGetReportDescriptor( 917 | IN WDFDEVICE Device, 918 | IN WDFREQUEST Request, 919 | IN BOOLEAN Retried, 920 | OUT BOOLEAN* CompleteRequest 921 | ) 922 | { 923 | NTSTATUS status = STATUS_SUCCESS; 924 | ULONG_PTR bytesToCopy; 925 | WDFMEMORY memory; 926 | 927 | PCYAPA_CONTEXT devContext = GetDeviceContext(Device); 928 | 929 | if (devContext->max_x == 0) { 930 | devContext->lastRequest = Request; 931 | WDF_TIMER_CONFIG timerConfig; 932 | WDFTIMER hTimer; 933 | WDF_OBJECT_ATTRIBUTES attributes; 934 | 935 | WDF_TIMER_CONFIG_INIT(&timerConfig, CyapaDescriptorTimer); 936 | 937 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 938 | attributes.ParentObject = Device; 939 | status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); 940 | 941 | WdfTimerStart(hTimer, WDF_REL_TIMEOUT_IN_MS(75)); 942 | *CompleteRequest = FALSE; 943 | } 944 | 945 | UNREFERENCED_PARAMETER(Device); 946 | 947 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 948 | "CyapaGetReportDescriptor Entry\n"); 949 | 950 | #define MT_TOUCH_COLLECTION \ 951 | MT_TOUCH_COLLECTION0 \ 952 | 0x26, devContext->max_x_hid[0], devContext->max_x_hid[1], /* LOGICAL_MAXIMUM (WIDTH) */ \ 953 | 0x46, devContext->phy_x_hid[0], devContext->phy_x_hid[1], /* PHYSICAL_MAXIMUM (WIDTH) */ \ 954 | MT_TOUCH_COLLECTION1 \ 955 | 0x26, devContext->max_y_hid[0], devContext->max_y_hid[1], /* LOGICAL_MAXIMUM (HEIGHT) */ \ 956 | 0x46, devContext->phy_y_hid[0], devContext->phy_y_hid[1], /* PHYSICAL_MAXIMUM (HEIGHT) */ \ 957 | MT_TOUCH_COLLECTION2 958 | 959 | HID_REPORT_DESCRIPTOR ReportDescriptor[] = { 960 | // 961 | // Multitouch report starts here 962 | // 963 | //TOUCH PAD input TLC 964 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 965 | 0x09, 0x05, // USAGE (Touch Pad) 966 | 0xa1, 0x01, // COLLECTION (Application) 967 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch pad) 968 | 0x09, 0x22, // USAGE (Finger) 969 | MT_TOUCH_COLLECTION 970 | MT_TOUCH_COLLECTION 971 | MT_TOUCH_COLLECTION 972 | MT_TOUCH_COLLECTION 973 | MT_TOUCH_COLLECTION 974 | USAGE_PAGES 975 | }; 976 | 977 | // 978 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 979 | // will correctly retrieve buffer from Irp->UserBuffer. 980 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 981 | // field irrespective of the ioctl buffer type. However, framework is very 982 | // strict about type checking. You cannot get Irp->UserBuffer by using 983 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 984 | // internal ioctl. 985 | // 986 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 987 | if (!NT_SUCCESS(status)) 988 | { 989 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 990 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 991 | 992 | return status; 993 | } 994 | 995 | // 996 | // Use hardcoded Report descriptor 997 | // 998 | bytesToCopy = DefaultHidDescriptor.DescriptorList[0].wReportLength; 999 | 1000 | if (bytesToCopy == 0) 1001 | { 1002 | status = STATUS_INVALID_DEVICE_STATE; 1003 | 1004 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1005 | "DefaultHidDescriptor's reportLength is zero, 0x%x\n", status); 1006 | 1007 | return status; 1008 | } 1009 | 1010 | status = WdfMemoryCopyFromBuffer(memory, 1011 | 0, 1012 | (PVOID)ReportDescriptor, 1013 | bytesToCopy); 1014 | if (!NT_SUCCESS(status)) 1015 | { 1016 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1017 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1018 | 1019 | return status; 1020 | } 1021 | 1022 | // 1023 | // Report how many bytes were copied 1024 | // 1025 | WdfRequestSetInformation(Request, bytesToCopy); 1026 | 1027 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1028 | "CyapaGetReportDescriptor Exit = 0x%x\n", status); 1029 | 1030 | if (Retried) { 1031 | WdfRequestComplete(Request, status); 1032 | } 1033 | 1034 | return status; 1035 | } 1036 | 1037 | 1038 | NTSTATUS 1039 | CyapaGetDeviceAttributes( 1040 | IN WDFREQUEST Request 1041 | ) 1042 | { 1043 | NTSTATUS status = STATUS_SUCCESS; 1044 | PHID_DEVICE_ATTRIBUTES deviceAttributes = NULL; 1045 | 1046 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1047 | "CyapaGetDeviceAttributes Entry\n"); 1048 | 1049 | // 1050 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1051 | // will correctly retrieve buffer from Irp->UserBuffer. 1052 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1053 | // field irrespective of the ioctl buffer type. However, framework is very 1054 | // strict about type checking. You cannot get Irp->UserBuffer by using 1055 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1056 | // internal ioctl. 1057 | // 1058 | status = WdfRequestRetrieveOutputBuffer(Request, 1059 | sizeof(HID_DEVICE_ATTRIBUTES), 1060 | &deviceAttributes, 1061 | NULL); 1062 | if (!NT_SUCCESS(status)) 1063 | { 1064 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1065 | "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); 1066 | 1067 | return status; 1068 | } 1069 | 1070 | // 1071 | // Set USB device descriptor 1072 | // 1073 | 1074 | deviceAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES); 1075 | deviceAttributes->VendorID = CYAPA_VID; 1076 | deviceAttributes->ProductID = CYAPA_PID; 1077 | deviceAttributes->VersionNumber = CYAPA_VERSION; 1078 | 1079 | // 1080 | // Report how many bytes were copied 1081 | // 1082 | WdfRequestSetInformation(Request, sizeof(HID_DEVICE_ATTRIBUTES)); 1083 | 1084 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1085 | "CyapaGetDeviceAttributes Exit = 0x%x\n", status); 1086 | 1087 | return status; 1088 | } 1089 | 1090 | NTSTATUS 1091 | CyapaGetString( 1092 | IN WDFREQUEST Request 1093 | ) 1094 | { 1095 | 1096 | NTSTATUS status = STATUS_SUCCESS; 1097 | PWSTR pwstrID; 1098 | size_t lenID; 1099 | WDF_REQUEST_PARAMETERS params; 1100 | void *pStringBuffer = NULL; 1101 | 1102 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1103 | "CyapaGetString Entry\n"); 1104 | 1105 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1106 | WdfRequestGetParameters(Request, ¶ms); 1107 | 1108 | switch ((ULONG_PTR)params.Parameters.DeviceIoControl.Type3InputBuffer & 0xFFFF) 1109 | { 1110 | case HID_STRING_ID_IMANUFACTURER: 1111 | pwstrID = L"Cyapa.\0"; 1112 | break; 1113 | 1114 | case HID_STRING_ID_IPRODUCT: 1115 | pwstrID = L"MaxTouch Touch Screen\0"; 1116 | break; 1117 | 1118 | case HID_STRING_ID_ISERIALNUMBER: 1119 | pwstrID = L"123123123\0"; 1120 | break; 1121 | 1122 | default: 1123 | pwstrID = NULL; 1124 | break; 1125 | } 1126 | 1127 | lenID = pwstrID ? wcslen(pwstrID)*sizeof(WCHAR) + sizeof(UNICODE_NULL) : 0; 1128 | 1129 | if (pwstrID == NULL) 1130 | { 1131 | 1132 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1133 | "CyapaGetString Invalid request type\n"); 1134 | 1135 | status = STATUS_INVALID_PARAMETER; 1136 | 1137 | return status; 1138 | } 1139 | 1140 | status = WdfRequestRetrieveOutputBuffer(Request, 1141 | lenID, 1142 | &pStringBuffer, 1143 | &lenID); 1144 | 1145 | if (!NT_SUCCESS(status)) 1146 | { 1147 | 1148 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1149 | "CyapaGetString WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1150 | 1151 | return status; 1152 | } 1153 | 1154 | RtlCopyMemory(pStringBuffer, pwstrID, lenID); 1155 | 1156 | WdfRequestSetInformation(Request, lenID); 1157 | 1158 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1159 | "CyapaGetString Exit = 0x%x\n", status); 1160 | 1161 | return status; 1162 | } 1163 | 1164 | NTSTATUS 1165 | CyapaWriteReport( 1166 | IN PCYAPA_CONTEXT DevContext, 1167 | IN WDFREQUEST Request 1168 | ) 1169 | { 1170 | UNREFERENCED_PARAMETER(DevContext); 1171 | 1172 | NTSTATUS status = STATUS_SUCCESS; 1173 | WDF_REQUEST_PARAMETERS params; 1174 | PHID_XFER_PACKET transferPacket = NULL; 1175 | 1176 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1177 | "CyapaWriteReport Entry\n"); 1178 | 1179 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1180 | WdfRequestGetParameters(Request, ¶ms); 1181 | 1182 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1183 | { 1184 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1185 | "CyapaWriteReport Xfer packet too small\n"); 1186 | 1187 | status = STATUS_BUFFER_TOO_SMALL; 1188 | } 1189 | else 1190 | { 1191 | 1192 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1193 | 1194 | if (transferPacket == NULL) 1195 | { 1196 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1197 | "CyapaWriteReport No xfer packet\n"); 1198 | 1199 | status = STATUS_INVALID_DEVICE_REQUEST; 1200 | } 1201 | else 1202 | { 1203 | // 1204 | // switch on the report id 1205 | // 1206 | 1207 | switch (transferPacket->reportId) 1208 | { 1209 | default: 1210 | 1211 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1212 | "CyapaWriteReport Unhandled report type %d\n", transferPacket->reportId); 1213 | 1214 | status = STATUS_INVALID_PARAMETER; 1215 | 1216 | break; 1217 | } 1218 | } 1219 | } 1220 | 1221 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1222 | "CyapaWriteReport Exit = 0x%x\n", status); 1223 | 1224 | return status; 1225 | 1226 | } 1227 | 1228 | NTSTATUS 1229 | CyapaProcessVendorReport( 1230 | IN PCYAPA_CONTEXT DevContext, 1231 | IN PVOID ReportBuffer, 1232 | IN ULONG ReportBufferLen, 1233 | OUT size_t* BytesWritten 1234 | ) 1235 | { 1236 | NTSTATUS status = STATUS_SUCCESS; 1237 | WDFREQUEST reqRead; 1238 | PVOID pReadReport = NULL; 1239 | size_t bytesReturned = 0; 1240 | 1241 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1242 | "CyapaProcessVendorReport Entry\n"); 1243 | 1244 | status = WdfIoQueueRetrieveNextRequest(DevContext->ReportQueue, 1245 | &reqRead); 1246 | 1247 | if (NT_SUCCESS(status)) 1248 | { 1249 | status = WdfRequestRetrieveOutputBuffer(reqRead, 1250 | ReportBufferLen, 1251 | &pReadReport, 1252 | &bytesReturned); 1253 | 1254 | if (NT_SUCCESS(status)) 1255 | { 1256 | // 1257 | // Copy ReportBuffer into read request 1258 | // 1259 | 1260 | if (bytesReturned > ReportBufferLen) 1261 | { 1262 | bytesReturned = ReportBufferLen; 1263 | } 1264 | 1265 | RtlCopyMemory(pReadReport, 1266 | ReportBuffer, 1267 | bytesReturned); 1268 | 1269 | // 1270 | // Complete read with the number of bytes returned as info 1271 | // 1272 | 1273 | WdfRequestCompleteWithInformation(reqRead, 1274 | status, 1275 | bytesReturned); 1276 | 1277 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1278 | "CyapaProcessVendorReport %d bytes returned\n", bytesReturned); 1279 | 1280 | // 1281 | // Return the number of bytes written for the write request completion 1282 | // 1283 | 1284 | *BytesWritten = bytesReturned; 1285 | 1286 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1287 | "%s completed, Queue:0x%p, Request:0x%p\n", 1288 | DbgHidInternalIoctlString(IOCTL_HID_READ_REPORT), 1289 | DevContext->ReportQueue, 1290 | reqRead); 1291 | } 1292 | else 1293 | { 1294 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1295 | "WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1296 | } 1297 | } 1298 | else 1299 | { 1300 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1301 | "WdfIoQueueRetrieveNextRequest failed Status 0x%x\n", status); 1302 | } 1303 | 1304 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1305 | "CyapaProcessVendorReport Exit = 0x%x\n", status); 1306 | 1307 | return status; 1308 | } 1309 | 1310 | NTSTATUS 1311 | CyapaReadReport( 1312 | IN PCYAPA_CONTEXT DevContext, 1313 | IN WDFREQUEST Request, 1314 | OUT BOOLEAN* CompleteRequest 1315 | ) 1316 | { 1317 | NTSTATUS status = STATUS_SUCCESS; 1318 | 1319 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1320 | "CyapaReadReport Entry\n"); 1321 | 1322 | // 1323 | // Forward this read request to our manual queue 1324 | // (in other words, we are going to defer this request 1325 | // until we have a corresponding write request to 1326 | // match it with) 1327 | // 1328 | 1329 | status = WdfRequestForwardToIoQueue(Request, DevContext->ReportQueue); 1330 | 1331 | if (!NT_SUCCESS(status)) 1332 | { 1333 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1334 | "WdfRequestForwardToIoQueue failed Status 0x%x\n", status); 1335 | } 1336 | else 1337 | { 1338 | *CompleteRequest = FALSE; 1339 | } 1340 | 1341 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1342 | "CyapaReadReport Exit = 0x%x\n", status); 1343 | 1344 | return status; 1345 | } 1346 | 1347 | NTSTATUS 1348 | CyapaSetFeature( 1349 | IN PCYAPA_CONTEXT DevContext, 1350 | IN WDFREQUEST Request, 1351 | OUT BOOLEAN* CompleteRequest 1352 | ) 1353 | { 1354 | UNREFERENCED_PARAMETER(CompleteRequest); 1355 | 1356 | NTSTATUS status = STATUS_SUCCESS; 1357 | WDF_REQUEST_PARAMETERS params; 1358 | PHID_XFER_PACKET transferPacket = NULL; 1359 | CyapaFeatureReport* pReport = NULL; 1360 | 1361 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1362 | "CyapaSetFeature Entry\n"); 1363 | 1364 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1365 | WdfRequestGetParameters(Request, ¶ms); 1366 | 1367 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1368 | { 1369 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1370 | "CyapaSetFeature Xfer packet too small\n"); 1371 | 1372 | status = STATUS_BUFFER_TOO_SMALL; 1373 | } 1374 | else 1375 | { 1376 | 1377 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1378 | 1379 | if (transferPacket == NULL) 1380 | { 1381 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1382 | "CyapaWriteReport No xfer packet\n"); 1383 | 1384 | status = STATUS_INVALID_DEVICE_REQUEST; 1385 | } 1386 | else 1387 | { 1388 | // 1389 | // switch on the report id 1390 | // 1391 | 1392 | switch (transferPacket->reportId) 1393 | { 1394 | case REPORTID_FEATURE: 1395 | 1396 | if (transferPacket->reportBufferLen == sizeof(CyapaFeatureReport)) 1397 | { 1398 | pReport = (CyapaFeatureReport*)transferPacket->reportBuffer; 1399 | 1400 | DevContext->DeviceMode = pReport->DeviceMode; 1401 | 1402 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1403 | "CyapaSetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1404 | } 1405 | else 1406 | { 1407 | status = STATUS_INVALID_PARAMETER; 1408 | 1409 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1410 | "CyapaSetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(CyapaFeatureReport) (%d)\n", 1411 | transferPacket->reportBufferLen, 1412 | sizeof(CyapaFeatureReport)); 1413 | } 1414 | 1415 | break; 1416 | 1417 | default: 1418 | 1419 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1420 | "CyapaSetFeature Unhandled report type %d\n", transferPacket->reportId); 1421 | 1422 | status = STATUS_INVALID_PARAMETER; 1423 | 1424 | break; 1425 | } 1426 | } 1427 | } 1428 | 1429 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1430 | "CyapaSetFeature Exit = 0x%x\n", status); 1431 | 1432 | return status; 1433 | } 1434 | 1435 | NTSTATUS 1436 | CyapaGetFeature( 1437 | IN PCYAPA_CONTEXT DevContext, 1438 | IN WDFREQUEST Request, 1439 | OUT BOOLEAN* CompleteRequest 1440 | ) 1441 | { 1442 | UNREFERENCED_PARAMETER(CompleteRequest); 1443 | 1444 | NTSTATUS status = STATUS_SUCCESS; 1445 | WDF_REQUEST_PARAMETERS params; 1446 | PHID_XFER_PACKET transferPacket = NULL; 1447 | 1448 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1449 | "CyapaGetFeature Entry\n"); 1450 | 1451 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1452 | WdfRequestGetParameters(Request, ¶ms); 1453 | 1454 | if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) 1455 | { 1456 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1457 | "CyapaGetFeature Xfer packet too small\n"); 1458 | 1459 | status = STATUS_BUFFER_TOO_SMALL; 1460 | } 1461 | else 1462 | { 1463 | 1464 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1465 | 1466 | if (transferPacket == NULL) 1467 | { 1468 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1469 | "CyapaGetFeature No xfer packet\n"); 1470 | 1471 | status = STATUS_INVALID_DEVICE_REQUEST; 1472 | } 1473 | else 1474 | { 1475 | // 1476 | // switch on the report id 1477 | // 1478 | 1479 | switch (transferPacket->reportId) 1480 | { 1481 | case REPORTID_MTOUCH: 1482 | { 1483 | 1484 | CyapaMaxCountReport* pReport = NULL; 1485 | 1486 | if (transferPacket->reportBufferLen >= sizeof(CyapaMaxCountReport)) 1487 | { 1488 | pReport = (CyapaMaxCountReport*)transferPacket->reportBuffer; 1489 | 1490 | pReport->MaximumCount = MULTI_MAX_COUNT; 1491 | 1492 | pReport->PadType = 0; 1493 | 1494 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1495 | "CyapaGetFeature MaximumCount = 0x%x\n", MULTI_MAX_COUNT); 1496 | } 1497 | else 1498 | { 1499 | status = STATUS_INVALID_PARAMETER; 1500 | 1501 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1502 | "CyapaGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(CyapaMaxCountReport) (%d)\n", 1503 | transferPacket->reportBufferLen, 1504 | sizeof(CyapaMaxCountReport)); 1505 | } 1506 | 1507 | break; 1508 | } 1509 | 1510 | case REPORTID_FEATURE: 1511 | { 1512 | 1513 | CyapaFeatureReport* pReport = NULL; 1514 | 1515 | if (transferPacket->reportBufferLen >= sizeof(CyapaFeatureReport)) 1516 | { 1517 | pReport = (CyapaFeatureReport*)transferPacket->reportBuffer; 1518 | 1519 | pReport->DeviceMode = DevContext->DeviceMode; 1520 | 1521 | pReport->DeviceIdentifier = 0; 1522 | 1523 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1524 | "CyapaGetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1525 | } 1526 | else 1527 | { 1528 | status = STATUS_INVALID_PARAMETER; 1529 | 1530 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1531 | "CyapaGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(CyapaFeatureReport) (%d)\n", 1532 | transferPacket->reportBufferLen, 1533 | sizeof(CyapaFeatureReport)); 1534 | } 1535 | 1536 | break; 1537 | } 1538 | 1539 | case REPORTID_PTPHQA: 1540 | { 1541 | uint8_t PTPHQA_BLOB[] = { REPORTID_PTPHQA, 0xfc, 0x28, 0xfe, 0x84, 0x40, 0xcb, 0x9a, 0x87, 0x0d, 0xbe, 0x57, 0x3c, 0xb6, 0x70, 0x09, 0x88, 0x07,\ 1542 | 0x97, 0x2d, 0x2b, 0xe3, 0x38, 0x34, 0xb6, 0x6c, 0xed, 0xb0, 0xf7, 0xe5, 0x9c, 0xf6, 0xc2, 0x2e, 0x84,\ 1543 | 0x1b, 0xe8, 0xb4, 0x51, 0x78, 0x43, 0x1f, 0x28, 0x4b, 0x7c, 0x2d, 0x53, 0xaf, 0xfc, 0x47, 0x70, 0x1b,\ 1544 | 0x59, 0x6f, 0x74, 0x43, 0xc4, 0xf3, 0x47, 0x18, 0x53, 0x1a, 0xa2, 0xa1, 0x71, 0xc7, 0x95, 0x0e, 0x31,\ 1545 | 0x55, 0x21, 0xd3, 0xb5, 0x1e, 0xe9, 0x0c, 0xba, 0xec, 0xb8, 0x89, 0x19, 0x3e, 0xb3, 0xaf, 0x75, 0x81,\ 1546 | 0x9d, 0x53, 0xb9, 0x41, 0x57, 0xf4, 0x6d, 0x39, 0x25, 0x29, 0x7c, 0x87, 0xd9, 0xb4, 0x98, 0x45, 0x7d,\ 1547 | 0xa7, 0x26, 0x9c, 0x65, 0x3b, 0x85, 0x68, 0x89, 0xd7, 0x3b, 0xbd, 0xff, 0x14, 0x67, 0xf2, 0x2b, 0xf0,\ 1548 | 0x2a, 0x41, 0x54, 0xf0, 0xfd, 0x2c, 0x66, 0x7c, 0xf8, 0xc0, 0x8f, 0x33, 0x13, 0x03, 0xf1, 0xd3, 0xc1, 0x0b,\ 1549 | 0x89, 0xd9, 0x1b, 0x62, 0xcd, 0x51, 0xb7, 0x80, 0xb8, 0xaf, 0x3a, 0x10, 0xc1, 0x8a, 0x5b, 0xe8, 0x8a,\ 1550 | 0x56, 0xf0, 0x8c, 0xaa, 0xfa, 0x35, 0xe9, 0x42, 0xc4, 0xd8, 0x55, 0xc3, 0x38, 0xcc, 0x2b, 0x53, 0x5c,\ 1551 | 0x69, 0x52, 0xd5, 0xc8, 0x73, 0x02, 0x38, 0x7c, 0x73, 0xb6, 0x41, 0xe7, 0xff, 0x05, 0xd8, 0x2b, 0x79,\ 1552 | 0x9a, 0xe2, 0x34, 0x60, 0x8f, 0xa3, 0x32, 0x1f, 0x09, 0x78, 0x62, 0xbc, 0x80, 0xe3, 0x0f, 0xbd, 0x65,\ 1553 | 0x20, 0x08, 0x13, 0xc1, 0xe2, 0xee, 0x53, 0x2d, 0x86, 0x7e, 0xa7, 0x5a, 0xc5, 0xd3, 0x7d, 0x98, 0xbe,\ 1554 | 0x31, 0x48, 0x1f, 0xfb, 0xda, 0xaf, 0xa2, 0xa8, 0x6a, 0x89, 0xd6, 0xbf, 0xf2, 0xd3, 0x32, 0x2a, 0x9a,\ 1555 | 0xe4, 0xcf, 0x17, 0xb7, 0xb8, 0xf4, 0xe1, 0x33, 0x08, 0x24, 0x8b, 0xc4, 0x43, 0xa5, 0xe5, 0x24, 0xc2 }; 1556 | if (transferPacket->reportBufferLen >= sizeof(PTPHQA_BLOB)) 1557 | { 1558 | uint8_t *blobBuffer = (uint8_t*)transferPacket->reportBuffer; 1559 | for (int i = 0; i < sizeof(PTPHQA_BLOB); i++) { 1560 | blobBuffer[i] = PTPHQA_BLOB[i]; 1561 | } 1562 | CyapaPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1563 | "CyapaGetFeature PHPHQA\n"); 1564 | } 1565 | else 1566 | { 1567 | status = STATUS_INVALID_PARAMETER; 1568 | 1569 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1570 | "CyapaGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(PTPHEQ_BLOB) (%d)\n", 1571 | transferPacket->reportBufferLen, 1572 | sizeof(CyapaFeatureReport)); 1573 | } 1574 | break; 1575 | } 1576 | 1577 | default: 1578 | 1579 | CyapaPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1580 | "CyapaGetFeature Unhandled report type %d\n", transferPacket->reportId); 1581 | 1582 | status = STATUS_INVALID_PARAMETER; 1583 | 1584 | break; 1585 | } 1586 | } 1587 | } 1588 | 1589 | CyapaPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1590 | "CyapaGetFeature Exit = 0x%x\n", status); 1591 | 1592 | return status; 1593 | } 1594 | 1595 | PCHAR 1596 | DbgHidInternalIoctlString( 1597 | IN ULONG IoControlCode 1598 | ) 1599 | { 1600 | switch (IoControlCode) 1601 | { 1602 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 1603 | return "IOCTL_HID_GET_DEVICE_DESCRIPTOR"; 1604 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 1605 | return "IOCTL_HID_GET_REPORT_DESCRIPTOR"; 1606 | case IOCTL_HID_READ_REPORT: 1607 | return "IOCTL_HID_READ_REPORT"; 1608 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 1609 | return "IOCTL_HID_GET_DEVICE_ATTRIBUTES"; 1610 | case IOCTL_HID_WRITE_REPORT: 1611 | return "IOCTL_HID_WRITE_REPORT"; 1612 | case IOCTL_HID_SET_FEATURE: 1613 | return "IOCTL_HID_SET_FEATURE"; 1614 | case IOCTL_HID_GET_FEATURE: 1615 | return "IOCTL_HID_GET_FEATURE"; 1616 | case IOCTL_HID_GET_STRING: 1617 | return "IOCTL_HID_GET_STRING"; 1618 | case IOCTL_HID_ACTIVATE_DEVICE: 1619 | return "IOCTL_HID_ACTIVATE_DEVICE"; 1620 | case IOCTL_HID_DEACTIVATE_DEVICE: 1621 | return "IOCTL_HID_DEACTIVATE_DEVICE"; 1622 | case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: 1623 | return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST"; 1624 | case IOCTL_HID_SET_OUTPUT_REPORT: 1625 | return "IOCTL_HID_SET_OUTPUT_REPORT"; 1626 | case IOCTL_HID_GET_INPUT_REPORT: 1627 | return "IOCTL_HID_GET_INPUT_REPORT"; 1628 | default: 1629 | return "Unknown IOCTL"; 1630 | } 1631 | } 1632 | --------------------------------------------------------------------------------