├── .gitattributes ├── crostouchscreen2 ├── stdint.h ├── crostouchscreen2.vcxproj.user ├── spb.h ├── trace.h ├── hidcommon.h ├── crostouchscreen2.vcxproj.filters ├── crostouchscreen2.inf ├── mip4_ts.h ├── mlfs.h ├── spb.cpp ├── crostouchscreen2.vcxproj └── mlfs.cpp ├── README.md ├── crostouchscreen2 Package ├── crostouchscreen2 Package.vcxproj.filters ├── crostouchscreen2 Package.vcxproj.user └── crostouchscreen2 Package.vcxproj ├── LICENSE.txt ├── .gitignore └── crostouchscreen2.sln /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /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-melfas 2 | Melfas MIP4 Touch Screen Driver for Braswell/Whiskey Lake/newer chromebooks. 3 | 4 | Tested on Acer C731T-C42N (reks). 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 Package/crostouchscreen2 Package.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | TestSign 8 | CN="WDKTestCert CoolStar,131547800501960319" | 8991599FD6CA439ACBDFBC6D8A4276F0DE420F7F 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /crostouchscreen2/crostouchscreen2.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | CN="WDKTestCert CoolStar,131002039613453615" | 47BA72C5A0D2F559EA9FD7E943B307D1E179A49E 13 | True 14 | 15 | -------------------------------------------------------------------------------- /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 | SpbXferDataSynchronously( 44 | _In_ SPB_CONTEXT* SpbContext, 45 | _In_ PVOID SendData, 46 | _In_ ULONG SendLength, 47 | _In_reads_bytes_(Length) PVOID Data, 48 | _In_ ULONG Length 49 | ); 50 | 51 | VOID 52 | SpbTargetDeinitialize( 53 | IN WDFDEVICE FxDevice, 54 | IN SPB_CONTEXT *SpbContext 55 | ); 56 | 57 | NTSTATUS 58 | SpbTargetInitialize( 59 | IN WDFDEVICE FxDevice, 60 | IN SPB_CONTEXT *SpbContext 61 | ); 62 | 63 | NTSTATUS 64 | SpbWriteDataSynchronously( 65 | IN SPB_CONTEXT *SpbContext, 66 | IN PVOID Data, 67 | IN ULONG Length 68 | ); -------------------------------------------------------------------------------- /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/hidcommon.h: -------------------------------------------------------------------------------- 1 | #if !defined(_MLFS_COMMON_H_) 2 | #define _MLFS_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 MLFS_PID 0xBACC 10 | #define MLFS_VID 0x00FF 11 | #define MLFS_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 _MLFS_MULTITOUCH_REPORT 52 | { 53 | 54 | BYTE ReportID; 55 | 56 | TOUCH Touch[10]; 57 | 58 | BYTE ActualCount; 59 | 60 | } MlfsMultiTouchReport; 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 _MLFS_FEATURE_REPORT 73 | { 74 | 75 | BYTE ReportID; 76 | 77 | BYTE DeviceMode; 78 | 79 | BYTE DeviceIdentifier; 80 | 81 | } MlfsFeatureReport; 82 | 83 | typedef struct _MLFS_MAXCOUNT_REPORT 84 | { 85 | 86 | BYTE ReportID; 87 | 88 | BYTE MaximumCount; 89 | 90 | } MlfsMaxCountReport; 91 | #pragma pack() 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /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 Mlfs 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\MLFS0000 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 Melfas Touch Screen" 78 | CrosTouchScreen.SVCDESC = "CrosTouchScreen Service" 79 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /crostouchscreen2/mip4_ts.h: -------------------------------------------------------------------------------- 1 | #include "stdint.h" 2 | 3 | #define MIP4_DEVICE_NAME "mip4_ts" 4 | 5 | /***************************************************************** 6 | * Protocol 7 | * Version : MIP 4.0 Rev 5.4 8 | *****************************************************************/ 9 | 10 | /* Address */ 11 | #define MIP4_R0_BOOT 0x00 12 | #define MIP4_R1_BOOT_MODE 0x01 13 | #define MIP4_R1_BOOT_BUF_ADDR 0x10 14 | #define MIP4_R1_BOOT_STATUS 0x20 15 | #define MIP4_R1_BOOT_CMD 0x30 16 | #define MIP4_R1_BOOT_TARGET_ADDR 0x40 17 | #define MIP4_R1_BOOT_SIZE 0x44 18 | 19 | #define MIP4_R0_INFO 0x01 20 | #define MIP4_R1_INFO_PRODUCT_NAME 0x00 21 | #define MIP4_R1_INFO_RESOLUTION_X 0x10 22 | #define MIP4_R1_INFO_RESOLUTION_Y 0x12 23 | #define MIP4_R1_INFO_NODE_NUM_X 0x14 24 | #define MIP4_R1_INFO_NODE_NUM_Y 0x15 25 | #define MIP4_R1_INFO_KEY_NUM 0x16 26 | #define MIP4_R1_INFO_PRESSURE_NUM 0x17 27 | #define MIP4_R1_INFO_LENGTH_X 0x18 28 | #define MIP4_R1_INFO_LENGTH_Y 0x1A 29 | #define MIP4_R1_INFO_PPM_X 0x1C 30 | #define MIP4_R1_INFO_PPM_Y 0x1D 31 | #define MIP4_R1_INFO_VERSION_BOOT 0x20 32 | #define MIP4_R1_INFO_VERSION_CORE 0x22 33 | #define MIP4_R1_INFO_VERSION_APP 0x24 34 | #define MIP4_R1_INFO_VERSION_PARAM 0x26 35 | #define MIP4_R1_INFO_SECT_BOOT_START 0x30 36 | #define MIP4_R1_INFO_SECT_BOOT_END 0x31 37 | #define MIP4_R1_INFO_SECT_CORE_START 0x32 38 | #define MIP4_R1_INFO_SECT_CORE_END 0x33 39 | #define MIP4_R1_INFO_SECT_APP_START 0x34 40 | #define MIP4_R1_INFO_SECT_APP_END 0x35 41 | #define MIP4_R1_INFO_SECT_PARAM_START 0x36 42 | #define MIP4_R1_INFO_SECT_PARAM_END 0x37 43 | #define MIP4_R1_INFO_BUILD_DATE 0x40 44 | #define MIP4_R1_INFO_BUILD_TIME 0x44 45 | #define MIP4_R1_INFO_CHECKSUM_PRECALC 0x48 46 | #define MIP4_R1_INFO_CHECKSUM_REALTIME 0x4A 47 | #define MIP4_R1_INFO_PROTOCOL_NAME 0x50 48 | #define MIP4_R1_INFO_PROTOCOL_VERSION 0x58 49 | #define MIP4_R1_INFO_IC_ID 0x70 50 | #define MIP4_R1_INFO_IC_NAME 0x71 51 | #define MIP4_R1_INFO_IC_VENDOR_ID 0x75 52 | #define MIP4_R1_INFO_IC_HW_CATEGORY 0x77 53 | #define MIP4_R1_INFO_CONTACT_THD_SCR 0x78 54 | #define MIP4_R1_INFO_CONTACT_THD_KEY 0x7A 55 | #define MIP4_R1_INFO_PID 0x7C 56 | #define MIP4_R1_INFO_VID 0x7E 57 | #define MIP4_R1_INFO_SLAVE_ADDR 0x80 58 | 59 | #define MIP4_R0_EVENT 0x02 60 | #define MIP4_R1_EVENT_SUPPORTED_FUNC 0x00 61 | #define MIP4_R1_EVENT_FORMAT 0x04 62 | #define MIP4_R1_EVENT_SIZE 0x06 63 | #define MIP4_R1_EVENT_PACKET_INFO 0x10 64 | #define MIP4_R1_EVENT_PACKET_DATA 0x11 65 | 66 | #define MIP4_R0_CTRL 0x06 67 | #define MIP4_R1_CTRL_READY_STATUS 0x00 68 | #define MIP4_R1_CTRL_EVENT_READY 0x01 69 | #define MIP4_R1_CTRL_MODE 0x10 70 | #define MIP4_R1_CTRL_EVENT_TRIGGER_TYPE 0x11 71 | #define MIP4_R1_CTRL_RECALIBRATE 0x12 72 | #define MIP4_R1_CTRL_POWER_STATE 0x13 73 | #define MIP4_R1_CTRL_GESTURE_TYPE 0x14 74 | #define MIP4_R1_CTRL_DISABLE_ESD_ALERT 0x18 75 | #define MIP4_R1_CTRL_CHARGER_MODE 0x19 76 | #define MIP4_R1_CTRL_HIGH_SENS_MODE 0x1A 77 | #define MIP4_R1_CTRL_WINDOW_MODE 0x1B 78 | #define MIP4_R1_CTRL_PALM_REJECTION 0x1C 79 | #define MIP4_R1_CTRL_EDGE_CORRECTION 0x1D 80 | #define MIP4_R1_CTRL_ENTER_GLOVE_MODE 0x1E 81 | #define MIP4_R1_CTRL_I2C_ON_LPM 0x1F 82 | #define MIP4_R1_CTRL_GESTURE_DEBUG 0x20 83 | #define MIP4_R1_CTRL_PALM_EVENT 0x22 84 | #define MIP4_R1_CTRL_PROXIMITY_SENSING 0x23 85 | 86 | /* Value */ 87 | #define MIP4_BOOT_MODE_BOOT 0x01 88 | #define MIP4_BOOT_MODE_APP 0x02 89 | 90 | #define MIP4_BOOT_STATUS_BUSY 0x05 91 | #define MIP4_BOOT_STATUS_ERROR 0x0E 92 | #define MIP4_BOOT_STATUS_DONE 0xA0 93 | 94 | #define MIP4_BOOT_CMD_MASS_ERASE 0x15 95 | #define MIP4_BOOT_CMD_PROGRAM 0x54 96 | #define MIP4_BOOT_CMD_ERASE 0x8F 97 | #define MIP4_BOOT_CMD_WRITE 0xA5 98 | #define MIP4_BOOT_CMD_READ 0xC2 99 | 100 | #define MIP4_EVENT_INPUT_TYPE_KEY 0 101 | #define MIP4_EVENT_INPUT_TYPE_SCREEN 1 102 | #define MIP4_EVENT_INPUT_TYPE_PROXIMITY 2 103 | 104 | #define I2C_RETRY_COUNT 3 /* 2~ */ 105 | 106 | #define MIP4_BUF_SIZE 128 107 | #define MIP4_MAX_FINGERS 10 108 | #define MIP4_MAX_KEYS 4 109 | 110 | #define MIP4_TOUCH_MAJOR_MIN 0 111 | #define MIP4_TOUCH_MAJOR_MAX 255 112 | #define MIP4_TOUCH_MINOR_MIN 0 113 | #define MIP4_TOUCH_MINOR_MAX 255 114 | #define MIP4_PRESSURE_MIN 0 115 | #define MIP4_PRESSURE_MAX 255 116 | 117 | #define MIP4_FW_UPDATE_DEBUG 0 /* 0 (default) or 1 */ 118 | 119 | struct mip4_fw_version { 120 | uint16_t boot; 121 | uint16_t core; 122 | uint16_t app; 123 | uint16_t param; 124 | }; 125 | 126 | #define MXT_T9_RELEASE (1 << 5) 127 | #define MXT_T9_PRESS (1 << 6) 128 | #define MXT_T9_DETECT (1 << 7) -------------------------------------------------------------------------------- /.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/mlfs.h: -------------------------------------------------------------------------------- 1 | #if !defined(_MLFS_H_) 2 | #define _MLFS_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 "mip4_ts.h" 23 | 24 | // 25 | // String definitions 26 | // 27 | 28 | #define DRIVERNAME "crostouchscreen2.sys: " 29 | 30 | #define MLFS_POOL_TAG (ULONG) 'sflM' 31 | 32 | #define NTDEVICE_NAME_STRING L"\\Device\\MLFS0000" 33 | #define SYMBOLIC_NAME_STRING L"\\DosDevices\\MLFS0000" 34 | 35 | #define MT_TOUCH_COLLECTION0 \ 36 | 0xa1, 0x02, /* COLLECTION (Logical) */ \ 37 | 0x09, 0x42, /* USAGE (Tip Switch) */ \ 38 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ 39 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ \ 40 | 0x75, 0x01, /* REPORT_SIZE (1) */ \ 41 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 42 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 43 | 0x09, 0x47, /* USAGE (Confidence) */ \ 44 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 45 | 0x95, 0x06, /* REPORT_COUNT (6) */ \ 46 | 0x81, 0x03, /* INPUT (Cnst,Ary,Abs) */ \ 47 | 0x75, 0x08, /* REPORT_SIZE (8) */ \ 48 | 0x09, 0x51, /* USAGE (Contact Identifier) */ \ 49 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 50 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 51 | 0x05, 0x01, /* USAGE_PAGE (Generic Desk.. */ \ 52 | 0x75, 0x10, /* REPORT_SIZE (16) */ \ 53 | 0x55, 0x00, /* UNIT_EXPONENT (0) */ \ 54 | 0x65, 0x00, /* UNIT (None) */ \ 55 | 0x35, 0x00, /* PHYSICAL_MINIMUM (0) */ \ 56 | 0x46, 0x00, 0x00, /* PHYSICAL_MAXIMUM (0) */ 57 | 58 | 59 | //0x26, 0x56, 0x05, /* LOGICAL_MAXIMUM (1366) */ 60 | 61 | #define MT_TOUCH_COLLECTION1 \ 62 | 0x09, 0x30, /* USAGE (X) */ \ 63 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ 64 | 65 | //0x26, 0x00, 0x03, /* LOGICAL_MAXIMUM (768) */ 66 | 67 | #define MT_TOUCH_COLLECTION2 \ 68 | 0x09, 0x31, /* USAGE (Y) */ \ 69 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 70 | 0x05, 0x0d, /* USAGE PAGE (Digitizers) */ \ 71 | 0x09, 0x48, /* USAGE (Width) */ \ 72 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 73 | 0x09, 0x49, /* USAGE (Height) */ \ 74 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 75 | 0xc0, /* END_COLLECTION */ 76 | 77 | #if 0 78 | 0x26, 0x56, 0x05, /* LOGICAL_MAXIMUM (1366) */ 79 | 0x26, 0x00, 0x03, /* LOGICAL_MAXIMUM (768) */ 80 | #endif 81 | 82 | #define MT_REF_TOUCH_COLLECTION \ 83 | MT_TOUCH_COLLECTION0 \ 84 | 0x26, 0x00, 0x00, /* LOGICAL_MAXIMUM (1366) */ \ 85 | MT_TOUCH_COLLECTION1 \ 86 | 0x26, 0x00, 0x00, /* LOGICAL_MAXIMUM (768) */ \ 87 | MT_TOUCH_COLLECTION2 \ 88 | 89 | #define USAGE_PAGE \ 90 | 0x05, 0x0d, /* USAGE_PAGE (Digitizers) */ \ 91 | 0x09, 0x54, /* USAGE (Contact Count) */ \ 92 | 0x95, 0x01, /* REPORT_COUNT (1) */ \ 93 | 0x75, 0x08, /* REPORT_SIZE (8) */ \ 94 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ \ 95 | 0x25, 0x08, /* LOGICAL_MAXIMUM (8) */ \ 96 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ \ 97 | 0x09, 0x55, /* USAGE(Contact Count Maximum) */ \ 98 | 0xb1, 0x02, /* FEATURE (Data,Var,Abs) */ \ 99 | 100 | // 101 | // This is the default report descriptor for the Hid device provided 102 | // by the mini driver in response to IOCTL_HID_GET_REPORT_DESCRIPTOR. 103 | // 104 | 105 | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR; 106 | 107 | #ifdef DESCRIPTOR_DEF 108 | HID_REPORT_DESCRIPTOR DefaultReportDescriptor[] = { 109 | // 110 | // Multitouch report starts here 111 | // 112 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 113 | 0x09, 0x04, // USAGE (Touch Screen) 114 | 0xa1, 0x01, // COLLECTION (Application) 115 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch) 116 | 0x09, 0x22, // USAGE (Finger) 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 | MT_REF_TOUCH_COLLECTION 127 | USAGE_PAGE 128 | 0xc0, // END_COLLECTION 129 | }; 130 | 131 | 132 | // 133 | // This is the default HID descriptor returned by the mini driver 134 | // in response to IOCTL_HID_GET_DEVICE_DESCRIPTOR. The size 135 | // of report descriptor is currently the size of DefaultReportDescriptor. 136 | // 137 | 138 | CONST HID_DESCRIPTOR DefaultHidDescriptor = { 139 | 0x09, // length of HID descriptor 140 | 0x21, // descriptor type == HID 0x21 141 | 0x0100, // hid spec release 142 | 0x00, // country code == Not Specified 143 | 0x01, // number of HID class descriptors 144 | { 0x22, // descriptor type 145 | sizeof(DefaultReportDescriptor) } // total length of report descriptor 146 | }; 147 | #endif 148 | 149 | #define true 1 150 | #define false 0 151 | 152 | typedef struct _MLFS_CONTEXT 153 | { 154 | 155 | WDFDEVICE FxDevice; 156 | 157 | WDFQUEUE ReportQueue; 158 | 159 | BYTE DeviceMode; 160 | 161 | SPB_CONTEXT I2CContext; 162 | 163 | WDFINTERRUPT Interrupt; 164 | 165 | BOOLEAN ConnectInterrupt; 166 | 167 | BOOLEAN TouchScreenBooted; 168 | 169 | BOOLEAN RegsSet; 170 | 171 | WDFTIMER Timer; 172 | 173 | UINT32 TouchCount; 174 | 175 | uint8_t Flags[20]; 176 | 177 | USHORT XValue[20]; 178 | 179 | USHORT YValue[20]; 180 | 181 | USHORT AREA[20]; 182 | 183 | uint16_t max_x; 184 | uint16_t max_y; 185 | 186 | uint8_t node_x; 187 | uint8_t node_y; 188 | uint8_t node_key; 189 | 190 | uint8_t ppm_x; 191 | uint8_t ppm_y; 192 | 193 | uint16_t event_size; 194 | uint8_t event_format; 195 | 196 | unsigned short key_code[MIP4_MAX_KEYS]; 197 | 198 | uint8_t max_x_hid[2]; 199 | uint8_t max_y_hid[2]; 200 | 201 | } MLFS_CONTEXT, *PMLFS_CONTEXT; 202 | 203 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MLFS_CONTEXT, GetDeviceContext) 204 | 205 | // 206 | // Function definitions 207 | // 208 | 209 | extern "C" { 210 | DRIVER_INITIALIZE DriverEntry; 211 | } 212 | 213 | EVT_WDF_DRIVER_UNLOAD MlfsDriverUnload; 214 | 215 | EVT_WDF_DRIVER_DEVICE_ADD MlfsEvtDeviceAdd; 216 | 217 | EVT_WDFDEVICE_WDM_IRP_PREPROCESS MlfsEvtWdmPreprocessMnQueryId; 218 | 219 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL MlfsEvtInternalDeviceControl; 220 | 221 | NTSTATUS 222 | MlfsGetHidDescriptor( 223 | IN WDFDEVICE Device, 224 | IN WDFREQUEST Request 225 | ); 226 | 227 | NTSTATUS 228 | MlfsGetReportDescriptor( 229 | IN WDFDEVICE Device, 230 | IN WDFREQUEST Request 231 | ); 232 | 233 | NTSTATUS 234 | MlfsGetDeviceAttributes( 235 | IN WDFREQUEST Request 236 | ); 237 | 238 | NTSTATUS 239 | MlfsGetString( 240 | IN WDFREQUEST Request 241 | ); 242 | 243 | NTSTATUS 244 | MlfsWriteReport( 245 | IN PMLFS_CONTEXT DevContext, 246 | IN WDFREQUEST Request 247 | ); 248 | 249 | NTSTATUS 250 | MlfsProcessVendorReport( 251 | IN PMLFS_CONTEXT DevContext, 252 | IN PVOID ReportBuffer, 253 | IN ULONG ReportBufferLen, 254 | OUT size_t* BytesWritten 255 | ); 256 | 257 | NTSTATUS 258 | MlfsReadReport( 259 | IN PMLFS_CONTEXT DevContext, 260 | IN WDFREQUEST Request, 261 | OUT BOOLEAN* CompleteRequest 262 | ); 263 | 264 | NTSTATUS 265 | MlfsSetFeature( 266 | IN PMLFS_CONTEXT DevContext, 267 | IN WDFREQUEST Request, 268 | OUT BOOLEAN* CompleteRequest 269 | ); 270 | 271 | NTSTATUS 272 | MlfsGetFeature( 273 | IN PMLFS_CONTEXT DevContext, 274 | IN WDFREQUEST Request, 275 | OUT BOOLEAN* CompleteRequest 276 | ); 277 | 278 | PCHAR 279 | DbgHidInternalIoctlString( 280 | IN ULONG IoControlCode 281 | ); 282 | 283 | // 284 | // Helper macros 285 | // 286 | 287 | #define DEBUG_LEVEL_ERROR 1 288 | #define DEBUG_LEVEL_INFO 2 289 | #define DEBUG_LEVEL_VERBOSE 3 290 | 291 | #define DBG_INIT 1 292 | #define DBG_PNP 2 293 | #define DBG_IOCTL 4 294 | 295 | #if 0 296 | #define MlfsPrint(dbglevel, dbgcatagory, fmt, ...) { \ 297 | if (MlfsDebugLevel >= dbglevel && \ 298 | (MlfsDebugCatagories && dbgcatagory)) \ 299 | { \ 300 | DbgPrint(DRIVERNAME); \ 301 | DbgPrint(fmt, __VA_ARGS__); \ 302 | } \ 303 | } 304 | #else 305 | #define MlfsPrint(dbglevel, fmt, ...) { \ 306 | } 307 | #endif 308 | 309 | #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 "mlfs.h" 22 | #include "spb.h" 23 | #include 24 | 25 | static ULONG MlfsDebugLevel = 100; 26 | static ULONG MlfsDebugCatagories = 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 | length = Length; 61 | memory = NULL; 62 | 63 | if (length > DEFAULT_SPB_BUFFER_SIZE) 64 | { 65 | status = WdfMemoryCreate( 66 | WDF_NO_OBJECT_ATTRIBUTES, 67 | NonPagedPool, 68 | MLFS_POOL_TAG, 69 | length, 70 | &memory, 71 | (PVOID *)&buffer); 72 | 73 | if (!NT_SUCCESS(status)) 74 | { 75 | MlfsPrint( 76 | DEBUG_LEVEL_ERROR, 77 | DBG_IOCTL, 78 | "Error allocating memory for Spb write - %!STATUS!", 79 | status); 80 | goto exit; 81 | } 82 | 83 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 84 | &memoryDescriptor, 85 | memory, 86 | NULL); 87 | } 88 | else 89 | { 90 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->WriteMemory, NULL); 91 | 92 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 93 | &memoryDescriptor, 94 | (PVOID)buffer, 95 | length); 96 | } 97 | 98 | RtlCopyMemory(buffer, Data, length); 99 | 100 | status = WdfIoTargetSendWriteSynchronously( 101 | SpbContext->SpbIoTarget, 102 | NULL, 103 | &memoryDescriptor, 104 | NULL, 105 | NULL, 106 | NULL); 107 | 108 | if (!NT_SUCCESS(status)) 109 | { 110 | MlfsPrint( 111 | DEBUG_LEVEL_ERROR, 112 | DBG_IOCTL, 113 | "Error writing to Spb - %!STATUS!", 114 | status); 115 | goto exit; 116 | } 117 | 118 | exit: 119 | 120 | if (NULL != memory) 121 | { 122 | WdfObjectDelete(memory); 123 | } 124 | 125 | return status; 126 | } 127 | 128 | NTSTATUS 129 | SpbWriteDataSynchronously( 130 | IN SPB_CONTEXT *SpbContext, 131 | IN PVOID Data, 132 | IN ULONG Length 133 | ) 134 | /*++ 135 | 136 | Routine Description: 137 | 138 | This routine abstracts creating and sending an I/O 139 | request (I2C Write) to the Spb I/O target and utilizes 140 | a helper routine to do work inside of locked code. 141 | 142 | Arguments: 143 | 144 | SpbContext - Pointer to the current device context 145 | Address - The I2C register address to write to 146 | Data - A buffer to receive the data at at the above address 147 | Length - The amount of data to be read from the above address 148 | 149 | Return Value: 150 | 151 | NTSTATUS Status indicating success or failure 152 | 153 | --*/ 154 | { 155 | NTSTATUS status; 156 | 157 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 158 | 159 | status = SpbDoWriteDataSynchronously( 160 | SpbContext, 161 | Data, 162 | Length); 163 | 164 | WdfWaitLockRelease(SpbContext->SpbLock); 165 | 166 | return status; 167 | } 168 | 169 | NTSTATUS 170 | SpbXferDataSynchronously( 171 | _In_ SPB_CONTEXT* SpbContext, 172 | _In_ PVOID SendData, 173 | _In_ ULONG SendLength, 174 | _In_reads_bytes_(Length) PVOID Data, 175 | _In_ ULONG Length 176 | ) 177 | /*++ 178 | Routine Description: 179 | This helper routine abstracts creating and sending an I/O 180 | request (I2C Read) to the Spb I/O target. 181 | Arguments: 182 | SpbContext - Pointer to the current device context 183 | Address - The I2C register address to read from 184 | Data - A buffer to receive the data at at the above address 185 | Length - The amount of data to be read from the above address 186 | Return Value: 187 | NTSTATUS Status indicating success or failure 188 | --*/ 189 | { 190 | PUCHAR buffer; 191 | WDFMEMORY memory; 192 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 193 | NTSTATUS status; 194 | ULONG_PTR bytesRead; 195 | 196 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 197 | 198 | memory = NULL; 199 | status = STATUS_INVALID_PARAMETER; 200 | bytesRead = 0; 201 | 202 | // 203 | // Xfer transactions start by writing an address pointer 204 | // 205 | status = SpbDoWriteDataSynchronously( 206 | SpbContext, 207 | SendData, 208 | SendLength); 209 | 210 | if (!NT_SUCCESS(status)) 211 | { 212 | MlfsPrint( 213 | DEBUG_LEVEL_ERROR, 214 | DBG_IOCTL, 215 | "Error setting address pointer for Spb read - %!STATUS!", 216 | status); 217 | goto exit; 218 | } 219 | 220 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 221 | { 222 | status = WdfMemoryCreate( 223 | WDF_NO_OBJECT_ATTRIBUTES, 224 | NonPagedPool, 225 | MLFS_POOL_TAG, 226 | Length, 227 | &memory, 228 | (PVOID*)&buffer); 229 | 230 | if (!NT_SUCCESS(status)) 231 | { 232 | MlfsPrint( 233 | DEBUG_LEVEL_ERROR, 234 | DBG_IOCTL, 235 | "Error allocating memory for Spb read - %!STATUS!", 236 | status); 237 | goto exit; 238 | } 239 | 240 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 241 | &memoryDescriptor, 242 | memory, 243 | NULL); 244 | } 245 | else 246 | { 247 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 248 | 249 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 250 | &memoryDescriptor, 251 | (PVOID)buffer, 252 | Length); 253 | } 254 | 255 | 256 | status = WdfIoTargetSendReadSynchronously( 257 | SpbContext->SpbIoTarget, 258 | NULL, 259 | &memoryDescriptor, 260 | NULL, 261 | NULL, 262 | &bytesRead); 263 | 264 | if (!NT_SUCCESS(status) || 265 | bytesRead != Length) 266 | { 267 | MlfsPrint( 268 | DEBUG_LEVEL_ERROR, 269 | DBG_IOCTL, 270 | "Error reading from Spb - %!STATUS!", 271 | status); 272 | goto exit; 273 | } 274 | 275 | // 276 | // Copy back to the caller's buffer 277 | // 278 | RtlCopyMemory(Data, buffer, Length); 279 | 280 | exit: 281 | if (NULL != memory) 282 | { 283 | WdfObjectDelete(memory); 284 | } 285 | 286 | WdfWaitLockRelease(SpbContext->SpbLock); 287 | 288 | return status; 289 | } 290 | 291 | VOID 292 | SpbTargetDeinitialize( 293 | IN WDFDEVICE FxDevice, 294 | IN SPB_CONTEXT *SpbContext 295 | ) 296 | /*++ 297 | 298 | Routine Description: 299 | 300 | This helper routine is used to free any members added to the SPB_CONTEXT, 301 | note the SPB I/O target is parented to the device and will be 302 | closed and free'd when the device is removed. 303 | 304 | Arguments: 305 | 306 | FxDevice - Handle to the framework device object 307 | SpbContext - Pointer to the current device context 308 | 309 | Return Value: 310 | 311 | NTSTATUS Status indicating success or failure 312 | 313 | --*/ 314 | { 315 | UNREFERENCED_PARAMETER(FxDevice); 316 | UNREFERENCED_PARAMETER(SpbContext); 317 | 318 | // 319 | // Free any SPB_CONTEXT allocations here 320 | // 321 | if (SpbContext->SpbLock != NULL) 322 | { 323 | WdfObjectDelete(SpbContext->SpbLock); 324 | } 325 | 326 | if (SpbContext->ReadMemory != NULL) 327 | { 328 | WdfObjectDelete(SpbContext->ReadMemory); 329 | } 330 | 331 | if (SpbContext->WriteMemory != NULL) 332 | { 333 | WdfObjectDelete(SpbContext->WriteMemory); 334 | } 335 | } 336 | 337 | NTSTATUS 338 | SpbTargetInitialize( 339 | IN WDFDEVICE FxDevice, 340 | IN SPB_CONTEXT *SpbContext 341 | ) 342 | /*++ 343 | 344 | Routine Description: 345 | 346 | This helper routine opens the Spb I/O target and 347 | initializes a request object used for the lifetime 348 | of communication between this driver and Spb. 349 | 350 | Arguments: 351 | 352 | FxDevice - Handle to the framework device object 353 | SpbContext - Pointer to the current device context 354 | 355 | Return Value: 356 | 357 | NTSTATUS Status indicating success or failure 358 | 359 | --*/ 360 | { 361 | WDF_OBJECT_ATTRIBUTES objectAttributes; 362 | WDF_IO_TARGET_OPEN_PARAMS openParams; 363 | UNICODE_STRING spbDeviceName; 364 | WCHAR spbDeviceNameBuffer[RESOURCE_HUB_PATH_SIZE]; 365 | NTSTATUS status; 366 | 367 | WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); 368 | objectAttributes.ParentObject = FxDevice; 369 | 370 | status = WdfIoTargetCreate( 371 | FxDevice, 372 | &objectAttributes, 373 | &SpbContext->SpbIoTarget); 374 | 375 | if (!NT_SUCCESS(status)) 376 | { 377 | MlfsPrint( 378 | DEBUG_LEVEL_ERROR, 379 | DBG_IOCTL, 380 | "Error creating IoTarget object - %!STATUS!", 381 | status); 382 | 383 | WdfObjectDelete(SpbContext->SpbIoTarget); 384 | goto exit; 385 | } 386 | 387 | RtlInitEmptyUnicodeString( 388 | &spbDeviceName, 389 | spbDeviceNameBuffer, 390 | sizeof(spbDeviceNameBuffer)); 391 | 392 | status = RESOURCE_HUB_CREATE_PATH_FROM_ID( 393 | &spbDeviceName, 394 | SpbContext->I2cResHubId.LowPart, 395 | SpbContext->I2cResHubId.HighPart); 396 | 397 | if (!NT_SUCCESS(status)) 398 | { 399 | MlfsPrint( 400 | DEBUG_LEVEL_ERROR, 401 | DBG_IOCTL, 402 | "Error creating Spb resource hub path string - %!STATUS!", 403 | status); 404 | goto exit; 405 | } 406 | 407 | WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( 408 | &openParams, 409 | &spbDeviceName, 410 | (GENERIC_READ | GENERIC_WRITE)); 411 | 412 | openParams.ShareAccess = 0; 413 | openParams.CreateDisposition = FILE_OPEN; 414 | openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; 415 | 416 | status = WdfIoTargetOpen(SpbContext->SpbIoTarget, &openParams); 417 | 418 | if (!NT_SUCCESS(status)) 419 | { 420 | MlfsPrint( 421 | DEBUG_LEVEL_ERROR, 422 | DBG_IOCTL, 423 | "Error opening Spb target for communication - %!STATUS!", 424 | status); 425 | goto exit; 426 | } 427 | 428 | // 429 | // Allocate some fixed-size buffers from NonPagedPool for typical 430 | // Spb transaction sizes to avoid pool fragmentation in most cases 431 | // 432 | status = WdfMemoryCreate( 433 | WDF_NO_OBJECT_ATTRIBUTES, 434 | NonPagedPool, 435 | MLFS_POOL_TAG, 436 | DEFAULT_SPB_BUFFER_SIZE, 437 | &SpbContext->WriteMemory, 438 | NULL); 439 | 440 | if (!NT_SUCCESS(status)) 441 | { 442 | MlfsPrint( 443 | DEBUG_LEVEL_ERROR, 444 | DBG_IOCTL, 445 | "Error allocating default memory for Spb write - %!STATUS!", 446 | status); 447 | goto exit; 448 | } 449 | 450 | status = WdfMemoryCreate( 451 | WDF_NO_OBJECT_ATTRIBUTES, 452 | NonPagedPool, 453 | MLFS_POOL_TAG, 454 | DEFAULT_SPB_BUFFER_SIZE, 455 | &SpbContext->ReadMemory, 456 | NULL); 457 | 458 | if (!NT_SUCCESS(status)) 459 | { 460 | MlfsPrint( 461 | DEBUG_LEVEL_ERROR, 462 | DBG_IOCTL, 463 | "Error allocating default memory for Spb read - %!STATUS!", 464 | status); 465 | goto exit; 466 | } 467 | 468 | // 469 | // Allocate a waitlock to guard access to the default buffers 470 | // 471 | status = WdfWaitLockCreate( 472 | WDF_NO_OBJECT_ATTRIBUTES, 473 | &SpbContext->SpbLock); 474 | 475 | if (!NT_SUCCESS(status)) 476 | { 477 | MlfsPrint( 478 | DEBUG_LEVEL_ERROR, 479 | DBG_IOCTL, 480 | "Error creating Spb Waitlock - %!STATUS!", 481 | status); 482 | goto exit; 483 | } 484 | 485 | exit: 486 | 487 | if (!NT_SUCCESS(status)) 488 | { 489 | SpbTargetDeinitialize(FxDevice, SpbContext); 490 | } 491 | 492 | return status; 493 | } -------------------------------------------------------------------------------- /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 | 10.0.22000.0 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 | http://timestamp.verisign.com/scripts/timstamp.dll 298 | 299 | 300 | DbgengKernelDebugger 301 | False 302 | True 303 | 304 | 305 | 306 | False 307 | False 308 | True 309 | 310 | 133563 311 | 312 | 313 | DbgengKernelDebugger 314 | False 315 | True 316 | 317 | 318 | 319 | False 320 | False 321 | True 322 | 323 | 133563 324 | 325 | 326 | 327 | SHA256 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | {36580c07-edc3-4c2b-b45f-6ab017e01a5d} 336 | 337 | 338 | 339 | 340 | 341 | -------------------------------------------------------------------------------- /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 | 188 | 189 | DbgengKernelDebugger 190 | 191 | 192 | DbgengKernelDebugger 193 | 194 | 195 | 196 | true 197 | trace.h 198 | true 199 | 200 | 201 | 2.9.2 202 | 203 | 204 | 205 | 206 | true 207 | trace.h 208 | true 209 | 210 | 211 | 2.9.2 212 | 213 | 214 | 215 | 216 | true 217 | trace.h 218 | true 219 | 220 | 221 | 2.9.2 222 | 223 | 224 | 225 | 226 | true 227 | trace.h 228 | true 229 | 230 | 231 | 2.9.2 232 | 233 | 234 | 235 | 236 | true 237 | trace.h 238 | true 239 | 240 | 241 | 2.9.2 242 | 243 | 244 | 245 | 246 | true 247 | trace.h 248 | true 249 | 250 | 251 | 2.9.2 252 | 253 | 254 | 255 | 256 | true 257 | trace.h 258 | true 259 | 260 | 261 | 2.9.2 262 | 263 | 264 | 265 | 266 | true 267 | trace.h 268 | true 269 | 270 | 271 | 2.9.2 272 | 273 | 274 | 275 | 276 | true 277 | trace.h 278 | true 279 | false 280 | 281 | 282 | 2.9.2 283 | 284 | 285 | 286 | 287 | true 288 | trace.h 289 | true 290 | false 291 | 292 | 293 | 2.9.2 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | true 303 | trace.h 304 | true 305 | 306 | 307 | 2.9.2 308 | 309 | 310 | 311 | 312 | true 313 | trace.h 314 | true 315 | 316 | 317 | 2.9.2 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | -------------------------------------------------------------------------------- /crostouchscreen2/mlfs.cpp: -------------------------------------------------------------------------------- 1 | #define DESCRIPTOR_DEF 2 | #include "mlfs.h" 3 | 4 | static ULONG MlfsDebugLevel = 100; 5 | static ULONG MlfsDebugCatagories = 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 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_INIT, 18 | "Driver Entry\n"); 19 | 20 | WDF_DRIVER_CONFIG_INIT(&config, MlfsEvtDeviceAdd); 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 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 38 | "WdfDriverCreate failed with status 0x%x\n", status); 39 | } 40 | 41 | return status; 42 | } 43 | 44 | static NTSTATUS mip4_i2c_xfer(PMLFS_CONTEXT pDevice, uint8_t *write_buf, unsigned int write_len, 45 | uint8_t *read_buf, unsigned int read_len) { 46 | NTSTATUS status; 47 | 48 | status = SpbXferDataSynchronously(&pDevice->I2CContext, write_buf, write_len, read_buf, read_len); 49 | return status; 50 | } 51 | 52 | NTSTATUS BOOTTOUCHSCREEN( 53 | _In_ PMLFS_CONTEXT devContext 54 | ) 55 | { 56 | NTSTATUS status; 57 | 58 | if (!devContext->TouchScreenBooted) { 59 | uint8_t cmd[2]; 60 | uint8_t buf[14]; 61 | /* Resolution */ 62 | 63 | cmd[0] = MIP4_R0_INFO; 64 | cmd[1] = MIP4_R1_INFO_RESOLUTION_X; 65 | 66 | status = mip4_i2c_xfer(devContext, cmd, 2, buf, 14); 67 | 68 | if (!NT_SUCCESS(status)) { 69 | DbgPrint("Unable to get resolution %d", status); 70 | return status; 71 | } 72 | 73 | uint16_t max_x = buf[0] | (buf[1] << 8); 74 | uint16_t max_y = buf[2] | (buf[3] << 8); 75 | 76 | devContext->max_x = max_x; 77 | devContext->max_y = max_y; 78 | 79 | devContext->node_x = buf[4]; 80 | devContext->node_y = buf[5]; 81 | devContext->node_key = buf[6]; 82 | 83 | //XXX: Wrong Max X 84 | max_x = devContext->node_x * (devContext->max_y / devContext->node_y); 85 | devContext->max_x = max_x; 86 | 87 | devContext->max_x_hid[0] = max_x; 88 | devContext->max_x_hid[1] = max_x >> 8; 89 | 90 | devContext->max_y_hid[0] = max_y; 91 | devContext->max_y_hid[1] = max_y >> 8; 92 | 93 | devContext->ppm_x = buf[12]; 94 | devContext->ppm_y = buf[13]; 95 | 96 | for (int i = 0; i < 14; i++) { 97 | buf[i] = 0; 98 | } 99 | 100 | cmd[0] = MIP4_R0_EVENT; 101 | cmd[1] = MIP4_R1_EVENT_SUPPORTED_FUNC; 102 | 103 | status = mip4_i2c_xfer(devContext, cmd, sizeof(cmd), buf, 7); 104 | 105 | if (!NT_SUCCESS(status)) { 106 | DbgPrint("Unable to get packet format %d", status); 107 | return status; 108 | } 109 | 110 | devContext->event_format = buf[4] | (buf[5] << 8); 111 | devContext->event_size = buf[6]; 112 | 113 | if (devContext->event_format == 2 || devContext->event_format > 3) { 114 | DbgPrint("Unknown Event Format %d\n", devContext->event_format); 115 | } 116 | devContext->TouchScreenBooted = true; 117 | } 118 | return STATUS_SUCCESS; 119 | } 120 | 121 | NTSTATUS 122 | OnPrepareHardware( 123 | _In_ WDFDEVICE FxDevice, 124 | _In_ WDFCMRESLIST FxResourcesRaw, 125 | _In_ WDFCMRESLIST FxResourcesTranslated 126 | ) 127 | /*++ 128 | 129 | Routine Description: 130 | 131 | This routine caches the SPB resource connection ID. 132 | 133 | Arguments: 134 | 135 | FxDevice - a handle to the framework device object 136 | FxResourcesRaw - list of translated hardware resources that 137 | the PnP manager has assigned to the device 138 | FxResourcesTranslated - list of raw hardware resources that 139 | the PnP manager has assigned to the device 140 | 141 | Return Value: 142 | 143 | Status 144 | 145 | --*/ 146 | { 147 | PMLFS_CONTEXT pDevice = GetDeviceContext(FxDevice); 148 | BOOLEAN fSpbResourceFound = FALSE; 149 | NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; 150 | 151 | UNREFERENCED_PARAMETER(FxResourcesRaw); 152 | 153 | // 154 | // Parse the peripheral's resources. 155 | // 156 | 157 | ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); 158 | 159 | for (ULONG i = 0; i < resourceCount; i++) 160 | { 161 | PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 162 | UCHAR Class; 163 | UCHAR Type; 164 | 165 | pDescriptor = WdfCmResourceListGetDescriptor( 166 | FxResourcesTranslated, i); 167 | 168 | switch (pDescriptor->Type) 169 | { 170 | case CmResourceTypeConnection: 171 | // 172 | // Look for I2C or SPI resource and save connection ID. 173 | // 174 | Class = pDescriptor->u.Connection.Class; 175 | Type = pDescriptor->u.Connection.Type; 176 | if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && 177 | Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) 178 | { 179 | if (fSpbResourceFound == FALSE) 180 | { 181 | status = STATUS_SUCCESS; 182 | pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; 183 | pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; 184 | fSpbResourceFound = TRUE; 185 | } 186 | else 187 | { 188 | } 189 | } 190 | break; 191 | default: 192 | // 193 | // Ignoring all other resource types. 194 | // 195 | break; 196 | } 197 | } 198 | 199 | // 200 | // An SPB resource is required. 201 | // 202 | 203 | if (fSpbResourceFound == FALSE) 204 | { 205 | status = STATUS_NOT_FOUND; 206 | } 207 | 208 | status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); 209 | 210 | if (!NT_SUCCESS(status)) 211 | { 212 | return status; 213 | } 214 | 215 | status = BOOTTOUCHSCREEN(pDevice); 216 | 217 | if (!NT_SUCCESS(status)) 218 | { 219 | return status; 220 | } 221 | 222 | return status; 223 | } 224 | 225 | NTSTATUS 226 | OnReleaseHardware( 227 | _In_ WDFDEVICE FxDevice, 228 | _In_ WDFCMRESLIST FxResourcesTranslated 229 | ) 230 | /*++ 231 | 232 | Routine Description: 233 | 234 | Arguments: 235 | 236 | FxDevice - a handle to the framework device object 237 | FxResourcesTranslated - list of raw hardware resources that 238 | the PnP manager has assigned to the device 239 | 240 | Return Value: 241 | 242 | Status 243 | 244 | --*/ 245 | { 246 | PMLFS_CONTEXT pDevice = GetDeviceContext(FxDevice); 247 | NTSTATUS status = STATUS_SUCCESS; 248 | 249 | UNREFERENCED_PARAMETER(FxResourcesTranslated); 250 | 251 | SpbTargetDeinitialize(FxDevice, &pDevice->I2CContext); 252 | 253 | return status; 254 | } 255 | 256 | NTSTATUS 257 | OnD0Entry( 258 | _In_ WDFDEVICE FxDevice, 259 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 260 | ) 261 | /*++ 262 | 263 | Routine Description: 264 | 265 | This routine allocates objects needed by the driver. 266 | 267 | Arguments: 268 | 269 | FxDevice - a handle to the framework device object 270 | FxPreviousState - previous power state 271 | 272 | Return Value: 273 | 274 | Status 275 | 276 | --*/ 277 | { 278 | UNREFERENCED_PARAMETER(FxPreviousState); 279 | 280 | PMLFS_CONTEXT pDevice = GetDeviceContext(FxDevice); 281 | NTSTATUS status = STATUS_SUCCESS; 282 | 283 | WdfTimerStart(pDevice->Timer, WDF_REL_TIMEOUT_IN_MS(10)); 284 | 285 | for (int i = 0; i < 20; i++) { 286 | pDevice->Flags[i] = 0; 287 | } 288 | 289 | pDevice->RegsSet = false; 290 | pDevice->ConnectInterrupt = true; 291 | 292 | return status; 293 | } 294 | 295 | NTSTATUS 296 | OnD0Exit( 297 | _In_ WDFDEVICE FxDevice, 298 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 299 | ) 300 | /*++ 301 | 302 | Routine Description: 303 | 304 | This routine destroys objects needed by the driver. 305 | 306 | Arguments: 307 | 308 | FxDevice - a handle to the framework device object 309 | FxPreviousState - previous power state 310 | 311 | Return Value: 312 | 313 | Status 314 | 315 | --*/ 316 | { 317 | UNREFERENCED_PARAMETER(FxPreviousState); 318 | 319 | PMLFS_CONTEXT pDevice = GetDeviceContext(FxDevice); 320 | 321 | WdfTimerStop(pDevice->Timer, TRUE); 322 | 323 | pDevice->ConnectInterrupt = false; 324 | 325 | return STATUS_SUCCESS; 326 | } 327 | 328 | void MlfsProcessInput(PMLFS_CONTEXT pDevice) { 329 | struct _MLFS_MULTITOUCH_REPORT report; 330 | report.ReportID = REPORTID_MTOUCH; 331 | 332 | int count = 0, i = 0; 333 | while (count < 10 && i < 20) { 334 | if (pDevice->Flags[i] != 0) { 335 | report.Touch[count].ContactID = i; 336 | report.Touch[count].Height = pDevice->AREA[i]; 337 | report.Touch[count].Width = pDevice->AREA[i]; 338 | 339 | report.Touch[count].XValue = pDevice->XValue[i]; 340 | report.Touch[count].YValue = pDevice->YValue[i]; 341 | 342 | uint8_t flags = pDevice->Flags[i]; 343 | if (flags & MXT_T9_DETECT) { 344 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 345 | } 346 | else if (flags & MXT_T9_PRESS) { 347 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 348 | } 349 | else if (flags & MXT_T9_RELEASE) { 350 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT; 351 | pDevice->Flags[i] = 0; 352 | } 353 | else 354 | report.Touch[count].Status = 0; 355 | 356 | count++; 357 | } 358 | i++; 359 | } 360 | 361 | report.ActualCount = count; 362 | 363 | if (count > 0) { 364 | size_t bytesWritten; 365 | MlfsProcessVendorReport(pDevice, &report, sizeof(report), &bytesWritten); 366 | } 367 | } 368 | 369 | static void mip4_report_touch(PMLFS_CONTEXT pDevice, uint8_t* packet) { 370 | int id; 371 | bool hover; 372 | bool palm; 373 | bool state; 374 | uint16_t x, y; 375 | uint8_t pressure_stage; 376 | uint8_t pressure; 377 | uint8_t size; 378 | uint8_t touch_major; 379 | uint8_t touch_minor; 380 | 381 | switch (pDevice->event_format) { 382 | case 0: 383 | case 1: 384 | /* Touch only */ 385 | state = packet[0] & BIT(7); 386 | hover = packet[0] & BIT(5); 387 | palm = packet[0] & BIT(4); 388 | id = (packet[0] & 0x0F) - 1; 389 | x = ((packet[1] & 0x0F) << 8) | packet[2]; 390 | y = (((packet[1] >> 4) & 0x0F) << 8) | 391 | packet[3]; 392 | pressure = packet[4]; 393 | size = packet[5]; 394 | if (pDevice->event_format == 0) { 395 | touch_major = packet[5]; 396 | touch_minor = packet[5]; 397 | } 398 | else { 399 | touch_major = packet[6]; 400 | touch_minor = packet[7]; 401 | } 402 | break; 403 | 404 | case 3: 405 | default: 406 | /* Touch + Force(Pressure) */ 407 | id = (packet[0] & 0x0F) - 1; 408 | hover = packet[1] & BIT(2); 409 | palm = packet[1] & BIT(1); 410 | state = packet[1] & BIT(0); 411 | x = ((packet[2] & 0x0F) << 8) | packet[3]; 412 | y = (((packet[2] >> 4) & 0x0F) << 8) | 413 | packet[4]; 414 | size = packet[6]; 415 | pressure_stage = (packet[7] & 0xF0) >> 4; 416 | pressure = ((packet[7] & 0x0F) << 8) | 417 | packet[8]; 418 | touch_major = packet[9]; 419 | touch_minor = packet[10]; 420 | break; 421 | } 422 | 423 | if (state) { 424 | pDevice->Flags[id] = MXT_T9_DETECT; 425 | pDevice->XValue[id] = x; 426 | pDevice->YValue[id] = y; 427 | pDevice->AREA[id] = touch_major; 428 | } 429 | else { 430 | pDevice->Flags[id] = MXT_T9_RELEASE; 431 | } 432 | } 433 | 434 | static void mip4_report_keys(PMLFS_CONTEXT pDevice, uint8_t* packet) 435 | { 436 | uint8_t key; 437 | bool down; 438 | 439 | switch (pDevice->event_format) { 440 | case 0: 441 | case 1: 442 | key = packet[0] & 0x0F; 443 | down = packet[0] & 0x80; 444 | break; 445 | 446 | case 3: 447 | default: 448 | key = packet[0] & 0x0F; 449 | down = packet[1] & 0x01; 450 | break; 451 | } 452 | 453 | /* Report key event */ 454 | if (key >= 1 && key <= pDevice->node_key) { 455 | unsigned short keycode = pDevice->key_code[key - 1]; 456 | 457 | DbgPrint("Key - ID: %d, keycode: %d, state: %d\n", 458 | key, keycode, down); 459 | } 460 | else { 461 | DbgPrint("Unknown key: %d\n", key); 462 | } 463 | } 464 | 465 | static NTSTATUS mip4_handle_packet(PMLFS_CONTEXT pDevice, uint8_t* packet) 466 | { 467 | uint8_t type; 468 | 469 | switch (pDevice->event_format) { 470 | case 0: 471 | case 1: 472 | type = (packet[0] & 0x40) >> 6; 473 | break; 474 | 475 | case 3: 476 | type = (packet[0] & 0xF0) >> 4; 477 | break; 478 | 479 | default: 480 | /* Should not happen unless we have corrupted firmware */ 481 | return STATUS_DEVICE_PROTOCOL_ERROR; 482 | } 483 | 484 | /* Report input event */ 485 | switch (type) { 486 | case MIP4_EVENT_INPUT_TYPE_KEY: 487 | mip4_report_keys(pDevice, packet); 488 | break; 489 | 490 | case MIP4_EVENT_INPUT_TYPE_SCREEN: 491 | mip4_report_touch(pDevice, packet); 492 | break; 493 | 494 | default: 495 | DbgPrint("Unknown event type: %d\n", type); 496 | break; 497 | } 498 | 499 | return STATUS_SUCCESS; 500 | } 501 | 502 | BOOLEAN OnInterruptIsr( 503 | WDFINTERRUPT Interrupt, 504 | ULONG MessageID) { 505 | UNREFERENCED_PARAMETER(MessageID); 506 | 507 | WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); 508 | PMLFS_CONTEXT pDevice = GetDeviceContext(Device); 509 | 510 | NTSTATUS status; 511 | 512 | if (!pDevice->ConnectInterrupt) 513 | return false; 514 | 515 | if (!pDevice->TouchScreenBooted) 516 | return false; 517 | 518 | uint8_t cmd[2]; 519 | uint8_t buf[MIP4_BUF_SIZE]; 520 | uint8_t size; 521 | bool alert; 522 | 523 | cmd[0] = MIP4_R0_EVENT; 524 | cmd[1] = MIP4_R1_EVENT_PACKET_INFO; 525 | 526 | status = mip4_i2c_xfer(pDevice, cmd, sizeof(cmd), buf, 1); 527 | 528 | if (!NT_SUCCESS(status)) { 529 | return false; 530 | } 531 | 532 | size = buf[0] & 0x7F; 533 | alert = buf[0] & 0x80; 534 | 535 | if (!size) { 536 | return true; 537 | } 538 | 539 | /* Read packet data */ 540 | cmd[0] = MIP4_R0_EVENT; 541 | cmd[1] = MIP4_R1_EVENT_PACKET_DATA; 542 | 543 | status = mip4_i2c_xfer(pDevice, cmd, sizeof(cmd), buf, size); 544 | if (!NT_SUCCESS(status)) { 545 | return true; 546 | } 547 | 548 | if (alert) { 549 | DbgPrint("Alert: %d\n", buf[0]); 550 | } 551 | else { 552 | for (int i = 0; i < size; i += pDevice->event_size) { 553 | status = mip4_handle_packet(pDevice, &buf[i]); 554 | if (!NT_SUCCESS(status)) { 555 | break; 556 | } 557 | } 558 | } 559 | 560 | MlfsProcessInput(pDevice); 561 | 562 | return true; 563 | } 564 | 565 | void MlfsTimerFunc(_In_ WDFTIMER hTimer) { 566 | WDFDEVICE Device = (WDFDEVICE)WdfTimerGetParentObject(hTimer); 567 | PMLFS_CONTEXT pDevice = GetDeviceContext(Device); 568 | 569 | if (!pDevice->ConnectInterrupt) 570 | return; 571 | 572 | if (!pDevice->RegsSet) 573 | return; 574 | 575 | MlfsProcessInput(pDevice); 576 | return; 577 | } 578 | 579 | NTSTATUS 580 | MlfsEvtDeviceAdd( 581 | IN WDFDRIVER Driver, 582 | IN PWDFDEVICE_INIT DeviceInit 583 | ) 584 | { 585 | NTSTATUS status = STATUS_SUCCESS; 586 | WDF_IO_QUEUE_CONFIG queueConfig; 587 | WDF_OBJECT_ATTRIBUTES attributes; 588 | WDFDEVICE device; 589 | WDF_INTERRUPT_CONFIG interruptConfig; 590 | WDFQUEUE queue; 591 | UCHAR minorFunction; 592 | PMLFS_CONTEXT devContext; 593 | 594 | UNREFERENCED_PARAMETER(Driver); 595 | 596 | PAGED_CODE(); 597 | 598 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_PNP, 599 | "MlfsEvtDeviceAdd called\n"); 600 | 601 | // 602 | // Tell framework this is a filter driver. Filter drivers by default are 603 | // not power policy owners. This works well for this driver because 604 | // HIDclass driver is the power policy owner for HID minidrivers. 605 | // 606 | 607 | WdfFdoInitSetFilter(DeviceInit); 608 | 609 | { 610 | WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; 611 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); 612 | 613 | pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; 614 | pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; 615 | pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; 616 | pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; 617 | 618 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); 619 | } 620 | 621 | // 622 | // Setup the device context 623 | // 624 | 625 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, MLFS_CONTEXT); 626 | 627 | // 628 | // Create a framework device object.This call will in turn create 629 | // a WDM device object, attach to the lower stack, and set the 630 | // appropriate flags and attributes. 631 | // 632 | 633 | status = WdfDeviceCreate(&DeviceInit, &attributes, &device); 634 | 635 | if (!NT_SUCCESS(status)) 636 | { 637 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 638 | "WdfDeviceCreate failed with status code 0x%x\n", status); 639 | 640 | return status; 641 | } 642 | 643 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); 644 | 645 | queueConfig.EvtIoInternalDeviceControl = MlfsEvtInternalDeviceControl; 646 | 647 | status = WdfIoQueueCreate(device, 648 | &queueConfig, 649 | WDF_NO_OBJECT_ATTRIBUTES, 650 | &queue 651 | ); 652 | 653 | if (!NT_SUCCESS(status)) 654 | { 655 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 656 | "WdfIoQueueCreate failed 0x%x\n", status); 657 | 658 | return status; 659 | } 660 | 661 | // 662 | // Create manual I/O queue to take care of hid report read requests 663 | // 664 | 665 | devContext = GetDeviceContext(device); 666 | 667 | devContext->TouchScreenBooted = false; 668 | 669 | devContext->FxDevice = device; 670 | 671 | WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); 672 | 673 | queueConfig.PowerManaged = WdfFalse; 674 | 675 | status = WdfIoQueueCreate(device, 676 | &queueConfig, 677 | WDF_NO_OBJECT_ATTRIBUTES, 678 | &devContext->ReportQueue 679 | ); 680 | 681 | if (!NT_SUCCESS(status)) 682 | { 683 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 684 | "WdfIoQueueCreate failed 0x%x\n", status); 685 | 686 | return status; 687 | } 688 | 689 | // 690 | // Create an interrupt object for hardware notifications 691 | // 692 | WDF_INTERRUPT_CONFIG_INIT( 693 | &interruptConfig, 694 | OnInterruptIsr, 695 | NULL); 696 | interruptConfig.PassiveHandling = TRUE; 697 | 698 | status = WdfInterruptCreate( 699 | device, 700 | &interruptConfig, 701 | WDF_NO_OBJECT_ATTRIBUTES, 702 | &devContext->Interrupt); 703 | 704 | if (!NT_SUCCESS(status)) 705 | { 706 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 707 | "Error creating WDF interrupt object - %!STATUS!", 708 | status); 709 | 710 | return status; 711 | } 712 | 713 | WDF_TIMER_CONFIG timerConfig; 714 | WDFTIMER hTimer; 715 | 716 | WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, MlfsTimerFunc, 10); 717 | 718 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 719 | attributes.ParentObject = device; 720 | status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); 721 | devContext->Timer = hTimer; 722 | if (!NT_SUCCESS(status)) 723 | { 724 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status); 725 | return status; 726 | } 727 | 728 | // 729 | // Initialize DeviceMode 730 | // 731 | 732 | devContext->DeviceMode = DEVICE_MODE_MOUSE; 733 | 734 | return status; 735 | } 736 | 737 | VOID 738 | MlfsEvtInternalDeviceControl( 739 | IN WDFQUEUE Queue, 740 | IN WDFREQUEST Request, 741 | IN size_t OutputBufferLength, 742 | IN size_t InputBufferLength, 743 | IN ULONG IoControlCode 744 | ) 745 | { 746 | NTSTATUS status = STATUS_SUCCESS; 747 | WDFDEVICE device; 748 | PMLFS_CONTEXT devContext; 749 | BOOLEAN completeRequest = TRUE; 750 | 751 | UNREFERENCED_PARAMETER(OutputBufferLength); 752 | UNREFERENCED_PARAMETER(InputBufferLength); 753 | 754 | device = WdfIoQueueGetDevice(Queue); 755 | devContext = GetDeviceContext(device); 756 | 757 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 758 | "%s, Queue:0x%p, Request:0x%p\n", 759 | DbgHidInternalIoctlString(IoControlCode), 760 | Queue, 761 | Request 762 | ); 763 | 764 | // 765 | // Please note that HIDCLASS provides the buffer in the Irp->UserBuffer 766 | // field irrespective of the ioctl buffer type. However, framework is very 767 | // strict about type checking. You cannot get Irp->UserBuffer by using 768 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 769 | // internal ioctl. So depending on the ioctl code, we will either 770 | // use retreive function or escape to WDM to get the UserBuffer. 771 | // 772 | 773 | switch (IoControlCode) 774 | { 775 | 776 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 777 | // 778 | // Retrieves the device's HID descriptor. 779 | // 780 | status = MlfsGetHidDescriptor(device, Request); 781 | break; 782 | 783 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 784 | // 785 | //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure. 786 | // 787 | status = MlfsGetDeviceAttributes(Request); 788 | break; 789 | 790 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 791 | // 792 | //Obtains the report descriptor for the HID device. 793 | // 794 | status = MlfsGetReportDescriptor(device, Request); 795 | break; 796 | 797 | case IOCTL_HID_GET_STRING: 798 | // 799 | // Requests that the HID minidriver retrieve a human-readable string 800 | // for either the manufacturer ID, the product ID, or the serial number 801 | // from the string descriptor of the device. The minidriver must send 802 | // a Get String Descriptor request to the device, in order to retrieve 803 | // the string descriptor, then it must extract the string at the 804 | // appropriate index from the string descriptor and return it in the 805 | // output buffer indicated by the IRP. Before sending the Get String 806 | // Descriptor request, the minidriver must retrieve the appropriate 807 | // index for the manufacturer ID, the product ID or the serial number 808 | // from the device extension of a top level collection associated with 809 | // the device. 810 | // 811 | status = MlfsGetString(Request); 812 | break; 813 | 814 | case IOCTL_HID_WRITE_REPORT: 815 | case IOCTL_HID_SET_OUTPUT_REPORT: 816 | // 817 | //Transmits a class driver-supplied report to the device. 818 | // 819 | status = MlfsWriteReport(devContext, Request); 820 | break; 821 | 822 | case IOCTL_HID_READ_REPORT: 823 | case IOCTL_HID_GET_INPUT_REPORT: 824 | // 825 | // Returns a report from the device into a class driver-supplied buffer. 826 | // 827 | status = MlfsReadReport(devContext, Request, &completeRequest); 828 | break; 829 | 830 | case IOCTL_HID_SET_FEATURE: 831 | // 832 | // This sends a HID class feature report to a top-level collection of 833 | // a HID class device. 834 | // 835 | status = MlfsSetFeature(devContext, Request, &completeRequest); 836 | break; 837 | 838 | case IOCTL_HID_GET_FEATURE: 839 | // 840 | // returns a feature report associated with a top-level collection 841 | // 842 | status = MlfsGetFeature(devContext, Request, &completeRequest); 843 | break; 844 | 845 | case IOCTL_HID_ACTIVATE_DEVICE: 846 | // 847 | // Makes the device ready for I/O operations. 848 | // 849 | case IOCTL_HID_DEACTIVATE_DEVICE: 850 | // 851 | // Causes the device to cease operations and terminate all outstanding 852 | // I/O requests. 853 | // 854 | default: 855 | status = STATUS_NOT_SUPPORTED; 856 | break; 857 | } 858 | 859 | if (completeRequest) 860 | { 861 | WdfRequestComplete(Request, status); 862 | 863 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 864 | "%s completed, Queue:0x%p, Request:0x%p\n", 865 | DbgHidInternalIoctlString(IoControlCode), 866 | Queue, 867 | Request 868 | ); 869 | } 870 | else 871 | { 872 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 873 | "%s deferred, Queue:0x%p, Request:0x%p\n", 874 | DbgHidInternalIoctlString(IoControlCode), 875 | Queue, 876 | Request 877 | ); 878 | } 879 | 880 | return; 881 | } 882 | 883 | NTSTATUS 884 | MlfsGetHidDescriptor( 885 | IN WDFDEVICE Device, 886 | IN WDFREQUEST Request 887 | ) 888 | { 889 | NTSTATUS status = STATUS_SUCCESS; 890 | size_t bytesToCopy = 0; 891 | WDFMEMORY memory; 892 | 893 | UNREFERENCED_PARAMETER(Device); 894 | 895 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 896 | "MlfsGetHidDescriptor Entry\n"); 897 | 898 | // 899 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 900 | // will correctly retrieve buffer from Irp->UserBuffer. 901 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 902 | // field irrespective of the ioctl buffer type. However, framework is very 903 | // strict about type checking. You cannot get Irp->UserBuffer by using 904 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 905 | // internal ioctl. 906 | // 907 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 908 | 909 | if (!NT_SUCCESS(status)) 910 | { 911 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 912 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 913 | 914 | return status; 915 | } 916 | 917 | // 918 | // Use hardcoded "HID Descriptor" 919 | // 920 | bytesToCopy = DefaultHidDescriptor.bLength; 921 | 922 | if (bytesToCopy == 0) 923 | { 924 | status = STATUS_INVALID_DEVICE_STATE; 925 | 926 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 927 | "DefaultHidDescriptor is zero, 0x%x\n", status); 928 | 929 | return status; 930 | } 931 | 932 | status = WdfMemoryCopyFromBuffer(memory, 933 | 0, // Offset 934 | (PVOID)&DefaultHidDescriptor, 935 | bytesToCopy); 936 | 937 | if (!NT_SUCCESS(status)) 938 | { 939 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 940 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 941 | 942 | return status; 943 | } 944 | 945 | // 946 | // Report how many bytes were copied 947 | // 948 | WdfRequestSetInformation(Request, bytesToCopy); 949 | 950 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 951 | "MlfsGetHidDescriptor Exit = 0x%x\n", status); 952 | 953 | return status; 954 | } 955 | 956 | NTSTATUS 957 | MlfsGetReportDescriptor( 958 | IN WDFDEVICE Device, 959 | IN WDFREQUEST Request 960 | ) 961 | { 962 | NTSTATUS status = STATUS_SUCCESS; 963 | ULONG_PTR bytesToCopy; 964 | WDFMEMORY memory; 965 | 966 | PMLFS_CONTEXT devContext = GetDeviceContext(Device); 967 | 968 | UNREFERENCED_PARAMETER(Device); 969 | 970 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 971 | "MlfsGetReportDescriptor Entry\n"); 972 | 973 | #define MT_TOUCH_COLLECTION \ 974 | MT_TOUCH_COLLECTION0 \ 975 | 0x26, devContext->max_x_hid[0], devContext->max_x_hid[1], /* LOGICAL_MAXIMUM (WIDTH) */ \ 976 | MT_TOUCH_COLLECTION1 \ 977 | 0x26, devContext->max_y_hid[0], devContext->max_y_hid[1], /* LOGICAL_MAXIMUM (HEIGHT) */ \ 978 | MT_TOUCH_COLLECTION2 \ 979 | 980 | HID_REPORT_DESCRIPTOR ReportDescriptor[] = { 981 | // 982 | // Multitouch report starts here 983 | // 984 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 985 | 0x09, 0x04, // USAGE (Touch Screen) 986 | 0xa1, 0x01, // COLLECTION (Application) 987 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch) 988 | 0x09, 0x22, // USAGE (Finger) 989 | MT_TOUCH_COLLECTION 990 | MT_TOUCH_COLLECTION 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 | USAGE_PAGE 1000 | 0xc0, // END_COLLECTION 1001 | }; 1002 | 1003 | // 1004 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1005 | // will correctly retrieve buffer from Irp->UserBuffer. 1006 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1007 | // field irrespective of the ioctl buffer type. However, framework is very 1008 | // strict about type checking. You cannot get Irp->UserBuffer by using 1009 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1010 | // internal ioctl. 1011 | // 1012 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 1013 | if (!NT_SUCCESS(status)) 1014 | { 1015 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1016 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 1017 | 1018 | return status; 1019 | } 1020 | 1021 | // 1022 | // Use hardcoded Report descriptor 1023 | // 1024 | bytesToCopy = DefaultHidDescriptor.DescriptorList[0].wReportLength; 1025 | 1026 | if (bytesToCopy == 0) 1027 | { 1028 | status = STATUS_INVALID_DEVICE_STATE; 1029 | 1030 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1031 | "DefaultHidDescriptor's reportLength is zero, 0x%x\n", status); 1032 | 1033 | return status; 1034 | } 1035 | 1036 | status = WdfMemoryCopyFromBuffer(memory, 1037 | 0, 1038 | (PVOID)ReportDescriptor, 1039 | bytesToCopy); 1040 | if (!NT_SUCCESS(status)) 1041 | { 1042 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1043 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1044 | 1045 | return status; 1046 | } 1047 | 1048 | // 1049 | // Report how many bytes were copied 1050 | // 1051 | WdfRequestSetInformation(Request, bytesToCopy); 1052 | 1053 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1054 | "MlfsGetReportDescriptor Exit = 0x%x\n", status); 1055 | 1056 | return status; 1057 | } 1058 | 1059 | 1060 | NTSTATUS 1061 | MlfsGetDeviceAttributes( 1062 | IN WDFREQUEST Request 1063 | ) 1064 | { 1065 | NTSTATUS status = STATUS_SUCCESS; 1066 | PHID_DEVICE_ATTRIBUTES deviceAttributes = NULL; 1067 | 1068 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1069 | "MlfsGetDeviceAttributes Entry\n"); 1070 | 1071 | // 1072 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1073 | // will correctly retrieve buffer from Irp->UserBuffer. 1074 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1075 | // field irrespective of the ioctl buffer type. However, framework is very 1076 | // strict about type checking. You cannot get Irp->UserBuffer by using 1077 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1078 | // internal ioctl. 1079 | // 1080 | status = WdfRequestRetrieveOutputBuffer(Request, 1081 | sizeof(HID_DEVICE_ATTRIBUTES), 1082 | (PVOID *)&deviceAttributes, 1083 | NULL); 1084 | if (!NT_SUCCESS(status)) 1085 | { 1086 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1087 | "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); 1088 | 1089 | return status; 1090 | } 1091 | 1092 | // 1093 | // Set USB device descriptor 1094 | // 1095 | 1096 | deviceAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES); 1097 | deviceAttributes->VendorID = MLFS_VID; 1098 | deviceAttributes->ProductID = MLFS_PID; 1099 | deviceAttributes->VersionNumber = MLFS_VERSION; 1100 | 1101 | // 1102 | // Report how many bytes were copied 1103 | // 1104 | WdfRequestSetInformation(Request, sizeof(HID_DEVICE_ATTRIBUTES)); 1105 | 1106 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1107 | "MlfsGetDeviceAttributes Exit = 0x%x\n", status); 1108 | 1109 | return status; 1110 | } 1111 | 1112 | NTSTATUS 1113 | MlfsGetString( 1114 | IN WDFREQUEST Request 1115 | ) 1116 | { 1117 | 1118 | NTSTATUS status = STATUS_SUCCESS; 1119 | PWSTR pwstrID; 1120 | size_t lenID; 1121 | WDF_REQUEST_PARAMETERS params; 1122 | void *pStringBuffer = NULL; 1123 | 1124 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1125 | "MlfsGetString Entry\n"); 1126 | 1127 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1128 | WdfRequestGetParameters(Request, ¶ms); 1129 | 1130 | switch ((ULONG_PTR)params.Parameters.DeviceIoControl.Type3InputBuffer & 0xFFFF) 1131 | { 1132 | case HID_STRING_ID_IMANUFACTURER: 1133 | pwstrID = L"Mlfs.\0"; 1134 | break; 1135 | 1136 | case HID_STRING_ID_IPRODUCT: 1137 | pwstrID = L"MaxTouch Touch Screen\0"; 1138 | break; 1139 | 1140 | case HID_STRING_ID_ISERIALNUMBER: 1141 | pwstrID = L"123123123\0"; 1142 | break; 1143 | 1144 | default: 1145 | pwstrID = NULL; 1146 | break; 1147 | } 1148 | 1149 | lenID = pwstrID ? wcslen(pwstrID) * sizeof(WCHAR) + sizeof(UNICODE_NULL) : 0; 1150 | 1151 | if (pwstrID == NULL) 1152 | { 1153 | 1154 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1155 | "MlfsGetString Invalid request type\n"); 1156 | 1157 | status = STATUS_INVALID_PARAMETER; 1158 | 1159 | return status; 1160 | } 1161 | 1162 | status = WdfRequestRetrieveOutputBuffer(Request, 1163 | lenID, 1164 | &pStringBuffer, 1165 | &lenID); 1166 | 1167 | if (!NT_SUCCESS(status)) 1168 | { 1169 | 1170 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1171 | "MlfsGetString WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1172 | 1173 | return status; 1174 | } 1175 | 1176 | RtlCopyMemory(pStringBuffer, pwstrID, lenID); 1177 | 1178 | WdfRequestSetInformation(Request, lenID); 1179 | 1180 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1181 | "MlfsGetString Exit = 0x%x\n", status); 1182 | 1183 | return status; 1184 | } 1185 | 1186 | NTSTATUS 1187 | MlfsWriteReport( 1188 | IN PMLFS_CONTEXT DevContext, 1189 | IN WDFREQUEST Request 1190 | ) 1191 | { 1192 | NTSTATUS status = STATUS_SUCCESS; 1193 | WDF_REQUEST_PARAMETERS params; 1194 | PHID_XFER_PACKET transferPacket = NULL; 1195 | size_t bytesWritten = 0; 1196 | 1197 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1198 | "MlfsWriteReport Entry\n"); 1199 | 1200 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1201 | WdfRequestGetParameters(Request, ¶ms); 1202 | 1203 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1204 | { 1205 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1206 | "MlfsWriteReport Xfer packet too small\n"); 1207 | 1208 | status = STATUS_BUFFER_TOO_SMALL; 1209 | } 1210 | else 1211 | { 1212 | 1213 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1214 | 1215 | if (transferPacket == NULL) 1216 | { 1217 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1218 | "MlfsWriteReport No xfer packet\n"); 1219 | 1220 | status = STATUS_INVALID_DEVICE_REQUEST; 1221 | } 1222 | else 1223 | { 1224 | // 1225 | // switch on the report id 1226 | // 1227 | 1228 | switch (transferPacket->reportId) 1229 | { 1230 | default: 1231 | 1232 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1233 | "MlfsWriteReport Unhandled report type %d\n", transferPacket->reportId); 1234 | 1235 | status = STATUS_INVALID_PARAMETER; 1236 | 1237 | break; 1238 | } 1239 | } 1240 | } 1241 | 1242 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1243 | "MlfsWriteReport Exit = 0x%x\n", status); 1244 | 1245 | return status; 1246 | 1247 | } 1248 | 1249 | NTSTATUS 1250 | MlfsProcessVendorReport( 1251 | IN PMLFS_CONTEXT DevContext, 1252 | IN PVOID ReportBuffer, 1253 | IN ULONG ReportBufferLen, 1254 | OUT size_t* BytesWritten 1255 | ) 1256 | { 1257 | NTSTATUS status = STATUS_SUCCESS; 1258 | WDFREQUEST reqRead; 1259 | PVOID pReadReport = NULL; 1260 | size_t bytesReturned = 0; 1261 | 1262 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1263 | "MlfsProcessVendorReport Entry\n"); 1264 | 1265 | status = WdfIoQueueRetrieveNextRequest(DevContext->ReportQueue, 1266 | &reqRead); 1267 | 1268 | if (NT_SUCCESS(status)) 1269 | { 1270 | status = WdfRequestRetrieveOutputBuffer(reqRead, 1271 | ReportBufferLen, 1272 | &pReadReport, 1273 | &bytesReturned); 1274 | 1275 | if (NT_SUCCESS(status)) 1276 | { 1277 | // 1278 | // Copy ReportBuffer into read request 1279 | // 1280 | 1281 | if (bytesReturned > ReportBufferLen) 1282 | { 1283 | bytesReturned = ReportBufferLen; 1284 | } 1285 | 1286 | RtlCopyMemory(pReadReport, 1287 | ReportBuffer, 1288 | bytesReturned); 1289 | 1290 | // 1291 | // Complete read with the number of bytes returned as info 1292 | // 1293 | 1294 | WdfRequestCompleteWithInformation(reqRead, 1295 | status, 1296 | bytesReturned); 1297 | 1298 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1299 | "MlfsProcessVendorReport %d bytes returned\n", bytesReturned); 1300 | 1301 | // 1302 | // Return the number of bytes written for the write request completion 1303 | // 1304 | 1305 | *BytesWritten = bytesReturned; 1306 | 1307 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1308 | "%s completed, Queue:0x%p, Request:0x%p\n", 1309 | DbgHidInternalIoctlString(IOCTL_HID_READ_REPORT), 1310 | DevContext->ReportQueue, 1311 | reqRead); 1312 | } 1313 | else 1314 | { 1315 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1316 | "WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1317 | } 1318 | } 1319 | else 1320 | { 1321 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1322 | "WdfIoQueueRetrieveNextRequest failed Status 0x%x\n", status); 1323 | } 1324 | 1325 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1326 | "MlfsProcessVendorReport Exit = 0x%x\n", status); 1327 | 1328 | return status; 1329 | } 1330 | 1331 | NTSTATUS 1332 | MlfsReadReport( 1333 | IN PMLFS_CONTEXT DevContext, 1334 | IN WDFREQUEST Request, 1335 | OUT BOOLEAN* CompleteRequest 1336 | ) 1337 | { 1338 | NTSTATUS status = STATUS_SUCCESS; 1339 | 1340 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1341 | "MlfsReadReport Entry\n"); 1342 | 1343 | // 1344 | // Forward this read request to our manual queue 1345 | // (in other words, we are going to defer this request 1346 | // until we have a corresponding write request to 1347 | // match it with) 1348 | // 1349 | 1350 | status = WdfRequestForwardToIoQueue(Request, DevContext->ReportQueue); 1351 | 1352 | if (!NT_SUCCESS(status)) 1353 | { 1354 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1355 | "WdfRequestForwardToIoQueue failed Status 0x%x\n", status); 1356 | } 1357 | else 1358 | { 1359 | *CompleteRequest = FALSE; 1360 | } 1361 | 1362 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1363 | "MlfsReadReport Exit = 0x%x\n", status); 1364 | 1365 | return status; 1366 | } 1367 | 1368 | NTSTATUS 1369 | MlfsSetFeature( 1370 | IN PMLFS_CONTEXT DevContext, 1371 | IN WDFREQUEST Request, 1372 | OUT BOOLEAN* CompleteRequest 1373 | ) 1374 | { 1375 | NTSTATUS status = STATUS_SUCCESS; 1376 | WDF_REQUEST_PARAMETERS params; 1377 | PHID_XFER_PACKET transferPacket = NULL; 1378 | MlfsFeatureReport* pReport = NULL; 1379 | 1380 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1381 | "MlfsSetFeature Entry\n"); 1382 | 1383 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1384 | WdfRequestGetParameters(Request, ¶ms); 1385 | 1386 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1387 | { 1388 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1389 | "MlfsSetFeature Xfer packet too small\n"); 1390 | 1391 | status = STATUS_BUFFER_TOO_SMALL; 1392 | } 1393 | else 1394 | { 1395 | 1396 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1397 | 1398 | if (transferPacket == NULL) 1399 | { 1400 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1401 | "MlfsWriteReport No xfer packet\n"); 1402 | 1403 | status = STATUS_INVALID_DEVICE_REQUEST; 1404 | } 1405 | else 1406 | { 1407 | // 1408 | // switch on the report id 1409 | // 1410 | 1411 | switch (transferPacket->reportId) 1412 | { 1413 | case REPORTID_FEATURE: 1414 | 1415 | if (transferPacket->reportBufferLen == sizeof(MlfsFeatureReport)) 1416 | { 1417 | pReport = (MlfsFeatureReport*)transferPacket->reportBuffer; 1418 | 1419 | DevContext->DeviceMode = pReport->DeviceMode; 1420 | 1421 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1422 | "MlfsSetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1423 | } 1424 | else 1425 | { 1426 | status = STATUS_INVALID_PARAMETER; 1427 | 1428 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1429 | "MlfsSetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(MlfsFeatureReport) (%d)\n", 1430 | transferPacket->reportBufferLen, 1431 | sizeof(MlfsFeatureReport)); 1432 | } 1433 | 1434 | break; 1435 | 1436 | default: 1437 | 1438 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1439 | "MlfsSetFeature Unhandled report type %d\n", transferPacket->reportId); 1440 | 1441 | status = STATUS_INVALID_PARAMETER; 1442 | 1443 | break; 1444 | } 1445 | } 1446 | } 1447 | 1448 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1449 | "MlfsSetFeature Exit = 0x%x\n", status); 1450 | 1451 | return status; 1452 | } 1453 | 1454 | NTSTATUS 1455 | MlfsGetFeature( 1456 | IN PMLFS_CONTEXT DevContext, 1457 | IN WDFREQUEST Request, 1458 | OUT BOOLEAN* CompleteRequest 1459 | ) 1460 | { 1461 | NTSTATUS status = STATUS_SUCCESS; 1462 | WDF_REQUEST_PARAMETERS params; 1463 | PHID_XFER_PACKET transferPacket = NULL; 1464 | 1465 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1466 | "MlfsGetFeature Entry\n"); 1467 | 1468 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1469 | WdfRequestGetParameters(Request, ¶ms); 1470 | 1471 | if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) 1472 | { 1473 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1474 | "MlfsGetFeature Xfer packet too small\n"); 1475 | 1476 | status = STATUS_BUFFER_TOO_SMALL; 1477 | } 1478 | else 1479 | { 1480 | 1481 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1482 | 1483 | if (transferPacket == NULL) 1484 | { 1485 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1486 | "MlfsGetFeature No xfer packet\n"); 1487 | 1488 | status = STATUS_INVALID_DEVICE_REQUEST; 1489 | } 1490 | else 1491 | { 1492 | // 1493 | // switch on the report id 1494 | // 1495 | 1496 | switch (transferPacket->reportId) 1497 | { 1498 | case REPORTID_MTOUCH: 1499 | { 1500 | 1501 | MlfsMaxCountReport* pReport = NULL; 1502 | 1503 | if (transferPacket->reportBufferLen == sizeof(MlfsMaxCountReport)) 1504 | { 1505 | pReport = (MlfsMaxCountReport*)transferPacket->reportBuffer; 1506 | 1507 | pReport->MaximumCount = MULTI_MAX_COUNT; 1508 | 1509 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1510 | "MlfsGetFeature MaximumCount = 0x%x\n", MULTI_MAX_COUNT); 1511 | } 1512 | else 1513 | { 1514 | status = STATUS_INVALID_PARAMETER; 1515 | 1516 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1517 | "MlfsGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(MlfsMaxCountReport) (%d)\n", 1518 | transferPacket->reportBufferLen, 1519 | sizeof(MlfsMaxCountReport)); 1520 | } 1521 | 1522 | break; 1523 | } 1524 | 1525 | case REPORTID_FEATURE: 1526 | { 1527 | 1528 | MlfsFeatureReport* pReport = NULL; 1529 | 1530 | if (transferPacket->reportBufferLen == sizeof(MlfsFeatureReport)) 1531 | { 1532 | pReport = (MlfsFeatureReport*)transferPacket->reportBuffer; 1533 | 1534 | pReport->DeviceMode = DevContext->DeviceMode; 1535 | 1536 | pReport->DeviceIdentifier = 0; 1537 | 1538 | MlfsPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1539 | "MlfsGetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1540 | } 1541 | else 1542 | { 1543 | status = STATUS_INVALID_PARAMETER; 1544 | 1545 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1546 | "MlfsGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(MlfsFeatureReport) (%d)\n", 1547 | transferPacket->reportBufferLen, 1548 | sizeof(MlfsFeatureReport)); 1549 | } 1550 | 1551 | break; 1552 | } 1553 | 1554 | default: 1555 | 1556 | MlfsPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1557 | "MlfsGetFeature Unhandled report type %d\n", transferPacket->reportId); 1558 | 1559 | status = STATUS_INVALID_PARAMETER; 1560 | 1561 | break; 1562 | } 1563 | } 1564 | } 1565 | 1566 | MlfsPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1567 | "MlfsGetFeature Exit = 0x%x\n", status); 1568 | 1569 | return status; 1570 | } 1571 | 1572 | PCHAR 1573 | DbgHidInternalIoctlString( 1574 | IN ULONG IoControlCode 1575 | ) 1576 | { 1577 | switch (IoControlCode) 1578 | { 1579 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 1580 | return "IOCTL_HID_GET_DEVICE_DESCRIPTOR"; 1581 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 1582 | return "IOCTL_HID_GET_REPORT_DESCRIPTOR"; 1583 | case IOCTL_HID_READ_REPORT: 1584 | return "IOCTL_HID_READ_REPORT"; 1585 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 1586 | return "IOCTL_HID_GET_DEVICE_ATTRIBUTES"; 1587 | case IOCTL_HID_WRITE_REPORT: 1588 | return "IOCTL_HID_WRITE_REPORT"; 1589 | case IOCTL_HID_SET_FEATURE: 1590 | return "IOCTL_HID_SET_FEATURE"; 1591 | case IOCTL_HID_GET_FEATURE: 1592 | return "IOCTL_HID_GET_FEATURE"; 1593 | case IOCTL_HID_GET_STRING: 1594 | return "IOCTL_HID_GET_STRING"; 1595 | case IOCTL_HID_ACTIVATE_DEVICE: 1596 | return "IOCTL_HID_ACTIVATE_DEVICE"; 1597 | case IOCTL_HID_DEACTIVATE_DEVICE: 1598 | return "IOCTL_HID_DEACTIVATE_DEVICE"; 1599 | case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: 1600 | return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST"; 1601 | case IOCTL_HID_SET_OUTPUT_REPORT: 1602 | return "IOCTL_HID_SET_OUTPUT_REPORT"; 1603 | case IOCTL_HID_GET_INPUT_REPORT: 1604 | return "IOCTL_HID_GET_INPUT_REPORT"; 1605 | default: 1606 | return "Unknown IOCTL"; 1607 | } 1608 | } --------------------------------------------------------------------------------