├── crostouchscreen2 ├── stdint.h ├── crostouchscreen2.vcxproj.user ├── trace.h ├── spb.h ├── hidcommon.h ├── crostouchscreen2.vcxproj.filters ├── crostouchscreen2.inf ├── crc.cpp ├── atmel.h ├── crostouchscreen2.vcxproj ├── spb.cpp ├── atmel_mxt.h └── atmel.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 | #include 2 | 3 | #define BIT(nr) (1UL << (nr)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # crostouchscreen2 2 | Atmel MaxTouch Touch Screen Driver for Acer C720P and Chromebook Pixel 2. 3 | 4 | Tested on Acer C720P. Works with up to 10 touches. 5 | 6 | # Credits 7 | 8 | Huge thanks to the vmulti and DragonFlyBSD projects, which I used for references. Also, thanks to Microsoft for open sourcing the Synaptics RMI I2C driver, which I also used as a reference. 9 | -------------------------------------------------------------------------------- /crostouchscreen2 Package/crostouchscreen2 Package.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {8E41214B-6785-4CFE-B992-037D68949A14} 6 | inf;inv;inx;mof;mc; 7 | 8 | 9 | -------------------------------------------------------------------------------- /crostouchscreen2 Package/crostouchscreen2 Package.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /crostouchscreen2/crostouchscreen2.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TestSign 5 | CN="WDKTestCert CoolStar,132809860365442907" | 9823BB26AF2B6AB70A2AE4F1FD79466E6351C77F 6 | 7 | 8 | CN="WDKTestCert CoolStar,131002039613453615" | 47BA72C5A0D2F559EA9FD7E943B307D1E179A49E 9 | True 10 | 11 | -------------------------------------------------------------------------------- /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_ UCHAR Address, 46 | _In_reads_bytes_(Length) PVOID Data, 47 | _In_ ULONG Length 48 | ); 49 | 50 | NTSTATUS 51 | SpbReadDataSynchronously16( 52 | _In_ SPB_CONTEXT *SpbContext, 53 | _In_ UINT16 Address, 54 | _In_reads_bytes_(Length) PVOID Data, 55 | _In_ ULONG Length 56 | ); 57 | 58 | VOID 59 | SpbTargetDeinitialize( 60 | IN WDFDEVICE FxDevice, 61 | IN SPB_CONTEXT *SpbContext 62 | ); 63 | 64 | NTSTATUS 65 | SpbTargetInitialize( 66 | IN WDFDEVICE FxDevice, 67 | IN SPB_CONTEXT *SpbContext 68 | ); 69 | 70 | NTSTATUS 71 | SpbWriteDataSynchronously( 72 | IN SPB_CONTEXT *SpbContext, 73 | IN UCHAR Address, 74 | IN PVOID Data, 75 | IN ULONG Length 76 | ); 77 | 78 | NTSTATUS 79 | SpbWriteDataSynchronously16( 80 | IN SPB_CONTEXT *SpbContext, 81 | IN UINT16 Address, 82 | IN PVOID Data, 83 | IN ULONG Length 84 | ); -------------------------------------------------------------------------------- /crostouchscreen2/hidcommon.h: -------------------------------------------------------------------------------- 1 | #if !defined(_ATMEL_COMMON_H_) 2 | #define _ATMEL_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 ATMEL_PID 0xBACC 10 | #define ATMEL_VID 0x00FF 11 | #define ATMEL_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 _ATMEL_MULTITOUCH_REPORT 52 | { 53 | 54 | BYTE ReportID; 55 | 56 | TOUCH Touch[10]; 57 | 58 | BYTE ActualCount; 59 | 60 | } AtmelMultiTouchReport; 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 _ATMEL_FEATURE_REPORT 73 | { 74 | 75 | BYTE ReportID; 76 | 77 | BYTE DeviceMode; 78 | 79 | BYTE DeviceIdentifier; 80 | 81 | } AtmelFeatureReport; 82 | 83 | typedef struct _ATMEL_MAXCOUNT_REPORT 84 | { 85 | 86 | BYTE ReportID; 87 | 88 | BYTE MaximumCount; 89 | 90 | } AtmelMaxCountReport; 91 | #pragma pack() 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /crostouchscreen2/crostouchscreen2.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | -------------------------------------------------------------------------------- /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 Atmel MaxTouch 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\ATML0001 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 Atmel MaxTouch Touch Screen" 78 | CrosTouchScreen.SVCDESC = "CrosTouchScreen Service" 79 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2015 CoolStar 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | 16 | ====================== Windows Driver Samples License ====================== 17 | 18 | The Microsoft Public License (MS-PL) 19 | Copyright (c) 2015 Microsoft 20 | 21 | This license governs use of the accompanying software. If you use the software, you 22 | accept this license. If you do not accept the license, do not use the software. 23 | 24 | 1. Definitions 25 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the 26 | same meaning here as under U.S. copyright law. 27 | A "contribution" is the original software, or any additions or changes to the software. 28 | A "contributor" is any person that distributes its contribution under this license. 29 | "Licensed patents" are a contributor's patent claims that read directly on its contribution. 30 | 31 | 2. Grant of Rights 32 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. 33 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 34 | 35 | 3. Conditions and Limitations 36 | (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. 37 | (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. 38 | (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 39 | (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. 40 | (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. -------------------------------------------------------------------------------- /crostouchscreen2/crc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 | * 4 | * This code is derived from software contributed to The DragonFly Project 5 | * by Matthew Dillon 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * 3. Neither the name of The DragonFly Project nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific, prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | *------------------------------------------------------------------------------ 35 | * Copyright 2011 Atmel Corporation. All rights reserved. 36 | * 37 | * Redistribution and use in source and binary forms, with or without 38 | * modification, are permitted provided that the following conditions are met: 39 | * 40 | * 1. Redistributions of source code must retain the above copyright notice, 41 | * this list of conditions and the following disclaimer. 42 | * 43 | * 2. Redistributions in binary form must reproduce the above copyright 44 | * notice, this list of conditions and the following disclaimer in the 45 | * documentation and/or other materials provided with the distribution. 46 | * 47 | * THIS SOFTWARE IS PROVIDED BY ATMEL ''AS IS'' AND ANY EXPRESS OR IMPLIED 48 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 49 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 50 | * EVENT SHALL ATMEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 52 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 53 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 54 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 55 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 56 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | *----------------------------------------------------------------------------- 58 | */ 59 | /* 60 | * This file contains a mix of code taken from the atmel-maxtouch/obp-utils 61 | * github codebase and my own for testing the atmel touchscreen chipset in 62 | * the Acer C720P chromebook. 63 | * 64 | * This code is independent and is used by both kernel AND user mode programs. 65 | */ 66 | 67 | #include 68 | #include "atmel.h" 69 | 70 | /*! 71 | * @brief Information block checksum return function. 72 | * @return 24-bit checksum value in 32-bit integer. 73 | */ 74 | uint32_t 75 | obp_convert_crc(struct mxt_raw_crc *crc) 76 | { 77 | return ((crc->CRC_hi << 16u) | (crc->CRC)); 78 | } 79 | 80 | /*! 81 | * @brief Information Block Checksum algorithm. 82 | * @return Calculated Information Block Checksum. 83 | */ 84 | static 85 | uint32_t 86 | crc24_2byte(uint32_t crc, uint8_t firstbyte, uint8_t secondbyte) 87 | { 88 | static const uint32_t CRCPOLY = 0x0080001B; 89 | uint32_t result; 90 | uint16_t data_word; 91 | 92 | data_word = (uint16_t)((uint16_t)(secondbyte << 8u) | firstbyte); 93 | result = ((crc << 1u) ^ (uint32_t)data_word); 94 | 95 | /* Check if 25th bit is set, and XOR the result to create 96 | * 24-bit checksum */ 97 | if (result & 0x1000000) { 98 | result ^= CRCPOLY; 99 | } 100 | return result; 101 | } 102 | 103 | /* 104 | * Return 24-bit crc. 105 | */ 106 | uint32_t 107 | obp_crc24(uint8_t *buf, size_t bytes) 108 | { 109 | uint32_t crc; 110 | size_t i; 111 | 112 | crc = 0; 113 | for (i = 0; i < (bytes & ~1); i += 2) { 114 | crc = crc24_2byte(crc, buf[i], buf[i + 1]); 115 | } 116 | if (i < bytes) 117 | crc = crc24_2byte(crc, buf[i], 0); 118 | crc &= 0x00FFFFFF; 119 | 120 | return crc; 121 | } -------------------------------------------------------------------------------- /.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/atmel.h: -------------------------------------------------------------------------------- 1 | #if !defined(_ATMEL_H_) 2 | #define _ATMEL_H_ 3 | 4 | #pragma warning(disable:4200) // suppress nameless struct/union warning 5 | #pragma warning(disable:4201) // suppress nameless struct/union warning 6 | #pragma warning(disable:4214) // suppress bit field types other than int warning 7 | #include 8 | #include 9 | 10 | #pragma warning(default:4200) 11 | #pragma warning(default:4201) 12 | #pragma warning(default:4214) 13 | #include 14 | 15 | #pragma warning(disable:4201) // suppress nameless struct/union warning 16 | #pragma warning(disable:4214) // suppress bit field types other than int warning 17 | #include 18 | 19 | #include "hidcommon.h" 20 | #include "spb.h" 21 | #include "atmel_mxt.h" 22 | 23 | // 24 | // String definitions 25 | // 26 | 27 | #define DRIVERNAME "crostouchscreen2.sys: " 28 | 29 | #define ATMEL_POOL_TAG (ULONG) 'lmtA' 30 | 31 | #define NTDEVICE_NAME_STRING L"\\Device\\ATML0001" 32 | #define SYMBOLIC_NAME_STRING L"\\DosDevices\\ATML0001" 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 _ATMEL_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 | WDFTIMER Timer; 171 | 172 | mxt_message_t lastmsg; 173 | 174 | mxt_rollup core; 175 | 176 | struct mxt_object *msgprocobj; 177 | struct mxt_object *cmdprocobj; 178 | 179 | mxt_id_info info; 180 | 181 | UINT32 TouchCount; 182 | 183 | uint8_t Flags[20]; 184 | 185 | USHORT XValue[20]; 186 | 187 | USHORT YValue[20]; 188 | 189 | USHORT AREA[20]; 190 | 191 | uint16_t max_x; 192 | uint16_t max_y; 193 | 194 | uint8_t max_x_hid[2]; 195 | uint8_t max_y_hid[2]; 196 | 197 | uint8_t num_touchids; 198 | uint8_t multitouch; 199 | 200 | struct t7_config t7_cfg; 201 | 202 | uint8_t t100_aux_ampl; 203 | uint8_t t100_aux_area; 204 | uint8_t t100_aux_vect; 205 | 206 | /* Cached parameters from object table */ 207 | uint16_t T5_address; 208 | uint8_t T5_msg_size; 209 | uint8_t T6_reportid; 210 | uint16_t T6_address; 211 | uint16_t T7_address; 212 | uint8_t T9_reportid_min; 213 | uint8_t T9_reportid_max; 214 | uint8_t T19_reportid; 215 | uint16_t T44_address; 216 | uint8_t T100_reportid_min; 217 | uint8_t T100_reportid_max; 218 | 219 | uint8_t max_reportid; 220 | 221 | uint8_t last_message_count; 222 | 223 | uint8_t interrupt_count; 224 | 225 | } ATMEL_CONTEXT, *PATMEL_CONTEXT; 226 | 227 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(ATMEL_CONTEXT, GetDeviceContext) 228 | 229 | // 230 | // Function definitions 231 | // 232 | 233 | extern "C" { 234 | DRIVER_INITIALIZE DriverEntry; 235 | } 236 | 237 | EVT_WDF_DRIVER_UNLOAD AtmelDriverUnload; 238 | 239 | EVT_WDF_DRIVER_DEVICE_ADD AtmelEvtDeviceAdd; 240 | 241 | EVT_WDFDEVICE_WDM_IRP_PREPROCESS AtmelEvtWdmPreprocessMnQueryId; 242 | 243 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL AtmelEvtInternalDeviceControl; 244 | 245 | NTSTATUS 246 | AtmelGetHidDescriptor( 247 | IN WDFDEVICE Device, 248 | IN WDFREQUEST Request 249 | ); 250 | 251 | NTSTATUS 252 | AtmelGetReportDescriptor( 253 | IN WDFDEVICE Device, 254 | IN WDFREQUEST Request 255 | ); 256 | 257 | NTSTATUS 258 | AtmelGetDeviceAttributes( 259 | IN WDFREQUEST Request 260 | ); 261 | 262 | NTSTATUS 263 | AtmelGetString( 264 | IN WDFREQUEST Request 265 | ); 266 | 267 | NTSTATUS 268 | AtmelWriteReport( 269 | IN PATMEL_CONTEXT DevContext, 270 | IN WDFREQUEST Request 271 | ); 272 | 273 | NTSTATUS 274 | AtmelProcessVendorReport( 275 | IN PATMEL_CONTEXT DevContext, 276 | IN PVOID ReportBuffer, 277 | IN ULONG ReportBufferLen, 278 | OUT size_t* BytesWritten 279 | ); 280 | 281 | NTSTATUS 282 | AtmelReadReport( 283 | IN PATMEL_CONTEXT DevContext, 284 | IN WDFREQUEST Request, 285 | OUT BOOLEAN* CompleteRequest 286 | ); 287 | 288 | NTSTATUS 289 | AtmelSetFeature( 290 | IN PATMEL_CONTEXT DevContext, 291 | IN WDFREQUEST Request, 292 | OUT BOOLEAN* CompleteRequest 293 | ); 294 | 295 | NTSTATUS 296 | AtmelGetFeature( 297 | IN PATMEL_CONTEXT DevContext, 298 | IN WDFREQUEST Request, 299 | OUT BOOLEAN* CompleteRequest 300 | ); 301 | 302 | PCHAR 303 | DbgHidInternalIoctlString( 304 | IN ULONG IoControlCode 305 | ); 306 | 307 | // 308 | // Helper macros 309 | // 310 | 311 | #define DEBUG_LEVEL_ERROR 1 312 | #define DEBUG_LEVEL_INFO 2 313 | #define DEBUG_LEVEL_VERBOSE 3 314 | 315 | #define DBG_INIT 1 316 | #define DBG_PNP 2 317 | #define DBG_IOCTL 4 318 | 319 | #if 0 320 | #define AtmelPrint(dbglevel, dbgcatagory, fmt, ...) { \ 321 | if (AtmelDebugLevel >= dbglevel && \ 322 | (AtmelDebugCatagories && dbgcatagory)) \ 323 | { \ 324 | DbgPrint(DRIVERNAME); \ 325 | DbgPrint(fmt, __VA_ARGS__); \ 326 | } \ 327 | } 328 | #else 329 | #define AtmelPrint(dbglevel, fmt, ...) { \ 330 | } 331 | #endif 332 | 333 | #endif -------------------------------------------------------------------------------- /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 | 327 | 328 | 329 | {36580c07-edc3-4c2b-b45f-6ab017e01a5d} 330 | 331 | 332 | 333 | 334 | 335 | -------------------------------------------------------------------------------- /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 | 198 | 199 | 2.9.2 200 | 201 | 202 | 203 | 204 | true 205 | trace.h 206 | true 207 | 208 | 209 | 2.9.2 210 | 211 | 212 | 213 | 214 | true 215 | trace.h 216 | true 217 | 218 | 219 | 2.9.2 220 | 221 | 222 | 223 | 224 | true 225 | trace.h 226 | true 227 | 228 | 229 | 2.9.2 230 | 231 | 232 | 233 | 234 | true 235 | trace.h 236 | true 237 | 238 | 239 | 2.9.2 240 | 241 | 242 | 243 | 244 | true 245 | trace.h 246 | true 247 | 248 | 249 | 2.9.2 250 | 251 | 252 | 253 | 254 | true 255 | trace.h 256 | true 257 | 258 | 259 | 2.9.2 260 | 261 | 262 | 263 | 264 | true 265 | trace.h 266 | true 267 | 268 | 269 | 2.9.2 270 | 271 | 272 | 273 | 274 | true 275 | trace.h 276 | true 277 | false 278 | 279 | 280 | 2.9.2 281 | 282 | 283 | 284 | 285 | true 286 | trace.h 287 | true 288 | false 289 | 290 | 291 | 2.9.2 292 | 293 | 294 | SHA256 295 | 296 | 297 | 298 | 299 | true 300 | trace.h 301 | true 302 | 303 | 304 | 2.9.2 305 | 306 | 307 | 308 | 309 | true 310 | trace.h 311 | true 312 | 313 | 314 | 2.9.2 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | -------------------------------------------------------------------------------- /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 "atmel.h" 22 | #include "spb.h" 23 | #include 24 | 25 | static ULONG AtmelDebugLevel = 100; 26 | static ULONG AtmelDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 27 | 28 | NTSTATUS 29 | SpbDoWriteDataSynchronously16( 30 | IN SPB_CONTEXT *SpbContext, 31 | IN UINT16 Address, 32 | IN PVOID Data, 33 | IN ULONG Length 34 | ) 35 | /*++ 36 | 37 | Routine Description: 38 | 39 | This helper routine abstracts creating and sending an I/O 40 | request (I2C Write) to the Spb I/O target. 41 | 42 | Arguments: 43 | 44 | SpbContext - Pointer to the current device context 45 | Address - The I2C register address to write to 46 | Data - A buffer to receive the data at at the above address 47 | Length - The amount of data to be read from the above address 48 | 49 | Return Value: 50 | 51 | NTSTATUS Status indicating success or failure 52 | 53 | --*/ 54 | { 55 | PUCHAR buffer; 56 | ULONG length; 57 | WDFMEMORY memory; 58 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 59 | NTSTATUS status; 60 | 61 | // 62 | // The address pointer and data buffer must be combined 63 | // into one contiguous buffer representing the write transaction. 64 | // 65 | length = Length + 2; 66 | memory = NULL; 67 | 68 | if (length > DEFAULT_SPB_BUFFER_SIZE) 69 | { 70 | status = WdfMemoryCreate( 71 | WDF_NO_OBJECT_ATTRIBUTES, 72 | NonPagedPool, 73 | ATMEL_POOL_TAG, 74 | length, 75 | &memory, 76 | (PVOID *)&buffer); 77 | 78 | if (!NT_SUCCESS(status)) 79 | { 80 | AtmelPrint( 81 | DEBUG_LEVEL_ERROR, 82 | DBG_IOCTL, 83 | "Error allocating memory for Spb write - %!STATUS!", 84 | status); 85 | goto exit; 86 | } 87 | 88 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 89 | &memoryDescriptor, 90 | memory, 91 | NULL); 92 | } 93 | else 94 | { 95 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->WriteMemory, NULL); 96 | 97 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 98 | &memoryDescriptor, 99 | (PVOID)buffer, 100 | length); 101 | } 102 | 103 | UINT16 AddressBuffer[] = { 104 | Address 105 | }; 106 | 107 | // 108 | // Transaction starts by specifying the address bytes 109 | // 110 | RtlCopyMemory(buffer, (UCHAR *)&AddressBuffer, sizeof(AddressBuffer)); 111 | 112 | // 113 | // Address is followed by the data payload 114 | // 115 | RtlCopyMemory((buffer + sizeof(AddressBuffer)), Data, length - sizeof(AddressBuffer)); 116 | 117 | status = WdfIoTargetSendWriteSynchronously( 118 | SpbContext->SpbIoTarget, 119 | NULL, 120 | &memoryDescriptor, 121 | NULL, 122 | NULL, 123 | NULL); 124 | 125 | if (!NT_SUCCESS(status)) 126 | { 127 | AtmelPrint( 128 | DEBUG_LEVEL_ERROR, 129 | DBG_IOCTL, 130 | "Error writing to Spb - %!STATUS!", 131 | status); 132 | goto exit; 133 | } 134 | 135 | exit: 136 | 137 | if (NULL != memory) 138 | { 139 | WdfObjectDelete(memory); 140 | } 141 | 142 | return status; 143 | } 144 | 145 | NTSTATUS 146 | SpbDoWriteDataSynchronously( 147 | IN SPB_CONTEXT *SpbContext, 148 | IN UCHAR Address, 149 | IN PVOID Data, 150 | IN ULONG Length 151 | ) 152 | /*++ 153 | 154 | Routine Description: 155 | 156 | This helper routine abstracts creating and sending an I/O 157 | request (I2C Write) to the Spb I/O target. 158 | 159 | Arguments: 160 | 161 | SpbContext - Pointer to the current device context 162 | Address - The I2C register address to write to 163 | Data - A buffer to receive the data at at the above address 164 | Length - The amount of data to be read from the above address 165 | 166 | Return Value: 167 | 168 | NTSTATUS Status indicating success or failure 169 | 170 | --*/ 171 | { 172 | PUCHAR buffer; 173 | ULONG length; 174 | WDFMEMORY memory; 175 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 176 | NTSTATUS status; 177 | 178 | // 179 | // The address pointer and data buffer must be combined 180 | // into one contiguous buffer representing the write transaction. 181 | // 182 | length = Length + 1; 183 | memory = NULL; 184 | 185 | if (length > DEFAULT_SPB_BUFFER_SIZE) 186 | { 187 | status = WdfMemoryCreate( 188 | WDF_NO_OBJECT_ATTRIBUTES, 189 | NonPagedPool, 190 | ATMEL_POOL_TAG, 191 | length, 192 | &memory, 193 | (PVOID *)&buffer); 194 | 195 | if (!NT_SUCCESS(status)) 196 | { 197 | AtmelPrint( 198 | DEBUG_LEVEL_ERROR, 199 | DBG_IOCTL, 200 | "Error allocating memory for Spb write - %!STATUS!", 201 | status); 202 | goto exit; 203 | } 204 | 205 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 206 | &memoryDescriptor, 207 | memory, 208 | NULL); 209 | } 210 | else 211 | { 212 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->WriteMemory, NULL); 213 | 214 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 215 | &memoryDescriptor, 216 | (PVOID)buffer, 217 | length); 218 | } 219 | 220 | // 221 | // Transaction starts by specifying the address bytes 222 | // 223 | RtlCopyMemory(buffer, &Address, sizeof(Address)); 224 | 225 | // 226 | // Address is followed by the data payload 227 | // 228 | RtlCopyMemory((buffer + sizeof(Address)), Data, length - sizeof(Address)); 229 | 230 | status = WdfIoTargetSendWriteSynchronously( 231 | SpbContext->SpbIoTarget, 232 | NULL, 233 | &memoryDescriptor, 234 | NULL, 235 | NULL, 236 | NULL); 237 | 238 | if (!NT_SUCCESS(status)) 239 | { 240 | AtmelPrint( 241 | DEBUG_LEVEL_ERROR, 242 | DBG_IOCTL, 243 | "Error writing to Spb - %!STATUS!", 244 | status); 245 | goto exit; 246 | } 247 | 248 | exit: 249 | 250 | if (NULL != memory) 251 | { 252 | WdfObjectDelete(memory); 253 | } 254 | 255 | return status; 256 | } 257 | 258 | NTSTATUS 259 | SpbWriteDataSynchronously( 260 | IN SPB_CONTEXT *SpbContext, 261 | IN UCHAR Address, 262 | IN PVOID Data, 263 | IN ULONG Length 264 | ) 265 | /*++ 266 | 267 | Routine Description: 268 | 269 | This routine abstracts creating and sending an I/O 270 | request (I2C Write) to the Spb I/O target and utilizes 271 | a helper routine to do work inside of locked code. 272 | 273 | Arguments: 274 | 275 | SpbContext - Pointer to the current device context 276 | Address - The I2C register address to write to 277 | Data - A buffer to receive the data at at the above address 278 | Length - The amount of data to be read from the above address 279 | 280 | Return Value: 281 | 282 | NTSTATUS Status indicating success or failure 283 | 284 | --*/ 285 | { 286 | NTSTATUS status; 287 | 288 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 289 | 290 | status = SpbDoWriteDataSynchronously( 291 | SpbContext, 292 | Address, 293 | Data, 294 | Length); 295 | 296 | WdfWaitLockRelease(SpbContext->SpbLock); 297 | 298 | return status; 299 | } 300 | 301 | NTSTATUS 302 | SpbWriteDataSynchronously16( 303 | IN SPB_CONTEXT *SpbContext, 304 | IN UINT16 Address, 305 | IN PVOID Data, 306 | IN ULONG Length 307 | ) 308 | /*++ 309 | 310 | Routine Description: 311 | 312 | This routine abstracts creating and sending an I/O 313 | request (I2C Write) to the Spb I/O target and utilizes 314 | a helper routine to do work inside of locked code. 315 | 316 | Arguments: 317 | 318 | SpbContext - Pointer to the current device context 319 | Address - The I2C register address to write to 320 | Data - A buffer to receive the data at at the above address 321 | Length - The amount of data to be read from the above address 322 | 323 | Return Value: 324 | 325 | NTSTATUS Status indicating success or failure 326 | 327 | --*/ 328 | { 329 | NTSTATUS status; 330 | 331 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 332 | 333 | status = SpbDoWriteDataSynchronously16( 334 | SpbContext, 335 | Address, 336 | Data, 337 | Length); 338 | 339 | WdfWaitLockRelease(SpbContext->SpbLock); 340 | 341 | return status; 342 | } 343 | 344 | NTSTATUS 345 | SpbReadDataSynchronously( 346 | _In_ SPB_CONTEXT *SpbContext, 347 | _In_ UCHAR Address, 348 | _In_reads_bytes_(Length) PVOID Data, 349 | _In_ ULONG Length 350 | ) 351 | /*++ 352 | 353 | Routine Description: 354 | 355 | This helper routine abstracts creating and sending an I/O 356 | request (I2C Read) to the Spb I/O target. 357 | 358 | Arguments: 359 | 360 | SpbContext - Pointer to the current device context 361 | Address - The I2C register address to read from 362 | Data - A buffer to receive the data at at the above address 363 | Length - The amount of data to be read from the above address 364 | 365 | Return Value: 366 | 367 | NTSTATUS Status indicating success or failure 368 | 369 | --*/ 370 | { 371 | PUCHAR buffer; 372 | WDFMEMORY memory; 373 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 374 | NTSTATUS status; 375 | ULONG_PTR bytesRead; 376 | 377 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 378 | 379 | memory = NULL; 380 | status = STATUS_INVALID_PARAMETER; 381 | bytesRead = 0; 382 | 383 | // 384 | // Read transactions start by writing an address pointer 385 | // 386 | status = SpbDoWriteDataSynchronously( 387 | SpbContext, 388 | Address, 389 | NULL, 390 | 0); 391 | 392 | if (!NT_SUCCESS(status)) 393 | { 394 | AtmelPrint( 395 | DEBUG_LEVEL_ERROR, 396 | DBG_IOCTL, 397 | "Error setting address pointer for Spb read - %!STATUS!", 398 | status); 399 | goto exit; 400 | } 401 | 402 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 403 | { 404 | status = WdfMemoryCreate( 405 | WDF_NO_OBJECT_ATTRIBUTES, 406 | NonPagedPool, 407 | ATMEL_POOL_TAG, 408 | Length, 409 | &memory, 410 | (PVOID *)&buffer); 411 | 412 | if (!NT_SUCCESS(status)) 413 | { 414 | AtmelPrint( 415 | DEBUG_LEVEL_ERROR, 416 | DBG_IOCTL, 417 | "Error allocating memory for Spb read - %!STATUS!", 418 | status); 419 | goto exit; 420 | } 421 | 422 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 423 | &memoryDescriptor, 424 | memory, 425 | NULL); 426 | } 427 | else 428 | { 429 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 430 | 431 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 432 | &memoryDescriptor, 433 | (PVOID)buffer, 434 | Length); 435 | } 436 | 437 | 438 | status = WdfIoTargetSendReadSynchronously( 439 | SpbContext->SpbIoTarget, 440 | NULL, 441 | &memoryDescriptor, 442 | NULL, 443 | NULL, 444 | &bytesRead); 445 | 446 | if (!NT_SUCCESS(status) || 447 | bytesRead != Length) 448 | { 449 | AtmelPrint( 450 | DEBUG_LEVEL_ERROR, 451 | DBG_IOCTL, 452 | "Error reading from Spb - %!STATUS!", 453 | status); 454 | goto exit; 455 | } 456 | 457 | // 458 | // Copy back to the caller's buffer 459 | // 460 | RtlCopyMemory(Data, buffer, Length); 461 | 462 | exit: 463 | if (NULL != memory) 464 | { 465 | WdfObjectDelete(memory); 466 | } 467 | 468 | WdfWaitLockRelease(SpbContext->SpbLock); 469 | 470 | return status; 471 | } 472 | 473 | NTSTATUS 474 | SpbReadDataSynchronously16( 475 | _In_ SPB_CONTEXT *SpbContext, 476 | _In_ UINT16 Address, 477 | _In_reads_bytes_(Length) PVOID Data, 478 | _In_ ULONG Length 479 | ) 480 | /*++ 481 | 482 | Routine Description: 483 | 484 | This helper routine abstracts creating and sending an I/O 485 | request (I2C Read) to the Spb I/O target. 486 | 487 | Arguments: 488 | 489 | SpbContext - Pointer to the current device context 490 | Address - The I2C register address to read from 491 | Data - A buffer to receive the data at at the above address 492 | Length - The amount of data to be read from the above address 493 | 494 | Return Value: 495 | 496 | NTSTATUS Status indicating success or failure 497 | 498 | --*/ 499 | { 500 | PUCHAR buffer; 501 | WDFMEMORY memory; 502 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 503 | NTSTATUS status; 504 | ULONG_PTR bytesRead; 505 | 506 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 507 | 508 | memory = NULL; 509 | status = STATUS_INVALID_PARAMETER; 510 | bytesRead = 0; 511 | 512 | // 513 | // Read transactions start by writing an address pointer 514 | // 515 | status = SpbDoWriteDataSynchronously16( 516 | SpbContext, 517 | Address, 518 | NULL, 519 | 0); 520 | 521 | if (!NT_SUCCESS(status)) 522 | { 523 | AtmelPrint( 524 | DEBUG_LEVEL_ERROR, 525 | DBG_IOCTL, 526 | "Error setting address pointer for Spb read - %!STATUS!", 527 | status); 528 | goto exit; 529 | } 530 | 531 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 532 | { 533 | status = WdfMemoryCreate( 534 | WDF_NO_OBJECT_ATTRIBUTES, 535 | NonPagedPool, 536 | ATMEL_POOL_TAG, 537 | Length, 538 | &memory, 539 | (PVOID *)&buffer); 540 | 541 | if (!NT_SUCCESS(status)) 542 | { 543 | AtmelPrint( 544 | DEBUG_LEVEL_ERROR, 545 | DBG_IOCTL, 546 | "Error allocating memory for Spb read - %!STATUS!", 547 | status); 548 | goto exit; 549 | } 550 | 551 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 552 | &memoryDescriptor, 553 | memory, 554 | NULL); 555 | } 556 | else 557 | { 558 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 559 | 560 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 561 | &memoryDescriptor, 562 | (PVOID)buffer, 563 | Length); 564 | } 565 | 566 | 567 | status = WdfIoTargetSendReadSynchronously( 568 | SpbContext->SpbIoTarget, 569 | NULL, 570 | &memoryDescriptor, 571 | NULL, 572 | NULL, 573 | &bytesRead); 574 | 575 | if (!NT_SUCCESS(status) || 576 | bytesRead != Length) 577 | { 578 | AtmelPrint( 579 | DEBUG_LEVEL_ERROR, 580 | DBG_IOCTL, 581 | "Error reading from Spb - %!STATUS!", 582 | status); 583 | goto exit; 584 | } 585 | 586 | // 587 | // Copy back to the caller's buffer 588 | // 589 | RtlCopyMemory(Data, buffer, Length); 590 | 591 | exit: 592 | if (NULL != memory) 593 | { 594 | WdfObjectDelete(memory); 595 | } 596 | 597 | WdfWaitLockRelease(SpbContext->SpbLock); 598 | 599 | return status; 600 | } 601 | 602 | VOID 603 | SpbTargetDeinitialize( 604 | IN WDFDEVICE FxDevice, 605 | IN SPB_CONTEXT *SpbContext 606 | ) 607 | /*++ 608 | 609 | Routine Description: 610 | 611 | This helper routine is used to free any members added to the SPB_CONTEXT, 612 | note the SPB I/O target is parented to the device and will be 613 | closed and free'd when the device is removed. 614 | 615 | Arguments: 616 | 617 | FxDevice - Handle to the framework device object 618 | SpbContext - Pointer to the current device context 619 | 620 | Return Value: 621 | 622 | NTSTATUS Status indicating success or failure 623 | 624 | --*/ 625 | { 626 | UNREFERENCED_PARAMETER(FxDevice); 627 | UNREFERENCED_PARAMETER(SpbContext); 628 | 629 | // 630 | // Free any SPB_CONTEXT allocations here 631 | // 632 | if (SpbContext->SpbLock != NULL) 633 | { 634 | WdfObjectDelete(SpbContext->SpbLock); 635 | } 636 | 637 | if (SpbContext->ReadMemory != NULL) 638 | { 639 | WdfObjectDelete(SpbContext->ReadMemory); 640 | } 641 | 642 | if (SpbContext->WriteMemory != NULL) 643 | { 644 | WdfObjectDelete(SpbContext->WriteMemory); 645 | } 646 | } 647 | 648 | NTSTATUS 649 | SpbTargetInitialize( 650 | IN WDFDEVICE FxDevice, 651 | IN SPB_CONTEXT *SpbContext 652 | ) 653 | /*++ 654 | 655 | Routine Description: 656 | 657 | This helper routine opens the Spb I/O target and 658 | initializes a request object used for the lifetime 659 | of communication between this driver and Spb. 660 | 661 | Arguments: 662 | 663 | FxDevice - Handle to the framework device object 664 | SpbContext - Pointer to the current device context 665 | 666 | Return Value: 667 | 668 | NTSTATUS Status indicating success or failure 669 | 670 | --*/ 671 | { 672 | WDF_OBJECT_ATTRIBUTES objectAttributes; 673 | WDF_IO_TARGET_OPEN_PARAMS openParams; 674 | UNICODE_STRING spbDeviceName; 675 | WCHAR spbDeviceNameBuffer[RESOURCE_HUB_PATH_SIZE]; 676 | NTSTATUS status; 677 | 678 | WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); 679 | objectAttributes.ParentObject = FxDevice; 680 | 681 | status = WdfIoTargetCreate( 682 | FxDevice, 683 | &objectAttributes, 684 | &SpbContext->SpbIoTarget); 685 | 686 | if (!NT_SUCCESS(status)) 687 | { 688 | AtmelPrint( 689 | DEBUG_LEVEL_ERROR, 690 | DBG_IOCTL, 691 | "Error creating IoTarget object - %!STATUS!", 692 | status); 693 | 694 | WdfObjectDelete(SpbContext->SpbIoTarget); 695 | goto exit; 696 | } 697 | 698 | RtlInitEmptyUnicodeString( 699 | &spbDeviceName, 700 | spbDeviceNameBuffer, 701 | sizeof(spbDeviceNameBuffer)); 702 | 703 | status = RESOURCE_HUB_CREATE_PATH_FROM_ID( 704 | &spbDeviceName, 705 | SpbContext->I2cResHubId.LowPart, 706 | SpbContext->I2cResHubId.HighPart); 707 | 708 | if (!NT_SUCCESS(status)) 709 | { 710 | AtmelPrint( 711 | DEBUG_LEVEL_ERROR, 712 | DBG_IOCTL, 713 | "Error creating Spb resource hub path string - %!STATUS!", 714 | status); 715 | goto exit; 716 | } 717 | 718 | WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( 719 | &openParams, 720 | &spbDeviceName, 721 | (GENERIC_READ | GENERIC_WRITE)); 722 | 723 | openParams.ShareAccess = 0; 724 | openParams.CreateDisposition = FILE_OPEN; 725 | openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; 726 | 727 | status = WdfIoTargetOpen(SpbContext->SpbIoTarget, &openParams); 728 | 729 | if (!NT_SUCCESS(status)) 730 | { 731 | AtmelPrint( 732 | DEBUG_LEVEL_ERROR, 733 | DBG_IOCTL, 734 | "Error opening Spb target for communication - %!STATUS!", 735 | status); 736 | goto exit; 737 | } 738 | 739 | // 740 | // Allocate some fixed-size buffers from NonPagedPool for typical 741 | // Spb transaction sizes to avoid pool fragmentation in most cases 742 | // 743 | status = WdfMemoryCreate( 744 | WDF_NO_OBJECT_ATTRIBUTES, 745 | NonPagedPool, 746 | ATMEL_POOL_TAG, 747 | DEFAULT_SPB_BUFFER_SIZE, 748 | &SpbContext->WriteMemory, 749 | NULL); 750 | 751 | if (!NT_SUCCESS(status)) 752 | { 753 | AtmelPrint( 754 | DEBUG_LEVEL_ERROR, 755 | DBG_IOCTL, 756 | "Error allocating default memory for Spb write - %!STATUS!", 757 | status); 758 | goto exit; 759 | } 760 | 761 | status = WdfMemoryCreate( 762 | WDF_NO_OBJECT_ATTRIBUTES, 763 | NonPagedPool, 764 | ATMEL_POOL_TAG, 765 | DEFAULT_SPB_BUFFER_SIZE, 766 | &SpbContext->ReadMemory, 767 | NULL); 768 | 769 | if (!NT_SUCCESS(status)) 770 | { 771 | AtmelPrint( 772 | DEBUG_LEVEL_ERROR, 773 | DBG_IOCTL, 774 | "Error allocating default memory for Spb read - %!STATUS!", 775 | status); 776 | goto exit; 777 | } 778 | 779 | // 780 | // Allocate a waitlock to guard access to the default buffers 781 | // 782 | status = WdfWaitLockCreate( 783 | WDF_NO_OBJECT_ATTRIBUTES, 784 | &SpbContext->SpbLock); 785 | 786 | if (!NT_SUCCESS(status)) 787 | { 788 | AtmelPrint( 789 | DEBUG_LEVEL_ERROR, 790 | DBG_IOCTL, 791 | "Error creating Spb Waitlock - %!STATUS!", 792 | status); 793 | goto exit; 794 | } 795 | 796 | exit: 797 | 798 | if (!NT_SUCCESS(status)) 799 | { 800 | SpbTargetDeinitialize(FxDevice, SpbContext); 801 | } 802 | 803 | return status; 804 | } -------------------------------------------------------------------------------- /crostouchscreen2/atmel_mxt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 | * 4 | * This code is derived from software contributed to The DragonFly Project 5 | * by Matthew Dillon 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in 15 | * the documentation and/or other materials provided with the 16 | * distribution. 17 | * 3. Neither the name of The DragonFly Project nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific, prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 | * SUCH DAMAGE. 33 | * 34 | *------------------------------------------------------------------------------ 35 | * Copyright 2011 Atmel Corporation. All rights reserved. 36 | * 37 | * Redistribution and use in source and binary forms, with or without 38 | * modification, are permitted provided that the following conditions are met: 39 | * 40 | * 1. Redistributions of source code must retain the above copyright notice, 41 | * this list of conditions and the following disclaimer. 42 | * 43 | * 2. Redistributions in binary form must reproduce the above copyright 44 | * notice, this list of conditions and the following disclaimer in the 45 | * documentation and/or other materials provided with the distribution. 46 | * 47 | * THIS SOFTWARE IS PROVIDED BY ATMEL ''AS IS'' AND ANY EXPRESS OR IMPLIED 48 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 49 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 50 | * EVENT SHALL ATMEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 51 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 52 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 53 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 54 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 55 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 56 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | *----------------------------------------------------------------------------- 58 | */ 59 | /* 60 | * This file contains a mix of code taken from the atmel-maxtouch/obp-utils 61 | * github codebase and my own for testing the atmel touchscreen chipset in 62 | * the Acer C720P chromebook. 63 | * 64 | * I have rewritten the linux mess for the most part. 65 | */ 66 | 67 | #include "stdint.h" 68 | 69 | #ifndef __packed 70 | #define __packed( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) 71 | #endif 72 | 73 | #ifndef _OBP_UTILS_H_ 74 | #define _OBP_UTILS_H_ 75 | 76 | /* 77 | * CRC structure hangs off the end of the object configuration array and 78 | * is calculated against { mxt_id_info, mxt_object[num_objects] }. 79 | * 80 | * { mxt_id_info, mxt_object[num_objects], mxt_raw_crc } 81 | */ 82 | __packed(struct mxt_raw_crc { 83 | uint16_t CRC; /* low 16 bits */ 84 | uint8_t CRC_hi; /* high 8 bits */ 85 | }); 86 | 87 | /* 88 | * register 0 - Base information structure 89 | */ 90 | __packed(struct mxt_id_info { 91 | uint8_t family; /*!< Device family */ 92 | uint8_t variant; /*!< Device variant */ 93 | 94 | uint8_t version; /*!< Firmware version (Major/minor nibbles) */ 95 | uint8_t build; /*!< Firmware build number */ 96 | 97 | uint8_t matrix_x_size; /*!< Matrix X Size */ 98 | uint8_t matrix_y_size; /*!< Matrix Y Size */ 99 | 100 | /*! Number of elements in the object table. The actual number of 101 | * objects can be different if any object has more than one 102 | * instance. 103 | */ 104 | uint8_t num_objects; 105 | }); 106 | 107 | /* Object types */ 108 | #define MXT_DEBUG_DIAGNOSTIC_T37 37 109 | #define MXT_GEN_MESSAGE_T5 5 110 | #define MXT_GEN_COMMAND_T6 6 111 | #define MXT_GEN_POWER_T7 7 112 | #define MXT_GEN_ACQUIRE_T8 8 113 | #define MXT_GEN_DATASOURCE_T53 53 114 | #define MXT_TOUCH_MULTI_T9 9 115 | #define MXT_TOUCH_KEYARRAY_T15 15 116 | #define MXT_TOUCH_PROXIMITY_T23 23 117 | #define MXT_TOUCH_PROXKEY_T52 52 118 | #define MXT_PROCI_GRIPFACE_T20 20 119 | #define MXT_PROCG_NOISE_T22 22 120 | #define MXT_PROCI_ONETOUCH_T24 24 121 | #define MXT_PROCI_TWOTOUCH_T27 27 122 | #define MXT_PROCI_GRIP_T40 40 123 | #define MXT_PROCI_PALM_T41 41 124 | #define MXT_PROCI_TOUCHSUPPRESSION_T42 42 125 | #define MXT_PROCI_STYLUS_T47 47 126 | #define MXT_PROCG_NOISESUPPRESSION_T48 48 127 | #define MXT_SPT_COMMSCONFIG_T18 18 128 | #define MXT_SPT_GPIOPWM_T19 19 129 | #define MXT_SPT_SELFTEST_T25 25 130 | #define MXT_SPT_CTECONFIG_T28 28 131 | #define MXT_SPT_USERDATA_T38 38 132 | #define MXT_SPT_DIGITIZER_T43 43 133 | #define MXT_SPT_MESSAGECOUNT_T44 44 134 | #define MXT_SPT_CTECONFIG_T46 46 135 | #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 136 | 137 | #define MXT_OBJECT_START 0x07 138 | 139 | /* 140 | * register 0 - Object configuration element(s) (occurs after mxt_id_info) 141 | */ 142 | __packed(struct mxt_object { 143 | uint8_t type; /* object type */ 144 | uint16_t start_address; /* start address of config structure */ 145 | //uint8_t start_pos_lsb; /* start address of config structure */ 146 | //uint8_t start_pos_msb; /* start address of config structure */ 147 | uint8_t size_minus_one; /* size of config - 1 */ 148 | uint8_t instances_minus_one; /* #of instances of object - 1 */ 149 | uint8_t num_report_ids; /* max# of touches, sliders, buts, etc*/ 150 | }); 151 | 152 | /* 153 | * message structures (MXT_GEN_MESSAGEPROCESSOR) 154 | */ 155 | __packed(struct mxt_message_any { 156 | uint8_t reportid; 157 | uint8_t data[7]; 158 | }); 159 | 160 | /* MXT_GEN_POWER_T7 field */ 161 | __packed(struct t7_config { 162 | uint8_t idle; 163 | uint8_t active; 164 | }); 165 | 166 | #define MXT_POWER_CFG_RUN 0 167 | #define MXT_POWER_CFG_DEEPSLEEP 1 168 | 169 | __packed(struct mxt_message_touch_t9 { 170 | uint8_t reportid; 171 | uint8_t flags; /* msg[0] */ 172 | uint8_t pos[3]; /* xxxxxxxx(hi) yyyyyyyy(hi) xxxxyyyy(lo) */ 173 | uint8_t area; 174 | uint8_t amplitude; 175 | }); 176 | 177 | /* MXT_TOUCH_MULTI_T9 field */ 178 | #define MXT_T9_CTRL 0 179 | #define MXT_T9_ORIENT 9 180 | #define MXT_T9_RANGE 18 181 | 182 | /* MXT_TOUCH_MULTI_T9 status */ 183 | #define MXT_T9_UNGRIP (1 << 0) 184 | #define MXT_T9_SUPPRESS (1 << 1) 185 | #define MXT_T9_AMP (1 << 2) 186 | #define MXT_T9_VECTOR (1 << 3) 187 | #define MXT_T9_MOVE (1 << 4) 188 | #define MXT_T9_RELEASE (1 << 5) 189 | #define MXT_T9_PRESS (1 << 6) 190 | #define MXT_T9_DETECT (1 << 7) 191 | 192 | __packed(struct t9_range { 193 | uint16_t x; /* x */ 194 | uint16_t y; /* y */ 195 | }); 196 | #define MXT_T9_ORIENT_SWITCH (1 << 0) 197 | 198 | typedef union mxt_message mxt_message_t; 199 | 200 | /* T100 Multiple Touch Touchscreen */ 201 | #define MXT_T100_CTRL 0 202 | #define MXT_T100_CFG1 1 203 | #define MXT_T100_TCHAUX 3 204 | #define MXT_T100_XRANGE 13 205 | #define MXT_T100_YRANGE 24 206 | 207 | #define MXT_T100_CFG_SWITCHXY BIT(5) 208 | 209 | #define MXT_T100_TCHAUX_VECT BIT(0) 210 | #define MXT_T100_TCHAUX_AMPL BIT(1) 211 | #define MXT_T100_TCHAUX_AREA BIT(2) 212 | 213 | #define MXT_T100_DETECT BIT(7) 214 | #define MXT_T100_TYPE_MASK 0x70 215 | 216 | enum t100_type { 217 | MXT_T100_TYPE_FINGER = 1, 218 | MXT_T100_TYPE_PASSIVE_STYLUS = 2, 219 | MXT_T100_TYPE_HOVERING_FINGER = 4, 220 | MXT_T100_TYPE_GLOVE = 5, 221 | MXT_T100_TYPE_LARGE_TOUCH = 6, 222 | }; 223 | 224 | #define MXT_DISTANCE_ACTIVE_TOUCH 0 225 | #define MXT_DISTANCE_HOVERING 1 226 | 227 | #define MXT_TOUCH_MAJOR_DEFAULT 1 228 | #define MXT_PRESSURE_DEFAULT 1 229 | 230 | __packed(struct mxt_message_touch_t100 { 231 | uint8_t reportid; 232 | uint8_t flags; /* msg[0] */ 233 | uint16_t x; 234 | uint16_t y; 235 | uint8_t area; 236 | uint8_t amplitude; 237 | }); 238 | 239 | __packed(union mxt_message { 240 | struct mxt_message_any any; 241 | struct mxt_message_touch_t9 touch_t9; 242 | struct mxt_message_touch_t100 touch_t100; 243 | }); 244 | 245 | /* 246 | * Object types 247 | */ 248 | #define MXT_RESERVED_T0 0 249 | #define MXT_RESERVED_T1 1 250 | #define MXT_DEBUG_DELTAS 2 251 | #define MXT_DEBUG_REFERENCES 3 252 | #define MXT_SIGNALS 4 253 | #define MXT_GEN_MESSAGEPROCESSOR 5 254 | #define MXT_GEN_COMMANDPROCESSOR 6 255 | #define MXT_GEN_POWERCONFIG 7 256 | #define MXT_ACQUISITIONCONFIG 8 257 | #define MXT_TOUCH_MULTITOUCHSCREEN9 9 258 | #define MXT_TOUCH_SINGLETOUCHSCREEN 10 259 | #define MXT_TOUCH_XSLIDER 11 260 | #define MXT_TOUCH_YSLIDER 12 261 | #define MXT_TOUCH_XWHEEL 13 262 | #define MXT_TOUCH_YWHEEL 14 263 | #define MXT_TOUCH_KEYARRAY 15 264 | #define MXT_PROCG_SIGNALFILTER 16 265 | #define MXT_PROCI_LINEARIZATIONTABLE 17 266 | #define MXT_SPT_COMMSCONFIG 18 267 | #define MXT_SPT_GPIOPWM 19 268 | #define MXT_PROCI_GRIPFACESUPPRESSION 20 269 | #define MXT_RESERVED21 21 270 | #define MXT_PROCG_NOISESUPPRESSION22 22 271 | #define MXT_TOUCH_PROXIMITY 23 272 | #define MXT_PROCI_ONETOUCHGESTUREPROCESSOR 24 273 | #define MXT_SPT_SELFTEST 25 274 | #define MXT_DEBUG_CTERANGE 26 275 | #define MXT_PROCI_TWOTOUCHGESTUREPROCESSOR 27 276 | #define MXT_SPT_CTECONFIG28 28 277 | #define MXT_SPT_GPI 29 278 | #define MXT_SPT_GATE 30 279 | #define MXT_TOUCH_KEYSET 31 280 | #define MXT_TOUCH_XSLIDERSET 32 281 | #define MXT_RESERVED33 33 282 | #define MXT_GEN_MESSAGEBLOCK 34 283 | #define MXT_SPT_PROTOTYPE 35 284 | #define MXT_RESERVED36 36 285 | #define MXT_DEBUG_DIAGNOSTIC 37 286 | #define MXT_SPT_USERDATA 38 287 | #define MXT_SPARE39 39 288 | #define MXT_PROCI_GRIPSUPPRESSION 40 289 | #define MXT_PROCI_PALMSUPPRESSION 41 290 | #define MXT_PROCI_TOUCHSUPPRESSION 42 291 | #define MXT_SPT_DIGITIZER 43 292 | #define MXT_SPT_MESSAGECOUNT 44 293 | #define MXT_PROCI_VIRTUALKEY 45 294 | #define MXT_SPT_CTECONFIG46 46 295 | #define MXT_PROCI_STYLUS 47 296 | #define MXT_PROCG_NOISESUPPRESSION48 48 297 | #define MXT_GEN_DUALPULSE 49 298 | #define MXT_SPARE50 50 299 | #define MXT_SPT_SONY_CUSTOM 51 300 | #define MXT_TOUCH_PROXKEY 52 301 | #define MXT_GEN_DATASOURCE 53 302 | #define MXT_PROCG_NOISESUPPRESSION54 54 303 | #define MXT_PROCI_ADAPTIVETHRESHOLD 55 304 | #define MXT_PROCI_SHIELDLESS 56 305 | #define MXT_PROCI_EXTRATOUCHSCREENDATA 57 306 | #define MXT_SPT_EXTRANOISESUPCTRLS 58 307 | #define MXT_SPT_FASTDRIFT 59 308 | #define MXT_SPT_TIMER 61 309 | #define MXT_PROCG_NOISESUPPRESSION62 62 310 | #define MXT_PROCI_ACTIVESTYLUS63 63 311 | #define MXT_SPT_REFERENCERELOAD 64 312 | #define MXT_PROCI_LENSBENDING 65 313 | #define MXT_SPT_GOLDENREFERENCES 66 314 | #define MXT_PROCI_CUSTOMGESTUREPROCESSOR 67 315 | #define MXT_SERIAL_DATA_COMMAND 68 316 | #define MXT_PROCI_PALMGESTUREPROCESSOR 69 317 | #define MXT_SPT_DYNAMICCONFIGURATIONCONTROLLER 70 318 | #define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER 71 319 | #define MXT_PROCG_NOISESUPPRESSION72 72 320 | #define MXT_PROCI_ZONEINDICATION 73 321 | #define MXT_PROCG_SIMPLEGESTUREPROCESSOR 74 322 | #define MXT_MOTION_SENSING_OBJECT 75 323 | #define MXT_PROCI_MOTION_GESTURES 76 324 | #define MXT_SPT_CTESCANCONFIG 77 325 | #define MXT_PROCI_GLOVEDETECTION 78 326 | #define MXT_SPT_TOUCHEVENTTRIGGER 79 327 | #define MXT_PROCI_RETRANSMISSIONCOMPENSATION 80 328 | #define MXT_PROCI_UNLOCKGESTURE 81 329 | #define MXT_SPT_NOISESUPEXTENSION 82 330 | #define MXT_ENVIRO_LIGHTSENSING 83 331 | #define MXT_PROCI_GESTUREPROCESSOR 84 332 | #define MXT_PEN_ACTIVESTYLUSPOWER 85 333 | #define MXT_PROCG_NOISESUPACTIVESTYLUS 86 334 | #define MXT_PEN_ACTIVESTYLUSDATA 87 335 | #define MXT_PEN_ACTIVESTYLUSRECEIVE 88 336 | #define MXT_PEN_ACTIVESTYLUSTRANSMIT 89 337 | #define MXT_PEN_ACTIVESTYLUSWINDOW 90 338 | #define MXT_DEBUG_CUSTOMDATACONFIG 91 339 | #define MXT_PROCI_SYMBOLGESTUREPROCESSOR 92 340 | #define MXT_PROCI_TOUCHSEQUENCELOGGER 93 341 | #define MXT_TOUCH_MULTITOUCHSCREEN 100 342 | #define MXT_SPT_TOUCHSCREENHOVER 101 343 | #define MXT_SPT_SELFCAPHOVERCTECONFIG 102 344 | #define MXT_PROCI_SCHNOISESUPPRESSION 103 345 | #define MXT_SPT_AUXTOUCHCONFIG 104 346 | #define MXT_SPT_DRIVENPLATEHOVERCONFIG 105 347 | #define MXT_SPT_ACTIVESTYLUSMMBCONFIG 106 348 | #define MXT_PROCI_ACTIVESTYLUS107 107 349 | #define MXT_PROCG_NOISESUPSELFCAP 108 350 | #define MXT_SPT_SELFCAPGLOBALCONFIG 109 351 | #define MXT_SPT_SELFCAPTUNINGPARAMS 110 352 | #define MXT_SPT_SELFCAPCONFIG 111 353 | #define MXT_SPT_PROXMEASURECONFIG 113 354 | #define MXT_GEN_INFOBLOCK16BIT 254 355 | #define MXT_RESERVED255 255 356 | 357 | #define MXTSTR(label) #label 358 | 359 | #define MXT_INIT_STRINGS \ 360 | { MXTSTR(MXT_RESERVED_T0), \ 361 | MXT_RESERVED_T0 }, \ 362 | { MXTSTR(MXT_RESERVED_T1), \ 363 | MXT_RESERVED_T1 }, \ 364 | { MXTSTR(MXT_DEBUG_DELTAS), \ 365 | MXT_DEBUG_DELTAS }, \ 366 | { MXTSTR(MXT_DEBUG_REFERENCES), \ 367 | MXT_DEBUG_REFERENCES }, \ 368 | { MXTSTR(MXT_SIGNALS), \ 369 | MXT_SIGNALS }, \ 370 | { MXTSTR(MXT_GEN_MESSAGEPROCESSOR), \ 371 | MXT_GEN_MESSAGEPROCESSOR }, \ 372 | { MXTSTR(MXT_GEN_COMMANDPROCESSOR), \ 373 | MXT_GEN_COMMANDPROCESSOR }, \ 374 | { MXTSTR(MXT_GEN_POWERCONFIG), \ 375 | MXT_GEN_POWERCONFIG }, \ 376 | { MXTSTR(MXT_ACQUISITIONCONFIG), \ 377 | MXT_ACQUISITIONCONFIG }, \ 378 | { MXTSTR(MXT_TOUCH_MULTITOUCHSCREEN), \ 379 | MXT_TOUCH_MULTITOUCHSCREEN }, \ 380 | { MXTSTR(MXT_TOUCH_SINGLETOUCHSCREEN), \ 381 | MXT_TOUCH_SINGLETOUCHSCREEN }, \ 382 | { MXTSTR(MXT_TOUCH_XSLIDER), \ 383 | MXT_TOUCH_XSLIDER }, \ 384 | { MXTSTR(MXT_TOUCH_YSLIDER), \ 385 | MXT_TOUCH_YSLIDER }, \ 386 | { MXTSTR(MXT_TOUCH_XWHEEL), \ 387 | MXT_TOUCH_XWHEEL }, \ 388 | { MXTSTR(MXT_TOUCH_YWHEEL), \ 389 | MXT_TOUCH_YWHEEL }, \ 390 | { MXTSTR(MXT_TOUCH_KEYARRAY), \ 391 | MXT_TOUCH_KEYARRAY }, \ 392 | { MXTSTR(MXT_PROCG_SIGNALFILTER), \ 393 | MXT_PROCG_SIGNALFILTER }, \ 394 | { MXTSTR(MXT_PROCI_LINEARIZATIONTABLE), \ 395 | MXT_PROCI_LINEARIZATIONTABLE }, \ 396 | { MXTSTR(MXT_SPT_COMMSCONFIG), \ 397 | MXT_SPT_COMMSCONFIG }, \ 398 | { MXTSTR(MXT_SPT_GPIOPWM), \ 399 | MXT_SPT_GPIOPWM }, \ 400 | { MXTSTR(MXT_PROCI_GRIPFACESUPPRESSION), \ 401 | MXT_PROCI_GRIPFACESUPPRESSION }, \ 402 | { MXTSTR(MXT_RESERVED21), \ 403 | MXT_RESERVED21 }, \ 404 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION22), \ 405 | MXT_PROCG_NOISESUPPRESSION22 }, \ 406 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION48), \ 407 | MXT_PROCG_NOISESUPPRESSION48 }, \ 408 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION54), \ 409 | MXT_PROCG_NOISESUPPRESSION54 }, \ 410 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION62), \ 411 | MXT_PROCG_NOISESUPPRESSION62 }, \ 412 | { MXTSTR(MXT_PROCG_NOISESUPPRESSION72), \ 413 | MXT_PROCG_NOISESUPPRESSION72 }, \ 414 | { MXTSTR(MXT_TOUCH_PROXIMITY), \ 415 | MXT_TOUCH_PROXIMITY }, \ 416 | { MXTSTR(MXT_PROCI_ONETOUCHGESTUREPROCESSOR), \ 417 | MXT_PROCI_ONETOUCHGESTUREPROCESSOR }, \ 418 | { MXTSTR(MXT_SPT_SELFTEST), \ 419 | MXT_SPT_SELFTEST }, \ 420 | { MXTSTR(MXT_DEBUG_CTERANGE), \ 421 | MXT_DEBUG_CTERANGE }, \ 422 | { MXTSTR(MXT_PROCI_TWOTOUCHGESTUREPROCESSOR), \ 423 | MXT_PROCI_TWOTOUCHGESTUREPROCESSOR }, \ 424 | { MXTSTR(MXT_SPT_CTECONFIG28), \ 425 | MXT_SPT_CTECONFIG28 }, \ 426 | { MXTSTR(MXT_SPT_CTECONFIG46), \ 427 | MXT_SPT_CTECONFIG46 }, \ 428 | { MXTSTR(MXT_SPT_GPI), \ 429 | MXT_SPT_GPI }, \ 430 | { MXTSTR(MXT_SPT_GATE), \ 431 | MXT_SPT_GATE }, \ 432 | { MXTSTR(MXT_TOUCH_KEYSET), \ 433 | MXT_TOUCH_KEYSET }, \ 434 | { MXTSTR(MXT_TOUCH_XSLIDERSET), \ 435 | MXT_TOUCH_XSLIDERSET }, \ 436 | { MXTSTR(MXT_RESERVED33), \ 437 | MXT_RESERVED33 }, \ 438 | { MXTSTR(MXT_GEN_MESSAGEBLOCK), \ 439 | MXT_GEN_MESSAGEBLOCK }, \ 440 | { MXTSTR(MXT_SPT_PROTOTYPE), \ 441 | MXT_SPT_PROTOTYPE }, \ 442 | { MXTSTR(MXT_RESERVED36), \ 443 | MXT_RESERVED36 }, \ 444 | { MXTSTR(MXT_DEBUG_DIAGNOSTIC), \ 445 | MXT_DEBUG_DIAGNOSTIC }, \ 446 | { MXTSTR(MXT_SPT_USERDATA), \ 447 | MXT_SPT_USERDATA }, \ 448 | { MXTSTR(MXT_SPARE39), \ 449 | MXT_SPARE39 }, \ 450 | { MXTSTR(MXT_PROCI_GRIPSUPPRESSION), \ 451 | MXT_PROCI_GRIPSUPPRESSION }, \ 452 | { MXTSTR(MXT_PROCI_PALMSUPPRESSION), \ 453 | MXT_PROCI_PALMSUPPRESSION }, \ 454 | { MXTSTR(MXT_PROCI_TOUCHSUPPRESSION), \ 455 | MXT_PROCI_TOUCHSUPPRESSION }, \ 456 | { MXTSTR(MXT_SPT_DIGITIZER), \ 457 | MXT_SPT_DIGITIZER }, \ 458 | { MXTSTR(MXT_SPT_MESSAGECOUNT), \ 459 | MXT_SPT_MESSAGECOUNT }, \ 460 | { MXTSTR(MXT_PROCI_VIRTUALKEY), \ 461 | MXT_PROCI_VIRTUALKEY }, \ 462 | { MXTSTR(MXT_PROCI_STYLUS), \ 463 | MXT_PROCI_STYLUS }, \ 464 | { MXTSTR(MXT_GEN_DUALPULSE), \ 465 | MXT_GEN_DUALPULSE }, \ 466 | { MXTSTR(MXT_SPARE50), \ 467 | MXT_SPARE50 }, \ 468 | { MXTSTR(MXT_SPT_SONY_CUSTOM), \ 469 | MXT_SPT_SONY_CUSTOM }, \ 470 | { MXTSTR(MXT_TOUCH_PROXKEY), \ 471 | MXT_TOUCH_PROXKEY }, \ 472 | { MXTSTR(MXT_GEN_DATASOURCE), \ 473 | MXT_GEN_DATASOURCE }, \ 474 | { MXTSTR(MXT_PROCI_ADAPTIVETHRESHOLD), \ 475 | MXT_PROCI_ADAPTIVETHRESHOLD }, \ 476 | { MXTSTR(MXT_PROCI_SHIELDLESS), \ 477 | MXT_PROCI_SHIELDLESS }, \ 478 | { MXTSTR(MXT_PROCI_EXTRATOUCHSCREENDATA), \ 479 | MXT_PROCI_EXTRATOUCHSCREENDATA }, \ 480 | { MXTSTR(MXT_SPT_EXTRANOISESUPCTRLS), \ 481 | MXT_SPT_EXTRANOISESUPCTRLS }, \ 482 | { MXTSTR(MXT_SPT_FASTDRIFT), \ 483 | MXT_SPT_FASTDRIFT }, \ 484 | { MXTSTR(MXT_SPT_TIMER), \ 485 | MXT_SPT_TIMER }, \ 486 | { MXTSTR(MXT_PROCI_ACTIVESTYLUS63), \ 487 | MXT_PROCI_ACTIVESTYLUS63 }, \ 488 | { MXTSTR(MXT_PROCI_ACTIVESTYLUS107), \ 489 | MXT_PROCI_ACTIVESTYLUS107 }, \ 490 | { MXTSTR(MXT_SPT_REFERENCERELOAD), \ 491 | MXT_SPT_REFERENCERELOAD }, \ 492 | { MXTSTR(MXT_PROCI_LENSBENDING), \ 493 | MXT_PROCI_LENSBENDING }, \ 494 | { MXTSTR(MXT_SPT_GOLDENREFERENCES), \ 495 | MXT_SPT_GOLDENREFERENCES }, \ 496 | { MXTSTR(MXT_PROCI_CUSTOMGESTUREPROCESSOR), \ 497 | MXT_PROCI_CUSTOMGESTUREPROCESSOR }, \ 498 | { MXTSTR(MXT_SERIAL_DATA_COMMAND), \ 499 | MXT_SERIAL_DATA_COMMAND }, \ 500 | { MXTSTR(MXT_PROCI_PALMGESTUREPROCESSOR), \ 501 | MXT_PROCI_PALMGESTUREPROCESSOR }, \ 502 | { MXTSTR(MXT_SPT_DYNAMICCONFIGURATIONCONTROLLER), \ 503 | MXT_SPT_DYNAMICCONFIGURATIONCONTROLLER }, \ 504 | { MXTSTR(MXT_SPT_DYNAMICCONFIGURATIONCONTAINER), \ 505 | MXT_SPT_DYNAMICCONFIGURATIONCONTAINER }, \ 506 | { MXTSTR(MXT_PROCI_ZONEINDICATION), \ 507 | MXT_PROCI_ZONEINDICATION }, \ 508 | { MXTSTR(MXT_PROCG_SIMPLEGESTUREPROCESSOR), \ 509 | MXT_PROCG_SIMPLEGESTUREPROCESSOR }, \ 510 | { MXTSTR(MXT_MOTION_SENSING_OBJECT), \ 511 | MXT_MOTION_SENSING_OBJECT }, \ 512 | { MXTSTR(MXT_PROCI_MOTION_GESTURES), \ 513 | MXT_PROCI_MOTION_GESTURES }, \ 514 | { MXTSTR(MXT_SPT_CTESCANCONFIG), \ 515 | MXT_SPT_CTESCANCONFIG }, \ 516 | { MXTSTR(MXT_PROCI_GLOVEDETECTION), \ 517 | MXT_PROCI_GLOVEDETECTION }, \ 518 | { MXTSTR(MXT_SPT_TOUCHEVENTTRIGGER), \ 519 | MXT_SPT_TOUCHEVENTTRIGGER }, \ 520 | { MXTSTR(MXT_PROCI_RETRANSMISSIONCOMPENSATION), \ 521 | MXT_PROCI_RETRANSMISSIONCOMPENSATION }, \ 522 | { MXTSTR(MXT_PROCI_UNLOCKGESTURE), \ 523 | MXT_PROCI_UNLOCKGESTURE }, \ 524 | { MXTSTR(MXT_SPT_NOISESUPEXTENSION), \ 525 | MXT_SPT_NOISESUPEXTENSION }, \ 526 | { MXTSTR(MXT_ENVIRO_LIGHTSENSING), \ 527 | MXT_ENVIRO_LIGHTSENSING }, \ 528 | { MXTSTR(MXT_PROCI_GESTUREPROCESSOR), \ 529 | MXT_PROCI_GESTUREPROCESSOR }, \ 530 | { MXTSTR(MXT_PEN_ACTIVESTYLUSPOWER), \ 531 | MXT_PEN_ACTIVESTYLUSPOWER }, \ 532 | { MXTSTR(MXT_PROCG_NOISESUPACTIVESTYLUS), \ 533 | MXT_PROCG_NOISESUPACTIVESTYLUS }, \ 534 | { MXTSTR(MXT_PEN_ACTIVESTYLUSDATA), \ 535 | MXT_PEN_ACTIVESTYLUSDATA }, \ 536 | { MXTSTR(MXT_PEN_ACTIVESTYLUSRECEIVE), \ 537 | MXT_PEN_ACTIVESTYLUSRECEIVE }, \ 538 | { MXTSTR(MXT_PEN_ACTIVESTYLUSTRANSMIT), \ 539 | MXT_PEN_ACTIVESTYLUSTRANSMIT }, \ 540 | { MXTSTR(MXT_PEN_ACTIVESTYLUSWINDOW), \ 541 | MXT_PEN_ACTIVESTYLUSWINDOW }, \ 542 | { MXTSTR(MXT_DEBUG_CUSTOMDATACONFIG), \ 543 | MXT_DEBUG_CUSTOMDATACONFIG }, \ 544 | { MXTSTR(MXT_PROCI_SYMBOLGESTUREPROCESSOR), \ 545 | MXT_PROCI_SYMBOLGESTUREPROCESSOR }, \ 546 | { MXTSTR(MXT_PROCI_TOUCHSEQUENCELOGGER), \ 547 | MXT_PROCI_TOUCHSEQUENCELOGGER }, \ 548 | { MXTSTR(MXT_TOUCH_MULTITOUCHSCREEN), \ 549 | MXT_TOUCH_MULTITOUCHSCREEN }, \ 550 | { MXTSTR(MXT_SPT_TOUCHSCREENHOVER), \ 551 | MXT_SPT_TOUCHSCREENHOVER }, \ 552 | { MXTSTR(MXT_SPT_SELFCAPHOVERCTECONFIG), \ 553 | MXT_SPT_SELFCAPHOVERCTECONFIG }, \ 554 | { MXTSTR(MXT_PROCI_SCHNOISESUPPRESSION), \ 555 | MXT_PROCI_SCHNOISESUPPRESSION }, \ 556 | { MXTSTR(MXT_SPT_AUXTOUCHCONFIG), \ 557 | MXT_SPT_AUXTOUCHCONFIG }, \ 558 | { MXTSTR(MXT_SPT_DRIVENPLATEHOVERCONFIG), \ 559 | MXT_SPT_DRIVENPLATEHOVERCONFIG }, \ 560 | { MXTSTR(MXT_SPT_ACTIVESTYLUSMMBCONFIG), \ 561 | MXT_SPT_ACTIVESTYLUSMMBCONFIG }, \ 562 | { MXTSTR(MXT_PROCG_NOISESUPSELFCAP), \ 563 | MXT_PROCG_NOISESUPSELFCAP }, \ 564 | { MXTSTR(MXT_SPT_SELFCAPGLOBALCONFIG), \ 565 | MXT_SPT_SELFCAPGLOBALCONFIG }, \ 566 | { MXTSTR(MXT_SPT_SELFCAPTUNINGPARAMS), \ 567 | MXT_SPT_SELFCAPTUNINGPARAMS }, \ 568 | { MXTSTR(MXT_SPT_SELFCAPCONFIG), \ 569 | MXT_SPT_SELFCAPCONFIG }, \ 570 | { MXTSTR(MXT_SPT_PROXMEASURECONFIG), \ 571 | MXT_SPT_PROXMEASURECONFIG }, \ 572 | { MXTSTR(MXT_GEN_INFOBLOCK16BIT), \ 573 | MXT_GEN_INFOBLOCK16BIT }, \ 574 | { MXTSTR(MXT_RESERVED255), \ 575 | MXT_RESERVED255 } 576 | 577 | /* Define for T6 status byte */ 578 | #define MXT_T6_STATUS_RESET (1 << 7) 579 | #define MXT_T6_STATUS_OFL (1 << 6) 580 | #define MXT_T6_STATUS_SIGERR (1 << 5) 581 | #define MXT_T6_STATUS_CAL (1 << 4) 582 | #define MXT_T6_STATUS_CFGERR (1 << 3) 583 | #define MXT_T6_STATUS_COMSERR (1 << 2) 584 | 585 | /* 586 | * MXT_GEN_COMMANDPROCESSOR object offsets. 587 | */ 588 | #define MXT_CMDPROC_RESET_OFF 0x00 589 | #define MXT_CMDPROC_BACKUPNV_OFF 0x01 590 | #define MXT_CMDPROC_CALIBRATE_OFF 0x02 591 | #define MXT_CMDPROC_REPORTALL_OFF 0x03 592 | #define MXT_CMDPROC_RESERVED04_OFF 0x04 593 | #define MXT_CMDPROC_DIAGNOSTIC_OFF 0x05 594 | 595 | /* Define for MXT_GEN_COMMAND_T6 */ 596 | #define MXT_BOOT_VALUE 0xa5 597 | #define MXT_RESET_VALUE 0x01 598 | #define MXT_BACKUP_VALUE 0x55 599 | 600 | /* 601 | * device driver helper structures 602 | */ 603 | struct mxt_strinfo { 604 | const char *id; 605 | int type; 606 | }; 607 | 608 | struct mxt_rollup { 609 | struct mxt_id_info info; 610 | struct mxt_object *objs; 611 | int nobjs; 612 | uint8_t *buf; 613 | }; 614 | 615 | struct atmel_softc { 616 | int flags[20]; 617 | int x[20]; 618 | int y[20]; 619 | int p[20]; 620 | int area[20]; 621 | int ampl[20]; 622 | }; 623 | 624 | /* 625 | * Kernel AND user mode support 626 | */ 627 | uint32_t obp_convert_crc(struct mxt_raw_crc *crc); 628 | uint32_t obp_crc24(uint8_t *buf, size_t bytes); 629 | 630 | #endif -------------------------------------------------------------------------------- /crostouchscreen2/atmel.cpp: -------------------------------------------------------------------------------- 1 | #define DESCRIPTOR_DEF 2 | #include "atmel.h" 3 | 4 | static ULONG AtmelDebugLevel = 100; 5 | static ULONG AtmelDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 6 | 7 | 8 | int AtmelProcessMessagesUntilInvalid(PATMEL_CONTEXT pDevice); 9 | 10 | NTSTATUS 11 | DriverEntry( 12 | __in PDRIVER_OBJECT DriverObject, 13 | __in PUNICODE_STRING RegistryPath 14 | ) 15 | { 16 | NTSTATUS status = STATUS_SUCCESS; 17 | WDF_DRIVER_CONFIG config; 18 | WDF_OBJECT_ATTRIBUTES attributes; 19 | 20 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_INIT, 21 | "Driver Entry\n"); 22 | 23 | WDF_DRIVER_CONFIG_INIT(&config, AtmelEvtDeviceAdd); 24 | 25 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 26 | 27 | // 28 | // Create a framework driver object to represent our driver. 29 | // 30 | 31 | status = WdfDriverCreate(DriverObject, 32 | RegistryPath, 33 | &attributes, 34 | &config, 35 | WDF_NO_HANDLE 36 | ); 37 | 38 | if (!NT_SUCCESS(status)) 39 | { 40 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 41 | "WdfDriverCreate failed with status 0x%x\n", status); 42 | } 43 | 44 | return status; 45 | } 46 | 47 | static size_t mxt_obj_size(const struct mxt_object *obj) 48 | { 49 | return obj->size_minus_one + 1; 50 | } 51 | 52 | static size_t mxt_obj_instances(const struct mxt_object *obj) 53 | { 54 | return obj->instances_minus_one + 1; 55 | } 56 | 57 | static 58 | struct mxt_object * 59 | mxt_findobject(struct mxt_rollup *core, int type) 60 | { 61 | int i; 62 | 63 | for (i = 0; i < core->nobjs; ++i) { 64 | if (core->objs[i].type == type) 65 | return(&core->objs[i]); 66 | } 67 | return NULL; 68 | } 69 | 70 | static NTSTATUS 71 | mxt_read_reg(PATMEL_CONTEXT devContext, uint16_t reg, void *rbuf, int bytes) 72 | { 73 | uint8_t wreg[2]; 74 | wreg[0] = reg & 255; 75 | wreg[1] = reg >> 8; 76 | 77 | uint16_t nreg = ((uint16_t *)wreg)[0]; 78 | 79 | NTSTATUS error = SpbReadDataSynchronously16(&devContext->I2CContext, nreg, rbuf, bytes); 80 | 81 | return error; 82 | } 83 | 84 | static NTSTATUS 85 | mxt_write_reg_buf(PATMEL_CONTEXT devContext, uint16_t reg, void *xbuf, int bytes) 86 | { 87 | uint8_t wreg[2]; 88 | wreg[0] = reg & 255; 89 | wreg[1] = reg >> 8; 90 | 91 | uint16_t nreg = ((uint16_t *)wreg)[0]; 92 | return SpbWriteDataSynchronously16(&devContext->I2CContext, nreg, xbuf, bytes); 93 | } 94 | 95 | static NTSTATUS 96 | mxt_write_reg(PATMEL_CONTEXT devContext, uint16_t reg, uint8_t val) 97 | { 98 | return mxt_write_reg_buf(devContext, reg, &val, 1); 99 | } 100 | 101 | static NTSTATUS 102 | mxt_write_object_off(PATMEL_CONTEXT devContext, struct mxt_object *obj, 103 | int offset, uint8_t val) 104 | { 105 | uint16_t reg = obj->start_address; 106 | 107 | reg += offset; 108 | return mxt_write_reg(devContext, reg, val); 109 | } 110 | 111 | static 112 | NTSTATUS 113 | atmel_reset_device(PATMEL_CONTEXT devContext) 114 | { 115 | return mxt_write_object_off(devContext, devContext->cmdprocobj, MXT_CMDPROC_RESET_OFF, 1); 116 | } 117 | 118 | static NTSTATUS mxt_read_t9_resolution(PATMEL_CONTEXT devContext) 119 | { 120 | struct t9_range range; 121 | unsigned char orient; 122 | NTSTATUS status; 123 | 124 | mxt_rollup core = devContext->core; 125 | mxt_object *resolutionobject = mxt_findobject(&core, MXT_TOUCH_MULTI_T9); 126 | 127 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T9_RANGE, &range, sizeof(range)); 128 | if (!NT_SUCCESS(status)) { 129 | return status; 130 | } 131 | 132 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T9_ORIENT, &orient, 1); 133 | if (!NT_SUCCESS(status)) { 134 | return status; 135 | } 136 | 137 | /* Handle default values */ 138 | if (range.x == 0) 139 | range.x = 1023; 140 | 141 | if (range.y == 0) 142 | range.y = 1023; 143 | 144 | if (orient & MXT_T9_ORIENT_SWITCH) { 145 | devContext->max_x = range.y + 1; 146 | devContext->max_y = range.x + 1; 147 | } 148 | else { 149 | devContext->max_x = range.x + 1; 150 | devContext->max_y = range.y + 1; 151 | } 152 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_PNP, "Screen Size: X: %d Y: %d\n", devContext->max_x, devContext->max_y); 153 | return status; 154 | } 155 | 156 | static NTSTATUS mxt_read_t100_config(PATMEL_CONTEXT devContext) 157 | { 158 | NTSTATUS status; 159 | uint16_t range_x, range_y; 160 | uint8_t cfg, tchaux; 161 | uint8_t aux; 162 | 163 | mxt_rollup core = devContext->core; 164 | mxt_object *resolutionobject = mxt_findobject(&core, MXT_TOUCH_MULTITOUCHSCREEN_T100); 165 | 166 | /* read touchscreen dimensions */ 167 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T100_XRANGE, &range_x, sizeof(range_x)); 168 | if (!NT_SUCCESS(status)) { 169 | return status; 170 | } 171 | 172 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T100_YRANGE, &range_y, sizeof(range_y)); 173 | if (!NT_SUCCESS(status)) { 174 | return status; 175 | } 176 | 177 | /* read orientation config */ 178 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T100_CFG1, &cfg, 1); 179 | if (!NT_SUCCESS(status)) { 180 | return status; 181 | } 182 | 183 | if (cfg & MXT_T100_CFG_SWITCHXY) { 184 | devContext->max_x = range_y + 1; 185 | devContext->max_y = range_x + 1; 186 | } 187 | else { 188 | devContext->max_x = range_x + 1; 189 | devContext->max_y = range_y + 1; 190 | } 191 | 192 | status = mxt_read_reg(devContext, resolutionobject->start_address + MXT_T100_TCHAUX, &tchaux, 1); 193 | if (!NT_SUCCESS(status)) { 194 | return status; 195 | } 196 | 197 | aux = 6; 198 | 199 | if (tchaux & MXT_T100_TCHAUX_VECT) 200 | devContext->t100_aux_vect = aux++; 201 | 202 | if (tchaux & MXT_T100_TCHAUX_AMPL) 203 | devContext->t100_aux_ampl = aux++; 204 | 205 | if (tchaux & MXT_T100_TCHAUX_AREA) 206 | devContext->t100_aux_area = aux++; 207 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_PNP, "Screen Size T100: X: %d Y: %d\n", devContext->max_x, devContext->max_y); 208 | return status; 209 | } 210 | 211 | static NTSTATUS mxt_set_t7_power_cfg(PATMEL_CONTEXT devContext, uint8_t sleep) 212 | { 213 | struct t7_config *new_config; 214 | struct t7_config deepsleep; 215 | deepsleep.active = deepsleep.idle = 0; 216 | struct t7_config active; 217 | active.active = 20; 218 | active.idle = 100; 219 | 220 | if (sleep == MXT_POWER_CFG_DEEPSLEEP) 221 | new_config = &deepsleep; 222 | else { 223 | new_config = &active; 224 | } 225 | 226 | return mxt_write_reg_buf(devContext, devContext->T7_address, 227 | new_config, sizeof(devContext->t7_cfg)); 228 | } 229 | 230 | VOID 231 | AtmelBootWorkItem( 232 | IN WDFWORKITEM WorkItem 233 | ) 234 | { 235 | WDFDEVICE Device = (WDFDEVICE)WdfWorkItemGetParentObject(WorkItem); 236 | PATMEL_CONTEXT pDevice = GetDeviceContext(Device); 237 | 238 | uint8_t test[8]; 239 | mxt_read_reg(pDevice, pDevice->T44_address, test, 0x07); 240 | 241 | WdfObjectDelete(WorkItem); 242 | } 243 | 244 | void AtmelBootTimer(_In_ WDFTIMER hTimer) { 245 | WDFDEVICE Device = (WDFDEVICE)WdfTimerGetParentObject(hTimer); 246 | PATMEL_CONTEXT pDevice = GetDeviceContext(Device); 247 | 248 | WDF_OBJECT_ATTRIBUTES attributes; 249 | WDF_WORKITEM_CONFIG workitemConfig; 250 | WDFWORKITEM hWorkItem; 251 | 252 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 253 | WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, ATMEL_CONTEXT); 254 | attributes.ParentObject = Device; 255 | WDF_WORKITEM_CONFIG_INIT(&workitemConfig, AtmelBootWorkItem); 256 | 257 | WdfWorkItemCreate(&workitemConfig, 258 | &attributes, 259 | &hWorkItem); 260 | 261 | WdfWorkItemEnqueue(hWorkItem); 262 | WdfTimerStop(hTimer, FALSE); 263 | } 264 | 265 | NTSTATUS BOOTTOUCHSCREEN( 266 | _In_ PATMEL_CONTEXT devContext 267 | ) 268 | { 269 | NTSTATUS status = STATUS_SUCCESS; 270 | if (!devContext->TouchScreenBooted) { 271 | int blksize; 272 | int totsize; 273 | uint32_t crc; 274 | mxt_rollup *core = &devContext->core; 275 | 276 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_PNP, "Initializing Touch Screen.\n"); 277 | 278 | status = mxt_read_reg(devContext, 0, &core->info, sizeof(core->info)); 279 | if (!NT_SUCCESS(status)) { 280 | return status; 281 | } 282 | 283 | core->nobjs = core->info.num_objects; 284 | 285 | if (core->nobjs < 0 || core->nobjs > 1024) { 286 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "init_device nobjs (%d) out of bounds\n", 287 | core.nobjs); 288 | } 289 | 290 | blksize = sizeof(core->info) + 291 | core->nobjs * sizeof(struct mxt_object); 292 | totsize = blksize + sizeof(struct mxt_raw_crc); 293 | 294 | core->buf = (uint8_t *)ExAllocatePoolWithTag(NonPagedPool, totsize, ATMEL_POOL_TAG); 295 | 296 | status = mxt_read_reg(devContext, 0, core->buf, totsize); 297 | if (!NT_SUCCESS(status)) { 298 | return status; 299 | } 300 | 301 | crc = obp_convert_crc((mxt_raw_crc *)((uint8_t *)core->buf + blksize)); 302 | 303 | if (obp_crc24(core->buf, blksize) != crc) { 304 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 305 | "init_device: configuration space " 306 | "crc mismatch %08x/%08x\n", 307 | crc, obp_crc24(core.buf, blksize)); 308 | } 309 | else { 310 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "CRC Matched!\n"); 311 | } 312 | 313 | core->objs = (mxt_object *)((uint8_t *)core->buf + 314 | sizeof(core->info)); 315 | 316 | devContext->msgprocobj = mxt_findobject(core, MXT_GEN_MESSAGEPROCESSOR); 317 | devContext->cmdprocobj = mxt_findobject(core, MXT_GEN_COMMANDPROCESSOR); 318 | 319 | int reportid = 1; 320 | for (int i = 0; i < core->nobjs; i++) { 321 | mxt_object *obj = &core->objs[i]; 322 | uint8_t min_id, max_id; 323 | 324 | if (obj->num_report_ids) { 325 | min_id = reportid; 326 | reportid += obj->num_report_ids * 327 | mxt_obj_instances(obj); 328 | max_id = reportid - 1; 329 | } 330 | else { 331 | min_id = 0; 332 | max_id = 0; 333 | } 334 | 335 | switch (obj->type) { 336 | case MXT_GEN_MESSAGE_T5: 337 | if (devContext->info.family == 0x80 && 338 | devContext->info.version < 0x20) { 339 | /* 340 | * On mXT224 firmware versions prior to V2.0 341 | * read and discard unused CRC byte otherwise 342 | * DMA reads are misaligned. 343 | */ 344 | devContext->T5_msg_size = mxt_obj_size(obj); 345 | } 346 | else { 347 | /* CRC not enabled, so skip last byte */ 348 | devContext->T5_msg_size = mxt_obj_size(obj) - 1; 349 | } 350 | devContext->T5_address = obj->start_address; 351 | break; 352 | case MXT_GEN_COMMAND_T6: 353 | devContext->T6_reportid = min_id; 354 | devContext->T6_address = obj->start_address; 355 | break; 356 | case MXT_GEN_POWER_T7: 357 | devContext->T7_address = obj->start_address; 358 | break; 359 | case MXT_TOUCH_MULTI_T9: 360 | devContext->multitouch = MXT_TOUCH_MULTI_T9; 361 | devContext->T9_reportid_min = min_id; 362 | devContext->T9_reportid_max = max_id; 363 | devContext->num_touchids = obj->num_report_ids 364 | * mxt_obj_instances(obj); 365 | break; 366 | case MXT_SPT_MESSAGECOUNT_T44: 367 | devContext->T44_address = obj->start_address; 368 | break; 369 | case MXT_SPT_GPIOPWM_T19: 370 | devContext->T19_reportid = min_id; 371 | break; 372 | case MXT_TOUCH_MULTITOUCHSCREEN_T100: 373 | devContext->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100; 374 | devContext->T100_reportid_min = min_id; 375 | devContext->T100_reportid_max = max_id; 376 | 377 | /* first two report IDs reserved */ 378 | devContext->num_touchids = obj->num_report_ids - 2; 379 | break; 380 | } 381 | } 382 | 383 | devContext->max_reportid = reportid; 384 | 385 | AtmelProcessMessagesUntilInvalid(devContext); 386 | 387 | if (devContext->multitouch == MXT_TOUCH_MULTI_T9) 388 | mxt_read_t9_resolution(devContext); 389 | else if (devContext->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) 390 | mxt_read_t100_config(devContext); 391 | 392 | if (devContext->multitouch == MXT_TOUCH_MULTI_T9 || devContext->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) { 393 | uint16_t max_x[] = { devContext->max_x }; 394 | uint16_t max_y[] = { devContext->max_y }; 395 | 396 | uint8_t *max_x8bit = (uint8_t *)max_x; 397 | uint8_t *max_y8bit = (uint8_t *)max_y; 398 | 399 | devContext->max_x_hid[0] = max_x8bit[0]; 400 | devContext->max_x_hid[1] = max_x8bit[1]; 401 | 402 | devContext->max_y_hid[0] = max_y8bit[0]; 403 | devContext->max_y_hid[1] = max_y8bit[1]; 404 | } 405 | 406 | status = atmel_reset_device(devContext); 407 | if (!NT_SUCCESS(status)) { 408 | return status; 409 | } 410 | 411 | WDF_TIMER_CONFIG timerConfig; 412 | WDFTIMER hTimer; 413 | WDF_OBJECT_ATTRIBUTES attributes; 414 | 415 | WDF_TIMER_CONFIG_INIT(&timerConfig, AtmelBootTimer); 416 | 417 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 418 | attributes.ParentObject = devContext->FxDevice; 419 | NTSTATUS status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); 420 | 421 | WdfTimerStart(hTimer, WDF_REL_TIMEOUT_IN_MS(200)); 422 | 423 | devContext->TouchScreenBooted = true; 424 | 425 | return status; 426 | } 427 | else { 428 | if (devContext->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) { 429 | status = mxt_set_t7_power_cfg(devContext, MXT_POWER_CFG_RUN); 430 | if (!NT_SUCCESS(status)) { 431 | return status; 432 | } 433 | } 434 | else { 435 | struct mxt_object *obj = mxt_findobject(&devContext->core, MXT_TOUCH_MULTI_T9); 436 | status = mxt_write_object_off(devContext, obj, MXT_T9_CTRL, 0x83); 437 | if (!NT_SUCCESS(status)) { 438 | return status; 439 | } 440 | } 441 | 442 | status = atmel_reset_device(devContext); 443 | return status; 444 | } 445 | } 446 | 447 | NTSTATUS 448 | OnPrepareHardware( 449 | _In_ WDFDEVICE FxDevice, 450 | _In_ WDFCMRESLIST FxResourcesRaw, 451 | _In_ WDFCMRESLIST FxResourcesTranslated 452 | ) 453 | /*++ 454 | 455 | Routine Description: 456 | 457 | This routine caches the SPB resource connection ID. 458 | 459 | Arguments: 460 | 461 | FxDevice - a handle to the framework device object 462 | FxResourcesRaw - list of translated hardware resources that 463 | the PnP manager has assigned to the device 464 | FxResourcesTranslated - list of raw hardware resources that 465 | the PnP manager has assigned to the device 466 | 467 | Return Value: 468 | 469 | Status 470 | 471 | --*/ 472 | { 473 | PATMEL_CONTEXT pDevice = GetDeviceContext(FxDevice); 474 | BOOLEAN fSpbResourceFound = FALSE; 475 | NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; 476 | 477 | UNREFERENCED_PARAMETER(FxResourcesRaw); 478 | 479 | // 480 | // Parse the peripheral's resources. 481 | // 482 | 483 | ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); 484 | 485 | for (ULONG i = 0; i < resourceCount; i++) 486 | { 487 | PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 488 | UCHAR Class; 489 | UCHAR Type; 490 | 491 | pDescriptor = WdfCmResourceListGetDescriptor( 492 | FxResourcesTranslated, i); 493 | 494 | switch (pDescriptor->Type) 495 | { 496 | case CmResourceTypeConnection: 497 | // 498 | // Look for I2C or SPI resource and save connection ID. 499 | // 500 | Class = pDescriptor->u.Connection.Class; 501 | Type = pDescriptor->u.Connection.Type; 502 | if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && 503 | Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) 504 | { 505 | if (fSpbResourceFound == FALSE) 506 | { 507 | status = STATUS_SUCCESS; 508 | pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; 509 | pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; 510 | fSpbResourceFound = TRUE; 511 | } 512 | else 513 | { 514 | } 515 | } 516 | break; 517 | default: 518 | // 519 | // Ignoring all other resource types. 520 | // 521 | break; 522 | } 523 | } 524 | 525 | // 526 | // An SPB resource is required. 527 | // 528 | 529 | if (fSpbResourceFound == FALSE) 530 | { 531 | status = STATUS_NOT_FOUND; 532 | } 533 | 534 | status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); 535 | 536 | if (!NT_SUCCESS(status)) 537 | { 538 | return status; 539 | } 540 | 541 | status = BOOTTOUCHSCREEN(pDevice); 542 | 543 | if (!NT_SUCCESS(status)) 544 | { 545 | return status; 546 | } 547 | 548 | return status; 549 | } 550 | 551 | NTSTATUS 552 | OnReleaseHardware( 553 | _In_ WDFDEVICE FxDevice, 554 | _In_ WDFCMRESLIST FxResourcesTranslated 555 | ) 556 | /*++ 557 | 558 | Routine Description: 559 | 560 | Arguments: 561 | 562 | FxDevice - a handle to the framework device object 563 | FxResourcesTranslated - list of raw hardware resources that 564 | the PnP manager has assigned to the device 565 | 566 | Return Value: 567 | 568 | Status 569 | 570 | --*/ 571 | { 572 | PATMEL_CONTEXT pDevice = GetDeviceContext(FxDevice); 573 | NTSTATUS status = STATUS_SUCCESS; 574 | 575 | UNREFERENCED_PARAMETER(FxResourcesTranslated); 576 | 577 | if (pDevice->core.buf != NULL) { 578 | ExFreePoolWithTag(pDevice->core.buf, ATMEL_POOL_TAG); 579 | } 580 | 581 | pDevice->core.buf = NULL; 582 | 583 | pDevice->msgprocobj = NULL; 584 | pDevice->cmdprocobj = NULL; 585 | 586 | SpbTargetDeinitialize(FxDevice, &pDevice->I2CContext); 587 | 588 | return status; 589 | } 590 | 591 | NTSTATUS 592 | OnD0Entry( 593 | _In_ WDFDEVICE FxDevice, 594 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 595 | ) 596 | /*++ 597 | 598 | Routine Description: 599 | 600 | This routine allocates objects needed by the driver. 601 | 602 | Arguments: 603 | 604 | FxDevice - a handle to the framework device object 605 | FxPreviousState - previous power state 606 | 607 | Return Value: 608 | 609 | Status 610 | 611 | --*/ 612 | { 613 | UNREFERENCED_PARAMETER(FxPreviousState); 614 | 615 | PATMEL_CONTEXT pDevice = GetDeviceContext(FxDevice); 616 | NTSTATUS status = STATUS_SUCCESS; 617 | 618 | WdfTimerStart(pDevice->Timer, WDF_REL_TIMEOUT_IN_MS(10)); 619 | 620 | atmel_reset_device(pDevice); 621 | 622 | for (int i = 0; i < 20; i++) { 623 | pDevice->Flags[i] = 0; 624 | } 625 | 626 | pDevice->RegsSet = false; 627 | pDevice->ConnectInterrupt = true; 628 | 629 | return status; 630 | } 631 | 632 | NTSTATUS 633 | OnD0Exit( 634 | _In_ WDFDEVICE FxDevice, 635 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 636 | ) 637 | /*++ 638 | 639 | Routine Description: 640 | 641 | This routine destroys objects needed by the driver. 642 | 643 | Arguments: 644 | 645 | FxDevice - a handle to the framework device object 646 | FxPreviousState - previous power state 647 | 648 | Return Value: 649 | 650 | Status 651 | 652 | --*/ 653 | { 654 | UNREFERENCED_PARAMETER(FxPreviousState); 655 | 656 | PATMEL_CONTEXT pDevice = GetDeviceContext(FxDevice); 657 | 658 | if (pDevice->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) 659 | mxt_set_t7_power_cfg(pDevice, MXT_POWER_CFG_DEEPSLEEP); 660 | else { 661 | struct mxt_object *obj = mxt_findobject(&pDevice->core, MXT_TOUCH_MULTI_T9); 662 | mxt_write_object_off(pDevice, obj, MXT_T9_CTRL, 0); 663 | } 664 | 665 | WdfTimerStop(pDevice->Timer, TRUE); 666 | 667 | pDevice->ConnectInterrupt = false; 668 | 669 | return STATUS_SUCCESS; 670 | } 671 | 672 | int AtmelProcessMessage(PATMEL_CONTEXT pDevice, uint8_t *message) { 673 | uint8_t report_id = message[0]; 674 | 675 | if (report_id == 0xff) 676 | return 0; 677 | 678 | if (report_id == pDevice->T6_reportid) { 679 | uint8_t status = message[1]; 680 | uint32_t crc = message[2] | (message[3] << 8) | (message[4] << 16); 681 | } 682 | else if (report_id >= pDevice->T9_reportid_min && report_id <= pDevice->T9_reportid_max) { 683 | uint8_t flags = message[1]; 684 | 685 | int rawx = (message[2] << 4) | ((message[4] >> 4) & 0xf); 686 | int rawy = (message[3] << 4) | ((message[4] & 0xf)); 687 | 688 | /* Handle 10/12 bit switching */ 689 | if (pDevice->max_x < 1024) 690 | rawx >>= 2; 691 | if (pDevice->max_y < 1024) 692 | rawy >>= 2; 693 | 694 | uint8_t area = message[5]; 695 | uint8_t ampl = message[6]; 696 | 697 | pDevice->Flags[report_id] = flags; 698 | pDevice->XValue[report_id] = rawx; 699 | pDevice->YValue[report_id] = rawy; 700 | pDevice->AREA[report_id] = area; 701 | } 702 | else if (report_id >= pDevice->T100_reportid_min && report_id <= pDevice->T100_reportid_max) { 703 | int reportid = report_id - pDevice->T100_reportid_min - 2; 704 | 705 | uint8_t flags = message[1]; 706 | 707 | uint8_t t9_flags = 0; //convert T100 flags to T9 708 | if (flags & MXT_T100_DETECT) 709 | t9_flags += MXT_T9_DETECT; 710 | else if (pDevice->Flags[reportid] & MXT_T100_DETECT) 711 | t9_flags += MXT_T9_RELEASE; 712 | 713 | int rawx = *((uint16_t *)&message[2]); 714 | int rawy = *((uint16_t *)&message[4]); 715 | 716 | if (reportid >= 0) { 717 | pDevice->Flags[reportid] = t9_flags; 718 | 719 | pDevice->XValue[reportid] = rawx; 720 | pDevice->YValue[reportid] = rawy; 721 | pDevice->AREA[reportid] = 10; 722 | } 723 | } 724 | 725 | struct _ATMEL_MULTITOUCH_REPORT report; 726 | report.ReportID = REPORTID_MTOUCH; 727 | 728 | int count = 0, i = 0; 729 | while (count < 10 && i < 20) { 730 | if (pDevice->Flags[i] != 0) { 731 | report.Touch[count].ContactID = i; 732 | report.Touch[count].Height = pDevice->AREA[i]; 733 | report.Touch[count].Width = pDevice->AREA[i]; 734 | 735 | report.Touch[count].XValue = pDevice->XValue[i]; 736 | report.Touch[count].YValue = pDevice->YValue[i]; 737 | 738 | uint8_t flags = pDevice->Flags[i]; 739 | if (flags & MXT_T9_DETECT) { 740 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 741 | } 742 | else if (flags & MXT_T9_PRESS) { 743 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 744 | } 745 | else if (flags & MXT_T9_RELEASE) { 746 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT; 747 | pDevice->Flags[i] = 0; 748 | } 749 | else 750 | report.Touch[count].Status = 0; 751 | 752 | count++; 753 | } 754 | i++; 755 | } 756 | 757 | report.ActualCount = count; 758 | 759 | if (count > 0) { 760 | size_t bytesWritten; 761 | AtmelProcessVendorReport(pDevice, &report, sizeof(report), &bytesWritten); 762 | } 763 | pDevice->RegsSet = true; 764 | return 1; 765 | } 766 | 767 | int AtmelReadAndProcessMessages(PATMEL_CONTEXT pDevice, uint8_t count) { 768 | uint8_t num_valid = 0; 769 | int i, ret; 770 | if (count > pDevice->max_reportid) 771 | return -1; 772 | 773 | uint8_t *msg_buf = (uint8_t *)ExAllocatePoolWithTag(NonPagedPool, pDevice->max_reportid * pDevice->T5_msg_size, ATMEL_POOL_TAG); 774 | 775 | for (int i = 0; i < pDevice->max_reportid * pDevice->T5_msg_size; i++) { 776 | msg_buf[i] = 0xff; 777 | } 778 | 779 | NTSTATUS status = mxt_read_reg(pDevice, pDevice->T5_address, msg_buf, pDevice->T5_msg_size * count); 780 | if (!NT_SUCCESS(status)) { 781 | ExFreePoolWithTag(msg_buf, ATMEL_POOL_TAG); 782 | return 0; 783 | } 784 | 785 | for (i = 0; i < count; i++) { 786 | ret = AtmelProcessMessage(pDevice, 787 | msg_buf + pDevice->T5_msg_size * i); 788 | 789 | if (ret == 1) 790 | num_valid++; 791 | } 792 | 793 | ExFreePoolWithTag(msg_buf, ATMEL_POOL_TAG); 794 | 795 | /* return number of messages read */ 796 | return num_valid; 797 | } 798 | 799 | int AtmelProcessMessagesUntilInvalid(PATMEL_CONTEXT pDevice) { 800 | int count, read; 801 | uint8_t tries = 2; 802 | 803 | count = pDevice->max_reportid; 804 | do { 805 | read = AtmelReadAndProcessMessages(pDevice, count); 806 | if (read < count) 807 | return 0; 808 | } while (--tries); 809 | return -1; 810 | } 811 | 812 | bool AtmelDeviceReadT44(PATMEL_CONTEXT pDevice) { 813 | NTSTATUS status; 814 | int ret; 815 | uint8_t count, num_left; 816 | 817 | uint8_t *msg_buf = (uint8_t *)ExAllocatePoolWithTag(NonPagedPool, pDevice->T5_msg_size + 1, ATMEL_POOL_TAG); 818 | 819 | /* Read T44 and T5 together */ 820 | status = mxt_read_reg(pDevice, pDevice->T44_address, msg_buf, pDevice->T5_msg_size); 821 | if (!NT_SUCCESS(status)) { 822 | goto end; 823 | } 824 | 825 | count = msg_buf[0]; 826 | 827 | if (count == 0) 828 | goto end; 829 | 830 | if (count > pDevice->max_reportid) { 831 | count = pDevice->max_reportid; 832 | } 833 | 834 | ret = AtmelProcessMessage(pDevice, msg_buf + 1); 835 | if (ret < 0) { 836 | goto end; 837 | } 838 | 839 | num_left = count - 1; 840 | 841 | if (num_left) { 842 | ret = AtmelReadAndProcessMessages(pDevice, num_left); 843 | if (ret < 0) 844 | goto end; 845 | //else if (ret != num_left) 846 | /// DbgPrint("T44: Unexpected invalid message!\n"); 847 | } 848 | 849 | end: 850 | ExFreePoolWithTag(msg_buf, ATMEL_POOL_TAG); 851 | return true; 852 | } 853 | 854 | bool AtmelDeviceRead(PATMEL_CONTEXT pDevice) { 855 | int total_handled, num_handled; 856 | uint8_t count = pDevice->last_message_count; 857 | 858 | if (count < 1 || count > pDevice->max_reportid) 859 | count = 1; 860 | 861 | /* include final invalid message */ 862 | total_handled = AtmelReadAndProcessMessages(pDevice, count + 1); 863 | if (total_handled < 0) 864 | return false; 865 | else if (total_handled <= count) 866 | goto update_count; 867 | 868 | /* keep reading two msgs until one is invalid or reportid limit */ 869 | do { 870 | num_handled = AtmelReadAndProcessMessages(pDevice, 2); 871 | if (num_handled < 0) 872 | return false; 873 | 874 | total_handled += num_handled; 875 | 876 | if (num_handled < 2) 877 | break; 878 | } while (total_handled < pDevice->num_touchids); 879 | 880 | update_count: 881 | pDevice->last_message_count = total_handled; 882 | 883 | return true; 884 | } 885 | 886 | void AtmelProcessInput(PATMEL_CONTEXT pDevice) { 887 | struct _ATMEL_MULTITOUCH_REPORT report; 888 | report.ReportID = REPORTID_MTOUCH; 889 | 890 | int count = 0, i = 0; 891 | while (count < 10 && i < 20) { 892 | if (pDevice->Flags[i] != 0) { 893 | report.Touch[count].ContactID = i; 894 | report.Touch[count].Height = pDevice->AREA[i]; 895 | report.Touch[count].Width = pDevice->AREA[i]; 896 | 897 | report.Touch[count].XValue = pDevice->XValue[i]; 898 | report.Touch[count].YValue = pDevice->YValue[i]; 899 | 900 | uint8_t flags = pDevice->Flags[i]; 901 | if (flags & MXT_T9_DETECT) { 902 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 903 | } 904 | else if (flags & MXT_T9_PRESS) { 905 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT | MULTI_TIPSWITCH_BIT; 906 | } 907 | else if (flags & MXT_T9_RELEASE) { 908 | report.Touch[count].Status = MULTI_CONFIDENCE_BIT; 909 | pDevice->Flags[i] = 0; 910 | } 911 | else 912 | report.Touch[count].Status = 0; 913 | 914 | count++; 915 | } 916 | i++; 917 | } 918 | 919 | report.ActualCount = count; 920 | 921 | if (count > 0) { 922 | size_t bytesWritten; 923 | AtmelProcessVendorReport(pDevice, &report, sizeof(report), &bytesWritten); 924 | } 925 | } 926 | BOOLEAN OnInterruptIsr( 927 | WDFINTERRUPT Interrupt, 928 | ULONG MessageID) { 929 | UNREFERENCED_PARAMETER(MessageID); 930 | 931 | WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); 932 | PATMEL_CONTEXT pDevice = GetDeviceContext(Device); 933 | 934 | if (!pDevice->ConnectInterrupt) 935 | return false; 936 | 937 | bool ret = true; 938 | 939 | if (pDevice->T44_address) 940 | ret = AtmelDeviceReadT44(pDevice); 941 | else 942 | ret = AtmelDeviceRead(pDevice); 943 | 944 | AtmelProcessInput(pDevice); 945 | 946 | return ret; 947 | } 948 | 949 | void AtmelTimerFunc(_In_ WDFTIMER hTimer) { 950 | WDFDEVICE Device = (WDFDEVICE)WdfTimerGetParentObject(hTimer); 951 | PATMEL_CONTEXT pDevice = GetDeviceContext(Device); 952 | 953 | if (!pDevice->ConnectInterrupt) 954 | return; 955 | 956 | if (!pDevice->RegsSet) 957 | return; 958 | 959 | AtmelProcessInput(pDevice); 960 | return; 961 | } 962 | 963 | NTSTATUS 964 | AtmelEvtDeviceAdd( 965 | IN WDFDRIVER Driver, 966 | IN PWDFDEVICE_INIT DeviceInit 967 | ) 968 | { 969 | NTSTATUS status = STATUS_SUCCESS; 970 | WDF_IO_QUEUE_CONFIG queueConfig; 971 | WDF_OBJECT_ATTRIBUTES attributes; 972 | WDFDEVICE device; 973 | WDF_INTERRUPT_CONFIG interruptConfig; 974 | WDFQUEUE queue; 975 | UCHAR minorFunction; 976 | PATMEL_CONTEXT devContext; 977 | 978 | UNREFERENCED_PARAMETER(Driver); 979 | 980 | PAGED_CODE(); 981 | 982 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_PNP, 983 | "AtmelEvtDeviceAdd called\n"); 984 | 985 | // 986 | // Tell framework this is a filter driver. Filter drivers by default are 987 | // not power policy owners. This works well for this driver because 988 | // HIDclass driver is the power policy owner for HID minidrivers. 989 | // 990 | 991 | WdfFdoInitSetFilter(DeviceInit); 992 | 993 | { 994 | WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; 995 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); 996 | 997 | pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; 998 | pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; 999 | pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; 1000 | pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; 1001 | 1002 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); 1003 | } 1004 | 1005 | // 1006 | // Setup the device context 1007 | // 1008 | 1009 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, ATMEL_CONTEXT); 1010 | 1011 | // 1012 | // Create a framework device object.This call will in turn create 1013 | // a WDM device object, attach to the lower stack, and set the 1014 | // appropriate flags and attributes. 1015 | // 1016 | 1017 | status = WdfDeviceCreate(&DeviceInit, &attributes, &device); 1018 | 1019 | if (!NT_SUCCESS(status)) 1020 | { 1021 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1022 | "WdfDeviceCreate failed with status code 0x%x\n", status); 1023 | 1024 | return status; 1025 | } 1026 | 1027 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); 1028 | 1029 | queueConfig.EvtIoInternalDeviceControl = AtmelEvtInternalDeviceControl; 1030 | 1031 | status = WdfIoQueueCreate(device, 1032 | &queueConfig, 1033 | WDF_NO_OBJECT_ATTRIBUTES, 1034 | &queue 1035 | ); 1036 | 1037 | if (!NT_SUCCESS(status)) 1038 | { 1039 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1040 | "WdfIoQueueCreate failed 0x%x\n", status); 1041 | 1042 | return status; 1043 | } 1044 | 1045 | // 1046 | // Create manual I/O queue to take care of hid report read requests 1047 | // 1048 | 1049 | devContext = GetDeviceContext(device); 1050 | 1051 | devContext->TouchScreenBooted = false; 1052 | 1053 | devContext->FxDevice = device; 1054 | 1055 | WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); 1056 | 1057 | queueConfig.PowerManaged = WdfFalse; 1058 | 1059 | status = WdfIoQueueCreate(device, 1060 | &queueConfig, 1061 | WDF_NO_OBJECT_ATTRIBUTES, 1062 | &devContext->ReportQueue 1063 | ); 1064 | 1065 | if (!NT_SUCCESS(status)) 1066 | { 1067 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1068 | "WdfIoQueueCreate failed 0x%x\n", status); 1069 | 1070 | return status; 1071 | } 1072 | 1073 | // 1074 | // Create an interrupt object for hardware notifications 1075 | // 1076 | WDF_INTERRUPT_CONFIG_INIT( 1077 | &interruptConfig, 1078 | OnInterruptIsr, 1079 | NULL); 1080 | interruptConfig.PassiveHandling = TRUE; 1081 | 1082 | status = WdfInterruptCreate( 1083 | device, 1084 | &interruptConfig, 1085 | WDF_NO_OBJECT_ATTRIBUTES, 1086 | &devContext->Interrupt); 1087 | 1088 | if (!NT_SUCCESS(status)) 1089 | { 1090 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1091 | "Error creating WDF interrupt object - %!STATUS!", 1092 | status); 1093 | 1094 | return status; 1095 | } 1096 | 1097 | WDF_TIMER_CONFIG timerConfig; 1098 | WDFTIMER hTimer; 1099 | 1100 | WDF_TIMER_CONFIG_INIT_PERIODIC(&timerConfig, AtmelTimerFunc, 10); 1101 | 1102 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 1103 | attributes.ParentObject = device; 1104 | status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); 1105 | devContext->Timer = hTimer; 1106 | if (!NT_SUCCESS(status)) 1107 | { 1108 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "(%!FUNC!) WdfTimerCreate failed status:%!STATUS!\n", status); 1109 | return status; 1110 | } 1111 | 1112 | // 1113 | // Initialize DeviceMode 1114 | // 1115 | 1116 | devContext->DeviceMode = DEVICE_MODE_MOUSE; 1117 | 1118 | return status; 1119 | } 1120 | 1121 | VOID 1122 | AtmelEvtInternalDeviceControl( 1123 | IN WDFQUEUE Queue, 1124 | IN WDFREQUEST Request, 1125 | IN size_t OutputBufferLength, 1126 | IN size_t InputBufferLength, 1127 | IN ULONG IoControlCode 1128 | ) 1129 | { 1130 | NTSTATUS status = STATUS_SUCCESS; 1131 | WDFDEVICE device; 1132 | PATMEL_CONTEXT devContext; 1133 | BOOLEAN completeRequest = TRUE; 1134 | 1135 | UNREFERENCED_PARAMETER(OutputBufferLength); 1136 | UNREFERENCED_PARAMETER(InputBufferLength); 1137 | 1138 | device = WdfIoQueueGetDevice(Queue); 1139 | devContext = GetDeviceContext(device); 1140 | 1141 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1142 | "%s, Queue:0x%p, Request:0x%p\n", 1143 | DbgHidInternalIoctlString(IoControlCode), 1144 | Queue, 1145 | Request 1146 | ); 1147 | 1148 | // 1149 | // Please note that HIDCLASS provides the buffer in the Irp->UserBuffer 1150 | // field irrespective of the ioctl buffer type. However, framework is very 1151 | // strict about type checking. You cannot get Irp->UserBuffer by using 1152 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1153 | // internal ioctl. So depending on the ioctl code, we will either 1154 | // use retreive function or escape to WDM to get the UserBuffer. 1155 | // 1156 | 1157 | switch (IoControlCode) 1158 | { 1159 | 1160 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 1161 | // 1162 | // Retrieves the device's HID descriptor. 1163 | // 1164 | status = AtmelGetHidDescriptor(device, Request); 1165 | break; 1166 | 1167 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 1168 | // 1169 | //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure. 1170 | // 1171 | status = AtmelGetDeviceAttributes(Request); 1172 | break; 1173 | 1174 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 1175 | // 1176 | //Obtains the report descriptor for the HID device. 1177 | // 1178 | status = AtmelGetReportDescriptor(device, Request); 1179 | break; 1180 | 1181 | case IOCTL_HID_GET_STRING: 1182 | // 1183 | // Requests that the HID minidriver retrieve a human-readable string 1184 | // for either the manufacturer ID, the product ID, or the serial number 1185 | // from the string descriptor of the device. The minidriver must send 1186 | // a Get String Descriptor request to the device, in order to retrieve 1187 | // the string descriptor, then it must extract the string at the 1188 | // appropriate index from the string descriptor and return it in the 1189 | // output buffer indicated by the IRP. Before sending the Get String 1190 | // Descriptor request, the minidriver must retrieve the appropriate 1191 | // index for the manufacturer ID, the product ID or the serial number 1192 | // from the device extension of a top level collection associated with 1193 | // the device. 1194 | // 1195 | status = AtmelGetString(Request); 1196 | break; 1197 | 1198 | case IOCTL_HID_WRITE_REPORT: 1199 | case IOCTL_HID_SET_OUTPUT_REPORT: 1200 | // 1201 | //Transmits a class driver-supplied report to the device. 1202 | // 1203 | status = AtmelWriteReport(devContext, Request); 1204 | break; 1205 | 1206 | case IOCTL_HID_READ_REPORT: 1207 | case IOCTL_HID_GET_INPUT_REPORT: 1208 | // 1209 | // Returns a report from the device into a class driver-supplied buffer. 1210 | // 1211 | status = AtmelReadReport(devContext, Request, &completeRequest); 1212 | break; 1213 | 1214 | case IOCTL_HID_SET_FEATURE: 1215 | // 1216 | // This sends a HID class feature report to a top-level collection of 1217 | // a HID class device. 1218 | // 1219 | status = AtmelSetFeature(devContext, Request, &completeRequest); 1220 | break; 1221 | 1222 | case IOCTL_HID_GET_FEATURE: 1223 | // 1224 | // returns a feature report associated with a top-level collection 1225 | // 1226 | status = AtmelGetFeature(devContext, Request, &completeRequest); 1227 | break; 1228 | 1229 | case IOCTL_HID_ACTIVATE_DEVICE: 1230 | // 1231 | // Makes the device ready for I/O operations. 1232 | // 1233 | case IOCTL_HID_DEACTIVATE_DEVICE: 1234 | // 1235 | // Causes the device to cease operations and terminate all outstanding 1236 | // I/O requests. 1237 | // 1238 | default: 1239 | status = STATUS_NOT_SUPPORTED; 1240 | break; 1241 | } 1242 | 1243 | if (completeRequest) 1244 | { 1245 | WdfRequestComplete(Request, status); 1246 | 1247 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1248 | "%s completed, Queue:0x%p, Request:0x%p\n", 1249 | DbgHidInternalIoctlString(IoControlCode), 1250 | Queue, 1251 | Request 1252 | ); 1253 | } 1254 | else 1255 | { 1256 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1257 | "%s deferred, Queue:0x%p, Request:0x%p\n", 1258 | DbgHidInternalIoctlString(IoControlCode), 1259 | Queue, 1260 | Request 1261 | ); 1262 | } 1263 | 1264 | return; 1265 | } 1266 | 1267 | NTSTATUS 1268 | AtmelGetHidDescriptor( 1269 | IN WDFDEVICE Device, 1270 | IN WDFREQUEST Request 1271 | ) 1272 | { 1273 | NTSTATUS status = STATUS_SUCCESS; 1274 | size_t bytesToCopy = 0; 1275 | WDFMEMORY memory; 1276 | 1277 | UNREFERENCED_PARAMETER(Device); 1278 | 1279 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1280 | "AtmelGetHidDescriptor Entry\n"); 1281 | 1282 | // 1283 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1284 | // will correctly retrieve buffer from Irp->UserBuffer. 1285 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1286 | // field irrespective of the ioctl buffer type. However, framework is very 1287 | // strict about type checking. You cannot get Irp->UserBuffer by using 1288 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1289 | // internal ioctl. 1290 | // 1291 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 1292 | 1293 | if (!NT_SUCCESS(status)) 1294 | { 1295 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1296 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 1297 | 1298 | return status; 1299 | } 1300 | 1301 | // 1302 | // Use hardcoded "HID Descriptor" 1303 | // 1304 | bytesToCopy = DefaultHidDescriptor.bLength; 1305 | 1306 | if (bytesToCopy == 0) 1307 | { 1308 | status = STATUS_INVALID_DEVICE_STATE; 1309 | 1310 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1311 | "DefaultHidDescriptor is zero, 0x%x\n", status); 1312 | 1313 | return status; 1314 | } 1315 | 1316 | status = WdfMemoryCopyFromBuffer(memory, 1317 | 0, // Offset 1318 | (PVOID)&DefaultHidDescriptor, 1319 | bytesToCopy); 1320 | 1321 | if (!NT_SUCCESS(status)) 1322 | { 1323 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1324 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1325 | 1326 | return status; 1327 | } 1328 | 1329 | // 1330 | // Report how many bytes were copied 1331 | // 1332 | WdfRequestSetInformation(Request, bytesToCopy); 1333 | 1334 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1335 | "AtmelGetHidDescriptor Exit = 0x%x\n", status); 1336 | 1337 | return status; 1338 | } 1339 | 1340 | NTSTATUS 1341 | AtmelGetReportDescriptor( 1342 | IN WDFDEVICE Device, 1343 | IN WDFREQUEST Request 1344 | ) 1345 | { 1346 | NTSTATUS status = STATUS_SUCCESS; 1347 | ULONG_PTR bytesToCopy; 1348 | WDFMEMORY memory; 1349 | 1350 | PATMEL_CONTEXT devContext = GetDeviceContext(Device); 1351 | 1352 | UNREFERENCED_PARAMETER(Device); 1353 | 1354 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1355 | "AtmelGetReportDescriptor Entry\n"); 1356 | 1357 | #define MT_TOUCH_COLLECTION \ 1358 | MT_TOUCH_COLLECTION0 \ 1359 | 0x26, devContext->max_x_hid[0], devContext->max_x_hid[1], /* LOGICAL_MAXIMUM (WIDTH) */ \ 1360 | MT_TOUCH_COLLECTION1 \ 1361 | 0x26, devContext->max_y_hid[0], devContext->max_y_hid[1], /* LOGICAL_MAXIMUM (HEIGHT) */ \ 1362 | MT_TOUCH_COLLECTION2 \ 1363 | 1364 | HID_REPORT_DESCRIPTOR ReportDescriptor[] = { 1365 | // 1366 | // Multitouch report starts here 1367 | // 1368 | 0x05, 0x0d, // USAGE_PAGE (Digitizers) 1369 | 0x09, 0x04, // USAGE (Touch Screen) 1370 | 0xa1, 0x01, // COLLECTION (Application) 1371 | 0x85, REPORTID_MTOUCH, // REPORT_ID (Touch) 1372 | 0x09, 0x22, // USAGE (Finger) 1373 | MT_TOUCH_COLLECTION 1374 | MT_TOUCH_COLLECTION 1375 | MT_TOUCH_COLLECTION 1376 | MT_TOUCH_COLLECTION 1377 | MT_TOUCH_COLLECTION 1378 | MT_TOUCH_COLLECTION 1379 | MT_TOUCH_COLLECTION 1380 | MT_TOUCH_COLLECTION 1381 | MT_TOUCH_COLLECTION 1382 | MT_TOUCH_COLLECTION 1383 | USAGE_PAGE 1384 | 0xc0, // END_COLLECTION 1385 | }; 1386 | 1387 | // 1388 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1389 | // will correctly retrieve buffer from Irp->UserBuffer. 1390 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1391 | // field irrespective of the ioctl buffer type. However, framework is very 1392 | // strict about type checking. You cannot get Irp->UserBuffer by using 1393 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1394 | // internal ioctl. 1395 | // 1396 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 1397 | if (!NT_SUCCESS(status)) 1398 | { 1399 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1400 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 1401 | 1402 | return status; 1403 | } 1404 | 1405 | // 1406 | // Use hardcoded Report descriptor 1407 | // 1408 | bytesToCopy = DefaultHidDescriptor.DescriptorList[0].wReportLength; 1409 | 1410 | if (bytesToCopy == 0) 1411 | { 1412 | status = STATUS_INVALID_DEVICE_STATE; 1413 | 1414 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1415 | "DefaultHidDescriptor's reportLength is zero, 0x%x\n", status); 1416 | 1417 | return status; 1418 | } 1419 | 1420 | status = WdfMemoryCopyFromBuffer(memory, 1421 | 0, 1422 | (PVOID)ReportDescriptor, 1423 | bytesToCopy); 1424 | if (!NT_SUCCESS(status)) 1425 | { 1426 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1427 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1428 | 1429 | return status; 1430 | } 1431 | 1432 | // 1433 | // Report how many bytes were copied 1434 | // 1435 | WdfRequestSetInformation(Request, bytesToCopy); 1436 | 1437 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1438 | "AtmelGetReportDescriptor Exit = 0x%x\n", status); 1439 | 1440 | return status; 1441 | } 1442 | 1443 | 1444 | NTSTATUS 1445 | AtmelGetDeviceAttributes( 1446 | IN WDFREQUEST Request 1447 | ) 1448 | { 1449 | NTSTATUS status = STATUS_SUCCESS; 1450 | PHID_DEVICE_ATTRIBUTES deviceAttributes = NULL; 1451 | 1452 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1453 | "AtmelGetDeviceAttributes Entry\n"); 1454 | 1455 | // 1456 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1457 | // will correctly retrieve buffer from Irp->UserBuffer. 1458 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1459 | // field irrespective of the ioctl buffer type. However, framework is very 1460 | // strict about type checking. You cannot get Irp->UserBuffer by using 1461 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1462 | // internal ioctl. 1463 | // 1464 | status = WdfRequestRetrieveOutputBuffer(Request, 1465 | sizeof(HID_DEVICE_ATTRIBUTES), 1466 | (PVOID *)&deviceAttributes, 1467 | NULL); 1468 | if (!NT_SUCCESS(status)) 1469 | { 1470 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1471 | "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); 1472 | 1473 | return status; 1474 | } 1475 | 1476 | // 1477 | // Set USB device descriptor 1478 | // 1479 | 1480 | deviceAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES); 1481 | deviceAttributes->VendorID = ATMEL_VID; 1482 | deviceAttributes->ProductID = ATMEL_PID; 1483 | deviceAttributes->VersionNumber = ATMEL_VERSION; 1484 | 1485 | // 1486 | // Report how many bytes were copied 1487 | // 1488 | WdfRequestSetInformation(Request, sizeof(HID_DEVICE_ATTRIBUTES)); 1489 | 1490 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1491 | "AtmelGetDeviceAttributes Exit = 0x%x\n", status); 1492 | 1493 | return status; 1494 | } 1495 | 1496 | NTSTATUS 1497 | AtmelGetString( 1498 | IN WDFREQUEST Request 1499 | ) 1500 | { 1501 | 1502 | NTSTATUS status = STATUS_SUCCESS; 1503 | PWSTR pwstrID; 1504 | size_t lenID; 1505 | WDF_REQUEST_PARAMETERS params; 1506 | void *pStringBuffer = NULL; 1507 | 1508 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1509 | "AtmelGetString Entry\n"); 1510 | 1511 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1512 | WdfRequestGetParameters(Request, ¶ms); 1513 | 1514 | switch ((ULONG_PTR)params.Parameters.DeviceIoControl.Type3InputBuffer & 0xFFFF) 1515 | { 1516 | case HID_STRING_ID_IMANUFACTURER: 1517 | pwstrID = L"Atmel.\0"; 1518 | break; 1519 | 1520 | case HID_STRING_ID_IPRODUCT: 1521 | pwstrID = L"MaxTouch Touch Screen\0"; 1522 | break; 1523 | 1524 | case HID_STRING_ID_ISERIALNUMBER: 1525 | pwstrID = L"123123123\0"; 1526 | break; 1527 | 1528 | default: 1529 | pwstrID = NULL; 1530 | break; 1531 | } 1532 | 1533 | lenID = pwstrID ? wcslen(pwstrID) * sizeof(WCHAR) + sizeof(UNICODE_NULL) : 0; 1534 | 1535 | if (pwstrID == NULL) 1536 | { 1537 | 1538 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1539 | "AtmelGetString Invalid request type\n"); 1540 | 1541 | status = STATUS_INVALID_PARAMETER; 1542 | 1543 | return status; 1544 | } 1545 | 1546 | status = WdfRequestRetrieveOutputBuffer(Request, 1547 | lenID, 1548 | &pStringBuffer, 1549 | &lenID); 1550 | 1551 | if (!NT_SUCCESS(status)) 1552 | { 1553 | 1554 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1555 | "AtmelGetString WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1556 | 1557 | return status; 1558 | } 1559 | 1560 | RtlCopyMemory(pStringBuffer, pwstrID, lenID); 1561 | 1562 | WdfRequestSetInformation(Request, lenID); 1563 | 1564 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1565 | "AtmelGetString Exit = 0x%x\n", status); 1566 | 1567 | return status; 1568 | } 1569 | 1570 | NTSTATUS 1571 | AtmelWriteReport( 1572 | IN PATMEL_CONTEXT DevContext, 1573 | IN WDFREQUEST Request 1574 | ) 1575 | { 1576 | NTSTATUS status = STATUS_SUCCESS; 1577 | WDF_REQUEST_PARAMETERS params; 1578 | PHID_XFER_PACKET transferPacket = NULL; 1579 | size_t bytesWritten = 0; 1580 | 1581 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1582 | "AtmelWriteReport Entry\n"); 1583 | 1584 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1585 | WdfRequestGetParameters(Request, ¶ms); 1586 | 1587 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1588 | { 1589 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1590 | "AtmelWriteReport Xfer packet too small\n"); 1591 | 1592 | status = STATUS_BUFFER_TOO_SMALL; 1593 | } 1594 | else 1595 | { 1596 | 1597 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1598 | 1599 | if (transferPacket == NULL) 1600 | { 1601 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1602 | "AtmelWriteReport No xfer packet\n"); 1603 | 1604 | status = STATUS_INVALID_DEVICE_REQUEST; 1605 | } 1606 | else 1607 | { 1608 | // 1609 | // switch on the report id 1610 | // 1611 | 1612 | switch (transferPacket->reportId) 1613 | { 1614 | default: 1615 | 1616 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1617 | "AtmelWriteReport Unhandled report type %d\n", transferPacket->reportId); 1618 | 1619 | status = STATUS_INVALID_PARAMETER; 1620 | 1621 | break; 1622 | } 1623 | } 1624 | } 1625 | 1626 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1627 | "AtmelWriteReport Exit = 0x%x\n", status); 1628 | 1629 | return status; 1630 | 1631 | } 1632 | 1633 | NTSTATUS 1634 | AtmelProcessVendorReport( 1635 | IN PATMEL_CONTEXT DevContext, 1636 | IN PVOID ReportBuffer, 1637 | IN ULONG ReportBufferLen, 1638 | OUT size_t* BytesWritten 1639 | ) 1640 | { 1641 | NTSTATUS status = STATUS_SUCCESS; 1642 | WDFREQUEST reqRead; 1643 | PVOID pReadReport = NULL; 1644 | size_t bytesReturned = 0; 1645 | 1646 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1647 | "AtmelProcessVendorReport Entry\n"); 1648 | 1649 | status = WdfIoQueueRetrieveNextRequest(DevContext->ReportQueue, 1650 | &reqRead); 1651 | 1652 | if (NT_SUCCESS(status)) 1653 | { 1654 | status = WdfRequestRetrieveOutputBuffer(reqRead, 1655 | ReportBufferLen, 1656 | &pReadReport, 1657 | &bytesReturned); 1658 | 1659 | if (NT_SUCCESS(status)) 1660 | { 1661 | // 1662 | // Copy ReportBuffer into read request 1663 | // 1664 | 1665 | if (bytesReturned > ReportBufferLen) 1666 | { 1667 | bytesReturned = ReportBufferLen; 1668 | } 1669 | 1670 | RtlCopyMemory(pReadReport, 1671 | ReportBuffer, 1672 | bytesReturned); 1673 | 1674 | // 1675 | // Complete read with the number of bytes returned as info 1676 | // 1677 | 1678 | WdfRequestCompleteWithInformation(reqRead, 1679 | status, 1680 | bytesReturned); 1681 | 1682 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1683 | "AtmelProcessVendorReport %d bytes returned\n", bytesReturned); 1684 | 1685 | // 1686 | // Return the number of bytes written for the write request completion 1687 | // 1688 | 1689 | *BytesWritten = bytesReturned; 1690 | 1691 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1692 | "%s completed, Queue:0x%p, Request:0x%p\n", 1693 | DbgHidInternalIoctlString(IOCTL_HID_READ_REPORT), 1694 | DevContext->ReportQueue, 1695 | reqRead); 1696 | } 1697 | else 1698 | { 1699 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1700 | "WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1701 | } 1702 | } 1703 | else 1704 | { 1705 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1706 | "WdfIoQueueRetrieveNextRequest failed Status 0x%x\n", status); 1707 | } 1708 | 1709 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1710 | "AtmelProcessVendorReport Exit = 0x%x\n", status); 1711 | 1712 | return status; 1713 | } 1714 | 1715 | NTSTATUS 1716 | AtmelReadReport( 1717 | IN PATMEL_CONTEXT DevContext, 1718 | IN WDFREQUEST Request, 1719 | OUT BOOLEAN* CompleteRequest 1720 | ) 1721 | { 1722 | NTSTATUS status = STATUS_SUCCESS; 1723 | 1724 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1725 | "AtmelReadReport Entry\n"); 1726 | 1727 | // 1728 | // Forward this read request to our manual queue 1729 | // (in other words, we are going to defer this request 1730 | // until we have a corresponding write request to 1731 | // match it with) 1732 | // 1733 | 1734 | status = WdfRequestForwardToIoQueue(Request, DevContext->ReportQueue); 1735 | 1736 | if (!NT_SUCCESS(status)) 1737 | { 1738 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1739 | "WdfRequestForwardToIoQueue failed Status 0x%x\n", status); 1740 | } 1741 | else 1742 | { 1743 | *CompleteRequest = FALSE; 1744 | } 1745 | 1746 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1747 | "AtmelReadReport Exit = 0x%x\n", status); 1748 | 1749 | return status; 1750 | } 1751 | 1752 | NTSTATUS 1753 | AtmelSetFeature( 1754 | IN PATMEL_CONTEXT DevContext, 1755 | IN WDFREQUEST Request, 1756 | OUT BOOLEAN* CompleteRequest 1757 | ) 1758 | { 1759 | NTSTATUS status = STATUS_SUCCESS; 1760 | WDF_REQUEST_PARAMETERS params; 1761 | PHID_XFER_PACKET transferPacket = NULL; 1762 | AtmelFeatureReport* pReport = NULL; 1763 | 1764 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1765 | "AtmelSetFeature Entry\n"); 1766 | 1767 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1768 | WdfRequestGetParameters(Request, ¶ms); 1769 | 1770 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1771 | { 1772 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1773 | "AtmelSetFeature Xfer packet too small\n"); 1774 | 1775 | status = STATUS_BUFFER_TOO_SMALL; 1776 | } 1777 | else 1778 | { 1779 | 1780 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1781 | 1782 | if (transferPacket == NULL) 1783 | { 1784 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1785 | "AtmelWriteReport No xfer packet\n"); 1786 | 1787 | status = STATUS_INVALID_DEVICE_REQUEST; 1788 | } 1789 | else 1790 | { 1791 | // 1792 | // switch on the report id 1793 | // 1794 | 1795 | switch (transferPacket->reportId) 1796 | { 1797 | case REPORTID_FEATURE: 1798 | 1799 | if (transferPacket->reportBufferLen == sizeof(AtmelFeatureReport)) 1800 | { 1801 | pReport = (AtmelFeatureReport*)transferPacket->reportBuffer; 1802 | 1803 | DevContext->DeviceMode = pReport->DeviceMode; 1804 | 1805 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1806 | "AtmelSetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1807 | } 1808 | else 1809 | { 1810 | status = STATUS_INVALID_PARAMETER; 1811 | 1812 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1813 | "AtmelSetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(AtmelFeatureReport) (%d)\n", 1814 | transferPacket->reportBufferLen, 1815 | sizeof(AtmelFeatureReport)); 1816 | } 1817 | 1818 | break; 1819 | 1820 | default: 1821 | 1822 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1823 | "AtmelSetFeature Unhandled report type %d\n", transferPacket->reportId); 1824 | 1825 | status = STATUS_INVALID_PARAMETER; 1826 | 1827 | break; 1828 | } 1829 | } 1830 | } 1831 | 1832 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1833 | "AtmelSetFeature Exit = 0x%x\n", status); 1834 | 1835 | return status; 1836 | } 1837 | 1838 | NTSTATUS 1839 | AtmelGetFeature( 1840 | IN PATMEL_CONTEXT DevContext, 1841 | IN WDFREQUEST Request, 1842 | OUT BOOLEAN* CompleteRequest 1843 | ) 1844 | { 1845 | NTSTATUS status = STATUS_SUCCESS; 1846 | WDF_REQUEST_PARAMETERS params; 1847 | PHID_XFER_PACKET transferPacket = NULL; 1848 | 1849 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1850 | "AtmelGetFeature Entry\n"); 1851 | 1852 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1853 | WdfRequestGetParameters(Request, ¶ms); 1854 | 1855 | if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) 1856 | { 1857 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1858 | "AtmelGetFeature Xfer packet too small\n"); 1859 | 1860 | status = STATUS_BUFFER_TOO_SMALL; 1861 | } 1862 | else 1863 | { 1864 | 1865 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1866 | 1867 | if (transferPacket == NULL) 1868 | { 1869 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1870 | "AtmelGetFeature No xfer packet\n"); 1871 | 1872 | status = STATUS_INVALID_DEVICE_REQUEST; 1873 | } 1874 | else 1875 | { 1876 | // 1877 | // switch on the report id 1878 | // 1879 | 1880 | switch (transferPacket->reportId) 1881 | { 1882 | case REPORTID_MTOUCH: 1883 | { 1884 | 1885 | AtmelMaxCountReport* pReport = NULL; 1886 | 1887 | if (transferPacket->reportBufferLen == sizeof(AtmelMaxCountReport)) 1888 | { 1889 | pReport = (AtmelMaxCountReport*)transferPacket->reportBuffer; 1890 | 1891 | pReport->MaximumCount = MULTI_MAX_COUNT; 1892 | 1893 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1894 | "AtmelGetFeature MaximumCount = 0x%x\n", MULTI_MAX_COUNT); 1895 | } 1896 | else 1897 | { 1898 | status = STATUS_INVALID_PARAMETER; 1899 | 1900 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1901 | "AtmelGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(AtmelMaxCountReport) (%d)\n", 1902 | transferPacket->reportBufferLen, 1903 | sizeof(AtmelMaxCountReport)); 1904 | } 1905 | 1906 | break; 1907 | } 1908 | 1909 | case REPORTID_FEATURE: 1910 | { 1911 | 1912 | AtmelFeatureReport* pReport = NULL; 1913 | 1914 | if (transferPacket->reportBufferLen == sizeof(AtmelFeatureReport)) 1915 | { 1916 | pReport = (AtmelFeatureReport*)transferPacket->reportBuffer; 1917 | 1918 | pReport->DeviceMode = DevContext->DeviceMode; 1919 | 1920 | pReport->DeviceIdentifier = 0; 1921 | 1922 | AtmelPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1923 | "AtmelGetFeature DeviceMode = 0x%x\n", DevContext->DeviceMode); 1924 | } 1925 | else 1926 | { 1927 | status = STATUS_INVALID_PARAMETER; 1928 | 1929 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1930 | "AtmelGetFeature Error transferPacket->reportBufferLen (%d) is different from sizeof(AtmelFeatureReport) (%d)\n", 1931 | transferPacket->reportBufferLen, 1932 | sizeof(AtmelFeatureReport)); 1933 | } 1934 | 1935 | break; 1936 | } 1937 | 1938 | default: 1939 | 1940 | AtmelPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1941 | "AtmelGetFeature Unhandled report type %d\n", transferPacket->reportId); 1942 | 1943 | status = STATUS_INVALID_PARAMETER; 1944 | 1945 | break; 1946 | } 1947 | } 1948 | } 1949 | 1950 | AtmelPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1951 | "AtmelGetFeature Exit = 0x%x\n", status); 1952 | 1953 | return status; 1954 | } 1955 | 1956 | PCHAR 1957 | DbgHidInternalIoctlString( 1958 | IN ULONG IoControlCode 1959 | ) 1960 | { 1961 | switch (IoControlCode) 1962 | { 1963 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 1964 | return "IOCTL_HID_GET_DEVICE_DESCRIPTOR"; 1965 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 1966 | return "IOCTL_HID_GET_REPORT_DESCRIPTOR"; 1967 | case IOCTL_HID_READ_REPORT: 1968 | return "IOCTL_HID_READ_REPORT"; 1969 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 1970 | return "IOCTL_HID_GET_DEVICE_ATTRIBUTES"; 1971 | case IOCTL_HID_WRITE_REPORT: 1972 | return "IOCTL_HID_WRITE_REPORT"; 1973 | case IOCTL_HID_SET_FEATURE: 1974 | return "IOCTL_HID_SET_FEATURE"; 1975 | case IOCTL_HID_GET_FEATURE: 1976 | return "IOCTL_HID_GET_FEATURE"; 1977 | case IOCTL_HID_GET_STRING: 1978 | return "IOCTL_HID_GET_STRING"; 1979 | case IOCTL_HID_ACTIVATE_DEVICE: 1980 | return "IOCTL_HID_ACTIVATE_DEVICE"; 1981 | case IOCTL_HID_DEACTIVATE_DEVICE: 1982 | return "IOCTL_HID_DEACTIVATE_DEVICE"; 1983 | case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: 1984 | return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST"; 1985 | case IOCTL_HID_SET_OUTPUT_REPORT: 1986 | return "IOCTL_HID_SET_OUTPUT_REPORT"; 1987 | case IOCTL_HID_GET_INPUT_REPORT: 1988 | return "IOCTL_HID_GET_INPUT_REPORT"; 1989 | default: 1990 | return "Unknown IOCTL"; 1991 | } 1992 | } --------------------------------------------------------------------------------