├── crostouchscreen2 ├── stdint.h ├── trace.h ├── spb.h ├── hidcommon.h ├── crostouchscreen2.vcxproj.user ├── crostouchscreen2.vcxproj.filters ├── crostouchscreen2.inf ├── elants.h ├── elan.h ├── spb.cpp ├── crostouchscreen2.vcxproj └── elan.cpp ├── README.md ├── crostouchscreen2 Package ├── crostouchscreen2 Package.vcxproj.filters ├── crostouchscreen2 Package.vcxproj.user └── crostouchscreen2 Package.vcxproj ├── LICENSE.txt ├── .gitignore └── crostouchscreen2.sln /crostouchscreen2/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; 7 | 8 | #define BIT(nr) (1UL << (nr)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # crostouchscreen2-elan 2 | Elan Touch Screen Driver for Dell Chromebook 13, Acer R11, etc. 3 | 4 | Tested on Acer R11 Chromebook (cyan) Works with up to 10 touches. 5 | 6 | # Credits 7 | 8 | Huge thanks to the vmulti and DragonFlyBSD projects, which I used for references. Also, thanks to Microsoft for open sourcing the Synaptics RMI I2C driver, which I also used as a reference. 9 | -------------------------------------------------------------------------------- /crostouchscreen2 Package/crostouchscreen2 Package.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {8E41214B-6785-4CFE-B992-037D68949A14} 6 | inf;inv;inx;mof;mc; 7 | 8 | 9 | -------------------------------------------------------------------------------- /crostouchscreen2/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 | -------------------------------------------------------------------------------- /crostouchscreen2/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_reads_bytes_(Length) PVOID Data, 46 | _In_ ULONG Length 47 | ); 48 | 49 | NTSTATUS 50 | SpbXferDataSynchronously( 51 | _In_ SPB_CONTEXT* SpbContext, 52 | _In_ PVOID SendData, 53 | _In_ ULONG SendLength, 54 | _In_reads_bytes_(Length) PVOID Data, 55 | _In_ ULONG Length 56 | ); 57 | 58 | 59 | VOID 60 | SpbTargetDeinitialize( 61 | IN WDFDEVICE FxDevice, 62 | IN SPB_CONTEXT *SpbContext 63 | ); 64 | 65 | NTSTATUS 66 | SpbTargetInitialize( 67 | IN WDFDEVICE FxDevice, 68 | IN SPB_CONTEXT *SpbContext 69 | ); 70 | 71 | NTSTATUS 72 | SpbWriteDataSynchronously( 73 | IN SPB_CONTEXT *SpbContext, 74 | IN PVOID Data, 75 | IN ULONG Length 76 | ); -------------------------------------------------------------------------------- /crostouchscreen2/hidcommon.h: -------------------------------------------------------------------------------- 1 | #if !defined(_ELAN_COMMON_H_) 2 | #define _ELAN_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 ELAN_PID 0xBACC 10 | #define ELAN_VID 0x00FF 11 | #define ELAN_VERSION 0x0001 12 | 13 | // 14 | // These are the report ids 15 | // 16 | 17 | #define REPORTID_MTOUCH 0x01 18 | #define REPORTID_FEATURE 0x02 19 | 20 | // 21 | // Multitouch specific report information 22 | // 23 | 24 | #define MULTI_TIPSWITCH_BIT 1 25 | #define MULTI_CONFIDENCE_BIT 2 26 | 27 | #define MULTI_MIN_COORDINATE 0x0000 28 | #define MULTI_MAX_COORDINATE 0x7FFF 29 | 30 | #define MULTI_MAX_COUNT 10 31 | 32 | #pragma pack(1) 33 | typedef struct 34 | { 35 | 36 | BYTE Status; 37 | 38 | BYTE ContactID; 39 | 40 | USHORT XValue; 41 | 42 | USHORT YValue; 43 | 44 | USHORT Width; 45 | 46 | USHORT Height; 47 | 48 | } 49 | TOUCH, *PTOUCH; 50 | 51 | typedef struct _ELAN_MULTITOUCH_REPORT 52 | { 53 | 54 | BYTE ReportID; 55 | 56 | TOUCH Touch[10]; 57 | 58 | BYTE ActualCount; 59 | 60 | } ElanMultiTouchReport; 61 | #pragma pack() 62 | 63 | // 64 | // Feature report infomation 65 | // 66 | 67 | #define DEVICE_MODE_MOUSE 0x00 68 | #define DEVICE_MODE_SINGLE_INPUT 0x01 69 | #define DEVICE_MODE_MULTI_INPUT 0x02 70 | 71 | #pragma pack(1) 72 | typedef struct _ELAN_FEATURE_REPORT 73 | { 74 | 75 | BYTE ReportID; 76 | 77 | BYTE DeviceMode; 78 | 79 | BYTE DeviceIdentifier; 80 | 81 | } ElanFeatureReport; 82 | 83 | typedef struct _ELAN_MAXCOUNT_REPORT 84 | { 85 | 86 | BYTE ReportID; 87 | 88 | BYTE MaximumCount; 89 | 90 | } ElanMaxCountReport; 91 | #pragma pack() 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /crostouchscreen2/crostouchscreen2.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Off 5 | 6 | 7 | 8 | 9 | 10 | 11 | True 12 | Off 13 | 14 | 15 | Off 16 | 17 | 18 | Off 19 | 20 | 21 | Off 22 | 23 | 24 | Off 25 | 26 | 27 | Off 28 | 29 | 30 | Off 31 | 32 | 33 | Off 34 | 35 | 36 | Off 37 | 38 | 39 | Off 40 | 41 | 42 | Off 43 | 44 | -------------------------------------------------------------------------------- /crostouchscreen2/crostouchscreen2.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 | Driver Files 24 | 25 | 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | -------------------------------------------------------------------------------- /crostouchscreen2/crostouchscreen2.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 Elan Touch Screen 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 = 12/16/2021,2.9.2 20 | CatalogFile = crostouchscreen2.cat 21 | PnpLockdown = 1 22 | 23 | [DestinationDirs] 24 | DefaultDestDir = 12 25 | 26 | ; ================= Class section ===================== 27 | 28 | [SourceDisksNames] 29 | 1 = %DiskId1%,,,"" 30 | 31 | [SourceDisksFiles] 32 | crostouchscreen2.sys = 1,, 33 | 34 | ;***************************************** 35 | ; CrosTouchScreen Install Section 36 | ;***************************************** 37 | 38 | [Manufacturer] 39 | %StdMfg%=Standard,NTAMD64 40 | 41 | ; Decorated model section take precedence over undecorated 42 | ; ones on XP and later. 43 | [Standard.NTAMD64] 44 | %CrosTouchScreen.DeviceDesc%=CrosTouchScreen_Device, ACPI\ELAN0001 45 | 46 | [CrosTouchScreen_Device.NT] 47 | CopyFiles=Drivers_Dir 48 | 49 | [CrosTouchScreen_Device.NT.HW] 50 | AddReg=CrosTouchScreen_AddReg 51 | 52 | [Drivers_Dir] 53 | crostouchscreen2.sys 54 | 55 | [CrosTouchScreen_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 | [CrosTouchScreen_Device.NT.Services] 62 | AddService = CrosTouchScreen,%SPSVCINST_ASSOCSERVICE%, CrosTouchScreen_Service_Inst 63 | 64 | ; -------------- CrosTouchScreen driver install sections 65 | [CrosTouchScreen_Service_Inst] 66 | DisplayName = %CrosTouchScreen.SVCDESC% 67 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 68 | StartType = 3 ; SERVICE_DEMAND_START 69 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 70 | ServiceBinary = %12%\crostouchscreen2.sys 71 | LoadOrderGroup = Base 72 | 73 | [Strings] 74 | SPSVCINST_ASSOCSERVICE= 0x00000002 75 | StdMfg = "CoolStar" 76 | DiskId1 = "CrosTouchScreen Installation Disk #1" 77 | CrosTouchScreen.DeviceDesc = "Chromebook Elan Touch Screen" 78 | CrosTouchScreen.SVCDESC = "CrosTouchScreen Service" 79 | -------------------------------------------------------------------------------- /crostouchscreen2/elants.h: -------------------------------------------------------------------------------- 1 | #include "stdint.h" 2 | 3 | #define ELAN_TS_RESOLUTION(n, m) (((n) - 1) * (m)) 4 | 5 | /* FW header data */ 6 | #define HEADER_SIZE 4 7 | #define FW_HDR_TYPE 0 8 | #define FW_HDR_COUNT 1 9 | #define FW_HDR_LENGTH 2 10 | 11 | /* Buffer mode Queue Header information */ 12 | #define QUEUE_HEADER_SINGLE 0x62 13 | #define QUEUE_HEADER_NORMAL 0X63 14 | #define QUEUE_HEADER_WAIT 0x64 15 | #define QUEUE_HEADER_NORMAL2 0x66 16 | 17 | /* Command header definition */ 18 | #define CMD_HEADER_WRITE 0x54 19 | #define CMD_HEADER_READ 0x53 20 | #define CMD_HEADER_6B_READ 0x5B 21 | #define CMD_HEADER_ROM_READ 0x96 22 | #define CMD_HEADER_RESP 0x52 23 | #define CMD_HEADER_6B_RESP 0x9B 24 | #define CMD_HEADER_ROM_RESP 0x95 25 | #define CMD_HEADER_HELLO 0x55 26 | #define CMD_HEADER_REK 0x66 27 | 28 | /* FW position data */ 29 | #define PACKET_SIZE_OLD 40 30 | #define PACKET_SIZE 55 31 | #define MAX_CONTACT_NUM 10 32 | #define FW_POS_HEADER 0 33 | #define FW_POS_STATE 1 34 | #define FW_POS_TOTAL 2 35 | #define FW_POS_XY 3 36 | #define FW_POS_TOOL_TYPE 33 37 | #define FW_POS_CHECKSUM 34 38 | #define FW_POS_WIDTH 35 39 | #define FW_POS_PRESSURE 45 40 | 41 | #define HEADER_REPORT_10_FINGER 0x62 42 | 43 | /* Header (4 bytes) plus 3 fill 10-finger packets */ 44 | #define MAX_PACKET_SIZE 169 45 | 46 | #define BOOT_TIME_DELAY_MS 50 47 | 48 | /* FW read command, 0x53 0x?? 0x0, 0x01 */ 49 | #define E_ELAN_INFO_FW_VER 0x00 50 | #define E_ELAN_INFO_BC_VER 0x10 51 | #define E_ELAN_INFO_X_RES 0x60 52 | #define E_ELAN_INFO_Y_RES 0x63 53 | #define E_ELAN_INFO_REK 0xD0 54 | #define E_ELAN_INFO_TEST_VER 0xE0 55 | #define E_ELAN_INFO_FW_ID 0xF0 56 | #define E_INFO_OSR 0xD6 57 | #define E_INFO_PHY_SCAN 0xD7 58 | #define E_INFO_PHY_DRIVER 0xD8 59 | 60 | /* FW write command, 0x54 0x?? 0x0, 0x01 */ 61 | #define E_POWER_STATE_SLEEP 0x50 62 | #define E_POWER_STATE_RESUME 0x58 63 | 64 | #define MAX_RETRIES 3 65 | #define MAX_FW_UPDATE_RETRIES 30 66 | 67 | #define ELAN_FW_PAGESIZE 132 68 | 69 | /* calibration timeout definition */ 70 | #define ELAN_CALI_TIMEOUT_MSEC 12000 71 | 72 | #define ELAN_POWERON_DELAY_USEC 500 73 | #define ELAN_RESET_DELAY_MSEC 20 74 | 75 | enum elants_chip_id { 76 | EKTH3500, 77 | EKTF3624, //not supported 78 | }; 79 | 80 | enum elants_state { 81 | ELAN_STATE_NORMAL, 82 | ELAN_WAIT_QUEUE_HEADER, 83 | ELAN_WAIT_RECALIBRATION, 84 | }; 85 | 86 | enum elants_iap_mode { 87 | ELAN_IAP_OPERATIONAL, 88 | ELAN_IAP_RECOVERY, 89 | }; 90 | 91 | #define MXT_T9_RELEASE (1 << 5) 92 | #define MXT_T9_PRESS (1 << 6) 93 | #define MXT_T9_DETECT (1 << 7) -------------------------------------------------------------------------------- /crostouchscreen2 Package/crostouchscreen2 Package.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TestSign 5 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 6 | 7 | 8 | TestSign 9 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 10 | 11 | 12 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 13 | 14 | 15 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 16 | 17 | 18 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 19 | 20 | 21 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 22 | 23 | 24 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 25 | 26 | 27 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 28 | 29 | 30 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 31 | 32 | 33 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 34 | 35 | 36 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 37 | 38 | 39 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 40 | 41 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2021 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. 14 | 15 | 16 | ====================== Windows Driver Samples License ====================== 17 | 18 | The Microsoft Public License (MS-PL) 19 | Copyright (c) 2015 Microsoft 20 | 21 | This license governs use of the accompanying software. If you use the software, you 22 | accept this license. If you do not accept the license, do not use the software. 23 | 24 | 1. Definitions 25 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the 26 | same meaning here as under U.S. copyright law. 27 | A "contribution" is the original software, or any additions or changes to the software. 28 | A "contributor" is any person that distributes its contribution under this license. 29 | "Licensed patents" are a contributor's patent claims that read directly on its contribution. 30 | 31 | 2. Grant of Rights 32 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. 33 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 34 | 35 | 3. Conditions and Limitations 36 | (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. 37 | (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. 38 | (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 39 | (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. 40 | (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /crostouchscreen2.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}") = "crostouchscreen2", "crostouchscreen2\crostouchscreen2.vcxproj", "{36580C07-EDC3-4C2B-B45F-6AB017E01A5D}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crostouchscreen2 Package", "crostouchscreen2 Package\crostouchscreen2 Package.vcxproj", "{3DAE7ED3-003A-4495-8352-3D7B5B5D846F}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D} = {36580C07-EDC3-4C2B-B45F-6AB017E01A5D} 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 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 30 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 31 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Debug|Win32.Deploy.0 = Win7 Debug|Win32 32 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 33 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 34 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64 35 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 36 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 37 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32 38 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 39 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Release|x64.Build.0 = Win7 Release|x64 40 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win7 Release|x64.Deploy.0 = Win7 Release|x64 41 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 42 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 43 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 44 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 45 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 46 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 47 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 48 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 49 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 50 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 51 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Release|x64.Build.0 = Win8 Release|x64 52 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 53 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 54 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 55 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 56 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 57 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 58 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 59 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 60 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 61 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 62 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 63 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 64 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 65 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 66 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 67 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Debug|Win32.Deploy.0 = Win7 Debug|Win32 68 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 69 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 70 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64 71 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 72 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 73 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32 74 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 75 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Release|x64.Build.0 = Win7 Release|x64 76 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win7 Release|x64.Deploy.0 = Win7 Release|x64 77 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 78 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 79 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 80 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 81 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 82 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 83 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 84 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 85 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 86 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 87 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Release|x64.Build.0 = Win8 Release|x64 88 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 89 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 90 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 91 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 92 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 93 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 94 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 95 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 96 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 97 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 98 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 99 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 100 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 101 | EndGlobalSection 102 | GlobalSection(SolutionProperties) = preSolution 103 | HideSolutionNode = FALSE 104 | EndGlobalSection 105 | EndGlobal 106 | -------------------------------------------------------------------------------- /crostouchscreen2/elan.h: -------------------------------------------------------------------------------- 1 | #if !defined(_ELAN_H_) 2 | #define _ELAN_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 | 22 | #include "elants.h" 23 | 24 | // 25 | // String definitions 26 | // 27 | 28 | #define DRIVERNAME "crostouchscreen2.sys: " 29 | 30 | #define ELAN_POOL_TAG (ULONG) 'stlE' 31 | #define ELAN_HARDWARE_IDS L"CoolStar\\ELAN0001\0\0" 32 | #define ELAN_HARDWARE_IDS_LENGTH sizeof(ELAN_HARDWARE_IDS) 33 | 34 | #define MT_TOUCH_COLLECTION0 \ 35 | 0xa1, 0x02, /* COLLECTION (Logical) */ \ 36 | 0x09, 0x42, /* USAGE (Tip Switch) */ \ 37 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ 38 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ 39 | 0x75, 0x01, /* REPORT_SIZE (1) */ \ 40 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 41 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 42 | 0x09, 0x47, /* USAGE (Confidence) */ \ 43 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 44 | 0x95, 0x06, /* REPORT_COUNT (6) */ \ 45 | 0x81, 0x03, /* INPUT (Cnst,Ary,Abs) */ \ 46 | 0x75, 0x08, /* REPORT_SIZE (8) */ \ 47 | 0x09, 0x51, /* USAGE (Contact Identifier) */ \ 48 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 49 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 50 | 0x05, 0x01, /* USAGE_PAGE (Generic Desk.. */ \ 51 | 0x75, 0x10, /* REPORT_SIZE (16) */ \ 52 | 0x55, 0x00, /* UNIT_EXPONENT (0) */ \ 53 | 0x65, 0x00, /* UNIT (None) */ \ 54 | 0x35, 0x00, /* PHYSICAL_MINIMUM (0) */ \ 55 | 0x46, 0x00, 0x00, /* PHYSICAL_MAXIMUM (0) */ 56 | 57 | 58 | //0x26, 0x56, 0x05, /* LOGICAL_MAXIMUM (1366) */ 59 | 60 | #define MT_TOUCH_COLLECTION1 \ 61 | 0x09, 0x30, /* USAGE (X) */ \ 62 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ 63 | 64 | //0x26, 0x00, 0x03, /* LOGICAL_MAXIMUM (768) */ 65 | 66 | #define MT_TOUCH_COLLECTION2 \ 67 | 0x09, 0x31, /* USAGE (Y) */ \ 68 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 69 | 0x05, 0x0d, /* USAGE PAGE (Digitizers) */ \ 70 | 0x09, 0x48, /* USAGE (Width) */ \ 71 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 72 | 0x09, 0x49, /* USAGE (Height) */ \ 73 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 74 | 0xc0, /* END_COLLECTION */ 75 | 76 | #if 0 77 | 0x26, 0x56, 0x05, /* LOGICAL_MAXIMUM (1366) */ 78 | 0x26, 0x00, 0x03, /* LOGICAL_MAXIMUM (768) */ 79 | #endif 80 | 81 | #define MT_REF_TOUCH_COLLECTION \ 82 | MT_TOUCH_COLLECTION0 \ 83 | 0x26, 0x00, 0x00, /* LOGICAL_MAXIMUM (1366) */ \ 84 | MT_TOUCH_COLLECTION1 \ 85 | 0x26, 0x00, 0x00, /* LOGICAL_MAXIMUM (768) */ \ 86 | MT_TOUCH_COLLECTION2 \ 87 | 88 | #define USAGE_PAGE \ 89 | 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ \ 90 | 0x09, 0x54, /* USAGE (Contact Count) */ \ 91 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 92 | 0x75, 0x08, /* REPORT_SIZE (8) */ \ 93 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ 94 | 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ \ 95 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 96 | 0x09, 0x55, /* USAGE(Contact Count Maximum) */ \ 97 | 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ \ 98 | 99 | // 100 | // This is the default report descriptor for the Hid device provided 101 | // by the mini driver in response to IOCTL_HID_GET_REPORT_DESCRIPTOR. 102 | // 103 | 104 | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR; 105 | 106 | #ifdef DESCRIPTOR_DEF 107 | HID_REPORT_DESCRIPTOR DefaultReportDescriptor[] = { 108 | // 109 | // Multitouch report starts here 110 | // 111 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 112 | 0x09, 0x04, // USAGE (Touch Screen) 113 | 0xa1, 0x01, // COLLECTION (Application) 114 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch) 115 | 0x09, 0x22, // USAGE (Finger) 116 | MT_REF_TOUCH_COLLECTION 117 | MT_REF_TOUCH_COLLECTION 118 | MT_REF_TOUCH_COLLECTION 119 | MT_REF_TOUCH_COLLECTION 120 | MT_REF_TOUCH_COLLECTION 121 | MT_REF_TOUCH_COLLECTION 122 | MT_REF_TOUCH_COLLECTION 123 | MT_REF_TOUCH_COLLECTION 124 | MT_REF_TOUCH_COLLECTION 125 | MT_REF_TOUCH_COLLECTION 126 | USAGE_PAGE 127 | 0xc0, // END_COLLECTION 128 | }; 129 | 130 | 131 | // 132 | // This is the default HID descriptor returned by the mini driver 133 | // in response to IOCTL_HID_GET_DEVICE_DESCRIPTOR. The size 134 | // of report descriptor is currently the size of DefaultReportDescriptor. 135 | // 136 | 137 | CONST HID_DESCRIPTOR DefaultHidDescriptor = { 138 | 0x09, // length of HID descriptor 139 | 0x21, // descriptor type == HID 0x21 140 | 0x0100, // hid spec release 141 | 0x00, // country code == Not Specified 142 | 0x01, // number of HID class descriptors 143 | { 0x22, // descriptor type 144 | sizeof(DefaultReportDescriptor) } // total length of report descriptor 145 | }; 146 | #endif 147 | 148 | #define true 1 149 | #define false 0 150 | 151 | typedef struct _ELAN_CONTEXT 152 | { 153 | 154 | WDFDEVICE FxDevice; 155 | 156 | WDFQUEUE ReportQueue; 157 | 158 | BYTE DeviceMode; 159 | 160 | SPB_CONTEXT I2CContext; 161 | 162 | WDFINTERRUPT Interrupt; 163 | 164 | BOOLEAN ConnectInterrupt; 165 | 166 | BOOLEAN TouchScreenBooted; 167 | 168 | BOOLEAN RegsSet; 169 | 170 | UINT32 TouchCount; 171 | 172 | uint8_t Flags[20]; 173 | 174 | USHORT XValue[20]; 175 | 176 | USHORT YValue[20]; 177 | 178 | USHORT AREA[20]; 179 | 180 | uint16_t max_x; 181 | uint16_t max_y; 182 | 183 | uint8_t max_x_hid[2]; 184 | uint8_t max_y_hid[2]; 185 | 186 | } ELAN_CONTEXT, *PELAN_CONTEXT; 187 | 188 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(ELAN_CONTEXT, GetDeviceContext) 189 | 190 | // 191 | // Function definitions 192 | // 193 | 194 | extern "C" { 195 | DRIVER_INITIALIZE DriverEntry; 196 | } 197 | 198 | EVT_WDF_DRIVER_UNLOAD ElanDriverUnload; 199 | 200 | EVT_WDF_DRIVER_DEVICE_ADD ElanEvtDeviceAdd; 201 | 202 | EVT_WDFDEVICE_WDM_IRP_PREPROCESS ElanEvtWdmPreprocessMnQueryId; 203 | 204 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL ElanEvtInternalDeviceControl; 205 | 206 | NTSTATUS 207 | ElanGetHidDescriptor( 208 | IN WDFDEVICE Device, 209 | IN WDFREQUEST Request 210 | ); 211 | 212 | NTSTATUS 213 | ElanGetReportDescriptor( 214 | IN WDFDEVICE Device, 215 | IN WDFREQUEST Request 216 | ); 217 | 218 | NTSTATUS 219 | ElanGetDeviceAttributes( 220 | IN WDFREQUEST Request 221 | ); 222 | 223 | NTSTATUS 224 | ElanGetString( 225 | IN WDFREQUEST Request 226 | ); 227 | 228 | NTSTATUS 229 | ElanWriteReport( 230 | IN PELAN_CONTEXT DevContext, 231 | IN WDFREQUEST Request 232 | ); 233 | 234 | NTSTATUS 235 | ElanProcessVendorReport( 236 | IN PELAN_CONTEXT DevContext, 237 | IN PVOID ReportBuffer, 238 | IN ULONG ReportBufferLen, 239 | OUT size_t* BytesWritten 240 | ); 241 | 242 | NTSTATUS 243 | ElanReadReport( 244 | IN PELAN_CONTEXT DevContext, 245 | IN WDFREQUEST Request, 246 | OUT BOOLEAN* CompleteRequest 247 | ); 248 | 249 | NTSTATUS 250 | ElanSetFeature( 251 | IN PELAN_CONTEXT DevContext, 252 | IN WDFREQUEST Request, 253 | OUT BOOLEAN* CompleteRequest 254 | ); 255 | 256 | NTSTATUS 257 | ElanGetFeature( 258 | IN PELAN_CONTEXT DevContext, 259 | IN WDFREQUEST Request, 260 | OUT BOOLEAN* CompleteRequest 261 | ); 262 | 263 | PCHAR 264 | DbgHidInternalIoctlString( 265 | IN ULONG IoControlCode 266 | ); 267 | 268 | // 269 | // Helper macros 270 | // 271 | 272 | #define DEBUG_LEVEL_ERROR 1 273 | #define DEBUG_LEVEL_INFO 2 274 | #define DEBUG_LEVEL_VERBOSE 3 275 | 276 | #define DBG_INIT 1 277 | #define DBG_PNP 2 278 | #define DBG_IOCTL 4 279 | 280 | #if 0 281 | #define ElanPrint(dbglevel, dbgcatagory, fmt, ...) { \ 282 | if (ElanDebugLevel >= dbglevel && \ 283 | (ElanDebugCatagories && dbgcatagory)) \ 284 | { \ 285 | DbgPrint(DRIVERNAME); \ 286 | DbgPrint(fmt, __VA_ARGS__); \ 287 | } \ 288 | } 289 | #else 290 | #define ElanPrint(dbglevel, fmt, ...) { \ 291 | } 292 | #endif 293 | 294 | #endif -------------------------------------------------------------------------------- /crostouchscreen2/spb.cpp: -------------------------------------------------------------------------------- 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 "elan.h" 22 | #include "spb.h" 23 | #include 24 | 25 | static ULONG ElanDebugLevel = 100; 26 | static ULONG ElanDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 27 | 28 | NTSTATUS 29 | SpbDoWriteDataSynchronously( 30 | IN SPB_CONTEXT *SpbContext, 31 | IN PVOID Data, 32 | IN ULONG Length 33 | ) 34 | /*++ 35 | 36 | Routine Description: 37 | 38 | This helper routine abstracts creating and sending an I/O 39 | request (I2C Write) to the Spb I/O target. 40 | 41 | Arguments: 42 | 43 | SpbContext - Pointer to the current device context 44 | Address - The I2C register address to write to 45 | Data - A buffer to receive the data at at the above address 46 | Length - The amount of data to be read from the above address 47 | 48 | Return Value: 49 | 50 | NTSTATUS Status indicating success or failure 51 | 52 | --*/ 53 | { 54 | PUCHAR buffer; 55 | ULONG length; 56 | WDFMEMORY memory; 57 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 58 | NTSTATUS status; 59 | 60 | // 61 | // The address pointer and data buffer must be combined 62 | // into one contiguous buffer representing the write transaction. 63 | // 64 | length = Length; 65 | memory = NULL; 66 | 67 | if (length > DEFAULT_SPB_BUFFER_SIZE) 68 | { 69 | status = WdfMemoryCreate( 70 | WDF_NO_OBJECT_ATTRIBUTES, 71 | NonPagedPool, 72 | ELAN_POOL_TAG, 73 | length, 74 | &memory, 75 | (PVOID *)&buffer); 76 | 77 | if (!NT_SUCCESS(status)) 78 | { 79 | ElanPrint( 80 | DEBUG_LEVEL_ERROR, 81 | DBG_IOCTL, 82 | "Error allocating memory for Spb write - %!STATUS!", 83 | status); 84 | goto exit; 85 | } 86 | 87 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 88 | &memoryDescriptor, 89 | memory, 90 | NULL); 91 | } 92 | else 93 | { 94 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->WriteMemory, NULL); 95 | 96 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 97 | &memoryDescriptor, 98 | (PVOID)buffer, 99 | length); 100 | } 101 | 102 | // 103 | // Address is followed by the data payload 104 | // 105 | RtlCopyMemory(buffer, Data, length); 106 | 107 | status = WdfIoTargetSendWriteSynchronously( 108 | SpbContext->SpbIoTarget, 109 | NULL, 110 | &memoryDescriptor, 111 | NULL, 112 | NULL, 113 | NULL); 114 | 115 | if (!NT_SUCCESS(status)) 116 | { 117 | ElanPrint( 118 | DEBUG_LEVEL_ERROR, 119 | DBG_IOCTL, 120 | "Error writing to Spb - %!STATUS!", 121 | status); 122 | goto exit; 123 | } 124 | 125 | exit: 126 | 127 | if (NULL != memory) 128 | { 129 | WdfObjectDelete(memory); 130 | } 131 | 132 | return status; 133 | } 134 | 135 | NTSTATUS 136 | SpbWriteDataSynchronously( 137 | IN SPB_CONTEXT *SpbContext, 138 | IN PVOID Data, 139 | IN ULONG Length 140 | ) 141 | /*++ 142 | 143 | Routine Description: 144 | 145 | This routine abstracts creating and sending an I/O 146 | request (I2C Write) to the Spb I/O target and utilizes 147 | a helper routine to do work inside of locked code. 148 | 149 | Arguments: 150 | 151 | SpbContext - Pointer to the current device context 152 | Address - The I2C register address to write to 153 | Data - A buffer to receive the data at at the above address 154 | Length - The amount of data to be read from the above address 155 | 156 | Return Value: 157 | 158 | NTSTATUS Status indicating success or failure 159 | 160 | --*/ 161 | { 162 | NTSTATUS status; 163 | 164 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 165 | 166 | status = SpbDoWriteDataSynchronously( 167 | SpbContext, 168 | Data, 169 | Length); 170 | 171 | WdfWaitLockRelease(SpbContext->SpbLock); 172 | 173 | return status; 174 | } 175 | 176 | NTSTATUS 177 | SpbXferDataSynchronously( 178 | _In_ SPB_CONTEXT* SpbContext, 179 | _In_ PVOID SendData, 180 | _In_ ULONG SendLength, 181 | _In_reads_bytes_(Length) PVOID Data, 182 | _In_ ULONG Length 183 | ) 184 | /*++ 185 | Routine Description: 186 | This helper routine abstracts creating and sending an I/O 187 | request (I2C Read) to the Spb I/O target. 188 | Arguments: 189 | SpbContext - Pointer to the current device context 190 | Address - The I2C register address to read from 191 | Data - A buffer to receive the data at at the above address 192 | Length - The amount of data to be read from the above address 193 | Return Value: 194 | NTSTATUS Status indicating success or failure 195 | --*/ 196 | { 197 | PUCHAR buffer; 198 | WDFMEMORY memory; 199 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 200 | NTSTATUS status; 201 | ULONG_PTR bytesRead; 202 | 203 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 204 | 205 | memory = NULL; 206 | status = STATUS_INVALID_PARAMETER; 207 | bytesRead = 0; 208 | 209 | // 210 | // Xfer transactions start by writing an address pointer 211 | // 212 | status = SpbDoWriteDataSynchronously( 213 | SpbContext, 214 | SendData, 215 | SendLength); 216 | 217 | if (!NT_SUCCESS(status)) 218 | { 219 | ElanPrint( 220 | DEBUG_LEVEL_ERROR, 221 | DBG_IOCTL, 222 | "Error setting address pointer for Spb read - %!STATUS!", 223 | status); 224 | goto exit; 225 | } 226 | 227 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 228 | { 229 | status = WdfMemoryCreate( 230 | WDF_NO_OBJECT_ATTRIBUTES, 231 | NonPagedPool, 232 | ELAN_POOL_TAG, 233 | Length, 234 | &memory, 235 | (PVOID*)&buffer); 236 | 237 | if (!NT_SUCCESS(status)) 238 | { 239 | ElanPrint( 240 | DEBUG_LEVEL_ERROR, 241 | DBG_IOCTL, 242 | "Error allocating memory for Spb read - %!STATUS!", 243 | status); 244 | goto exit; 245 | } 246 | 247 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 248 | &memoryDescriptor, 249 | memory, 250 | NULL); 251 | } 252 | else 253 | { 254 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 255 | 256 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 257 | &memoryDescriptor, 258 | (PVOID)buffer, 259 | Length); 260 | } 261 | 262 | 263 | status = WdfIoTargetSendReadSynchronously( 264 | SpbContext->SpbIoTarget, 265 | NULL, 266 | &memoryDescriptor, 267 | NULL, 268 | NULL, 269 | &bytesRead); 270 | 271 | if (!NT_SUCCESS(status) || 272 | bytesRead != Length) 273 | { 274 | ElanPrint( 275 | DEBUG_LEVEL_ERROR, 276 | DBG_IOCTL, 277 | "Error reading from Spb - %!STATUS!", 278 | status); 279 | goto exit; 280 | } 281 | 282 | // 283 | // Copy back to the caller's buffer 284 | // 285 | RtlCopyMemory(Data, buffer, Length); 286 | 287 | exit: 288 | if (NULL != memory) 289 | { 290 | WdfObjectDelete(memory); 291 | } 292 | 293 | WdfWaitLockRelease(SpbContext->SpbLock); 294 | 295 | return status; 296 | } 297 | 298 | NTSTATUS 299 | SpbReadDataSynchronously( 300 | _In_ SPB_CONTEXT *SpbContext, 301 | _In_reads_bytes_(Length) PVOID Data, 302 | _In_ ULONG Length 303 | ) 304 | /*++ 305 | 306 | Routine Description: 307 | 308 | This helper routine abstracts creating and sending an I/O 309 | request (I2C Read) to the Spb I/O target. 310 | 311 | Arguments: 312 | 313 | SpbContext - Pointer to the current device context 314 | Address - The I2C register address to read from 315 | Data - A buffer to receive the data at at the above address 316 | Length - The amount of data to be read from the above address 317 | 318 | Return Value: 319 | 320 | NTSTATUS Status indicating success or failure 321 | 322 | --*/ 323 | { 324 | PUCHAR buffer; 325 | WDFMEMORY memory; 326 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 327 | NTSTATUS status; 328 | ULONG_PTR bytesRead; 329 | 330 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 331 | 332 | memory = NULL; 333 | status = STATUS_INVALID_PARAMETER; 334 | bytesRead = 0; 335 | 336 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 337 | { 338 | status = WdfMemoryCreate( 339 | WDF_NO_OBJECT_ATTRIBUTES, 340 | NonPagedPool, 341 | ELAN_POOL_TAG, 342 | Length, 343 | &memory, 344 | (PVOID *)&buffer); 345 | 346 | if (!NT_SUCCESS(status)) 347 | { 348 | ElanPrint( 349 | DEBUG_LEVEL_ERROR, 350 | DBG_IOCTL, 351 | "Error allocating memory for Spb read - %!STATUS!", 352 | status); 353 | goto exit; 354 | } 355 | 356 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 357 | &memoryDescriptor, 358 | memory, 359 | NULL); 360 | } 361 | else 362 | { 363 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 364 | 365 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 366 | &memoryDescriptor, 367 | (PVOID)buffer, 368 | Length); 369 | } 370 | 371 | 372 | status = WdfIoTargetSendReadSynchronously( 373 | SpbContext->SpbIoTarget, 374 | NULL, 375 | &memoryDescriptor, 376 | NULL, 377 | NULL, 378 | &bytesRead); 379 | 380 | if (!NT_SUCCESS(status) || 381 | bytesRead != Length) 382 | { 383 | ElanPrint( 384 | DEBUG_LEVEL_ERROR, 385 | DBG_IOCTL, 386 | "Error reading from Spb - %!STATUS!", 387 | status); 388 | goto exit; 389 | } 390 | 391 | // 392 | // Copy back to the caller's buffer 393 | // 394 | RtlCopyMemory(Data, buffer, Length); 395 | 396 | exit: 397 | if (NULL != memory) 398 | { 399 | WdfObjectDelete(memory); 400 | } 401 | 402 | WdfWaitLockRelease(SpbContext->SpbLock); 403 | 404 | return status; 405 | } 406 | 407 | VOID 408 | SpbTargetDeinitialize( 409 | IN WDFDEVICE FxDevice, 410 | IN SPB_CONTEXT *SpbContext 411 | ) 412 | /*++ 413 | 414 | Routine Description: 415 | 416 | This helper routine is used to free any members added to the SPB_CONTEXT, 417 | note the SPB I/O target is parented to the device and will be 418 | closed and free'd when the device is removed. 419 | 420 | Arguments: 421 | 422 | FxDevice - Handle to the framework device object 423 | SpbContext - Pointer to the current device context 424 | 425 | Return Value: 426 | 427 | NTSTATUS Status indicating success or failure 428 | 429 | --*/ 430 | { 431 | UNREFERENCED_PARAMETER(FxDevice); 432 | UNREFERENCED_PARAMETER(SpbContext); 433 | 434 | // 435 | // Free any SPB_CONTEXT allocations here 436 | // 437 | if (SpbContext->SpbLock != NULL) 438 | { 439 | WdfObjectDelete(SpbContext->SpbLock); 440 | } 441 | 442 | if (SpbContext->ReadMemory != NULL) 443 | { 444 | WdfObjectDelete(SpbContext->ReadMemory); 445 | } 446 | 447 | if (SpbContext->WriteMemory != NULL) 448 | { 449 | WdfObjectDelete(SpbContext->WriteMemory); 450 | } 451 | } 452 | 453 | NTSTATUS 454 | SpbTargetInitialize( 455 | IN WDFDEVICE FxDevice, 456 | IN SPB_CONTEXT *SpbContext 457 | ) 458 | /*++ 459 | 460 | Routine Description: 461 | 462 | This helper routine opens the Spb I/O target and 463 | initializes a request object used for the lifetime 464 | of communication between this driver and Spb. 465 | 466 | Arguments: 467 | 468 | FxDevice - Handle to the framework device object 469 | SpbContext - Pointer to the current device context 470 | 471 | Return Value: 472 | 473 | NTSTATUS Status indicating success or failure 474 | 475 | --*/ 476 | { 477 | WDF_OBJECT_ATTRIBUTES objectAttributes; 478 | WDF_IO_TARGET_OPEN_PARAMS openParams; 479 | UNICODE_STRING spbDeviceName; 480 | WCHAR spbDeviceNameBuffer[RESOURCE_HUB_PATH_SIZE]; 481 | NTSTATUS status; 482 | 483 | WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); 484 | objectAttributes.ParentObject = FxDevice; 485 | 486 | status = WdfIoTargetCreate( 487 | FxDevice, 488 | &objectAttributes, 489 | &SpbContext->SpbIoTarget); 490 | 491 | if (!NT_SUCCESS(status)) 492 | { 493 | ElanPrint( 494 | DEBUG_LEVEL_ERROR, 495 | DBG_IOCTL, 496 | "Error creating IoTarget object - %!STATUS!", 497 | status); 498 | 499 | WdfObjectDelete(SpbContext->SpbIoTarget); 500 | goto exit; 501 | } 502 | 503 | RtlInitEmptyUnicodeString( 504 | &spbDeviceName, 505 | spbDeviceNameBuffer, 506 | sizeof(spbDeviceNameBuffer)); 507 | 508 | status = RESOURCE_HUB_CREATE_PATH_FROM_ID( 509 | &spbDeviceName, 510 | SpbContext->I2cResHubId.LowPart, 511 | SpbContext->I2cResHubId.HighPart); 512 | 513 | if (!NT_SUCCESS(status)) 514 | { 515 | ElanPrint( 516 | DEBUG_LEVEL_ERROR, 517 | DBG_IOCTL, 518 | "Error creating Spb resource hub path string - %!STATUS!", 519 | status); 520 | goto exit; 521 | } 522 | 523 | WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( 524 | &openParams, 525 | &spbDeviceName, 526 | (GENERIC_READ | GENERIC_WRITE)); 527 | 528 | openParams.ShareAccess = 0; 529 | openParams.CreateDisposition = FILE_OPEN; 530 | openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; 531 | 532 | status = WdfIoTargetOpen(SpbContext->SpbIoTarget, &openParams); 533 | 534 | if (!NT_SUCCESS(status)) 535 | { 536 | ElanPrint( 537 | DEBUG_LEVEL_ERROR, 538 | DBG_IOCTL, 539 | "Error opening Spb target for communication - %!STATUS!", 540 | status); 541 | goto exit; 542 | } 543 | 544 | // 545 | // Allocate some fixed-size buffers from NonPagedPool for typical 546 | // Spb transaction sizes to avoid pool fragmentation in most cases 547 | // 548 | status = WdfMemoryCreate( 549 | WDF_NO_OBJECT_ATTRIBUTES, 550 | NonPagedPool, 551 | ELAN_POOL_TAG, 552 | DEFAULT_SPB_BUFFER_SIZE, 553 | &SpbContext->WriteMemory, 554 | NULL); 555 | 556 | if (!NT_SUCCESS(status)) 557 | { 558 | ElanPrint( 559 | DEBUG_LEVEL_ERROR, 560 | DBG_IOCTL, 561 | "Error allocating default memory for Spb write - %!STATUS!", 562 | status); 563 | goto exit; 564 | } 565 | 566 | status = WdfMemoryCreate( 567 | WDF_NO_OBJECT_ATTRIBUTES, 568 | NonPagedPool, 569 | ELAN_POOL_TAG, 570 | DEFAULT_SPB_BUFFER_SIZE, 571 | &SpbContext->ReadMemory, 572 | NULL); 573 | 574 | if (!NT_SUCCESS(status)) 575 | { 576 | ElanPrint( 577 | DEBUG_LEVEL_ERROR, 578 | DBG_IOCTL, 579 | "Error allocating default memory for Spb read - %!STATUS!", 580 | status); 581 | goto exit; 582 | } 583 | 584 | // 585 | // Allocate a waitlock to guard access to the default buffers 586 | // 587 | status = WdfWaitLockCreate( 588 | WDF_NO_OBJECT_ATTRIBUTES, 589 | &SpbContext->SpbLock); 590 | 591 | if (!NT_SUCCESS(status)) 592 | { 593 | ElanPrint( 594 | DEBUG_LEVEL_ERROR, 595 | DBG_IOCTL, 596 | "Error creating Spb Waitlock - %!STATUS!", 597 | status); 598 | goto exit; 599 | } 600 | 601 | exit: 602 | 603 | if (!NT_SUCCESS(status)) 604 | { 605 | SpbTargetDeinitialize(FxDevice, SpbContext); 606 | } 607 | 608 | return status; 609 | } -------------------------------------------------------------------------------- /crostouchscreen2/crostouchscreen2.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 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D} 55 | {1bc93793-694f-48fe-9372-81e2b05556fd} 56 | v4.5 57 | 11.0 58 | Win8.1 Debug 59 | Win32 60 | crostouchscreen2 61 | 10.0.22000.0 62 | 63 | 64 | 65 | WindowsV6.3 66 | true 67 | WindowsKernelModeDriver10.0 68 | Driver 69 | KMDF 70 | 71 | 72 | WindowsV6.3 73 | false 74 | WindowsKernelModeDriver10.0 75 | Driver 76 | KMDF 77 | 78 | 79 | Windows8 80 | true 81 | WindowsKernelModeDriver10.0 82 | Driver 83 | KMDF 84 | 85 | 86 | Windows8 87 | false 88 | WindowsKernelModeDriver10.0 89 | Driver 90 | KMDF 91 | 92 | 93 | Windows7 94 | true 95 | WindowsKernelModeDriver10.0 96 | Driver 97 | KMDF 98 | 99 | 100 | Windows7 101 | false 102 | WindowsKernelModeDriver10.0 103 | Driver 104 | KMDF 105 | 106 | 107 | WindowsV6.3 108 | true 109 | WindowsKernelModeDriver10.0 110 | Driver 111 | KMDF 112 | 113 | 114 | WindowsV6.3 115 | false 116 | WindowsKernelModeDriver10.0 117 | Driver 118 | KMDF 119 | 120 | 121 | Windows8 122 | true 123 | WindowsKernelModeDriver10.0 124 | Driver 125 | KMDF 126 | 127 | 128 | Windows8 129 | false 130 | WindowsKernelModeDriver10.0 131 | Driver 132 | KMDF 133 | 134 | 135 | Windows7 136 | true 137 | WindowsKernelModeDriver10.0 138 | Driver 139 | KMDF 140 | 141 | 142 | Windows7 143 | false 144 | WindowsKernelModeDriver10.0 145 | Driver 146 | KMDF 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | DbgengKernelDebugger 158 | 159 | 160 | DbgengKernelDebugger 161 | 162 | 163 | DbgengKernelDebugger 164 | 165 | 166 | DbgengKernelDebugger 167 | 168 | 169 | DbgengKernelDebugger 170 | 171 | 172 | DbgengKernelDebugger 173 | 174 | 175 | DbgengKernelDebugger 176 | 177 | 178 | DbgengKernelDebugger 179 | 180 | 181 | DbgengKernelDebugger 182 | 183 | 184 | DbgengKernelDebugger 185 | 186 | 187 | DbgengKernelDebugger 188 | 189 | 190 | DbgengKernelDebugger 191 | 192 | 193 | 194 | true 195 | trace.h 196 | true 197 | false 198 | 199 | 200 | 2.9.3 201 | 202 | 203 | 204 | 205 | true 206 | trace.h 207 | true 208 | false 209 | 210 | 211 | 2.9.3 212 | 213 | 214 | 215 | 216 | true 217 | trace.h 218 | true 219 | false 220 | 221 | 222 | 2.9.3 223 | 224 | 225 | 226 | 227 | true 228 | trace.h 229 | true 230 | false 231 | 232 | 233 | 2.9.3 234 | 235 | 236 | 237 | 238 | true 239 | trace.h 240 | true 241 | false 242 | 243 | 244 | 2.9.3 245 | 246 | 247 | 248 | 249 | true 250 | trace.h 251 | true 252 | false 253 | 254 | 255 | 2.9.3 256 | 257 | 258 | 259 | 260 | true 261 | trace.h 262 | true 263 | false 264 | 265 | 266 | 2.9.3 267 | 268 | 269 | 270 | 271 | true 272 | trace.h 273 | true 274 | false 275 | 276 | 277 | 2.9.3 278 | 279 | 280 | 281 | 282 | true 283 | trace.h 284 | true 285 | false 286 | 287 | 288 | 2.9.3 289 | 290 | 291 | 292 | 293 | true 294 | trace.h 295 | true 296 | false 297 | 298 | 299 | 2.9.3 300 | 301 | 302 | 303 | 304 | true 305 | trace.h 306 | true 307 | false 308 | 309 | 310 | 2.9.3 311 | 312 | 313 | 314 | 315 | true 316 | trace.h 317 | true 318 | false 319 | 320 | 321 | 2.9.3 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | -------------------------------------------------------------------------------- /crostouchscreen2 Package/crostouchscreen2 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 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F} 55 | {4605da2c-74a5-4865-98e1-152ef136825f} 56 | v4.5 57 | 11.0 58 | Win8.1 Debug 59 | Win32 60 | crostouchscreen2_Package 61 | $(LatestTargetPlatformVersion) 62 | 63 | 64 | 65 | WindowsV6.3 66 | true 67 | WindowsKernelModeDriver10.0 68 | Utility 69 | Package 70 | true 71 | 72 | 73 | WindowsV6.3 74 | false 75 | WindowsKernelModeDriver10.0 76 | Utility 77 | Package 78 | true 79 | 80 | 81 | Windows8 82 | true 83 | WindowsKernelModeDriver10.0 84 | Utility 85 | Package 86 | true 87 | 88 | 89 | Windows8 90 | false 91 | WindowsKernelModeDriver10.0 92 | Utility 93 | Package 94 | true 95 | 96 | 97 | Windows7 98 | true 99 | WindowsKernelModeDriver10.0 100 | Utility 101 | Package 102 | true 103 | 104 | 105 | Windows7 106 | false 107 | WindowsKernelModeDriver10.0 108 | Utility 109 | Package 110 | true 111 | 112 | 113 | WindowsV6.3 114 | true 115 | WindowsKernelModeDriver10.0 116 | Utility 117 | Package 118 | true 119 | 120 | 121 | WindowsV6.3 122 | false 123 | WindowsKernelModeDriver10.0 124 | Utility 125 | Package 126 | true 127 | 128 | 129 | Windows8 130 | true 131 | WindowsKernelModeDriver10.0 132 | Utility 133 | Package 134 | true 135 | 136 | 137 | Windows8 138 | false 139 | WindowsKernelModeDriver10.0 140 | Utility 141 | Package 142 | true 143 | 144 | 145 | Windows7 146 | true 147 | WindowsKernelModeDriver10.0 148 | Utility 149 | Package 150 | true 151 | 152 | 153 | Windows7 154 | false 155 | WindowsKernelModeDriver10.0 156 | Utility 157 | Package 158 | true 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | DbgengKernelDebugger 170 | False 171 | True 172 | 173 | 174 | 175 | False 176 | False 177 | True 178 | 179 | 133563 180 | 181 | 182 | DbgengKernelDebugger 183 | False 184 | True 185 | 186 | 187 | 188 | False 189 | False 190 | True 191 | 192 | 133563 193 | 194 | 195 | DbgengKernelDebugger 196 | False 197 | True 198 | 199 | 200 | 201 | False 202 | False 203 | True 204 | 205 | 133563 206 | 207 | 208 | DbgengKernelDebugger 209 | False 210 | True 211 | 212 | 213 | 214 | False 215 | False 216 | True 217 | 218 | 133563 219 | 220 | 221 | DbgengKernelDebugger 222 | False 223 | True 224 | 225 | 226 | 227 | False 228 | False 229 | True 230 | 231 | 133563 232 | 233 | 234 | DbgengKernelDebugger 235 | False 236 | True 237 | 238 | 239 | 240 | False 241 | False 242 | True 243 | 244 | 133563 245 | 246 | 247 | DbgengKernelDebugger 248 | False 249 | True 250 | 251 | 252 | 253 | False 254 | False 255 | True 256 | 257 | 133563 258 | 259 | 260 | DbgengKernelDebugger 261 | False 262 | True 263 | 264 | 265 | 266 | False 267 | False 268 | True 269 | 270 | 133563 271 | 272 | 273 | DbgengKernelDebugger 274 | False 275 | True 276 | 277 | 278 | 279 | False 280 | False 281 | True 282 | 283 | 133563 284 | 285 | 286 | DbgengKernelDebugger 287 | False 288 | True 289 | 290 | 291 | 292 | False 293 | False 294 | True 295 | 296 | 133563 297 | 298 | 299 | DbgengKernelDebugger 300 | False 301 | True 302 | 303 | 304 | 305 | False 306 | False 307 | True 308 | 309 | 133563 310 | 311 | 312 | DbgengKernelDebugger 313 | False 314 | True 315 | 316 | 317 | 318 | False 319 | False 320 | True 321 | 322 | 133563 323 | 324 | 325 | 326 | SHA256 327 | 328 | 329 | 330 | 331 | SHA256 332 | 333 | 334 | 335 | 336 | SHA256 337 | 338 | 339 | 340 | 341 | SHA256 342 | 343 | 344 | 345 | 346 | SHA256 347 | 348 | 349 | 350 | 351 | SHA256 352 | 353 | 354 | 355 | 356 | SHA256 357 | 358 | 359 | 360 | 361 | SHA256 362 | 363 | 364 | 365 | 366 | SHA256 367 | 368 | 369 | 370 | 371 | SHA256 372 | 373 | 374 | 375 | 376 | SHA256 377 | 378 | 379 | 380 | 381 | SHA256 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | {36580c07-edc3-4c2b-b45f-6ab017e01a5d} 390 | 391 | 392 | 393 | 394 | 395 | -------------------------------------------------------------------------------- /crostouchscreen2/elan.cpp: -------------------------------------------------------------------------------- 1 | #define DESCRIPTOR_DEF 2 | #include "elan.h" 3 | 4 | static ULONG ElanDebugLevel = 100; 5 | static ULONG ElanDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 6 | 7 | NTSTATUS 8 | DriverEntry( 9 | __in PDRIVER_OBJECT DriverObject, 10 | __in PUNICODE_STRING RegistryPath 11 | ) 12 | { 13 | NTSTATUS status = STATUS_SUCCESS; 14 | WDF_DRIVER_CONFIG config; 15 | WDF_OBJECT_ATTRIBUTES attributes; 16 | 17 | ElanPrint(DEBUG_LEVEL_INFO, DBG_INIT, 18 | "Driver Entry\n"); 19 | 20 | WDF_DRIVER_CONFIG_INIT(&config, ElanEvtDeviceAdd); 21 | 22 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 23 | 24 | // 25 | // Create a framework driver object to represent our driver. 26 | // 27 | 28 | status = WdfDriverCreate(DriverObject, 29 | RegistryPath, 30 | &attributes, 31 | &config, 32 | WDF_NO_HANDLE 33 | ); 34 | 35 | if (!NT_SUCCESS(status)) 36 | { 37 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 38 | "WdfDriverCreate failed with status 0x%x\n", status); 39 | } 40 | 41 | return status; 42 | } 43 | 44 | static NTSTATUS elants_i2c_send(PELAN_CONTEXT pDevice, uint8_t *data, size_t size) { 45 | return SpbWriteDataSynchronously(&pDevice->I2CContext, data, (ULONG)size); 46 | } 47 | 48 | static NTSTATUS elants_i2c_read(PELAN_CONTEXT pDevice, uint8_t *data, size_t size) { 49 | return SpbReadDataSynchronously(&pDevice->I2CContext, data, (ULONG)size); 50 | } 51 | 52 | static NTSTATUS elants_i2c_execute_command(PELAN_CONTEXT pDevice, uint8_t* cmd, size_t cmd_size, 53 | uint8_t* resp, size_t resp_size, const char* cmd_name) { 54 | uint8_t expected_response; 55 | 56 | switch (cmd[0]) { 57 | case CMD_HEADER_READ: 58 | expected_response = CMD_HEADER_RESP; 59 | break; 60 | 61 | case CMD_HEADER_6B_READ: 62 | expected_response = CMD_HEADER_6B_RESP; 63 | break; 64 | 65 | case CMD_HEADER_ROM_READ: 66 | expected_response = CMD_HEADER_ROM_RESP; 67 | break; 68 | 69 | default: 70 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "(%s): invalid command: %s\n", 71 | cmd_name); 72 | return STATUS_INVALID_PARAMETER; 73 | } 74 | 75 | NTSTATUS status = SpbXferDataSynchronously(&pDevice->I2CContext, cmd, cmd_size, resp, resp_size); 76 | if (status != STATUS_SUCCESS) { 77 | return status; 78 | } 79 | 80 | if (resp[FW_HDR_TYPE] != expected_response) { 81 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "unexpected response: %s (0x%x)\n", cmd_name, resp[FW_HDR_TYPE]); 82 | return STATUS_DEVICE_DATA_ERROR; 83 | } 84 | return status; 85 | } 86 | 87 | NTSTATUS BOOTTOUCHSCREEN( 88 | _In_ PELAN_CONTEXT devContext 89 | ) 90 | { 91 | NTSTATUS status = STATUS_SUCCESS; 92 | 93 | LARGE_INTEGER delay; 94 | if (!devContext->TouchScreenBooted) { 95 | #define MAX_RETRIES 3 96 | for (int retries = 0; retries < MAX_RETRIES; retries++) { 97 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Initializing... (attempt %d)\n", retries); 98 | uint8_t soft_rst_cmd[] = { 0x77, 0x77, 0x77, 0x77 }; 99 | status = elants_i2c_send(devContext, soft_rst_cmd, sizeof(soft_rst_cmd)); 100 | 101 | delay.QuadPart = -30 * 10; 102 | KeDelayExecutionThread(KernelMode, FALSE, &delay); 103 | 104 | if (!NT_SUCCESS(status)) { 105 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unable to send soft reset\n"); 106 | if (retries < MAX_RETRIES - 1) { 107 | continue; 108 | } 109 | else { 110 | break; 111 | } 112 | } 113 | 114 | for (int bootretries = 0; bootretries < MAX_RETRIES; bootretries++){ 115 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Booting... (attempt %d)\n", bootretries); 116 | uint8_t boot_cmd[] = { 0x4D, 0x61, 0x69, 0x6E }; 117 | status = elants_i2c_send(devContext, boot_cmd, sizeof(boot_cmd)); 118 | 119 | delay.QuadPart = -1 * BOOT_TIME_DELAY_MS * 10; 120 | KeDelayExecutionThread(KernelMode, FALSE, &delay); 121 | 122 | if (!NT_SUCCESS(status)) { 123 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unable to send boot cmd\n"); 124 | if (bootretries < MAX_RETRIES - 1) { 125 | continue; 126 | } 127 | else { 128 | break; 129 | } 130 | } 131 | 132 | //Get Hello Packet 133 | uint8_t hello_packet[] = { 0x55, 0x55, 0x55, 0x55 }; 134 | 135 | uint8_t buf[HEADER_SIZE]; 136 | status = elants_i2c_read(devContext, buf, sizeof(buf)); 137 | if (status != STATUS_SUCCESS) { 138 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unable to read hello packet!\n"); 139 | if (bootretries < MAX_RETRIES - 1) { 140 | continue; 141 | } 142 | else { 143 | break; 144 | } 145 | } 146 | 147 | if (memcmp(buf, hello_packet, sizeof(hello_packet))) { 148 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Failed to get hello packet! Got: 0x%x 0x%x 0x%x 0x%x\n", buf[0], buf[1], buf[2], buf[3]); 149 | if (bootretries < MAX_RETRIES - 1) { 150 | continue; 151 | } 152 | else { 153 | DbgPrint("Warning: Allow malformed hello packet\n"); 154 | break; 155 | } 156 | } 157 | } 158 | } 159 | if (!NT_SUCCESS(status)) { 160 | return status; 161 | } 162 | 163 | //Begin EKTH3500 query 164 | uint8_t resp[17]; 165 | uint16_t phy_x, phy_y, rows, cols, osr; 166 | uint8_t get_resolution_cmd[] = { 167 | CMD_HEADER_6B_READ, 0x00, 0x00, 0x00, 0x00, 0x00 168 | }; 169 | uint8_t get_osr_cmd[] = { 170 | CMD_HEADER_READ, E_INFO_OSR, 0x00, 0x01 171 | }; 172 | uint8_t get_physical_scan_cmd[] = { 173 | CMD_HEADER_READ, E_INFO_PHY_SCAN, 0x00, 0x01 174 | }; 175 | uint8_t get_physical_drive_cmd[] = { 176 | CMD_HEADER_READ, E_INFO_PHY_DRIVER, 0x00, 0x01 177 | }; 178 | status = elants_i2c_execute_command(devContext, get_resolution_cmd, sizeof(get_resolution_cmd), resp, sizeof(resp), "get resolution"); 179 | if (status != STATUS_SUCCESS) { 180 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unable to get resolution!\n"); 181 | return status; 182 | } 183 | rows = resp[2] + resp[6] + resp[10]; 184 | cols = resp[3] + resp[7] + resp[11]; 185 | 186 | status = elants_i2c_execute_command(devContext, get_osr_cmd, sizeof(get_osr_cmd), resp, sizeof(resp), "get osr"); 187 | if (status != STATUS_SUCCESS) { 188 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unable to get osr!\n"); 189 | return status; 190 | } 191 | 192 | osr = resp[3]; 193 | 194 | status = elants_i2c_execute_command(devContext, get_physical_scan_cmd, sizeof(get_physical_scan_cmd), resp, sizeof(resp), "get physical scan"); 195 | if (status != STATUS_SUCCESS) { 196 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unable to get physical scan!\n"); 197 | return status; 198 | } 199 | 200 | phy_x = (resp[2] << 8) | resp[3]; 201 | 202 | status = elants_i2c_execute_command(devContext, get_physical_drive_cmd, sizeof(get_physical_drive_cmd), resp, sizeof(resp), "get physical drive"); 203 | if (status != STATUS_SUCCESS) { 204 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unable to get physical drive!\n"); 205 | return status; 206 | } 207 | 208 | phy_y = (resp[2] << 8) | resp[3]; 209 | 210 | devContext->max_x = ELAN_TS_RESOLUTION(rows, osr); 211 | devContext->max_y = ELAN_TS_RESOLUTION(cols, osr); 212 | 213 | devContext->max_x_hid[0] = devContext->max_x; 214 | devContext->max_x_hid[1] = devContext->max_x >> 8; 215 | 216 | devContext->max_y_hid[0] = devContext->max_y; 217 | devContext->max_y_hid[1] = devContext->max_y >> 8; 218 | 219 | ElanPrint(DEBUG_LEVEL_INFO, DBG_INIT, "max x: %d, max y: %d, phy x: %d, phy y: %d\n", devContext->max_x, devContext->max_y, phy_x, phy_y); 220 | 221 | uint8_t soft_rst_cmd[] = { 0x77, 0x77, 0x77, 0x77 }; 222 | status = elants_i2c_send(devContext, soft_rst_cmd, sizeof(soft_rst_cmd)); 223 | if (!NT_SUCCESS(status)) { 224 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unable to send soft reset\n"); 225 | return status; 226 | } 227 | 228 | devContext->TouchScreenBooted = true; 229 | } 230 | return status; 231 | } 232 | 233 | NTSTATUS 234 | OnPrepareHardware( 235 | _In_ WDFDEVICE FxDevice, 236 | _In_ WDFCMRESLIST FxResourcesRaw, 237 | _In_ WDFCMRESLIST FxResourcesTranslated 238 | ) 239 | /*++ 240 | 241 | Routine Description: 242 | 243 | This routine caches the SPB resource connection ID. 244 | 245 | Arguments: 246 | 247 | FxDevice - a handle to the framework device object 248 | FxResourcesRaw - list of translated hardware resources that 249 | the PnP manager has assigned to the device 250 | FxResourcesTranslated - list of raw hardware resources that 251 | the PnP manager has assigned to the device 252 | 253 | Return Value: 254 | 255 | Status 256 | 257 | --*/ 258 | { 259 | PELAN_CONTEXT pDevice = GetDeviceContext(FxDevice); 260 | BOOLEAN fSpbResourceFound = FALSE; 261 | NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; 262 | 263 | UNREFERENCED_PARAMETER(FxResourcesRaw); 264 | 265 | // 266 | // Parse the peripheral's resources. 267 | // 268 | 269 | ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); 270 | 271 | for (ULONG i = 0; i < resourceCount; i++) 272 | { 273 | PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 274 | UCHAR Class; 275 | UCHAR Type; 276 | 277 | pDescriptor = WdfCmResourceListGetDescriptor( 278 | FxResourcesTranslated, i); 279 | 280 | switch (pDescriptor->Type) 281 | { 282 | case CmResourceTypeConnection: 283 | // 284 | // Look for I2C or SPI resource and save connection ID. 285 | // 286 | Class = pDescriptor->u.Connection.Class; 287 | Type = pDescriptor->u.Connection.Type; 288 | if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && 289 | Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) 290 | { 291 | if (fSpbResourceFound == FALSE) 292 | { 293 | status = STATUS_SUCCESS; 294 | pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; 295 | pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; 296 | fSpbResourceFound = TRUE; 297 | } 298 | else 299 | { 300 | } 301 | } 302 | break; 303 | default: 304 | // 305 | // Ignoring all other resource types. 306 | // 307 | break; 308 | } 309 | } 310 | 311 | // 312 | // An SPB resource is required. 313 | // 314 | 315 | if (fSpbResourceFound == FALSE) 316 | { 317 | status = STATUS_NOT_FOUND; 318 | } 319 | 320 | status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); 321 | 322 | if (!NT_SUCCESS(status)) 323 | { 324 | return status; 325 | } 326 | 327 | status = BOOTTOUCHSCREEN(pDevice); 328 | 329 | if (!NT_SUCCESS(status)) 330 | { 331 | return status; 332 | } 333 | 334 | return status; 335 | } 336 | 337 | NTSTATUS 338 | OnReleaseHardware( 339 | _In_ WDFDEVICE FxDevice, 340 | _In_ WDFCMRESLIST FxResourcesTranslated 341 | ) 342 | /*++ 343 | 344 | Routine Description: 345 | 346 | Arguments: 347 | 348 | FxDevice - a handle to the framework device object 349 | FxResourcesTranslated - list of raw hardware resources that 350 | the PnP manager has assigned to the device 351 | 352 | Return Value: 353 | 354 | Status 355 | 356 | --*/ 357 | { 358 | PELAN_CONTEXT pDevice = GetDeviceContext(FxDevice); 359 | NTSTATUS status = STATUS_SUCCESS; 360 | 361 | UNREFERENCED_PARAMETER(FxResourcesTranslated); 362 | 363 | SpbTargetDeinitialize(FxDevice, &pDevice->I2CContext); 364 | 365 | return status; 366 | } 367 | 368 | NTSTATUS 369 | OnD0Entry( 370 | _In_ WDFDEVICE FxDevice, 371 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 372 | ) 373 | /*++ 374 | 375 | Routine Description: 376 | 377 | This routine allocates objects needed by the driver. 378 | 379 | Arguments: 380 | 381 | FxDevice - a handle to the framework device object 382 | FxPreviousState - previous power state 383 | 384 | Return Value: 385 | 386 | Status 387 | 388 | --*/ 389 | { 390 | UNREFERENCED_PARAMETER(FxPreviousState); 391 | 392 | PELAN_CONTEXT pDevice = GetDeviceContext(FxDevice); 393 | NTSTATUS status = STATUS_SUCCESS; 394 | 395 | if (!pDevice->TouchScreenBooted) { 396 | status = BOOTTOUCHSCREEN(pDevice); 397 | if (status != STATUS_SUCCESS) { 398 | return status; 399 | } 400 | } 401 | 402 | for (int i = 0; i < 20; i++) { 403 | pDevice->Flags[i] = 0; 404 | } 405 | 406 | pDevice->RegsSet = false; 407 | pDevice->ConnectInterrupt = true; 408 | 409 | return status; 410 | } 411 | 412 | NTSTATUS 413 | OnD0Exit( 414 | _In_ WDFDEVICE FxDevice, 415 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 416 | ) 417 | /*++ 418 | 419 | Routine Description: 420 | 421 | This routine destroys objects needed by the driver. 422 | 423 | Arguments: 424 | 425 | FxDevice - a handle to the framework device object 426 | FxPreviousState - previous power state 427 | 428 | Return Value: 429 | 430 | Status 431 | 432 | --*/ 433 | { 434 | UNREFERENCED_PARAMETER(FxPreviousState); 435 | 436 | PELAN_CONTEXT pDevice = GetDeviceContext(FxDevice); 437 | 438 | pDevice->ConnectInterrupt = false; 439 | pDevice->TouchScreenBooted = false; 440 | 441 | return STATUS_SUCCESS; 442 | } 443 | 444 | void ElanProcessInput(PELAN_CONTEXT pDevice) { 445 | struct _ELAN_MULTITOUCH_REPORT report; 446 | report.ReportID = REPORTID_MTOUCH; 447 | 448 | int count = 0, i = 0; 449 | while (count < 10 && i < 20) { 450 | if (pDevice->Flags[i] != 0) { 451 | report.Touch[count].ContactID = i; 452 | report.Touch[count].Height = pDevice->AREA[i]; 453 | report.Touch[count].Width = pDevice->AREA[i]; 454 | 455 | report.Touch[count].XValue = pDevice->XValue[i]; 456 | report.Touch[count].YValue = pDevice->YValue[i]; 457 | 458 | uint8_t flags = pDevice->Flags[i]; 459 | if (flags & MXT_T9_DETECT) { 460 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 461 | } 462 | else if (flags & MXT_T9_PRESS) { 463 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 464 | } 465 | else if (flags & MXT_T9_RELEASE) { 466 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT; 467 | pDevice->Flags[i] = 0; 468 | } 469 | else 470 | report.Touch[count].Status = 0; 471 | 472 | count++; 473 | } 474 | i++; 475 | } 476 | 477 | report.ActualCount = count; 478 | 479 | if (count > 0) { 480 | size_t bytesWritten; 481 | ElanProcessVendorReport(pDevice, &report, sizeof(report), &bytesWritten); 482 | } 483 | } 484 | 485 | static void elants_i2c_mt_event(PELAN_CONTEXT pDevice, uint8_t *buf) { 486 | unsigned int n_fingers; 487 | uint16_t finger_state; 488 | 489 | n_fingers = buf[FW_POS_STATE + 1] & 0x0f; 490 | finger_state = ((buf[FW_POS_STATE + 1] & 0x30) << 4) | 491 | buf[FW_POS_STATE]; 492 | 493 | for (int i = 0; i < MAX_CONTACT_NUM; i++) { 494 | if (finger_state & 1) { 495 | unsigned int x, y, p, w; 496 | 497 | uint8_t *pos; 498 | 499 | pos = &buf[FW_POS_XY + i * 3]; 500 | x = (((uint16_t)pos[0] & 0xf0) << 4) | pos[1]; 501 | y = (((uint16_t)pos[0] & 0x0f) << 8) | pos[2]; 502 | p = buf[FW_POS_PRESSURE + i]; 503 | w = buf[FW_POS_WIDTH + i]; 504 | 505 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, "i=%d x=%d y=%d p=%d w=%d\n", 506 | i, x, y, p, w); 507 | 508 | pDevice->Flags[i] = MXT_T9_DETECT; 509 | pDevice->XValue[i] = x; 510 | pDevice->YValue[i] = y; 511 | pDevice->AREA[i] = w; 512 | 513 | n_fingers--; 514 | } 515 | else if (pDevice->Flags[i] == MXT_T9_DETECT) { 516 | pDevice->Flags[i] = MXT_T9_RELEASE; 517 | } 518 | finger_state >>= 1; 519 | } 520 | 521 | ElanProcessInput(pDevice); 522 | } 523 | 524 | static uint8_t elants_i2c_calculate_checksum(uint8_t *buf) 525 | { 526 | uint8_t checksum = 0; 527 | uint8_t i; 528 | 529 | for (i = 0; i < FW_POS_CHECKSUM; i++) 530 | checksum += buf[i]; 531 | 532 | return checksum; 533 | } 534 | 535 | static void elants_i2c_event(PELAN_CONTEXT pDevice, uint8_t *buf) { 536 | uint8_t checksum = elants_i2c_calculate_checksum(buf); 537 | 538 | if (buf[FW_POS_CHECKSUM] != checksum) { 539 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "invalid checksum for packet 0x02x: %02x vs. %02x\n", buf[FW_POS_HEADER], checksum, buf[FW_POS_CHECKSUM]); 540 | } 541 | else if (buf[FW_POS_HEADER] != HEADER_REPORT_10_FINGER) { 542 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "unknown packet type: %02x\n", buf[FW_POS_HEADER]); 543 | } 544 | else 545 | elants_i2c_mt_event(pDevice, buf); 546 | } 547 | 548 | BOOLEAN OnInterruptIsr( 549 | WDFINTERRUPT Interrupt, 550 | ULONG MessageID) { 551 | UNREFERENCED_PARAMETER(MessageID); 552 | 553 | WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); 554 | PELAN_CONTEXT pDevice = GetDeviceContext(Device); 555 | 556 | if (!pDevice->ConnectInterrupt) 557 | return false; 558 | 559 | if (!pDevice->TouchScreenBooted) 560 | return false; 561 | 562 | uint8_t buf[MAX_PACKET_SIZE]; 563 | NTSTATUS status = elants_i2c_read(pDevice, buf, sizeof(buf)); 564 | if (!NT_SUCCESS(status)) { 565 | return false; 566 | } 567 | 568 | switch (buf[FW_HDR_TYPE]) { 569 | case QUEUE_HEADER_SINGLE: 570 | elants_i2c_event(pDevice, &buf[HEADER_SIZE]); 571 | break; 572 | case QUEUE_HEADER_NORMAL: 573 | int report_count = buf[FW_HDR_COUNT]; 574 | if (report_count == 0 || report_count > 3) { 575 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "bad report count: %d\n", report_count); 576 | break; 577 | } 578 | 579 | int report_len = buf[FW_HDR_LENGTH] / report_count; 580 | if (report_len != PACKET_SIZE) { 581 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "mismatching report length: %d\n", report_len); 582 | break; 583 | } 584 | 585 | for (int i = 0; i < report_count; i++) { 586 | uint8_t *newbuf = buf + HEADER_SIZE + i * PACKET_SIZE; 587 | elants_i2c_event(pDevice, newbuf); 588 | } 589 | 590 | break; 591 | } 592 | 593 | return true; 594 | } 595 | 596 | NTSTATUS 597 | ElanEvtDeviceAdd( 598 | IN WDFDRIVER Driver, 599 | IN PWDFDEVICE_INIT DeviceInit 600 | ) 601 | { 602 | NTSTATUS status = STATUS_SUCCESS; 603 | WDF_IO_QUEUE_CONFIG queueConfig; 604 | WDF_OBJECT_ATTRIBUTES attributes; 605 | WDFDEVICE device; 606 | WDF_INTERRUPT_CONFIG interruptConfig; 607 | WDFQUEUE queue; 608 | UCHAR minorFunction; 609 | PELAN_CONTEXT devContext; 610 | 611 | UNREFERENCED_PARAMETER(Driver); 612 | 613 | PAGED_CODE(); 614 | 615 | ElanPrint(DEBUG_LEVEL_INFO, DBG_PNP, 616 | "ElanEvtDeviceAdd called\n"); 617 | 618 | // 619 | // Tell framework this is a filter driver. Filter drivers by default are 620 | // not power policy owners. This works well for this driver because 621 | // HIDclass driver is the power policy owner for HID minidrivers. 622 | // 623 | 624 | WdfFdoInitSetFilter(DeviceInit); 625 | 626 | { 627 | WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; 628 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); 629 | 630 | pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; 631 | pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; 632 | pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; 633 | pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; 634 | 635 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); 636 | } 637 | 638 | // 639 | // Setup the device context 640 | // 641 | 642 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, ELAN_CONTEXT); 643 | 644 | // 645 | // Create a framework device object.This call will in turn create 646 | // a WDM device object, attach to the lower stack, and set the 647 | // appropriate flags and attributes. 648 | // 649 | 650 | status = WdfDeviceCreate(&DeviceInit, &attributes, &device); 651 | 652 | if (!NT_SUCCESS(status)) 653 | { 654 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 655 | "WdfDeviceCreate failed with status code 0x%x\n", status); 656 | 657 | return status; 658 | } 659 | 660 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); 661 | 662 | queueConfig.EvtIoInternalDeviceControl = ElanEvtInternalDeviceControl; 663 | 664 | status = WdfIoQueueCreate(device, 665 | &queueConfig, 666 | WDF_NO_OBJECT_ATTRIBUTES, 667 | &queue 668 | ); 669 | 670 | if (!NT_SUCCESS(status)) 671 | { 672 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 673 | "WdfIoQueueCreate failed 0x%x\n", status); 674 | 675 | return status; 676 | } 677 | 678 | // 679 | // Create manual I/O queue to take care of hid report read requests 680 | // 681 | 682 | devContext = GetDeviceContext(device); 683 | 684 | devContext->TouchScreenBooted = false; 685 | 686 | devContext->FxDevice = device; 687 | 688 | WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); 689 | 690 | queueConfig.PowerManaged = WdfFalse; 691 | 692 | status = WdfIoQueueCreate(device, 693 | &queueConfig, 694 | WDF_NO_OBJECT_ATTRIBUTES, 695 | &devContext->ReportQueue 696 | ); 697 | 698 | if (!NT_SUCCESS(status)) 699 | { 700 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 701 | "WdfIoQueueCreate failed 0x%x\n", status); 702 | 703 | return status; 704 | } 705 | 706 | // 707 | // Create an interrupt object for hardware notifications 708 | // 709 | WDF_INTERRUPT_CONFIG_INIT( 710 | &interruptConfig, 711 | OnInterruptIsr, 712 | NULL); 713 | interruptConfig.PassiveHandling = TRUE; 714 | 715 | status = WdfInterruptCreate( 716 | device, 717 | &interruptConfig, 718 | WDF_NO_OBJECT_ATTRIBUTES, 719 | &devContext->Interrupt); 720 | 721 | if (!NT_SUCCESS(status)) 722 | { 723 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 724 | "Error creating WDF interrupt object - %!STATUS!", 725 | status); 726 | 727 | return status; 728 | } 729 | 730 | // 731 | // Initialize DeviceMode 732 | // 733 | 734 | devContext->DeviceMode = DEVICE_MODE_MOUSE; 735 | 736 | return status; 737 | } 738 | 739 | VOID 740 | ElanEvtInternalDeviceControl( 741 | IN WDFQUEUE Queue, 742 | IN WDFREQUEST Request, 743 | IN size_t OutputBufferLength, 744 | IN size_t InputBufferLength, 745 | IN ULONG IoControlCode 746 | ) 747 | { 748 | NTSTATUS status = STATUS_SUCCESS; 749 | WDFDEVICE device; 750 | PELAN_CONTEXT devContext; 751 | BOOLEAN completeRequest = TRUE; 752 | 753 | UNREFERENCED_PARAMETER(OutputBufferLength); 754 | UNREFERENCED_PARAMETER(InputBufferLength); 755 | 756 | device = WdfIoQueueGetDevice(Queue); 757 | devContext = GetDeviceContext(device); 758 | 759 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 760 | "%s, Queue:0x%p, Request:0x%p\n", 761 | DbgHidInternalIoctlString(IoControlCode), 762 | Queue, 763 | Request 764 | ); 765 | 766 | // 767 | // Please note that HIDCLASS provides the buffer in the Irp->UserBuffer 768 | // field irrespective of the ioctl buffer type. However, framework is very 769 | // strict about type checking. You cannot get Irp->UserBuffer by using 770 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 771 | // internal ioctl. So depending on the ioctl code, we will either 772 | // use retreive function or escape to WDM to get the UserBuffer. 773 | // 774 | 775 | switch (IoControlCode) 776 | { 777 | 778 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 779 | // 780 | // Retrieves the device's HID descriptor. 781 | // 782 | status = ElanGetHidDescriptor(device, Request); 783 | break; 784 | 785 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 786 | // 787 | //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure. 788 | // 789 | status = ElanGetDeviceAttributes(Request); 790 | break; 791 | 792 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 793 | // 794 | //Obtains the report descriptor for the HID device. 795 | // 796 | status = ElanGetReportDescriptor(device, Request); 797 | break; 798 | 799 | case IOCTL_HID_GET_STRING: 800 | // 801 | // Requests that the HID minidriver retrieve a human-readable string 802 | // for either the manufacturer ID, the product ID, or the serial number 803 | // from the string descriptor of the device. The minidriver must send 804 | // a Get String Descriptor request to the device, in order to retrieve 805 | // the string descriptor, then it must extract the string at the 806 | // appropriate index from the string descriptor and return it in the 807 | // output buffer indicated by the IRP. Before sending the Get String 808 | // Descriptor request, the minidriver must retrieve the appropriate 809 | // index for the manufacturer ID, the product ID or the serial number 810 | // from the device extension of a top level collection associated with 811 | // the device. 812 | // 813 | status = ElanGetString(Request); 814 | break; 815 | 816 | case IOCTL_HID_WRITE_REPORT: 817 | case IOCTL_HID_SET_OUTPUT_REPORT: 818 | // 819 | //Transmits a class driver-supplied report to the device. 820 | // 821 | status = ElanWriteReport(devContext, Request); 822 | break; 823 | 824 | case IOCTL_HID_READ_REPORT: 825 | case IOCTL_HID_GET_INPUT_REPORT: 826 | // 827 | // Returns a report from the device into a class driver-supplied buffer. 828 | // 829 | status = ElanReadReport(devContext, Request, &completeRequest); 830 | break; 831 | 832 | case IOCTL_HID_SET_FEATURE: 833 | // 834 | // This sends a HID class feature report to a top-level collection of 835 | // a HID class device. 836 | // 837 | status = ElanSetFeature(devContext, Request, &completeRequest); 838 | break; 839 | 840 | case IOCTL_HID_GET_FEATURE: 841 | // 842 | // returns a feature report associated with a top-level collection 843 | // 844 | status = ElanGetFeature(devContext, Request, &completeRequest); 845 | break; 846 | 847 | case IOCTL_HID_ACTIVATE_DEVICE: 848 | // 849 | // Makes the device ready for I/O operations. 850 | // 851 | case IOCTL_HID_DEACTIVATE_DEVICE: 852 | // 853 | // Causes the device to cease operations and terminate all outstanding 854 | // I/O requests. 855 | // 856 | default: 857 | status = STATUS_NOT_SUPPORTED; 858 | break; 859 | } 860 | 861 | if (completeRequest) 862 | { 863 | WdfRequestComplete(Request, status); 864 | 865 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 866 | "%s completed, Queue:0x%p, Request:0x%p\n", 867 | DbgHidInternalIoctlString(IoControlCode), 868 | Queue, 869 | Request 870 | ); 871 | } 872 | else 873 | { 874 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 875 | "%s deferred, Queue:0x%p, Request:0x%p\n", 876 | DbgHidInternalIoctlString(IoControlCode), 877 | Queue, 878 | Request 879 | ); 880 | } 881 | 882 | return; 883 | } 884 | 885 | NTSTATUS 886 | ElanGetHidDescriptor( 887 | IN WDFDEVICE Device, 888 | IN WDFREQUEST Request 889 | ) 890 | { 891 | NTSTATUS status = STATUS_SUCCESS; 892 | size_t bytesToCopy = 0; 893 | WDFMEMORY memory; 894 | 895 | UNREFERENCED_PARAMETER(Device); 896 | 897 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 898 | "ElanGetHidDescriptor Entry\n"); 899 | 900 | // 901 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 902 | // will correctly retrieve buffer from Irp->UserBuffer. 903 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 904 | // field irrespective of the ioctl buffer type. However, framework is very 905 | // strict about type checking. You cannot get Irp->UserBuffer by using 906 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 907 | // internal ioctl. 908 | // 909 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 910 | 911 | if (!NT_SUCCESS(status)) 912 | { 913 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 914 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 915 | 916 | return status; 917 | } 918 | 919 | // 920 | // Use hardcoded "HID Descriptor" 921 | // 922 | bytesToCopy = DefaultHidDescriptor.bLength; 923 | 924 | if (bytesToCopy == 0) 925 | { 926 | status = STATUS_INVALID_DEVICE_STATE; 927 | 928 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 929 | "DefaultHidDescriptor is zero, 0x%x\n", status); 930 | 931 | return status; 932 | } 933 | 934 | status = WdfMemoryCopyFromBuffer(memory, 935 | 0, // Offset 936 | (PVOID)&DefaultHidDescriptor, 937 | bytesToCopy); 938 | 939 | if (!NT_SUCCESS(status)) 940 | { 941 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 942 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 943 | 944 | return status; 945 | } 946 | 947 | // 948 | // Report how many bytes were copied 949 | // 950 | WdfRequestSetInformation(Request, bytesToCopy); 951 | 952 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 953 | "ElanGetHidDescriptor Exit = 0x%x\n", status); 954 | 955 | return status; 956 | } 957 | 958 | NTSTATUS 959 | ElanGetReportDescriptor( 960 | IN WDFDEVICE Device, 961 | IN WDFREQUEST Request 962 | ) 963 | { 964 | NTSTATUS status = STATUS_SUCCESS; 965 | ULONG_PTR bytesToCopy; 966 | WDFMEMORY memory; 967 | 968 | PELAN_CONTEXT devContext = GetDeviceContext(Device); 969 | 970 | UNREFERENCED_PARAMETER(Device); 971 | 972 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 973 | "ElanGetReportDescriptor Entry\n"); 974 | 975 | #define MT_TOUCH_COLLECTION \ 976 | MT_TOUCH_COLLECTION0 \ 977 | 0x26, devContext->max_x_hid[0], devContext->max_x_hid[1], /* LOGICAL_MAXIMUM (WIDTH) */ \ 978 | MT_TOUCH_COLLECTION1 \ 979 | 0x26, devContext->max_y_hid[0], devContext->max_y_hid[1], /* LOGICAL_MAXIMUM (HEIGHT) */ \ 980 | MT_TOUCH_COLLECTION2 \ 981 | 982 | HID_REPORT_DESCRIPTOR ReportDescriptor[] = { 983 | // 984 | // Multitouch report starts here 985 | // 986 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 987 | 0x09, 0x04, // USAGE (Touch Screen) 988 | 0xa1, 0x01, // COLLECTION (Application) 989 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch) 990 | 0x09, 0x22, // USAGE (Finger) 991 | MT_TOUCH_COLLECTION 992 | MT_TOUCH_COLLECTION 993 | MT_TOUCH_COLLECTION 994 | MT_TOUCH_COLLECTION 995 | MT_TOUCH_COLLECTION 996 | MT_TOUCH_COLLECTION 997 | MT_TOUCH_COLLECTION 998 | MT_TOUCH_COLLECTION 999 | MT_TOUCH_COLLECTION 1000 | MT_TOUCH_COLLECTION 1001 | USAGE_PAGE 1002 | 0xc0, // END_COLLECTION 1003 | }; 1004 | 1005 | // 1006 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1007 | // will correctly retrieve buffer from Irp->UserBuffer. 1008 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1009 | // field irrespective of the ioctl buffer type. However, framework is very 1010 | // strict about type checking. You cannot get Irp->UserBuffer by using 1011 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1012 | // internal ioctl. 1013 | // 1014 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 1015 | if (!NT_SUCCESS(status)) 1016 | { 1017 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1018 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 1019 | 1020 | return status; 1021 | } 1022 | 1023 | // 1024 | // Use hardcoded Report descriptor 1025 | // 1026 | bytesToCopy = DefaultHidDescriptor.DescriptorList[0].wReportLength; 1027 | 1028 | if (bytesToCopy == 0) 1029 | { 1030 | status = STATUS_INVALID_DEVICE_STATE; 1031 | 1032 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1033 | "DefaultHidDescriptor's reportLength is zero, 0x%x\n", status); 1034 | 1035 | return status; 1036 | } 1037 | 1038 | status = WdfMemoryCopyFromBuffer(memory, 1039 | 0, 1040 | (PVOID)ReportDescriptor, 1041 | bytesToCopy); 1042 | if (!NT_SUCCESS(status)) 1043 | { 1044 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1045 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1046 | 1047 | return status; 1048 | } 1049 | 1050 | // 1051 | // Report how many bytes were copied 1052 | // 1053 | WdfRequestSetInformation(Request, bytesToCopy); 1054 | 1055 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1056 | "ElanGetReportDescriptor Exit = 0x%x\n", status); 1057 | 1058 | return status; 1059 | } 1060 | 1061 | 1062 | NTSTATUS 1063 | ElanGetDeviceAttributes( 1064 | IN WDFREQUEST Request 1065 | ) 1066 | { 1067 | NTSTATUS status = STATUS_SUCCESS; 1068 | PHID_DEVICE_ATTRIBUTES deviceAttributes = NULL; 1069 | 1070 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1071 | "ElanGetDeviceAttributes Entry\n"); 1072 | 1073 | // 1074 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1075 | // will correctly retrieve buffer from Irp->UserBuffer. 1076 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1077 | // field irrespective of the ioctl buffer type. However, framework is very 1078 | // strict about type checking. You cannot get Irp->UserBuffer by using 1079 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1080 | // internal ioctl. 1081 | // 1082 | status = WdfRequestRetrieveOutputBuffer(Request, 1083 | sizeof(HID_DEVICE_ATTRIBUTES), 1084 | (PVOID *)&deviceAttributes, 1085 | NULL); 1086 | if (!NT_SUCCESS(status)) 1087 | { 1088 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1089 | "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); 1090 | 1091 | return status; 1092 | } 1093 | 1094 | // 1095 | // Set USB device descriptor 1096 | // 1097 | 1098 | deviceAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES); 1099 | deviceAttributes->VendorID = ELAN_VID; 1100 | deviceAttributes->ProductID = ELAN_PID; 1101 | deviceAttributes->VersionNumber = ELAN_VERSION; 1102 | 1103 | // 1104 | // Report how many bytes were copied 1105 | // 1106 | WdfRequestSetInformation(Request, sizeof(HID_DEVICE_ATTRIBUTES)); 1107 | 1108 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1109 | "ElanGetDeviceAttributes Exit = 0x%x\n", status); 1110 | 1111 | return status; 1112 | } 1113 | 1114 | NTSTATUS 1115 | ElanGetString( 1116 | IN WDFREQUEST Request 1117 | ) 1118 | { 1119 | 1120 | NTSTATUS status = STATUS_SUCCESS; 1121 | PWSTR pwstrID; 1122 | size_t lenID; 1123 | WDF_REQUEST_PARAMETERS params; 1124 | void *pStringBuffer = NULL; 1125 | 1126 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1127 | "ElanGetString Entry\n"); 1128 | 1129 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1130 | WdfRequestGetParameters(Request, ¶ms); 1131 | 1132 | switch ((ULONG_PTR)params.Parameters.DeviceIoControl.Type3InputBuffer & 0xFFFF) 1133 | { 1134 | case HID_STRING_ID_IMANUFACTURER: 1135 | pwstrID = L"Elan.\0"; 1136 | break; 1137 | 1138 | case HID_STRING_ID_IPRODUCT: 1139 | pwstrID = L"MaxTouch Touch Screen\0"; 1140 | break; 1141 | 1142 | case HID_STRING_ID_ISERIALNUMBER: 1143 | pwstrID = L"123123123\0"; 1144 | break; 1145 | 1146 | default: 1147 | pwstrID = NULL; 1148 | break; 1149 | } 1150 | 1151 | lenID = pwstrID ? wcslen(pwstrID) * sizeof(WCHAR) + sizeof(UNICODE_NULL) : 0; 1152 | 1153 | if (pwstrID == NULL) 1154 | { 1155 | 1156 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1157 | "ElanGetString Invalid request type\n"); 1158 | 1159 | status = STATUS_INVALID_PARAMETER; 1160 | 1161 | return status; 1162 | } 1163 | 1164 | status = WdfRequestRetrieveOutputBuffer(Request, 1165 | lenID, 1166 | &pStringBuffer, 1167 | &lenID); 1168 | 1169 | if (!NT_SUCCESS(status)) 1170 | { 1171 | 1172 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1173 | "ElanGetString WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1174 | 1175 | return status; 1176 | } 1177 | 1178 | RtlCopyMemory(pStringBuffer, pwstrID, lenID); 1179 | 1180 | WdfRequestSetInformation(Request, lenID); 1181 | 1182 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1183 | "ElanGetString Exit = 0x%x\n", status); 1184 | 1185 | return status; 1186 | } 1187 | 1188 | NTSTATUS 1189 | ElanWriteReport( 1190 | IN PELAN_CONTEXT DevContext, 1191 | IN WDFREQUEST Request 1192 | ) 1193 | { 1194 | NTSTATUS status = STATUS_SUCCESS; 1195 | WDF_REQUEST_PARAMETERS params; 1196 | PHID_XFER_PACKET transferPacket = NULL; 1197 | 1198 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1199 | "ElanWriteReport Entry\n"); 1200 | 1201 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1202 | WdfRequestGetParameters(Request, ¶ms); 1203 | 1204 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1205 | { 1206 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1207 | "ElanWriteReport Xfer packet too small\n"); 1208 | 1209 | status = STATUS_BUFFER_TOO_SMALL; 1210 | } 1211 | else 1212 | { 1213 | 1214 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1215 | 1216 | if (transferPacket == NULL) 1217 | { 1218 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1219 | "ElanWriteReport No xfer packet\n"); 1220 | 1221 | status = STATUS_INVALID_DEVICE_REQUEST; 1222 | } 1223 | else 1224 | { 1225 | // 1226 | // switch on the report id 1227 | // 1228 | 1229 | switch (transferPacket->reportId) 1230 | { 1231 | default: 1232 | 1233 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1234 | "ElanWriteReport Unhandled report type %d\n", transferPacket->reportId); 1235 | 1236 | status = STATUS_INVALID_PARAMETER; 1237 | 1238 | break; 1239 | } 1240 | } 1241 | } 1242 | 1243 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1244 | "ElanWriteReport Exit = 0x%x\n", status); 1245 | 1246 | return status; 1247 | 1248 | } 1249 | 1250 | NTSTATUS 1251 | ElanProcessVendorReport( 1252 | IN PELAN_CONTEXT DevContext, 1253 | IN PVOID ReportBuffer, 1254 | IN ULONG ReportBufferLen, 1255 | OUT size_t* BytesWritten 1256 | ) 1257 | { 1258 | NTSTATUS status = STATUS_SUCCESS; 1259 | WDFREQUEST reqRead; 1260 | PVOID pReadReport = NULL; 1261 | size_t bytesReturned = 0; 1262 | 1263 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1264 | "ElanProcessVendorReport Entry\n"); 1265 | 1266 | status = WdfIoQueueRetrieveNextRequest(DevContext->ReportQueue, 1267 | &reqRead); 1268 | 1269 | if (NT_SUCCESS(status)) 1270 | { 1271 | status = WdfRequestRetrieveOutputBuffer(reqRead, 1272 | ReportBufferLen, 1273 | &pReadReport, 1274 | &bytesReturned); 1275 | 1276 | if (NT_SUCCESS(status)) 1277 | { 1278 | // 1279 | // Copy ReportBuffer into read request 1280 | // 1281 | 1282 | if (bytesReturned > ReportBufferLen) 1283 | { 1284 | bytesReturned = ReportBufferLen; 1285 | } 1286 | 1287 | RtlCopyMemory(pReadReport, 1288 | ReportBuffer, 1289 | bytesReturned); 1290 | 1291 | // 1292 | // Complete read with the number of bytes returned as info 1293 | // 1294 | 1295 | WdfRequestCompleteWithInformation(reqRead, 1296 | status, 1297 | bytesReturned); 1298 | 1299 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1300 | "ElanProcessVendorReport %d bytes returned\n", bytesReturned); 1301 | 1302 | // 1303 | // Return the number of bytes written for the write request completion 1304 | // 1305 | 1306 | *BytesWritten = bytesReturned; 1307 | 1308 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1309 | "%s completed, Queue:0x%p, Request:0x%p\n", 1310 | DbgHidInternalIoctlString(IOCTL_HID_READ_REPORT), 1311 | DevContext->ReportQueue, 1312 | reqRead); 1313 | } 1314 | else 1315 | { 1316 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1317 | "WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1318 | } 1319 | } 1320 | else 1321 | { 1322 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1323 | "WdfIoQueueRetrieveNextRequest failed Status 0x%x\n", status); 1324 | } 1325 | 1326 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1327 | "ElanProcessVendorReport Exit = 0x%x\n", status); 1328 | 1329 | return status; 1330 | } 1331 | 1332 | NTSTATUS 1333 | ElanReadReport( 1334 | IN PELAN_CONTEXT DevContext, 1335 | IN WDFREQUEST Request, 1336 | OUT BOOLEAN* CompleteRequest 1337 | ) 1338 | { 1339 | NTSTATUS status = STATUS_SUCCESS; 1340 | 1341 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1342 | "ElanReadReport Entry\n"); 1343 | 1344 | // 1345 | // Forward this read request to our manual queue 1346 | // (in other words, we are going to defer this request 1347 | // until we have a corresponding write request to 1348 | // match it with) 1349 | // 1350 | 1351 | status = WdfRequestForwardToIoQueue(Request, DevContext->ReportQueue); 1352 | 1353 | if (!NT_SUCCESS(status)) 1354 | { 1355 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1356 | "WdfRequestForwardToIoQueue failed Status 0x%x\n", status); 1357 | } 1358 | else 1359 | { 1360 | *CompleteRequest = FALSE; 1361 | } 1362 | 1363 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1364 | "ElanReadReport Exit = 0x%x\n", status); 1365 | 1366 | return status; 1367 | } 1368 | 1369 | NTSTATUS 1370 | ElanSetFeature( 1371 | IN PELAN_CONTEXT DevContext, 1372 | IN WDFREQUEST Request, 1373 | OUT BOOLEAN* CompleteRequest 1374 | ) 1375 | { 1376 | NTSTATUS status = STATUS_SUCCESS; 1377 | WDF_REQUEST_PARAMETERS params; 1378 | PHID_XFER_PACKET transferPacket = NULL; 1379 | ElanFeatureReport* pReport = NULL; 1380 | 1381 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1382 | "ElanSetFeature Entry\n"); 1383 | 1384 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1385 | WdfRequestGetParameters(Request, ¶ms); 1386 | 1387 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1388 | { 1389 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1390 | "ElanSetFeature Xfer packet too small\n"); 1391 | 1392 | status = STATUS_BUFFER_TOO_SMALL; 1393 | } 1394 | else 1395 | { 1396 | 1397 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1398 | 1399 | if (transferPacket == NULL) 1400 | { 1401 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1402 | "ElanWriteReport No xfer packet\n"); 1403 | 1404 | status = STATUS_INVALID_DEVICE_REQUEST; 1405 | } 1406 | else 1407 | { 1408 | // 1409 | // switch on the report id 1410 | // 1411 | 1412 | switch (transferPacket->reportId) 1413 | { 1414 | case REPORTID_FEATURE: 1415 | 1416 | if (transferPacket->reportBufferLen == sizeof(ElanFeatureReport)) 1417 | { 1418 | pReport = (ElanFeatureReport*)transferPacket->reportBuffer; 1419 | 1420 | DevContext->DeviceMode = pReport->DeviceMode; 1421 | 1422 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1423 | "ElanSetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1424 | } 1425 | else 1426 | { 1427 | status = STATUS_INVALID_PARAMETER; 1428 | 1429 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1430 | "ElanSetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(ElanFeatureReport) (%d)\n", 1431 | transferPacket->reportBufferLen, 1432 | sizeof(ElanFeatureReport)); 1433 | } 1434 | 1435 | break; 1436 | 1437 | default: 1438 | 1439 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1440 | "ElanSetFeature Unhandled report type %d\n", transferPacket->reportId); 1441 | 1442 | status = STATUS_INVALID_PARAMETER; 1443 | 1444 | break; 1445 | } 1446 | } 1447 | } 1448 | 1449 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1450 | "ElanSetFeature Exit = 0x%x\n", status); 1451 | 1452 | return status; 1453 | } 1454 | 1455 | NTSTATUS 1456 | ElanGetFeature( 1457 | IN PELAN_CONTEXT DevContext, 1458 | IN WDFREQUEST Request, 1459 | OUT BOOLEAN* CompleteRequest 1460 | ) 1461 | { 1462 | NTSTATUS status = STATUS_SUCCESS; 1463 | WDF_REQUEST_PARAMETERS params; 1464 | PHID_XFER_PACKET transferPacket = NULL; 1465 | 1466 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1467 | "ElanGetFeature Entry\n"); 1468 | 1469 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1470 | WdfRequestGetParameters(Request, ¶ms); 1471 | 1472 | if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) 1473 | { 1474 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1475 | "ElanGetFeature Xfer packet too small\n"); 1476 | 1477 | status = STATUS_BUFFER_TOO_SMALL; 1478 | } 1479 | else 1480 | { 1481 | 1482 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1483 | 1484 | if (transferPacket == NULL) 1485 | { 1486 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1487 | "ElanGetFeature No xfer packet\n"); 1488 | 1489 | status = STATUS_INVALID_DEVICE_REQUEST; 1490 | } 1491 | else 1492 | { 1493 | // 1494 | // switch on the report id 1495 | // 1496 | 1497 | switch (transferPacket->reportId) 1498 | { 1499 | case REPORTID_MTOUCH: 1500 | { 1501 | 1502 | ElanMaxCountReport* pReport = NULL; 1503 | 1504 | if (transferPacket->reportBufferLen == sizeof(ElanMaxCountReport)) 1505 | { 1506 | pReport = (ElanMaxCountReport*)transferPacket->reportBuffer; 1507 | 1508 | pReport->MaximumCount = MULTI_MAX_COUNT; 1509 | 1510 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1511 | "ElanGetFeature MaximumCount = 0x%x\n", MULTI_MAX_COUNT); 1512 | } 1513 | else 1514 | { 1515 | status = STATUS_INVALID_PARAMETER; 1516 | 1517 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1518 | "ElanGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(ElanMaxCountReport) (%d)\n", 1519 | transferPacket->reportBufferLen, 1520 | sizeof(ElanMaxCountReport)); 1521 | } 1522 | 1523 | break; 1524 | } 1525 | 1526 | case REPORTID_FEATURE: 1527 | { 1528 | 1529 | ElanFeatureReport* pReport = NULL; 1530 | 1531 | if (transferPacket->reportBufferLen == sizeof(ElanFeatureReport)) 1532 | { 1533 | pReport = (ElanFeatureReport*)transferPacket->reportBuffer; 1534 | 1535 | pReport->DeviceMode = DevContext->DeviceMode; 1536 | 1537 | pReport->DeviceIdentifier = 0; 1538 | 1539 | ElanPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1540 | "ElanGetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1541 | } 1542 | else 1543 | { 1544 | status = STATUS_INVALID_PARAMETER; 1545 | 1546 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1547 | "ElanGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(ElanFeatureReport) (%d)\n", 1548 | transferPacket->reportBufferLen, 1549 | sizeof(ElanFeatureReport)); 1550 | } 1551 | 1552 | break; 1553 | } 1554 | 1555 | default: 1556 | 1557 | ElanPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1558 | "ElanGetFeature Unhandled report type %d\n", transferPacket->reportId); 1559 | 1560 | status = STATUS_INVALID_PARAMETER; 1561 | 1562 | break; 1563 | } 1564 | } 1565 | } 1566 | 1567 | ElanPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1568 | "ElanGetFeature Exit = 0x%x\n", status); 1569 | 1570 | return status; 1571 | } 1572 | 1573 | PCHAR 1574 | DbgHidInternalIoctlString( 1575 | IN ULONG IoControlCode 1576 | ) 1577 | { 1578 | switch (IoControlCode) 1579 | { 1580 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 1581 | return "IOCTL_HID_GET_DEVICE_DESCRIPTOR"; 1582 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 1583 | return "IOCTL_HID_GET_REPORT_DESCRIPTOR"; 1584 | case IOCTL_HID_READ_REPORT: 1585 | return "IOCTL_HID_READ_REPORT"; 1586 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 1587 | return "IOCTL_HID_GET_DEVICE_ATTRIBUTES"; 1588 | case IOCTL_HID_WRITE_REPORT: 1589 | return "IOCTL_HID_WRITE_REPORT"; 1590 | case IOCTL_HID_SET_FEATURE: 1591 | return "IOCTL_HID_SET_FEATURE"; 1592 | case IOCTL_HID_GET_FEATURE: 1593 | return "IOCTL_HID_GET_FEATURE"; 1594 | case IOCTL_HID_GET_STRING: 1595 | return "IOCTL_HID_GET_STRING"; 1596 | case IOCTL_HID_ACTIVATE_DEVICE: 1597 | return "IOCTL_HID_ACTIVATE_DEVICE"; 1598 | case IOCTL_HID_DEACTIVATE_DEVICE: 1599 | return "IOCTL_HID_DEACTIVATE_DEVICE"; 1600 | case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: 1601 | return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST"; 1602 | case IOCTL_HID_SET_OUTPUT_REPORT: 1603 | return "IOCTL_HID_SET_OUTPUT_REPORT"; 1604 | case IOCTL_HID_GET_INPUT_REPORT: 1605 | return "IOCTL_HID_GET_INPUT_REPORT"; 1606 | default: 1607 | return "Unknown IOCTL"; 1608 | } 1609 | } --------------------------------------------------------------------------------