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