├── .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 | }
--------------------------------------------------------------------------------