master 29d277880f16 cached
112 files
557.0 KB
179.2k tokens
230 symbols
1 requests
Download .txt
Showing preview only (590K chars total). Download the full file or copy to clipboard to get everything.
Repository: imbushuo/mac-precision-touchpad
Branch: master
Commit: 29d277880f16
Files: 112
Total size: 557.0 KB

Directory structure:
gitextract_kok6b9fh/

├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       └── github-issue-sync.yml
├── .gitignore
├── AmtPtpDevice.Settings.sln
├── AmtPtpDriver.sln
├── LICENSE-GPL.md
├── LICENSE-MIT.md
├── LICENSE.md
├── README.md
├── es/
│   └── New-CabinetFile.ps1
└── src/
    ├── AmtPtpDevice.Settings/
    │   ├── AmtPtpDevice.Settings.csproj
    │   ├── App.xaml
    │   ├── App.xaml.cs
    │   ├── Comm/
    │   │   └── UsbHidDeviceAccessSubscription.cs
    │   ├── DataObjects/
    │   │   ├── Mt2BatteryStatusReport.cs
    │   │   └── PtpUserModeConfReport.cs
    │   ├── MainPage.xaml
    │   ├── MainPage.xaml.cs
    │   ├── Package.appxmanifest
    │   └── Properties/
    │       ├── AssemblyInfo.cs
    │       └── Default.rd.xml
    ├── AmtPtpDeviceSpiKm/
    │   ├── AmtPtpDeviceSpiKm.vcxproj
    │   ├── AmtPtpDeviceSpiKm.vcxproj.filters
    │   ├── AppleDefinition.h
    │   ├── Device.c
    │   ├── Device.h
    │   ├── Driver.c
    │   ├── Driver.h
    │   ├── HID/
    │   │   ├── SpiTrackpadSeries1.h
    │   │   ├── SpiTrackpadSeries2.h
    │   │   └── SpiTrackpadSeries3.h
    │   ├── Hid.c
    │   ├── Hid.h
    │   ├── HidCommon.h
    │   ├── Input.c
    │   ├── Input.h
    │   ├── Public.h
    │   ├── Queue.c
    │   ├── Queue.h
    │   └── Trace.h
    ├── AmtPtpDeviceUniversalPkg/
    │   ├── AmtPtpDevice.inf
    │   ├── AmtPtpDeviceUniversalPkg.vcxproj
    │   └── AmtPtpDeviceUniversalPkg.vcxproj.filters
    ├── AmtPtpDeviceUsbKm/
    │   ├── AmtPtpDeviceUsbKm.vcxproj
    │   ├── AmtPtpDeviceUsbKm.vcxproj.filters
    │   ├── DebugUtils.c
    │   ├── Device.c
    │   ├── Device.h
    │   ├── Driver.c
    │   ├── Driver.h
    │   ├── Hid.c
    │   ├── Interrupt.c
    │   ├── Public.h
    │   ├── Queue.c
    │   ├── Queue.h
    │   ├── Resource.rc
    │   ├── Trace.h
    │   ├── include/
    │   │   ├── AppleDefinition.h
    │   │   ├── Hid.h
    │   │   ├── hid/
    │   │   │   └── HidCommon.h
    │   │   └── metadata/
    │   │       └── WellspringT2.h
    │   └── resource.h
    ├── AmtPtpDeviceUsbUm/
    │   ├── AmtPtpDevice.wprp
    │   ├── Device.c
    │   ├── Driver.c
    │   ├── Hid.c
    │   ├── InputInterrupt.c
    │   ├── MagicTrackpad2PtpDevice.vcxproj
    │   ├── MagicTrackpad2PtpDevice.vcxproj.filters
    │   ├── Queue.c
    │   ├── Resource.rc
    │   └── include/
    │       ├── AppleDefinition.h
    │       ├── Device.h
    │       ├── DeviceFamily/
    │       │   ├── Wellspring3.h
    │       │   ├── Wellspring5.h
    │       │   ├── Wellspring6.h
    │       │   ├── Wellspring7A.h
    │       │   ├── Wellspring8.h
    │       │   └── WellspringMt2.h
    │       ├── Driver.h
    │       ├── Hid.h
    │       ├── HidCommon.h
    │       ├── ModernTrace.h
    │       ├── Queue.h
    │       ├── StaticHidRegistry.h
    │       ├── Trace.h
    │       └── resource.h
    └── AmtPtpHidFilter/
        ├── AmtPtpHidFilter.inf
        ├── AmtPtpHidFilter.vcxproj
        ├── AmtPtpHidFilter.vcxproj.filters
        ├── Detour.c
        ├── Device.c
        ├── Diagnostics.c
        ├── Driver.c
        ├── Hid.c
        ├── Input.c
        ├── Queue.c
        └── include/
            ├── Device.h
            ├── Diagnostics.h
            ├── Driver.h
            ├── Hac.h
            ├── HidCommon.h
            ├── HidDevice.h
            ├── HidMiniport.h
            ├── Input.h
            ├── Metadata/
            │   ├── MagicTrackpad2.h
            │   ├── StaticHidRegistry.h
            │   └── WindowsHID.h
            ├── Queue.h
            └── Trace.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

*.c linguist-language=C
*.h linguist-language=C

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report for driver defects or malfunctions
title: ''
labels: bug
assignees: ''

---

**Pre-report checks**

- [ ] Have you checked (use search) [Azure DevOps Board](https://ligstd.visualstudio.com/Apple%20PTP%20Trackpad/_workitems/recentlyupdated) and Github issues for known bugs and plans?

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

**Expected behavior**
A clear and concise description of what you expected to happen.

**Traces**
If applicable, add WPP traces to help explain your problem.

**Environment**
Add your device model, driver type (USB or SPI) and OS version here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''

---

**Pre-report checks**
- [ ] Have you checked (use search) [Azure DevOps Board](https://ligstd.visualstudio.com/Apple%20PTP%20Trackpad/_workitems/recentlyupdated) and Github issues for known bugs and plans?

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/workflows/github-issue-sync.yml
================================================
# Synchronizes Github issue to Azure DevOps Board

name: EngSys-ProjectManagement-GithubIssueOnewaySync

on:
  issues:
    types:
      [opened, edited, deleted, closed, reopened, labeled, unlabeled, assigned]

jobs:
  alert:
    runs-on: ubuntu-latest
    steps:
      - uses: danhellem/github-actions-issue-to-work-item@master
        env:
          ado_token: "${{ secrets.ADO_PERSONAL_ACCESS_TOKEN }}"
          github_token: "${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}"
          ado_organization: "ligstd"
          ado_project: "Apple PTP Trackpad"
          ado_area_path: "Apple PTP Trackpad"
          ado_iteration_path: "Apple PTP Trackpad\\Github Triage"
          ado_wit: "User Story"
          ado_new_state: "New"
          ado_active_state: "Active"
          ado_close_state: "Closed"
          ado_bypassrules: true
          log_level: 100


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
[Xx]64/
[Xx]86/
[Bb]uild/
bld/
[Bb]in/
[Oo]bj/
intermediate/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# DNX
project.lock.json
artifacts/

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml

# TODO: Un-comment the next line if you do not want to checkin
# your web deploy settings because they may include unencrypted
# passwords
#*.pubxml
*.publishproj

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directory
AppPackages/
BundleArtifacts/

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# LightSwitch generated files
GeneratedArtifacts/
ModelManifest.xml

# Paket dependency manager
.paket/paket.exe

# FAKE - F# Make
.fake/
/external


================================================
FILE: AmtPtpDevice.Settings.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{12BD4199-3AFB-4418-ACFB-873717B99C8F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmtPtpDevice.Settings", "src\AmtPtpDevice.Settings\AmtPtpDevice.Settings.csproj", "{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|ARM = Debug|ARM
		Debug|x64 = Debug|x64
		Debug|x86 = Debug|x86
		Release|ARM = Release|ARM
		Release|x64 = Release|x64
		Release|x86 = Release|x86
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|ARM.ActiveCfg = Debug|ARM
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|ARM.Build.0 = Debug|ARM
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|ARM.Deploy.0 = Debug|ARM
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|x64.ActiveCfg = Debug|x64
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|x64.Build.0 = Debug|x64
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|x64.Deploy.0 = Debug|x64
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|x86.ActiveCfg = Debug|x86
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|x86.Build.0 = Debug|x86
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Debug|x86.Deploy.0 = Debug|x86
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|ARM.ActiveCfg = Release|ARM
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|ARM.Build.0 = Release|ARM
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|ARM.Deploy.0 = Release|ARM
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|x64.ActiveCfg = Release|x64
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|x64.Build.0 = Release|x64
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|x64.Deploy.0 = Release|x64
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|x86.ActiveCfg = Release|x86
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|x86.Build.0 = Release|x86
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}.Release|x86.Deploy.0 = Release|x86
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(NestedProjects) = preSolution
		{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F} = {12BD4199-3AFB-4418-ACFB-873717B99C8F}
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {5FFBB604-8825-4E20-B999-77FF3E00602B}
	EndGlobalSection
EndGlobal


================================================
FILE: AmtPtpDriver.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29102.190
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2557B86E-6ED8-495A-B9A5-BF80CD5C4DAC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "contrib", "contrib", "{1C0E2F63-A3D6-4B44-BDC7-22F6E31EA9F2}"
	ProjectSection(SolutionItems) = preProject
		App Interface.md = App Interface.md
		LICENSE-GPL.md = LICENSE-GPL.md
		LICENSE-MIT.md = LICENSE-MIT.md
		LICENSE.md = LICENSE.md
		README.md = README.md
	EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmtPtpDeviceUsbUm", "src\AmtPtpDeviceUsbUm\MagicTrackpad2PtpDevice.vcxproj", "{87EFA31B-25EB-4944-A30A-300171BFFF57}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmtPtpDeviceSpiKm", "src\AmtPtpDeviceSpiKm\AmtPtpDeviceSpiKm.vcxproj", "{FC08B706-5661-47FA-A840-053B06125750}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmtPtpDeviceUsbKm", "src\AmtPtpDeviceUsbKm\AmtPtpDeviceUsbKm.vcxproj", "{AB3E45E7-C524-47C1-9677-728BA2A19344}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmtPtpDeviceUniversalPkg", "src\AmtPtpDeviceUniversalPkg\AmtPtpDeviceUniversalPkg.vcxproj", "{7AB0A246-AA1C-433B-9E16-88956C51A565}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmtPtpHidFilter", "src\AmtPtpHidFilter\AmtPtpHidFilter.vcxproj", "{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|ARM64 = Debug|ARM64
		Debug|x64 = Debug|x64
		Release|ARM64 = Release|ARM64
		Release|x64 = Release|x64
		ReleaseSigned|ARM64 = ReleaseSigned|ARM64
		ReleaseSigned|x64 = ReleaseSigned|x64
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|ARM64.Build.0 = Debug|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|ARM64.Deploy.0 = Debug|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|x64.ActiveCfg = Debug|x64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|x64.Build.0 = Debug|x64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|x64.Deploy.0 = Debug|x64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|ARM64.ActiveCfg = Release|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|ARM64.Build.0 = Release|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|ARM64.Deploy.0 = Release|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|x64.ActiveCfg = Release|x64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|x64.Build.0 = Release|x64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|x64.Deploy.0 = Release|x64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|ARM64.Deploy.0 = ReleaseSigned|ARM64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64
		{87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|x64.Deploy.0 = ReleaseSigned|x64
		{FC08B706-5661-47FA-A840-053B06125750}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.Debug|ARM64.Build.0 = Debug|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.Debug|ARM64.Deploy.0 = Debug|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.Debug|x64.ActiveCfg = Debug|x64
		{FC08B706-5661-47FA-A840-053B06125750}.Debug|x64.Build.0 = Debug|x64
		{FC08B706-5661-47FA-A840-053B06125750}.Debug|x64.Deploy.0 = Debug|x64
		{FC08B706-5661-47FA-A840-053B06125750}.Release|ARM64.ActiveCfg = Release|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.Release|ARM64.Build.0 = Release|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.Release|ARM64.Deploy.0 = Release|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.Release|x64.ActiveCfg = Release|x64
		{FC08B706-5661-47FA-A840-053B06125750}.Release|x64.Build.0 = Release|x64
		{FC08B706-5661-47FA-A840-053B06125750}.Release|x64.Deploy.0 = Release|x64
		{FC08B706-5661-47FA-A840-053B06125750}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.ReleaseSigned|ARM64.Deploy.0 = ReleaseSigned|ARM64
		{FC08B706-5661-47FA-A840-053B06125750}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64
		{FC08B706-5661-47FA-A840-053B06125750}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64
		{FC08B706-5661-47FA-A840-053B06125750}.ReleaseSigned|x64.Deploy.0 = ReleaseSigned|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Debug|ARM64.Build.0 = Debug|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Debug|ARM64.Deploy.0 = Debug|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Debug|x64.ActiveCfg = Debug|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Debug|x64.Build.0 = Debug|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Debug|x64.Deploy.0 = Debug|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Release|ARM64.ActiveCfg = Release|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Release|ARM64.Build.0 = Release|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Release|ARM64.Deploy.0 = Release|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Release|x64.ActiveCfg = Release|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Release|x64.Build.0 = Release|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.Release|x64.Deploy.0 = Release|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.ReleaseSigned|ARM64.Deploy.0 = ReleaseSigned|ARM64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64
		{AB3E45E7-C524-47C1-9677-728BA2A19344}.ReleaseSigned|x64.Deploy.0 = ReleaseSigned|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Debug|ARM64.Build.0 = Debug|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Debug|ARM64.Deploy.0 = Debug|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Debug|x64.ActiveCfg = Debug|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Debug|x64.Build.0 = Debug|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Debug|x64.Deploy.0 = Debug|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Release|ARM64.ActiveCfg = Release|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Release|ARM64.Build.0 = Release|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Release|ARM64.Deploy.0 = Release|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Release|x64.ActiveCfg = Release|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Release|x64.Build.0 = Release|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.Release|x64.Deploy.0 = Release|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.ReleaseSigned|ARM64.Deploy.0 = ReleaseSigned|ARM64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64
		{7AB0A246-AA1C-433B-9E16-88956C51A565}.ReleaseSigned|x64.Deploy.0 = ReleaseSigned|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Debug|ARM64.ActiveCfg = Debug|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Debug|ARM64.Build.0 = Debug|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Debug|ARM64.Deploy.0 = Debug|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Debug|x64.ActiveCfg = Debug|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Debug|x64.Build.0 = Debug|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Debug|x64.Deploy.0 = Debug|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Release|ARM64.ActiveCfg = Release|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Release|ARM64.Build.0 = Release|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Release|ARM64.Deploy.0 = Release|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Release|x64.ActiveCfg = Release|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Release|x64.Build.0 = Release|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.Release|x64.Deploy.0 = Release|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.ReleaseSigned|ARM64.Deploy.0 = ReleaseSigned|ARM64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}.ReleaseSigned|x64.Deploy.0 = ReleaseSigned|x64
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(NestedProjects) = preSolution
		{87EFA31B-25EB-4944-A30A-300171BFFF57} = {2557B86E-6ED8-495A-B9A5-BF80CD5C4DAC}
		{FC08B706-5661-47FA-A840-053B06125750} = {2557B86E-6ED8-495A-B9A5-BF80CD5C4DAC}
		{AB3E45E7-C524-47C1-9677-728BA2A19344} = {2557B86E-6ED8-495A-B9A5-BF80CD5C4DAC}
		{7AB0A246-AA1C-433B-9E16-88956C51A565} = {2557B86E-6ED8-495A-B9A5-BF80CD5C4DAC}
		{EE63C42B-F401-4F55-ADBB-14C16BD3B18C} = {2557B86E-6ED8-495A-B9A5-BF80CD5C4DAC}
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {E8D62F4C-ADCF-4882-AA6B-CA7D97CB284B}
	EndGlobalSection
EndGlobal


================================================
FILE: LICENSE-GPL.md
================================================
The GNU General Public License, Version 2, June 1991 (GPLv2)
============================================================

> Copyright (C) 1989, 1991 Free Software Foundation, Inc.
> 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

Everyone is permitted to copy and distribute verbatim copies of this license
document, but changing it is not allowed.


Preamble
--------

The licenses for most software are designed to take away your freedom to share
and change it. By contrast, the GNU General Public License is intended to
guarantee your freedom to share and change free software--to make sure the
software is free for all its users. This General Public License applies to most
of the Free Software Foundation's software and to any other program whose
authors commit to using it. (Some other Free Software Foundation software is
covered by the GNU Lesser General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom to
distribute copies of free software (and charge for this service if you wish),
that you receive source code or can get it if you want it, that you can change
the software or use pieces of it in new free programs; and that you know you can
do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny
you these rights or to ask you to surrender the rights. These restrictions
translate to certain responsibilities for you if you distribute copies of the
software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a
fee, you must give the recipients all the rights that you have. You must make
sure that they, too, receive or can get the source code. And you must show them
these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer
you this license which gives you legal permission to copy, distribute and/or
modify the software.

Also, for each author's protection and ours, we want to make certain that
everyone understands that there is no warranty for this free software. If the
software is modified by someone else and passed on, we want its recipients to
know that what they have is not the original, so that any problems introduced by
others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish
to avoid the danger that redistributors of a free program will individually
obtain patent licenses, in effect making the program proprietary. To prevent
this, we have made it clear that any patent must be licensed for everyone's free
use or not licensed at all.

The precise terms and conditions for copying, distribution and modification
follow.


Terms And Conditions For Copying, Distribution And Modification
---------------------------------------------------------------

**0.** This License applies to any program or other work which contains a notice
placed by the copyright holder saying it may be distributed under the terms of
this General Public License. The "Program", below, refers to any such program or
work, and a "work based on the Program" means either the Program or any
derivative work under copyright law: that is to say, a work containing the
Program or a portion of it, either verbatim or with modifications and/or
translated into another language. (Hereinafter, translation is included without
limitation in the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not covered by
this License; they are outside its scope. The act of running the Program is not
restricted, and the output from the Program is covered only if its contents
constitute a work based on the Program (independent of having been made by
running the Program). Whether that is true depends on what the Program does.

**1.** You may copy and distribute verbatim copies of the Program's source code
as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this License
and to the absence of any warranty; and give any other recipients of the Program
a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at
your option offer warranty protection in exchange for a fee.

**2.** You may modify your copy or copies of the Program or any portion of it,
thus forming a work based on the Program, and copy and distribute such
modifications or work under the terms of Section 1 above, provided that you also
meet all of these conditions:

*   **a)** You must cause the modified files to carry prominent notices stating
    that you changed the files and the date of any change.

*   **b)** You must cause any work that you distribute or publish, that in whole
    or in part contains or is derived from the Program or any part thereof, to
    be licensed as a whole at no charge to all third parties under the terms of
    this License.

*   **c)** If the modified program normally reads commands interactively when
    run, you must cause it, when started running for such interactive use in the
    most ordinary way, to print or display an announcement including an
    appropriate copyright notice and a notice that there is no warranty (or
    else, saying that you provide a warranty) and that users may redistribute
    the program under these conditions, and telling the user how to view a copy
    of this License. (Exception: if the Program itself is interactive but does
    not normally print such an announcement, your work based on the Program is
    not required to print an announcement.)

These requirements apply to the modified work as a whole. If identifiable
sections of that work are not derived from the Program, and can be reasonably
considered independent and separate works in themselves, then this License, and
its terms, do not apply to those sections when you distribute them as separate
works. But when you distribute the same sections as part of a whole which is a
work based on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the entire whole,
and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your
rights to work written entirely by you; rather, the intent is to exercise the
right to control the distribution of derivative or collective works based on the
Program.

In addition, mere aggregation of another work not based on the Program with the
Program (or with a work based on the Program) on a volume of a storage or
distribution medium does not bring the other work under the scope of this
License.

**3.** You may copy and distribute the Program (or a work based on it, under
Section 2) in object code or executable form under the terms of Sections 1 and 2
above provided that you also do one of the following:

*   **a)** Accompany it with the complete corresponding machine-readable source
    code, which must be distributed under the terms of Sections 1 and 2 above on
    a medium customarily used for software interchange; or,

*   **b)** Accompany it with a written offer, valid for at least three years, to
    give any third party, for a charge no more than your cost of physically
    performing source distribution, a complete machine-readable copy of the
    corresponding source code, to be distributed under the terms of Sections 1
    and 2 above on a medium customarily used for software interchange; or,

*   **c)** Accompany it with the information you received as to the offer to
    distribute corresponding source code. (This alternative is allowed only for
    noncommercial distribution and only if you received the program in object
    code or executable form with such an offer, in accord with Subsection b
    above.)

The source code for a work means the preferred form of the work for making
modifications to it. For an executable work, complete source code means all the
source code for all modules it contains, plus any associated interface
definition files, plus the scripts used to control compilation and installation
of the executable. However, as a special exception, the source code distributed
need not include anything that is normally distributed (in either source or
binary form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component itself
accompanies the executable.

If distribution of executable or object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the source code
from the same place counts as distribution of the source code, even though third
parties are not compelled to copy the source along with the object code.

**4.** You may not copy, modify, sublicense, or distribute the Program except as
expressly provided under this License. Any attempt otherwise to copy, modify,
sublicense or distribute the Program is void, and will automatically terminate
your rights under this License. However, parties who have received copies, or
rights, from you under this License will not have their licenses terminated so
long as such parties remain in full compliance.

**5.** You are not required to accept this License, since you have not signed
it. However, nothing else grants you permission to modify or distribute the
Program or its derivative works. These actions are prohibited by law if you do
not accept this License. Therefore, by modifying or distributing the Program (or
any work based on the Program), you indicate your acceptance of this License to
do so, and all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

**6.** Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these terms and
conditions. You may not impose any further restrictions on the recipients'
exercise of the rights granted herein. You are not responsible for enforcing
compliance by third parties to this License.

**7.** If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues), conditions
are imposed on you (whether by court order, agreement or otherwise) that
contradict the conditions of this License, they do not excuse you from the
conditions of this License. If you cannot distribute so as to satisfy
simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Program at all.
For example, if a patent license would not permit royalty-free redistribution of
the Program by all those who receive copies directly or indirectly through you,
then the only way you could satisfy both it and this License would be to refrain
entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply and the
section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or
other property right claims or to contest validity of any such claims; this
section has the sole purpose of protecting the integrity of the free software
distribution system, which is implemented by public license practices. Many
people have made generous contributions to the wide range of software
distributed through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing to
distribute software through any other system and a licensee cannot impose that
choice.

This section is intended to make thoroughly clear what is believed to be a
consequence of the rest of this License.

**8.** If the distribution and/or use of the Program is restricted in certain
countries either by patents or by copyrighted interfaces, the original copyright
holder who places the Program under this License may add an explicit
geographical distribution limitation excluding those countries, so that
distribution is permitted only in or among countries not thus excluded. In such
case, this License incorporates the limitation as if written in the body of this
License.

**9.** The Free Software Foundation may publish revised and/or new versions of
the General Public License from time to time. Such new versions will be similar
in spirit to the present version, but may differ in detail to address new
problems or concerns.

Each version is given a distinguishing version number. If the Program specifies
a version number of this License which applies to it and "any later version",
you have the option of following the terms and conditions either of that version
or of any later version published by the Free Software Foundation. If the
Program does not specify a version number of this License, you may choose any
version ever published by the Free Software Foundation.

**10.** If you wish to incorporate parts of the Program into other free programs
whose distribution conditions are different, write to the author to ask for
permission. For software which is copyrighted by the Free Software Foundation,
write to the Free Software Foundation; we sometimes make exceptions for this.
Our decision will be guided by the two goals of preserving the free status of
all derivatives of our free software and of promoting the sharing and reuse of
software generally.


No Warranty
-----------

**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.


================================================
FILE: LICENSE-MIT.md
================================================
The MIT License (MIT)
=====================

Copyright  `2018` `Bingxing Wang`

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the Software), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: LICENSE.md
================================================
Dual-licensed project notice
=====================

Copyright 2018-2019, Bingxing Wang and other project contributors.

- The USB PTP project, `AmtPtpDeviceUsbUm` and `AmtPtpDeviceUsbKm` are licensed under [GPLv2](LICENSE-GPL.md).
- The SPI PTP project, `AmtPtpDeviceSpiKm` is licensed unser [MIT](LICENSE-MIT.md).


================================================
FILE: README.md
================================================
# Windows Precision Touchpad Implementation for Apple MacBook family/Magic Trackpad 2

[![Build Status](https://ligstd.visualstudio.com/_apis/public/build/definitions/7694e0d0-94e3-4fd2-b39a-ecd261e1ba2e/22/badge)](https://ligstd.visualstudio.com/Apple%20PTP%20Trackpad/_build?definitionId=22)

This project implements Windows Precision Touchpad Protocol for Apple MacBook family/Magic Trackpad 2 on Windows 10. Both USB (traditional and T2), SPI and Bluetooth trackpads are supported.

## Donation?

A few people asked me why I removed donation. My current financial situation doesn't require me to accept donation for the budget of future development. If you are considering donation, please consider other meaningful projects and foundations, such as [Electronic Frontier Foundation](https://www.eff.org/).

## Official Driver?

Bootcamp 6.1.5 offers official driver for T2-based model and Magic Trackpad 2. You can also consider using the official driver if you have such Mac. If you have an older model (e.g. MacBooks before 2018/2019), this is the only implementation for these models (yet). 

## Future Plans and feature tracking

Use the [Azure DevOps Board](https://ligstd.visualstudio.com/Apple%20PTP%20Trackpad/_workitems/) to track feature and device support plans. Bug reports should go to Github issues.

## See it in action (YouTube video)

[![Watch the video](https://img.youtube.com/vi/-GWlfw7omdo/hqdefault.jpg)](https://youtu.be/-GWlfw7omdo)

## Converged Installation Guide

**IMPORTANT:** Given changes in Microsoft driver code signing policy, and the compliance need of EV certificate, CI auto builds beyond 2021/01/06 04:00AM EST will not be automatically signed with normal code signing certificate. These builds are still supposed via TestSigning, but not recommended for normal users. Proper WHQL and EV dual-signed packages will be released manually, which can be downloaded from the release page.

0. Make sure you uninstalled `Trackpad++` completely if you have previously does so
1. Go to the release tab in Github and download the newest version for your architecture
2. Right click `AmtPtpDevice.inf` and install it
3. If you have a Magic Trackpad 2 and want to use it in Bluetooth mode: manaully pair it in PC Settings.

**Note: it is unnecessary to enable test signing, or install the certificate manually. Doing so may cause problems in installation. See [this issue](https://github.com/imbushuo/mac-precision-touchpad/issues/228#issuecomment-538689587) for detailed explanation.**

## Also Uninstallation (extremely important for reinstallation `Trackpad++` and such)

See also [here](https://magicutilities.net/magic-trackpad/help/mac-precision-touchpad-driver-installed).

1. Go to device manager
2. Find the "Apple Precision Touch Device", "Apple Multi-touch Trackpad HID filter" and "Apple Multi-touch Auxiliary Services"
3. Right click "remove the device" and also check "uninstall driver"
4. Rescan devices

## Installation with Chocolatey

The drivers are available as a [Chocolatey package](https://chocolatey.org/packages/mac-precision-touchpad/). To install using [Chocolatey](https://chocolatey.org) run:

```
choco install mac-precision-touchpad
```

## For developers

- SPI/T2 version is kernel-mode driver, using KMDF Framework v1.23. Bluetooth driver uses KMDF Framework 1.15. Windows 10 Driver Development Kit Version 2004 or higher is required for development and testing.
- USB version is a user-mode driver, using UMDF Framework v2.15. Windows 10 Driver Development Kit Version 2004 or higher is required for development and testing.
- `ReleaseSigned` configuration is reserved for production build only, and it will be rendered as unsigned if you attempt to build using that configuration. (Historically it's signed, but due to EV certificate's requirements, the process has changed.)

## Device support

There is a bring-up issue for certain MacBook Pro and MacBook Air. I am looking into it. If you have such device with Windows installed, please contact me so I can look into the issue remotely (as I don't have many devices).

- [x] Non-Retina MacBook 
- [x] Some non-Retina MacBook Pro (2011 and 2012)
- [x] MacBook Pro with Retina Display (MacBookPro 10,1, MacBookPro10,2 & MacBookPro11,1)
- [x] All recent MacBook Air (Please report if your model is not supported)
- [x] MacBook Pro with Retina Display (2013, 2014, 2015, 13-inch & 15-inch)
- [x] New MacBook (12-inch)
- [x] MacBook Pro 2015, 2016, 2017 (a few SPI devices are in work-in-progress state)
- [x] T2-based devices: MacBook Air 2018, MacBook Pro 2017/2018/2019/2020: Use default fallback, experience might not be optimal. Open a issue if you encountered dead touch regions.
- [x] Magic Trackpad 2 & 3 (USB)
- [x] Magic Trackpad 2 & 3 (Bluetooth connection)

## Roadmap

- [x] Touchpad Device Power Management
- [x] Touchpad Protocol Stack Implementation
- [x] Touchpad Raw Input Output (in Driver Trace)
- [x] HID Protocol Implementation (PTP Touch)
- [x] HID Protocol Implementation (Configuration)
- [x] Device Test (Magic Trackpad 2)
- [x] Refine input experience (tip switch detection and pressure)
- [x] Refine input experience (gesture experience)
- [x] More Models
- [x] SPI
- [x] KM Driver cross-cert
- [x] Bluetooth
- [ ] Defuzz
- [ ] Input sensitivity configuration

## Acknowledgements

**UPDATE 2021/05**: She got an M1 Mac now.

People familiar with me know that I don't use Apple MacBook (so development work of this driver occurs on a Surface Pro 4). People probably think it doesn't make sense that I started this project. The motivation behind this project origin from complaints from my girlfriend. Hearing about frequent complains about Dell XPS 13's touchpad (though it passed Precision Touchpad certification), I decided to start this project, so by the time she switches to MacBook Pro, she will have excellent touchpad experience out-of-box, even on Windows. This driver is made for you, but also for everyone.

I would like to thank projects like [magictrackpad2-dkms](https://github.com/robbi5/magictrackpad2-dkms) and [macbook12-spi-driver](https://github.com/cb22/macbook12-spi-driver) that inspire me. I would also like to thank my friends for providing me immense help on devices and testing.
 
## License

- USB driver is licensed under [GPLv2](LICENSE-GPL.md).
- SPI driver is licensed under [MIT](LICENSE-MIT.md).



================================================
FILE: es/New-CabinetFile.ps1
================================================
 <#
.SYNOPSIS
    Creates a new cabinet .CAB file on disk.

.DESCRIPTION
    This cmdlet creates a new cabinet .CAB file using MAKECAB.EXE and adds
    all the files specified to the cabinet file itself.

.PARAMETER Name
    The output file name of the cabinet .CAB file, such as MyNewCabinet.cab.
    This should not be the entire file path, only the target file name.

.PARAMETER Fil
    One or more file references that are to be added to the cabinet .CAB file.
    FileInfo objects (as generated by Get-Item etc) or strings can be passed
    in via the pipeline to be added to the cabinet file.

.PARAMETER DestinationPath
    The output file path that the cabinet file will be saved in. It is also
    used for resolving any ambiguous file references, i.e. any file passed in
    via file name and not full path.

    If not specified the current working directory is used for the output file
    and attempting to resolve all ambiguous file references.

.PARAMETER NoClobber
    Will not overwrite of an existing file. By default, if a file exists in the
    specified path, New-CabinetFile overwrites the file without warning.

.EXAMPLE
    New-CabinetFile -Name MyCabinet.cab -File "File01.exe","File02.txt"
    
    This creates a new MyCabinet.cab file in the current directory and adds the File01.exe and File02.txt files to it, also from the current directory.
.EXAMPLE
    Get-ChildItem C:\CabFile\ | New-CabinetFile -Name MyCabinet.cab -DestinationPath C:\Users\UserA\Documents

    This creates a new C:\Users\UserA\Documents\MyCabinet.cab file and adds all files within the C:\CabFile\ directory into it.
#>
function New-CabinetFile {
    [CmdletBinding()]
    Param(
        [Parameter(HelpMessage="Target .CAB file name.", Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [Alias("FilePath")]
        [string] $Name,

        [Parameter(HelpMessage="Content directory to add to the .CAB.", Position=1, Mandatory=$true, ValueFromPipeline=$false)]
        [ValidateNotNullOrEmpty()]
        [string[]] $ContentDirectory,

	[Parameter(HelpMessage="Default package directory path.", Position=2, ValueFromPipelineByPropertyName=$true)]
        [AllowNull()]
        [string[]] $DestinationDir,

        [Parameter(HelpMessage="Default intput/output path.", Position=3, ValueFromPipelineByPropertyName=$true)]
        [AllowNull()]
        [string[]] $DestinationPath,

        [Parameter(HelpMessage="Do not overwrite any existing .cab file.")]
        [Switch] $NoClobber
        )

    Begin { 
    
        ## If $DestinationPath is blank, use the current directory by default
        if ($DestinationPath -eq $null) { $DestinationPath = (Get-Location).Path; }
        Write-Verbose "New-CabinetFile using default path '$DestinationPath'.";
        Write-Verbose "Creating target cabinet file '$(Join-Path $DestinationPath $Name)'.";

        ## Test the -NoClobber switch
        if ($NoClobber) {
            ## If file already exists then throw a terminating error
            if (Test-Path -Path (Join-Path $DestinationPath $Name)) { throw "Output file '$(Join-Path $DestinationPath $Name)' already exists."; }
        }

        ## Cab files require a directive file, see 'http://msdn.microsoft.com/en-us/library/bb417343.aspx#dir_file_syntax' for more info
        $ddf = ";*** MakeCAB Directive file`r`n";
        $ddf += ";`r`n";
        $ddf += ".OPTION EXPLICIT`r`n";
        $ddf += ".Set CabinetNameTemplate=$Name`r`n";
        $ddf += ".Set DiskDirectory1=$DestinationPath`r`n";
        $ddf += ".Set MaxDiskSize=0`r`n";
	$ddf += ".Set MaxDiskFileCount=0`r`n";
	$ddf += ".Set FolderFileCountThreshold=0`r`n";
	$ddf += ".Set FolderSizeThreshold=0`r`n";
	$ddf += ".Set MaxCabinetSize=0`r`n";
	$ddf += ".Set CompressionType=MSZIP`r`n";
        $ddf += ".Set Cabinet=on`r`n";
        $ddf += ".Set Compress=on`r`n";
        ## Redirect the auto-generated Setup.rpt and Setup.inf files to the temp directory
        $ddf += ".Set RptFileName=$(Join-Path $ENV:TEMP "setup.rpt")`r`n";
        $ddf += ".Set InfFileName=$(Join-Path $ENV:TEMP "setup.inf")`r`n";
	$ddf += ".Set DestinationDir=$DestinationDir`r`n";

        ## If -Verbose, echo the directive file
        if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
            foreach ($ddfLine in $ddf -split [Environment]::NewLine) {
                Write-Verbose $ddfLine;
            }
        }
    }

    Process {
        $File = Get-ChildItem -Path $ContentDirectory
   
        ## Enumerate all the files add to the cabinet directive file
        foreach ($fileToAdd in $File) {
            Write-Verbose """$($fileToAdd.FullName)""";
            $ddf += """$($fileToAdd.FullName)""`r`n";
        }     
    }

    End {
    
        $ddfFile = Join-Path $DestinationPath "$Name.ddf";
        $ddf | Out-File $ddfFile -Encoding ascii | Out-Null;

        Write-Verbose "Launching 'C:\Windows\system32\makecab.exe /f ""$ddfFile""'.";
        $makeCab = Invoke-Expression "C:\Windows\system32\makecab.exe /F ""$ddfFile""";

        ## If Verbose, echo the MakeCab response/output
        if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
            ## Recreate the output as Verbose output
            foreach ($line in $makeCab -split [environment]::NewLine) {
                if ($line.Contains("ERROR:")) { throw $line; }
                else { Write-Verbose $line; }
            }
        }

        ## Delete the temporary .ddf file
        Write-Verbose "Deleting the directive file '$ddfFile'.";
        Remove-Item $ddfFile;

        ## Return the newly created .CAB FileInfo object to the pipeline
        Get-Item (Join-Path $DestinationPath $Name);
    }
} 


# SIG # Begin signature block
# MIIiHgYJKoZIhvcNAQcCoIIiDzCCIgsCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCRCQB92A0VZQ1H
# CrjdJBO3wNCibdvKCfaDDpqy7YVEv6CCEaEwggV+MIIEZqADAgECAhBn3vQ+8Xva
# 4k/1lAYG0sCEMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM
# EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy
# dmljZXMwHhcNMDQwMTAxMDAwMDAwWhcNMjgxMjMxMjM1OTU5WjCBhTELMAkGA1UE
# BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2Fs
# Zm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9E
# TyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKP
# S38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6
# dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
# 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEn
# vGfDyi62a+pGx8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7
# tKuY2e7gUYPDCUZObT6Z+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKj
# WiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChW
# rBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl
# 8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe0
# 1a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFc
# OmpH4MN5WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwID
# AQABo4HyMIHvMB8GA1UdIwQYMBaAFKARCiM+lvEH7OKvKe+CpX/QMKS0MB0GA1Ud
# DgQWBBS7r34CPfqm8TyEjq3uOJjs2TIy1DAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
# AQH/BAUwAwEB/zARBgNVHSAECjAIMAYGBFUdIAAwQwYDVR0fBDwwOjA4oDagNIYy
# aHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5j
# cmwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v
# ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggEBAH/yVjWwbZVKTnSvOuJvAYuH0zKX
# 7fhA0ndTEdfHFi7GneZIVr6Aqfi8eNLIYxeujO0WMfofGMkOx+5IeZ/Hybm8zIgV
# 42hh0Z8dS2GB11YEY8IIaSbw8OUv38AKK6kF9AJaaonXtIRClePr93YgXjXZwM0l
# CBNMcTiOh7AzhJGZHpHxrJ4/px1ggSw2QVSg4kYGC6wbx5k2jF6hC6Se2UJGJMXF
# W4GuraCg3J82uI3CHRX6iK2BEDkfRPArn90QVAwHNLE20RT9BwI9/3JVqyfWLIFB
# cSmNQfRQVxp+ZWCvy8Uodpius6hTdovmIVJr6iHQhA5JTohT2pIu5x0IZtcwggX1
# MIIE3aADAgECAhEAzhB+CIZCWs8DPSazYRw0CzANBgkqhkiG9w0BAQsFADCBkTEL
# MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
# BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNzA1BgNVBAMT
# LkNPTU9ETyBSU0EgRXh0ZW5kZWQgVmFsaWRhdGlvbiBDb2RlIFNpZ25pbmcgQ0Ew
# HhcNMjAwOTAzMDAwMDAwWhcNMjEwOTAzMjM1OTU5WjCB+TEQMA4GA1UEBRMHMjk0
# NDU3MDETMBEGCysGAQQBgjc8AgEDEwJISzEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdh
# bml6YXRpb24xCzAJBgNVBAYTAkhLMRIwEAYDVQQHDAlIb25nIEtvbmcxGzAZBgNV
# BAkMEkt3dW4gVG9uZywgS293bG9vbjEtMCsGA1UECQwkUm0gODMgMy9GIFlhdSBM
# ZWUgQ3RyIDQ1IEhvaSBZdWVuIFJkMSEwHwYDVQQKDBhBcGVydHVyZSBTY2llbmNl
# IExpbWl0ZWQxITAfBgNVBAMMGEFwZXJ0dXJlIFNjaWVuY2UgTGltaXRlZDCCASIw
# DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANpH4ZmvIRFMLmWWKKkn187aPxTg
# aIU6w0i8KjrUGA+eowWGAJLCr5Bt3zU9Q3IlAIs+SrvCn/soOADIl90qAg7Z4X57
# GZUXtBm2LmtIRTFS1d8nTUL0GxRIJvfmv16rDGN/ZIHT7oRnZNqqvDNH0EJSSpPS
# jULt+JCaIaEPr3ugURNXtUKlAMnc/TVprsZ/uOCfGqoNSzPfBb/Xo+tubb3NgChJ
# 9vwY9NpuLyNwhTDnA4XD9HYDVWrpXSMuyMUw2tH/NevBD0uycdSeiEOL+QYafR+t
# 8INUjRkAblsNVBkwv/SrhTFSKYuTaH91QomE118/W/XJmP6srrEKLM0Im+ECAwEA
# AaOCAdwwggHYMB8GA1UdIwQYMBaAFN+P8yAM6cqmBNhbWDcqPatG3INJMB0GA1Ud
# DgQWBBRsjK5AOHjIz7lAXUG7aRZD49Ns6jAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0T
# AQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzARBglghkgBhvhCAQEEBAMCBBAw
# SQYDVR0gBEIwQDA1BgwrBgEEAbIxAQIBBgEwJTAjBggrBgEFBQcCARYXaHR0cHM6
# Ly9zZWN0aWdvLmNvbS9DUFMwBwYFZ4EMAQMwVQYDVR0fBE4wTDBKoEigRoZEaHR0
# cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRXh0ZW5kZWRWYWxpZGF0aW9u
# Q29kZVNpZ25pbmdDQS5jcmwwgYYGCCsGAQUFBwEBBHoweDBQBggrBgEFBQcwAoZE
# aHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRXh0ZW5kZWRWYWxpZGF0
# aW9uQ29kZVNpZ25pbmdDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNv
# bW9kb2NhLmNvbTAlBgNVHREEHjAcoBoGCCsGAQUFBwgDoA4wDAwKSEstMjk0NDU3
# MDANBgkqhkiG9w0BAQsFAAOCAQEAM5EqUWtJItHkyrMhjQpQ6UHr/jxpsCQoNqaE
# 96LCP0mJxEyyS/00x+FiGwGKXZBUdS+JP77A2ndP6pcIS+sNlkoLag3KshBCzkHN
# 8uLgPsHRRMExTNw5lNVHCURfQZeh94bNGPXpX8hpqrOL2rIjtQw01fo9qmsXymTU
# LCFEh2hdGDM2SLG9rZ7qVgXa+Wd4IqLJ7Xk850guyf1eeTlza3WzZAzrqxWWLq3u
# k5fHO2u34ggwBVjBpDbR7Ko7IMR/HrI/1GOVTY4OHZ3eP/jm5vpSvx3ThLegkFt0
# R6Jw0kAvcwTqsw7DrJCJRnfX8TN9ojsP54vMvwWsXNoh24Fh7jCCBiIwggQKoAMC
# AQICEG3UcusCrgQG492EP1/hReEwDQYJKoZIhvcNAQEMBQAwgYUxCzAJBgNVBAYT
# AkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZv
# cmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYDVQQDEyJDT01PRE8g
# UlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE0MTIwMzAwMDAwMFoXDTI5
# MTIwMjIzNTk1OVowgZExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1h
# bmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBM
# aW1pdGVkMTcwNQYDVQQDEy5DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24g
# Q29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
# iv29Q/A9yFUf81mK8Fq03JPRZBVKioSlLcsm+OBFOKO5AcVPEwhZ0DFUys2QYaM+
# LPJNFVzU7sNqIpdI0QZDNAmZyc8wxJ9E/Vac7szng7mBzcjaCxwSSP9vouzEdcsJ
# cM9R5buLn6q9eAZ9ldZhgfbaU8esnbMAuh7UvkBiCZmDPUXdTWWVBMz8+sdbeuIu
# DD1VNVc1SImJ8rlWpUtQGxzemJC98y7ciKnxdZuoPqIF2UG173etF8Ba9aPbTZ/R
# xLF7g7XuEJQrLnKuvu+VKZxSYsUsbSL3fUR6EF9jk2lN2X2ymrFOtVm//4X7vazs
# 4Sum4yws6Nlu219NF3jLUwIDAQABo4IBfjCCAXowHwYDVR0jBBgwFoAUu69+Aj36
# pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFN+P8yAM6cqmBNhbWDcqPatG3INJMA4G
# A1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBMGA1UdJQQMMAoGCCsG
# AQUFBwMDMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczov
# L3NlY3VyZS5jb21vZG8uY29tL0NQUzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8v
# Y3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5
# LmNybDBxBggrBgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t
# b2RvY2EuY29tL0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhho
# dHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAGZO7LcW
# d28R6Btdak7Z8otssVYoQIvAMcSZSCM9+A7ogJfvbSALHxPEhvsXNBXhjlT3wrgA
# cxXgKNnauvqCVML367/DNtAwn+WhHJTf73zo9ix4oqzPJmoVoRUx1jE0mL1TT8SE
# g6PEllw92P7W+VT/Z5Nt+D4rayyiCHxWSIEyGLJurJDB2+TeOYuG5ccYQFmk35ZH
# urJ/sfhXD4WAdDgOOlhiHv5S4+auUwmG/o+b21ZWzAewicEE8VMLbG937LIf7PZb
# QENgDxurGFS0EASO+A7py4OxevI0TmpUTOmDKumwMCUczmKODuuF5in+sUrj8q48
# kfVMob7IFw5cu0JN4xqKks0+IH7d6XWx6h90XJ5UwpQ3smHdBxZZf5aAFuCZtdJu
# sMkjBhWs0SP0M4vOdfDBhtP/4S76kE/+Rvm720+7t/7RDSsE8dLRlYUsii64hVby
# w4RSoekzsetQyKGwn+PDizqHnudV09NtNBcwDWgiC9W57XM1csPtpzfN40OuRc00
# vyjKh2LtQ6Sv+ssxyyFYYUZetsZ6ph5TKqj4XFEfOloQDyjA5HSLdMYEqvhLJigK
# MonbnSpgcWrDlk4WuWO/YZVnjEsuu7BOg+lNMeWOJyL1PCZ7RJHT1Frw03z0OL4U
# mpkOi7Fb6uSLDxGdd0KCHFw61NqriC+NVzBUMYIP0zCCD88CAQEwgacwgZExCzAJ
# BgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcT
# B1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTcwNQYDVQQDEy5D
# T01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gQ29kZSBTaWduaW5nIENBAhEA
# zhB+CIZCWs8DPSazYRw0CzANBglghkgBZQMEAgEFAKB8MBAGCisGAQQBgjcCAQwx
# AjAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM
# BgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCAjxebzHD5YPMAKQpqHpwx+76aQ
# a0jmJhb7cbUjUTbPdTANBgkqhkiG9w0BAQEFAASCAQCCAt2hgKDtfM+0OHweiT0s
# JQ92TiwNq91vsGFtzYPbPfeJrfZSp6hDYqgeYdMOSqKLnQghUlDu5Hg+cL3INDjo
# Nes0CXldNlIBv7cVBq/euacKxe4ihKomILBSPYKCS9dCsqBvGBIblfuXJ3Kz0S9Z
# IlXiNvRwhz4GNCPeJfYgNxGabG/jZkjGfjJkWIKHmxuErwFWZnASQ9s2F1/tDvBE
# T2XHjeikoNPA85X73Ivg9E6CzJe02jsZAoQqZyDCqIelxAiIHRHqqV20T868ypln
# HHLr8nbxj9vcCVRAsZMow2bEhAoIpRLkNqIeghMfi8SEIoug3bCx4bqAwLZAf+6Q
# oYINfjCCDXoGCisGAQQBgjcDAwExgg1qMIINZgYJKoZIhvcNAQcCoIINVzCCDVMC
# AQMxDzANBglghkgBZQMEAgEFADB4BgsqhkiG9w0BCRABBKBpBGcwZQIBAQYJYIZI
# AYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIIUw89LmZyq9yuRiOCvCxSfW/yKPr9iv
# djHHx7eqHD0YAhEAxV6DgaDoWwVUZz4s7WsA7xgPMjAyMTA3MTcyMDEyMzhaoIIK
# NzCCBP4wggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZIhvcNAQELBQAw
# cjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ
# d3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVk
# IElEIFRpbWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0zMTAxMDYwMDAw
# MDBaMEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4G
# A1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVNlLQMULUmEP4d
# yG+RawyW5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXeAhjzeG28ffnH
# bQk9vmp2h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPsTm0zinxdRS1L
# sVDmQTo3VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMDgzEpSlwMMYpK
# jIjF9zBa+RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8H6GHq756Wwog
# L0sJyZWnjbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4MIIBtDAOBgNV
# HQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcD
# CDBBBgNVHSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIBFhtodHRwOi8v
# d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+Ka7S5GGlsqIl
# ssgXNW4wHQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEGA1UdHwRqMGgw
# MqAwoC6GLGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtdHMu
# Y3JsMDKgMKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVk
# LXRzLmNybDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
# cC5kaWdpY2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNlcnRzLmRpZ2lj
# ZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBpbmdDQS5jcnQw
# DQYJKoZIhvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJRdAojR6OrktIl
# xHBZvhSg5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo9VFKeHk2eie3
# 8+dSn5On7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPtkMyNoRdzDfTz
# ZTlwS/Oc1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ2CKadRVC9S0y
# OIHa9GCiurRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdKDXF+l7f0P4Tr
# weOjSaH6zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUxMIIEGaADAgEC
# AhAKoSXW1jIbfkHkBdo2l8IVMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVT
# MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
# b20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xNjAx
# MDcxMjAwMDBaFw0zMTAxMDcxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV
# BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0EwggEi
# MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC90DLuS82Pf92puoKZxTlUKFe2
# I0rEDgdFM1EQfdD5fU1ofue2oPSNs4jkl79jIZCYvxO8V9PD4X4I1moUADj3Lh47
# 7sym9jJZ/l9lP+Cb6+NGRwYaVX4LJ37AovWg4N4iPw7/fpX786O6Ij4YrBHk8JkD
# bTuFfAnT7l3ImgtU46gJcWvgzyIQD3XPcXJOCq3fQDpct1HhoXkUxk0kIzBdvOw8
# YGqsLwfM/fDqR9mIUF79Zm5WYScpiYRR5oLnRlD9lCosp+R1PrqYD4R/nzEU1q3V
# 8mTLex4F0IQZchfxFwbvPc3WTe8GQv2iUypPhR3EHTyvz9qsEPXdrKzpVv+TAgMB
# AAGjggHOMIIByjAdBgNVHQ4EFgQU9LbhIB3+Ka7S5GGlsqIlssgXNW4wHwYDVR0j
# BBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wEgYDVR0TAQH/BAgwBgEB/wIBADAO
# BgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgweQYIKwYBBQUHAQEE
# bTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYB
# BQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy
# ZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0
# dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5j
# cmwwUAYDVR0gBEkwRzA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0dHBz
# Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEB
# CwUAA4IBAQBxlRLpUYdWac3v3dp8qmN6s3jPBjdAhO9LhL/KzwMC/cWnww4gQiyv
# d/MrHwwhWiq3BTQdaq6Z+CeiZr8JqmDfdqQ6kw/4stHYfBli6F6CJR7Euhx7LCHi
# 1lssFDVDBGiy23UC4HLHmNY8ZOUfSBAYX4k4YU1iRiSHY4yRUiyvKYnleB/WCxSl
# gNcSR3CzddWThZN+tpJn+1Nhiaj1a5bA9FhpDXzIAbG5KHW3mWOFIoxhynmUfln8
# jA/jb7UBJrZspe6HUSHkWGCbugwtK22ixH67xCUrRwIIfEmuE7bhfEJCKMYYVs9B
# NLZmXbZ0e/VWMyIvIjayS6JKldj1po5SMYIChjCCAoICAQEwgYYwcjELMAkGA1UE
# BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj
# ZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVz
# dGFtcGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TANBglghkgBZQMEAgEFAKCB0TAa
# BgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTIxMDcx
# NzIwMTIzOFowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU4deCqOGRvu9ryhaRtaq0
# lKYkm/MwLwYJKoZIhvcNAQkEMSIEIBi4VIMj/rgKAw2B5w6wOyyLTcgf6+XdUArV
# h8qRoJ0dMDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEILMQkAa8CtmDB5FXKeBEA0Fc
# g+MpK2FPJpZMjTVx7PWpMA0GCSqGSIb3DQEBAQUABIIBALhqaRM/3fVZszOSaYxc
# 96Uswcj3YX2AyqwvZRoSY0ut7bCCc61FVMA6s0//Xgy3dGIjD/oqPH6TjYOO60Re
# FzeEusomgXtzLW7dIkbLJ+k3KtkyYcu18uGlctTjI13xdP6icr22zGKzrC8YCkLm
# GWu8gr4cBVNI/oVEWS4MWW3wvmNZNwh8gfZyr8gmLfSygSyxWtmjFyiYiYiTU/Lo
# gBe+oQcWdRVkkCcqC60ON8a9Ew16qIIV1myCW3SjHRSHqKtZAmWtQDAU7eR8vOmD
# m7aiwyEmYFovhQakstiMySWnQ5vSu3kHJG+pNmSJ6x9h9vDnj1GeLPUr9+KjqYaN
# Y24=
# SIG # End signature block


================================================
FILE: src/AmtPtpDevice.Settings/AmtPtpDevice.Settings.csproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProjectGuid>{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}</ProjectGuid>
    <OutputType>AppContainerExe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>AmtPtpDevice.Settings</RootNamespace>
    <AssemblyName>AmtPtpDevice.Settings</AssemblyName>
    <DefaultLanguage>en-US</DefaultLanguage>
    <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
    <TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.15063.0</TargetPlatformVersion>
    <TargetPlatformMinVersion>10.0.15063.0</TargetPlatformMinVersion>
    <MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <WindowsXamlEnableOverview>true</WindowsXamlEnableOverview>
    <PackageCertificateKeyFile>AmtPtpDevice.Settings_TemporaryKey.pfx</PackageCertificateKeyFile>
    <RuntimeIdentifiers>win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot</RuntimeIdentifiers>
    <AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
    <AppxBundle>Always</AppxBundle>
    <AppxBundlePlatforms>x86|x64|arm</AppxBundlePlatforms>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x86\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>x86</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
    <OutputPath>bin\x86\Release\</OutputPath>
    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x86</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\ARM\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>ARM</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
    <OutputPath>bin\ARM\Release\</OutputPath>
    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>ARM</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\x64\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <NoWarn>;2008</NoWarn>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
    <OutputPath>bin\x64\Release\</OutputPath>
    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
    <Optimize>true</Optimize>
    <NoWarn>;2008</NoWarn>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <UseVSHostingProcess>false</UseVSHostingProcess>
    <ErrorReport>prompt</ErrorReport>
    <Prefer32Bit>true</Prefer32Bit>
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
    </Compile>
    <Compile Include="Comm\UsbHidDeviceAccessSubscription.cs" />
    <Compile Include="DataObjects\Mt2BatteryStatusReport.cs" />
    <Compile Include="DataObjects\PtpUserModeConfReport.cs" />
    <Compile Include="MainPage.xaml.cs">
      <DependentUpon>MainPage.xaml</DependentUpon>
    </Compile>
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <AppxManifest Include="Package.appxmanifest">
      <SubType>Designer</SubType>
    </AppxManifest>
    <None Include="AmtPtpDevice.Settings_TemporaryKey.pfx" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="Properties\Default.rd.xml" />
    <Content Include="Assets\LockScreenLogo.scale-200.png" />
    <Content Include="Assets\SplashScreen.scale-200.png" />
    <Content Include="Assets\Square150x150Logo.scale-200.png" />
    <Content Include="Assets\Square44x44Logo.scale-200.png" />
    <Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
    <Content Include="Assets\StoreLogo.png" />
    <Content Include="Assets\Wide310x150Logo.scale-200.png" />
  </ItemGroup>
  <ItemGroup>
    <ApplicationDefinition Include="App.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </ApplicationDefinition>
    <Page Include="MainPage.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
      <Version>5.4.2</Version>
    </PackageReference>
    <PackageReference Include="System.ValueTuple">
      <Version>4.4.0</Version>
    </PackageReference>
  </ItemGroup>
  <ItemGroup />
  <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
    <VisualStudioVersion>14.0</VisualStudioVersion>
  </PropertyGroup>
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

================================================
FILE: src/AmtPtpDevice.Settings/App.xaml
================================================
<Application
    x:Class="AmtPtpDevice.Settings.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:AmtPtpDevice.Settings"
    RequestedTheme="Light">

</Application>


================================================
FILE: src/AmtPtpDevice.Settings/App.xaml.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace AmtPtpDevice.Settings
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (e.PrelaunchActivated == false)
            {
                if (rootFrame.Content == null)
                {
                    // When the navigation stack isn't restored navigate to the first page,
                    // configuring the new page by passing required information as a navigation
                    // parameter
                    rootFrame.Navigate(typeof(MainPage), e.Arguments);
                }
                // Ensure the current window is active
                Window.Current.Activate();
            }
        }

        /// <summary>
        /// Invoked when Navigation to a certain page fails
        /// </summary>
        /// <param name="sender">The Frame which failed navigation</param>
        /// <param name="e">Details about the navigation failure</param>
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            deferral.Complete();
        }
    }
}


================================================
FILE: src/AmtPtpDevice.Settings/Comm/UsbHidDeviceAccessSubscription.cs
================================================
using System;
using System.Threading;
using Windows.Devices.Enumeration;
using Windows.Devices.HumanInterfaceDevice;
using Windows.Storage;

namespace AmtPtpDevice.Settings.Comm
{
    public class UsbHidDeviceAccessSubscription : IDisposable
    {

        private string m_deviceId;
        private HidDevice m_device;
        private int m_refCount;
        private DeviceWatcher m_deviceWatcher;
        private EventHandler m_targetDeviceAvailable;

        public string AqsString { get; }
        public HidDevice Device
        {
            get
            {
                return m_device;
            }
        }

        public event EventHandler TargetDeviceAvailable
        {
            add
            {
                lock (m_targetDeviceAvailable)
                {
                    m_targetDeviceAvailable += value;
                }

                Interlocked.Increment(ref m_refCount);
                m_deviceWatcher.Start();
            }
            remove
            {
                Interlocked.Decrement(ref m_refCount);
                if (m_refCount == 0)
                {
                    m_deviceWatcher.Stop();
                }

                lock (m_targetDeviceAvailable)
                {
                    m_targetDeviceAvailable -= value;
                }
            }
        }
        public event EventHandler TargetDeviceLost;

        public UsbHidDeviceAccessSubscription(string aqsString)
        {
            AqsString = aqsString;
            m_device = null;
            m_deviceId = null;
            m_targetDeviceAvailable = new EventHandler((d, a) => { });
            m_deviceWatcher = DeviceInformation.CreateWatcher(aqsString);
            m_deviceWatcher.Added += SbDeviceAdded;
            m_deviceWatcher.Removed += SbDeviceRemoved;
        }

        private void SbDeviceRemoved(DeviceWatcher sender, DeviceInformationUpdate args)
        {
            if (m_deviceId != args.Id) return;

            try
            {
                m_device.Dispose();
            }
            finally
            {
                TargetDeviceLost?.Invoke(this, null);
            }
        }

        private async void SbDeviceAdded(DeviceWatcher sender, DeviceInformation args)
        {
            m_device = await HidDevice.FromIdAsync(args.Id, FileAccessMode.ReadWrite);
            m_deviceId = args.Id;
            m_targetDeviceAvailable?.Invoke(this, null);
        }

        #region IDisposable Support
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    m_deviceWatcher.Added -= SbDeviceAdded;
                    m_deviceWatcher.Removed -= SbDeviceRemoved;
                    m_deviceWatcher.Stop();
                    m_device.Dispose();
                }

                m_deviceId = null;
                m_deviceWatcher = null;
                m_device = null;
                disposedValue = true;
            }
        }

        // This code added to correctly implement the disposable pattern.
        public void Dispose()
        {
            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
            Dispose(true);
        }
        #endregion

    }
}


================================================
FILE: src/AmtPtpDevice.Settings/DataObjects/Mt2BatteryStatusReport.cs
================================================
using System.Runtime.InteropServices;

namespace AmtPtpDevice.Settings.DataObjects
{
    public struct Mt2BatteryStatusReport
    {
        public byte ReportId;
        public byte BatteryFlags;
        public byte ChargeStatus;
    }
}


================================================
FILE: src/AmtPtpDevice.Settings/DataObjects/PtpUserModeConfReport.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AmtPtpDevice.Settings.DataObjects
{
    public struct PtpUserModeConfReport
    {
        public byte ReportId;
        public byte PressureQualificationLevel;
        public byte SingleContactSizeQualificationLevel;
        public byte MultipleContactSizeQualificationLevel;
    }
}


================================================
FILE: src/AmtPtpDevice.Settings/MainPage.xaml
================================================
<Page
    x:Class="AmtPtpDevice.Settings.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:AmtPtpDevice.Settings"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource  ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="48" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid Grid.Row="0" Background="{ThemeResource AppBarBackground}">
            <TextBlock Margin="15,0,0,0" VerticalAlignment="Center"
                Style="{StaticResource BaseTextBlockStyle}">
                <Run Typography.Capitals="AllPetiteCaps">Input Settings</Run>
            </TextBlock>
        </Grid>
        <StackPanel x:Name="m_deviceControl" Margin="15,10" Grid.Row="1" Visibility="Collapsed">
            <TextBlock x:Name="m_battStatus" Margin="0,0,0,10"
                    Style="{StaticResource BaseTextBlockStyle}"  />
            <Slider x:Name="m_sensitivitySlider" 
                    Minimum="0" Maximum="20" 
                    ValueChanged="OnSliderValueChanged"
                    Header="Touch sensitivity" />
            <Slider x:Name="m_confidenceSlider" 
                    Minimum="0" Maximum="25" 
                    ValueChanged="OnConfidenceSliderValueChanged"
                    Header="Single finger confidence threshold" />
            <Slider x:Name="m_muConfidenceSlider" 
                    Minimum="0" Maximum="25" 
                    ValueChanged="OnMuConfidenceSliderValueChanged"
                    Header="Multiple finger confidence threshold" />
            <HyperlinkButton Margin="0,10,0,0" 
                    Click="OnGestureButtonClicked"
                    Content="Gesture settings" />
            <TextBlock Style="{StaticResource BodyTextBlockStyle}"
                    Text="Note: Settings won't be persisted for debug purpose. To reset values, unplug and plug in your trackpad." />
        </StackPanel>
        <StackPanel x:Name="m_disconnctedView" Margin="15,10" Grid.Row="1">
            <TextBlock Margin="0,0,0,10"
                       Text="Please connect your device and continue."
                       Style="{StaticResource BaseTextBlockStyle}"  />
        </StackPanel>
    </Grid>
</Page>


================================================
FILE: src/AmtPtpDevice.Settings/MainPage.xaml.cs
================================================
using AmtPtpDevice.Settings.Comm;
using AmtPtpDevice.Settings.DataObjects;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Devices.HumanInterfaceDevice;
using Windows.Foundation;
using Windows.Foundation.Metadata;
using Windows.Storage.Streams;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

namespace AmtPtpDevice.Settings
{
    public sealed partial class MainPage : Page
    {
        private PtpUserModeConfReport m_report;
        private bool m_isInitialDataPresented = false;
        private UsbHidDeviceAccessSubscription m_inputDevice;
        private UsbHidDeviceAccessSubscription m_battery;

        public MainPage()
        {
            this.InitializeComponent();
            ApplicationView.GetForCurrentView().SetPreferredMinSize(new Size(480, 500));
            ApplicationView.PreferredLaunchViewSize = new Size(480, 500);
            ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;

            this.Loaded += OnPageLoaded;
        }

        private void OnPageLoaded(object sender, RoutedEventArgs e)
        {
            SetupWatcher();

            if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.ApplicationView"))
            {
                var titleBar = ApplicationView.GetForCurrentView().TitleBar;
                if (titleBar != null)
                {
                    titleBar.ButtonBackgroundColor = titleBar.ButtonInactiveBackgroundColor 
                        = ((SolidColorBrush) Resources["AppBarBackground"]).Color;
                    titleBar.ButtonForegroundColor = ((SolidColorBrush) Resources["ApplicationForegroundThemeBrush"]).Color;
                    titleBar.BackgroundColor = titleBar.InactiveBackgroundColor 
                        = ((SolidColorBrush) Resources["AppBarBackground"]).Color;
                    titleBar.ForegroundColor = ((SolidColorBrush) Resources["ApplicationForegroundThemeBrush"]).Color;
                }
            }
        }

        private void SetupWatcher()
        {
            m_inputDevice = new UsbHidDeviceAccessSubscription(HidDevice.GetDeviceSelector(0xff00, 0x0001, 0x05ac, 0x0265));
            m_battery = new UsbHidDeviceAccessSubscription(HidDevice.GetDeviceSelector(0xff00, 0x0014, 0x05ac, 0x0265));

            m_inputDevice.TargetDeviceAvailable += OnInputDeviceAvailable;
            m_inputDevice.TargetDeviceLost += OnInputDeviceLost;
            m_battery.TargetDeviceAvailable += OnBatteryAvailable;
        }

        private async void OnBatteryAvailable(object sender, EventArgs e)
        {
            var bReport = await m_battery.Device.GetInputReportAsync(0x90);
            var ptr = Marshal.AllocHGlobal((int) bReport.Data.Length);
            Marshal.Copy(bReport.Data.ToArray(), 0, ptr, (int) bReport.Data.Length);

            var battReport = Marshal.PtrToStructure<Mt2BatteryStatusReport>(ptr);
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                m_battStatus.Text = $"Battery is {battReport.ChargeStatus}% charged.";
            });

            Marshal.FreeHGlobal(ptr);
        }

        private async void OnInputDeviceLost(object sender, EventArgs e)
        {
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                // Set visibility
                m_disconnctedView.Visibility = Visibility.Visible;
                m_deviceControl.Visibility = Visibility.Collapsed;
                // Set state
                m_isInitialDataPresented = false;
            });
        }

        private async void OnInputDeviceAvailable(object sender, EventArgs e)
        {
            var sReport = await m_inputDevice.Device.GetFeatureReportAsync(0x09);
            var ptr = Marshal.AllocHGlobal((int)sReport.Data.Length);
            Marshal.Copy(sReport.Data.ToArray(), 0, ptr, (int)sReport.Data.Length);

            m_report = Marshal.PtrToStructure<PtpUserModeConfReport>(ptr);
            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                // Set value
                m_sensitivitySlider.Value = m_report.PressureQualificationLevel;
                m_confidenceSlider.Value = m_report.SingleContactSizeQualificationLevel;
                m_muConfidenceSlider.Value = m_report.MultipleContactSizeQualificationLevel;

                // Set visibility
                m_disconnctedView.Visibility = Visibility.Collapsed;
                m_deviceControl.Visibility = Visibility.Visible;

                // Set state
                m_isInitialDataPresented = true;
            });

            Marshal.FreeHGlobal(ptr);
        }

        private async void ApplySettings()
        {
            if (m_inputDevice.Device == null || !m_isInitialDataPresented) return;

            m_report.PressureQualificationLevel = (byte) m_sensitivitySlider.Value;
            m_report.SingleContactSizeQualificationLevel = (byte) m_confidenceSlider.Value;
            m_report.MultipleContactSizeQualificationLevel = (byte) m_muConfidenceSlider.Value;

            var featureReport = m_inputDevice.Device.CreateFeatureReport(0x09);
            using (var datawriter = new DataWriter())
            {
                datawriter.WriteByte(0x09);
                datawriter.WriteByte(m_report.PressureQualificationLevel);
                datawriter.WriteByte(m_report.SingleContactSizeQualificationLevel);
                datawriter.WriteByte(m_report.MultipleContactSizeQualificationLevel);
                featureReport.Data = datawriter.DetachBuffer();
                await m_inputDevice.Device.SendFeatureReportAsync(featureReport);
            }
        }

        private async void OnGestureButtonClicked(object sender, RoutedEventArgs e)
        {
            await Launcher.LaunchUriAsync(new Uri("ms-settings:devices-touchpad"));
        }

        private void OnSliderValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
        {
            ApplySettings();
        }

        private void OnConfidenceSliderValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
        {
            ApplySettings();
        }

        private void OnMuConfidenceSliderValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
        {
            ApplySettings();
        }
    }
}


================================================
FILE: src/AmtPtpDevice.Settings/Package.appxmanifest
================================================
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
  <Identity Name="4dbffcf3-8ff3-459b-95e8-64691ffade0a" Publisher="CN=imbushuo" Version="1.0.0.0" />
  <mp:PhoneIdentity PhoneProductId="4dbffcf3-8ff3-459b-95e8-64691ffade0a" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
  <Properties>
    <DisplayName>AmtPtpDevice.Settings</DisplayName>
    <PublisherDisplayName>imbushuo</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>
  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>
  <Resources>
    <Resource Language="x-generate" />
  </Resources>
  <Applications>
    <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="AmtPtpDevice.Settings.App">
      <uap:VisualElements DisplayName="Magic Trackpad Settings" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="Apple Magic Trackpad 2 Settings App" BackgroundColor="transparent">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" ShortName="Magic Trackpad Settings">
        </uap:DefaultTile>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
    </Application>
  </Applications>
  <Capabilities>
    <Capability Name="internetClient" />
    <DeviceCapability Name="humaninterfacedevice">
      <Device Id="vidpid:05ac 0265">
        <!-- Input experience settings -->
        <Function Type="usage:FF00 0001" />
        <!-- Battery information -->
        <Function Type="usage:FF00 0014" />
      </Device>
    </DeviceCapability>
  </Capabilities>
</Package>

================================================
FILE: src/AmtPtpDevice.Settings/Properties/AssemblyInfo.cs
================================================
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AmtPtpDevice.Settings")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AmtPtpDevice.Settings")]
[assembly: AssemblyCopyright("Copyright ©  2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

================================================
FILE: src/AmtPtpDevice.Settings/Properties/Default.rd.xml
================================================
<!--
    This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
    developers. However, you can modify these parameters to modify the behavior of the .NET Native
    optimizer.

    Runtime Directives are documented at https://go.microsoft.com/fwlink/?LinkID=391919

    To fully enable reflection for App1.MyClass and all of its public/private members
    <Type Name="App1.MyClass" Dynamic="Required All"/>

    To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
    <TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />

    Using the Namespace directive to apply reflection policy to all the types in a particular namespace
    <Namespace Name="DataClasses.ViewModels" Serialize="All" />
-->

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
  <Application>
    <!--
      An Assembly element with Name="*Application*" applies to all assemblies in
      the application package. The asterisks are not wildcards.
    -->
    <Assembly Name="*Application*" Dynamic="Required All" />
    
    
    <!-- Add your application specific runtime directives here. -->


  </Application>
</Directives>

================================================
FILE: src/AmtPtpDeviceSpiKm/AmtPtpDeviceSpiKm.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="ReleaseSigned|ARM64">
      <Configuration>ReleaseSigned</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="ReleaseSigned|x64">
      <Configuration>ReleaseSigned</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|ARM64">
      <Configuration>Debug</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|ARM64">
      <Configuration>Release</Configuration>
      <Platform>ARM64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="Device.c" />
    <ClCompile Include="Driver.c" />
    <ClCompile Include="Hid.c" />
    <ClCompile Include="Input.c" />
    <ClCompile Include="Queue.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AppleDefinition.h" />
    <ClInclude Include="Device.h" />
    <ClInclude Include="Driver.h" />
    <ClInclude Include="Hid.h" />
    <ClInclude Include="HidCommon.h" />
    <ClInclude Include="HID\SpiTrackpadSeries1.h" />
    <ClInclude Include="HID\SpiTrackpadSeries2.h" />
    <ClInclude Include="HID\SpiTrackpadSeries3.h" />
    <ClInclude Include="Input.h" />
    <ClInclude Include="Public.h" />
    <ClInclude Include="Queue.h" />
    <ClInclude Include="Trace.h" />
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{FC08B706-5661-47FA-A840-053B06125750}</ProjectGuid>
    <TemplateGuid>{497e31cb-056b-4f31-abb8-447fd55ee5a5}</TemplateGuid>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
    <Configuration>Debug</Configuration>
    <Platform Condition="'$(Platform)' == ''">Win32</Platform>
    <RootNamespace>AmtPtpDeviceSpiKm</RootNamespace>
  </PropertyGroup>
  <!-- They told me this: https://help.github.com/en/articles/software-in-virtual-environments-for-github-actions#windows-server-2019 -->
  <PropertyGroup>
    <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <PropertyGroup Condition="'$(BuildEnvironment)'=='Github'">
    <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <TargetVersion>Windows10</TargetVersion>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
    <ConfigurationType>Driver</ConfigurationType>
    <DriverType>KMDF</DriverType>
    <DriverTargetPlatform>Universal</DriverTargetPlatform>
    <_NT_TARGET_VERSION>0xA000004</_NT_TARGET_VERSION>
    <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
    <KMDF_VERSION_MINOR>23</KMDF_VERSION_MINOR>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <TargetVersion>Windows10</TargetVersion>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
    <ConfigurationType>Driver</ConfigurationType>
    <DriverType>KMDF</DriverType>
    <DriverTargetPlatform>Universal</DriverTargetPlatform>
    <_NT_TARGET_VERSION>0xA000004</_NT_TARGET_VERSION>
    <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
    <KMDF_VERSION_MINOR>23</KMDF_VERSION_MINOR>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|x64'" Label="Configuration">
    <TargetVersion>Windows10</TargetVersion>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
    <ConfigurationType>Driver</ConfigurationType>
    <DriverType>KMDF</DriverType>
    <DriverTargetPlatform>Universal</DriverTargetPlatform>
    <_NT_TARGET_VERSION>0xA000004</_NT_TARGET_VERSION>
    <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
    <KMDF_VERSION_MINOR>23</KMDF_VERSION_MINOR>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
    <TargetVersion>Windows10</TargetVersion>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
    <ConfigurationType>Driver</ConfigurationType>
    <DriverType>KMDF</DriverType>
    <DriverTargetPlatform>Universal</DriverTargetPlatform>
    <_NT_TARGET_VERSION>0xA000004</_NT_TARGET_VERSION>
    <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
    <KMDF_VERSION_MINOR>23</KMDF_VERSION_MINOR>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
    <TargetVersion>Windows10</TargetVersion>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
    <ConfigurationType>Driver</ConfigurationType>
    <DriverType>KMDF</DriverType>
    <DriverTargetPlatform>Universal</DriverTargetPlatform>
    <_NT_TARGET_VERSION>0xA000004</_NT_TARGET_VERSION>
    <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
    <KMDF_VERSION_MINOR>23</KMDF_VERSION_MINOR>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|ARM64'" Label="Configuration">
    <TargetVersion>Windows10</TargetVersion>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
    <ConfigurationType>Driver</ConfigurationType>
    <DriverType>KMDF</DriverType>
    <DriverTargetPlatform>Universal</DriverTargetPlatform>
    <_NT_TARGET_VERSION>0xA000004</_NT_TARGET_VERSION>
    <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
    <KMDF_VERSION_MINOR>23</KMDF_VERSION_MINOR>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup />
  <!-- For release signed config on Azure pipeline, CI pipeline don't sign it. We do that locally -->
  <PropertyGroup Condition="'$(Configuration)'=='ReleaseSigned'">
    <TimeStampServer>http://timestamp.digicert.com</TimeStampServer>
    <ProductionCertificate>$(ProductionCertPath)</ProductionCertificate>
    <SignMode Condition="'$(BuildEnvironment)'!='AzurePipeline'">ProductionSign</SignMode>
    <SignMode Condition="'$(BuildEnvironment)'=='AzurePipeline'">Off</SignMode>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
    <OutDir>$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\</OutDir>
    <IntDir>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\</IntDir>
    <IncludePath>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)</IncludePath>
    <TimeStampServer>http://timestamp.digicert.com</TimeStampServer>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
    <OutDir>$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\</OutDir>
    <IntDir>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\</IntDir>
    <IncludePath>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)</IncludePath>
    <TimeStampServer>http://timestamp.digicert.com</TimeStampServer>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|x64'">
    <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
    <OutDir>$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\</OutDir>
    <IntDir>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\</IntDir>
    <IncludePath>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)</IncludePath>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
    <OutDir>$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\</OutDir>
    <IntDir>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\</IntDir>
    <IncludePath>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)</IncludePath>
    <TimeStampServer>http://timestamp.digicert.com</TimeStampServer>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
    <OutDir>$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\</OutDir>
    <IntDir>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\</IntDir>
    <IncludePath>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)</IncludePath>
    <TimeStampServer>http://timestamp.digicert.com</TimeStampServer>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|ARM64'">
    <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
    <OutDir>$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\</OutDir>
    <IntDir>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\</IntDir>
    <IncludePath>$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)</IncludePath>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <WppEnabled>true</WppEnabled>
      <WppRecorderEnabled>true</WppRecorderEnabled>
      <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
      <WppKernelMode>true</WppKernelMode>
      <DisableSpecificWarnings>4214</DisableSpecificWarnings>
    </ClCompile>
    <DriverSign>
      <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
    </DriverSign>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <WppEnabled>true</WppEnabled>
      <WppRecorderEnabled>true</WppRecorderEnabled>
      <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
      <WppKernelMode>true</WppKernelMode>
      <DisableSpecificWarnings>4214</DisableSpecificWarnings>
    </ClCompile>
    <DriverSign>
      <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
    </DriverSign>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|x64'">
    <ClCompile>
      <WppEnabled>true</WppEnabled>
      <WppRecorderEnabled>true</WppRecorderEnabled>
      <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
      <WppKernelMode>true</WppKernelMode>
      <DisableSpecificWarnings>4214</DisableSpecificWarnings>
    </ClCompile>
    <DriverSign>
      <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
    </DriverSign>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
    <ClCompile>
      <WppEnabled>true</WppEnabled>
      <WppRecorderEnabled>true</WppRecorderEnabled>
      <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
      <WppKernelMode>true</WppKernelMode>
      <DisableSpecificWarnings>4214</DisableSpecificWarnings>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseSigned|ARM64'">
    <ClCompile>
      <WppEnabled>true</WppEnabled>
      <WppRecorderEnabled>true</WppRecorderEnabled>
      <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
      <WppKernelMode>true</WppKernelMode>
      <DisableSpecificWarnings>4214</DisableSpecificWarnings>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
    <ClCompile>
      <WppEnabled>true</WppEnabled>
      <WppRecorderEnabled>true</WppRecorderEnabled>
      <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
      <WppKernelMode>true</WppKernelMode>
      <DisableSpecificWarnings>4214</DisableSpecificWarnings>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <FilesToPackage Include="$(TargetPath)" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

================================================
FILE: src/AmtPtpDeviceSpiKm/AmtPtpDeviceSpiKm.vcxproj.filters
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Header Files">
      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
    </Filter>
    <Filter Include="Resource Files">
      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
    </Filter>
    <Filter Include="Driver Files">
      <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
      <Extensions>inf;inv;inx;mof;mc;</Extensions>
    </Filter>
    <Filter Include="Device Specific Metadata Files">
      <UniqueIdentifier>{895871d8-b6bd-4578-bd98-bec2cb45183b}</UniqueIdentifier>
    </Filter>
    <Filter Include="Source Files">
      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="Device.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Driver.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Public.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Queue.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Trace.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="AppleDefinition.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Hid.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="HID\SpiTrackpadSeries1.h">
      <Filter>Device Specific Metadata Files</Filter>
    </ClInclude>
    <ClInclude Include="HidCommon.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Input.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="HID\SpiTrackpadSeries2.h">
      <Filter>Device Specific Metadata Files</Filter>
    </ClInclude>
    <ClInclude Include="HID\SpiTrackpadSeries3.h">
      <Filter>Device Specific Metadata Files</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="Device.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="Driver.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="Queue.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="Hid.c">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="Input.c">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
</Project>

================================================
FILE: src/AmtPtpDeviceSpiKm/AppleDefinition.h
================================================
#pragma once

#define SPI_TRACKPAD_MAX_FINGERS 10
#define DEVICE_VID 0x8910

typedef struct _SPI_TRACKPAD_FINGER
{
	SHORT OriginalX;
	SHORT OriginalY;
	SHORT X;
	SHORT Y;
	SHORT HorizontalAccel;
	SHORT VerticalAccel;
	SHORT ToolMajor;
	SHORT ToolMinor;
	SHORT Orientation;
	SHORT TouchMajor;
	SHORT TouchMinor;
	SHORT Rsvd1;
	SHORT Rsvd2;
	SHORT Pressure;
	SHORT Rsvd3;
} SPI_TRACKPAD_FINGER, *PSPI_TRACKPAD_FINGER;

typedef struct _SPI_TRACKPAD_PACKET
{
	UINT8 PacketType;
	UINT8 ClickOccurred;
	UINT8 Reserved0[5];
	UINT8 IsFinger;
	UINT8 Reserved1[16];
	UINT8 FingerDataLength;
	UINT8 Reserved2[5];
	UINT8 NumOfFingers;
	UINT8 ClickOccurred2;
	UINT8 State1;
	UINT8 State2;
	UINT8 State3;
	UINT8 Padding;
	UINT8 Reserved3[10];
	SPI_TRACKPAD_FINGER Fingers[SPI_TRACKPAD_MAX_FINGERS];
} SPI_TRACKPAD_PACKET, *PSPI_TRACKPAD_PACKET;

typedef struct _SPI_SET_FEATURE {
	UINT8 BusLocation;
	UINT8 Status;
} SPI_SET_FEATURE, *PSPI_SET_FEATURE;

#define HID_REPORTID_MOUSE  2
#define HID_XFER_PACKET_SIZE 255

static const SPI_TRACKPAD_INFO SpiTrackpadConfigTable[] = 
{
	/* MacBookPro11,1 / MacBookPro12,1 */
	{ 0x05ac, 0x0272, -4750, 5280, -150, 6730 },
	{ 0x05ac, 0x0273, -4750, 5280, -150, 6730 },
	/* MacBook9 */
	{ 0x05ac, 0x0275, -5087, 5579, -128, 6089 },
	/* MacBookPro14,1 / MacBookPro14,2 */
	{ 0x05ac, 0x0276, -6243, 6749, -170, 7685 },
	{ 0x05ac, 0x0277, -6243, 6749, -170, 7685 },
	/* MacBookPro14,3 */
	{ 0x05ac, 0x0278, -7456, 7976, -163, 9283 },
	/* MacBook10 */
	{ 0x05ac, 0x0279, -5087, 5579, -128, 6089 },
	/* MacBookAir7,2 fallback */
	{ 0x05ac, 0x0290, -5087, 5579, -128, 6089 },
	{ 0x05ac, 0x0291, -5087, 5579, -128, 6089 },
	/* Terminator */
	{ 0 }
};


================================================
FILE: src/AmtPtpDeviceSpiKm/Device.c
================================================
/*++

Module Name:

    device.c - Device handling events for example driver.

Abstract:

   This file contains the device entry points and callbacks.
    
Environment:

    Kernel-mode Driver Framework

--*/

#include "driver.h"
#include "device.tmh"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, AmtPtpDeviceSpiKmCreateDevice)
#endif

NTSTATUS
AmtPtpDeviceSpiKmCreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
{
    WDF_OBJECT_ATTRIBUTES DeviceAttributes;
	WDF_OBJECT_ATTRIBUTES TimerAttributes;
    PDEVICE_CONTEXT pDeviceContext;
	WDF_TIMER_CONFIG TimerConfig;
    WDFDEVICE Device;
    NTSTATUS Status;

	WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;

    PAGED_CODE();

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Entry"
	);

	// Initialize Power Callback
	WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

	// Initialize PNP power event callbacks
	pnpPowerCallbacks.EvtDevicePrepareHardware = AmtPtpEvtDevicePrepareHardware;
	pnpPowerCallbacks.EvtDeviceD0Entry = AmtPtpEvtDeviceD0Entry;
	pnpPowerCallbacks.EvtDeviceD0Exit = AmtPtpEvtDeviceD0Exit;
	pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = AmtPtpEvtDeviceSelfManagedIoInitOrRestart;
	pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = AmtPtpEvtDeviceSelfManagedIoInitOrRestart;
	WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

	// Create WDF device object
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DeviceAttributes, DEVICE_CONTEXT);

    Status = WdfDeviceCreate(&DeviceInit, &DeviceAttributes, &Device);

    if (NT_SUCCESS(Status)) 
	{
        //
        // Get a pointer to the device context structure that we just associated
        // with the device object. We define this structure in the device.h
        // header file. DeviceGetContext is an inline function generated by
        // using the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in device.h.
        // This function will do the type checking and return the device context.
        // If you pass a wrong object handle it will return NULL and assert if
        // run under framework verifier mode.
        //
        pDeviceContext = DeviceGetContext(Device);

		//
		// Put itself in
		//
		pDeviceContext->SpiDevice = Device;

		//
		// Create a list of buffers
		//
		Status = WdfLookasideListCreate(
			WDF_NO_OBJECT_ATTRIBUTES,
			REPORT_BUFFER_SIZE,
			NonPagedPoolNx,
			WDF_NO_OBJECT_ATTRIBUTES,
			PTP_LIST_POOL_TAG,
			&pDeviceContext->HidReadBufferLookaside
		);

		if (!NT_SUCCESS(Status)) {
			TraceEvents(
				TRACE_LEVEL_ERROR,
				TRACE_DRIVER,
				"%!FUNC! WdfLookasideListCreate failed with %!STATUS!",
				Status
			);
			goto exit;
		}

		//
		// Create power-on recovery timer
		//
		WDF_TIMER_CONFIG_INIT(&TimerConfig, AmtPtpPowerRecoveryTimerCallback);
		TimerConfig.AutomaticSerialization = TRUE;
		WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes);
		TimerAttributes.ParentObject = Device;
		TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive;
		Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &pDeviceContext->PowerOnRecoveryTimer);
		if (!NT_SUCCESS(Status)) {
			TraceEvents(
				TRACE_LEVEL_ERROR,
				TRACE_DRIVER,
				"%!FUNC! WdfTimerCreate failed with %!STATUS!",
				Status
			);
			goto exit;
		}

		//
		// Retrieve IO target.
		//
		pDeviceContext->SpiTrackpadIoTarget = WdfDeviceGetIoTarget(Device);
		if (pDeviceContext->SpiTrackpadIoTarget == NULL) 
		{
			Status = STATUS_INVALID_DEVICE_STATE;
			goto exit;
		}

		//
		// Reset power status.
		//
		pDeviceContext->DeviceStatus = D3;

        //
        // Create a device interface so that applications can find and talk
        // to us.
        //
        Status = WdfDeviceCreateDeviceInterface(
            Device,
            &GUID_DEVINTERFACE_AmtPtpDeviceSpiKm,
            NULL // ReferenceString
        );

        if (NT_SUCCESS(Status)) 
		{
            //
            // Initialize the I/O Package and any Queues
            //
            Status = AmtPtpDeviceSpiKmQueueInitialize(Device);
        }
    }

exit:
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Exit, Status = %!STATUS!",
		Status
	);

    return Status;
}

NTSTATUS
AmtPtpEvtDevicePrepareHardware(
	_In_ WDFDEVICE Device,
	_In_ WDFCMRESLIST ResourceList,
	_In_ WDFCMRESLIST ResourceListTranslated
)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_CONTEXT pDeviceContext;

	WDF_MEMORY_DESCRIPTOR HidAttributeMemoryDescriptor;
	HID_DEVICE_ATTRIBUTES DeviceAttributes;
	
	const SPI_TRACKPAD_INFO* pTrackpadInfo;
	BOOLEAN DeviceFound = FALSE;

	WDFKEY ParamRegistryKey;
	DECLARE_CONST_UNICODE_STRING(DesiredReportTypeKey, L"DesiredReportType");
	ULONG DesiredReportTypeValue, Length, ValueType = 0;

	PAGED_CODE();
	UNREFERENCED_PARAMETER(ResourceList);
	UNREFERENCED_PARAMETER(ResourceListTranslated);

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Entry"
	);

	pDeviceContext = DeviceGetContext(Device);
	if (pDeviceContext == NULL)
	{
		Status = STATUS_INVALID_DEVICE_STATE;
		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_DRIVER,
			"%!FUNC! pDeviceContext == NULL"
		);

		goto exit;
	}

	// Request device attribute descriptor for self-identification.
	RtlZeroMemory(&DeviceAttributes, sizeof(DeviceAttributes));
	WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
		&HidAttributeMemoryDescriptor,
		(PVOID) &DeviceAttributes,
		sizeof(DeviceAttributes)
	);

	Status = WdfIoTargetSendInternalIoctlSynchronously(
		pDeviceContext->SpiTrackpadIoTarget,
		NULL,
		IOCTL_HID_GET_DEVICE_ATTRIBUTES,
		NULL,
		&HidAttributeMemoryDescriptor,
		NULL,
		NULL
	);

	if (!NT_SUCCESS(Status))
	{
		KdPrintEx((
			DPFLTR_IHVDRIVER_ID,
			DPFLTR_INFO_LEVEL,
			"WdfIoTargetSendInternalIoctlSynchronously failed, status = 0x%x \n",
			Status
		));

		goto exit;
	}

	pDeviceContext->HidVendorID = DeviceAttributes.VendorID;
	pDeviceContext->HidProductID = DeviceAttributes.ProductID;
	pDeviceContext->HidVersionNumber = DeviceAttributes.VersionNumber;

	// Find proper metadata in HID registry
	for (pTrackpadInfo = SpiTrackpadConfigTable; pTrackpadInfo->VendorId; ++pTrackpadInfo)
	{
		if (pTrackpadInfo->VendorId == DeviceAttributes.VendorID &&
			pTrackpadInfo->ProductId == DeviceAttributes.ProductID)
		{
			pDeviceContext->TrackpadInfo.ProductId = pTrackpadInfo->ProductId;
			pDeviceContext->TrackpadInfo.VendorId = pTrackpadInfo->VendorId;
			pDeviceContext->TrackpadInfo.XMin = pTrackpadInfo->XMin;
			pDeviceContext->TrackpadInfo.XMax = pTrackpadInfo->XMax;
			pDeviceContext->TrackpadInfo.YMin = pTrackpadInfo->YMin;
			pDeviceContext->TrackpadInfo.YMax = pTrackpadInfo->YMax;

			DeviceFound = TRUE;
			break;
		}
	}

	if (!DeviceFound)
	{
		Status = STATUS_NOT_FOUND;
		goto exit;
	}

	// Check the desired report type.
	Status = WdfDriverOpenParametersRegistryKey(
		WdfDeviceGetDriver(Device),
		KEY_READ,
		WDF_NO_OBJECT_ATTRIBUTES,
		&ParamRegistryKey
	);

	if (NT_SUCCESS(Status))
	{
		Status = WdfRegistryQueryValue(
			ParamRegistryKey,
			&DesiredReportTypeKey,
			sizeof(ULONG),
			&DesiredReportTypeValue,
			&Length,
			&ValueType
		);

		if (NT_SUCCESS(Status))
		{
			switch (DesiredReportTypeValue)
			{
			case 0:
				pDeviceContext->ReportType = PrecisionTouchpad;
				break;
			case 1:
				pDeviceContext->ReportType = Touchscreen;
				break;
			default:
				Status = STATUS_INVALID_PARAMETER;
				break;
			}
		}

		WdfRegistryClose(ParamRegistryKey);
	}

	// We don't really care if that param read fails.
	Status = STATUS_SUCCESS;

exit:
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Exit, Status = %!STATUS!",
		Status
	);

	return Status;
}

NTSTATUS
AmtPtpEvtDeviceD0Entry(
	_In_ WDFDEVICE Device,
	_In_ WDF_POWER_DEVICE_STATE PreviousState
)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_CONTEXT pDeviceContext;

	// Log status
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Entry - coming from %s",
		DbgDevicePowerString(PreviousState)
	);

	pDeviceContext = DeviceGetContext(Device);

	// We will configure the device in Self Managed IO init / restart routine
	pDeviceContext->DeviceStatus = D0ActiveAndUnconfigured;

	// Set time
	KeQueryPerformanceCounter(&pDeviceContext->LastReportTime);

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! <-- AmtPtpDeviceEvtDeviceD0Entry"
	);

	return Status;
}

NTSTATUS
AmtPtpEvtDeviceD0Exit(
	_In_ WDFDEVICE Device,
	_In_ WDF_POWER_DEVICE_STATE TargetState
)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_CONTEXT pDeviceContext;
	WDFREQUEST OutstandingRequest;

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - moving to %s",
		DbgDevicePowerString(TargetState)
	);

	pDeviceContext = DeviceGetContext(Device);
	pDeviceContext->DeviceStatus = D3;

	// Cancel all outstanding requests
	while (NT_SUCCESS(Status)) {
		Status = WdfIoQueueRetrieveNextRequest(
			pDeviceContext->HidQueue, 
			&OutstandingRequest
		);

		if (NT_SUCCESS(Status)) {
			WdfRequestComplete(OutstandingRequest, STATUS_CANCELLED);
		}
	}

	// When the queue is empty, this is expected
	Status = STATUS_SUCCESS;

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Exit"
	);

	return Status;
}

NTSTATUS
AmtPtpEvtDeviceSelfManagedIoInitOrRestart(
	_In_ WDFDEVICE Device
)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_CONTEXT pDeviceContext;

	TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
	pDeviceContext = DeviceGetContext(Device);
	
	Status = AmtPtpSpiSetState(Device, TRUE);
	if (!NT_SUCCESS(Status))
	{
		// In this case, we will retry after 5 seconds. Block any incoming requests.
		TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "%!FUNC! AmtPtpSpiSetState failed with %!STATUS!. Retry after 5 seconds", Status);
		Status = STATUS_SUCCESS;
		WdfTimerStart(pDeviceContext->PowerOnRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(5));
		goto exit;
	}
	else
	{
		// Set time and status
		pDeviceContext->DeviceStatus = D0ActiveAndConfigured;
		KeQueryPerformanceCounter(&pDeviceContext->LastReportTime);
	}

exit:
	TraceEvents(TRACE_LEVEL_INFORMATION,TRACE_DRIVER, "%!FUNC! Exit, Status = %!STATUS!", Status);
	return Status;
}

PCHAR
DbgDevicePowerString(
	_In_ WDF_POWER_DEVICE_STATE Type
)
{
	switch (Type)
	{
	case WdfPowerDeviceInvalid:
		return "WdfPowerDeviceInvalid";
	case WdfPowerDeviceD0:
		return "WdfPowerDeviceD0";
	case WdfPowerDeviceD1:
		return "WdfPowerDeviceD1";
	case WdfPowerDeviceD2:
		return "WdfPowerDeviceD2";
	case WdfPowerDeviceD3:
		return "WdfPowerDeviceD3";
	case WdfPowerDeviceD3Final:
		return "WdfPowerDeviceD3Final";
	case WdfPowerDevicePrepareForHibernation:
		return "WdfPowerDevicePrepareForHibernation";
	case WdfPowerDeviceMaximum:
		return "WdfPowerDeviceMaximum";
	default:
		return "UnKnown Device Power State";
	}
}

NTSTATUS
AmtPtpSpiSetState(
	_In_ WDFDEVICE Device,
	_In_ BOOLEAN DesiredState
)
{
	NTSTATUS Status;
	PDEVICE_CONTEXT pDeviceContext;
	UCHAR HidPacketBuffer[HID_XFER_PACKET_SIZE];
	WDF_MEMORY_DESCRIPTOR HidMemoryDescriptor;
	PHID_XFER_PACKET pHidPacket;
	PSPI_SET_FEATURE pSpiSetStatus;

	pDeviceContext = DeviceGetContext(Device);
	if (pDeviceContext == NULL)
	{
		Status = STATUS_INVALID_DEVICE_STATE;
		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_DRIVER,
			"%!FUNC! pDeviceContext == NULL"
		);

		goto exit;
	}

	RtlZeroMemory(HidPacketBuffer, sizeof(HidPacketBuffer));
	pHidPacket = (PHID_XFER_PACKET) &HidPacketBuffer;
	WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
		&HidMemoryDescriptor,
		(PVOID) &HidPacketBuffer,
		HID_XFER_PACKET_SIZE
	);

	pHidPacket->reportId = HID_REPORTID_MOUSE;
	pHidPacket->reportBufferLen = sizeof(SPI_SET_FEATURE);
	pHidPacket->reportBuffer = (PUCHAR) pHidPacket + sizeof(HID_XFER_PACKET);
	pSpiSetStatus = (PSPI_SET_FEATURE) pHidPacket->reportBuffer;

	// SPI Bus, location 2
	pSpiSetStatus->BusLocation = 2;
	pSpiSetStatus->Status = DesiredState ? 1 : 0;

	// Will non-internal IOCTL work?
	Status = WdfIoTargetSendInternalIoctlSynchronously(
		pDeviceContext->SpiTrackpadIoTarget,
		NULL,
		IOCTL_HID_SET_FEATURE,
		&HidMemoryDescriptor,
		NULL,
		NULL,
		NULL
	);

	if (!NT_SUCCESS(Status))
	{
		TraceEvents(
			TRACE_LEVEL_ERROR,
			TRACE_DRIVER,
			"%!FUNC! WdfIoTargetSendIoctlSynchronously failed with %!STATUS!",
			Status
		);
	}
	else
	{
		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_DRIVER,
			"%!FUNC! Changed trackpad status to %d",
			DesiredState
		);
	}

exit:
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Exit, Status = %!STATUS!",
		Status
	);

	return Status;
}

void AmtPtpPowerRecoveryTimerCallback(
	WDFTIMER Timer
)
{
	WDFDEVICE Device;
	PDEVICE_CONTEXT pDeviceContext;
	NTSTATUS Status = STATUS_SUCCESS;

	TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
	Device = WdfTimerGetParentObject(Timer);
	pDeviceContext = DeviceGetContext(Device);

	Status = AmtPtpSpiSetState(Device, TRUE);
	if (NT_SUCCESS(Status))
	{
		// Triage request and set status
		AmtPtpSpiInputIssueRequest(Device);
		pDeviceContext->DeviceStatus = D0ActiveAndConfigured;
	}

	TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit, Status = %!STATUS!", Status);
}


================================================
FILE: src/AmtPtpDeviceSpiKm/Device.h
================================================
/*++

Module Name:

    device.h

Abstract:

    This file contains the device definitions.

Environment:

    Kernel-mode Driver Framework

--*/

#include "public.h"

EXTERN_C_START

typedef struct _SPI_TRACKPAD_INFO {
	USHORT VendorId;
	USHORT ProductId;
	SHORT XMin;
	SHORT XMax;
	SHORT YMin;
	SHORT YMax;
} SPI_TRACKPAD_INFO, *PSPI_TRACKPAD_INFO;

// Stupid Microsoft only assigns a UCHAR for touch ID
// we could have a better approach
typedef struct _PTP_AAPL_MAPPING {
	SHORT OriginalX;
	SHORT OriginalY;
	INT8 ContactID;
} PTP_AAPL_MAPPING, *PPTP_AAPL_MAPPING;

#define MAPPING_MAX 10

typedef enum _REPORT_TYPE {
	PrecisionTouchpad = 0,
	Touchscreen = 1,
	InvalidReportType = 0x7fffffff,
} REPORT_TYPE;

typedef enum _PTP_AAPL_DEVICE_POWER_STATUS {
	D3 = 0,
	D0ActiveAndConfigured = 1,
	D0ActiveAndUnconfigured = 2
} PTP_AAPL_DEVICE_POWER_STATUS;

//
// The device context performs the same job as
// a WDM device extension in the driver frameworks
//
typedef struct _DEVICE_CONTEXT
{
	// IO content
	WDFDEVICE	SpiDevice;
	WDFIOTARGET SpiTrackpadIoTarget;
	PTP_AAPL_DEVICE_POWER_STATUS DeviceStatus;
	HANDLE		InputPollThreadHandle;
	WDFQUEUE	HidQueue;

	// SPI device metadata
	USHORT HidVendorID;
	USHORT HidProductID;
	USHORT HidVersionNumber;
	SPI_TRACKPAD_INFO TrackpadInfo;
	REPORT_TYPE ReportType;

	// Windows PTP context
	BOOLEAN PtpInputOn;
	BOOLEAN PtpReportTouch;
	BOOLEAN PtpReportButton;

	// Timer
	LARGE_INTEGER LastReportTime;
	WDFTIMER PowerOnRecoveryTimer;

	// List of buffers
	WDFLOOKASIDE HidReadBufferLookaside;

} DEVICE_CONTEXT, *PDEVICE_CONTEXT;

//
// This macro will generate an inline function called DeviceGetContext
// which will be used to get a pointer to the device context memory
// in a type safe manner.
//
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, DeviceGetContext)

//
// Request context
//
typedef struct _WORKER_REQUEST_CONTEXT {
	PDEVICE_CONTEXT DeviceContext;
	WDFMEMORY RequestMemory;
} WORKER_REQUEST_CONTEXT, *PWORKER_REQUEST_CONTEXT;

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WORKER_REQUEST_CONTEXT, WorkerRequestGetContext)

//
// Function to initialize the device and its callbacks
//
NTSTATUS
AmtPtpDeviceSpiKmCreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    );

EVT_WDF_DEVICE_PREPARE_HARDWARE AmtPtpEvtDevicePrepareHardware;
EVT_WDF_DEVICE_D0_ENTRY AmtPtpEvtDeviceD0Entry;
EVT_WDF_DEVICE_D0_EXIT AmtPtpEvtDeviceD0Exit;

NTSTATUS
AmtPtpEvtDeviceSelfManagedIoInitOrRestart(
	_In_ WDFDEVICE Device
);

PCHAR
DbgDevicePowerString(
	_In_ WDF_POWER_DEVICE_STATE Type
);

NTSTATUS
AmtPtpSpiSetState(
	_In_ WDFDEVICE Device,
	_In_ BOOLEAN DesiredState
);

void AmtPtpPowerRecoveryTimerCallback(
	WDFTIMER Timer
);

EXTERN_C_END


================================================
FILE: src/AmtPtpDeviceSpiKm/Driver.c
================================================
/*++

Module Name:

    driver.c

Abstract:

    This file contains the driver entry points and callbacks.

Environment:

    Kernel-mode Driver Framework

--*/

#include "driver.h"
#include "driver.tmh"

#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, AmtPtpDeviceSpiKmEvtDeviceAdd)
#pragma alloc_text (PAGE, AmtPtpDeviceSpiKmEvtDriverContextCleanup)
#endif

NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:
    DriverEntry initializes the driver and is the first routine called by the
    system after the driver is loaded. DriverEntry specifies the other entry
    points in the function driver, such as EvtDevice and DriverUnload.

Parameters Description:

    DriverObject - represents the instance of the function driver that is loaded
    into memory. DriverEntry must initialize members of DriverObject before it
    returns to the caller. DriverObject is allocated by the system before the
    driver is loaded, and it is released by the system after the system unloads
    the function driver from memory.

    RegistryPath - represents the driver specific path in the Registry.
    The function driver can use the path to store driver related data between
    reboots. The path does not store hardware instance specific data.

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise.

--*/
{
    WDF_DRIVER_CONFIG config;
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES attributes;

    //
    // Initialize WPP Tracing
    //
    WPP_INIT_TRACING(DriverObject, RegistryPath);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
	KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "DriverEntry Entry \n"));

    //
    // Register a cleanup callback so that we can call WPP_CLEANUP when
    // the framework driver object is deleted during driver unload.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.EvtCleanupCallback = AmtPtpDeviceSpiKmEvtDriverContextCleanup;

    WDF_DRIVER_CONFIG_INIT(&config,
                           AmtPtpDeviceSpiKmEvtDeviceAdd
                           );

    status = WdfDriverCreate(DriverObject,
                             RegistryPath,
                             &attributes,
                             &config,
                             WDF_NO_HANDLE
                             );

    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
		KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "WdfDriverCreate failed \n"));
        WPP_CLEANUP(DriverObject);
        return status;
    }

	KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "DriverEntry Exit \n"));
    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");

    return status;
}

NTSTATUS
AmtPtpDeviceSpiKmEvtDeviceAdd(
    _In_    WDFDRIVER       Driver,
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
/*++
Routine Description:

    EvtDeviceAdd is called by the framework in response to AddDevice
    call from the PnP manager. We create and initialize a device object to
    represent a new instance of the device.

Arguments:

    Driver - Handle to a framework driver object created in DriverEntry

    DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS status;

    UNREFERENCED_PARAMETER(Driver);
    PAGED_CODE();

    TraceEvents(
		TRACE_LEVEL_INFORMATION, 
		TRACE_DRIVER, 
		"%!FUNC! Entry"
	);

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Set FDO driver filter"
	);

	WdfFdoInitSetFilter(DeviceInit);
	WdfPdoInitAllowForwardingRequestToParent(DeviceInit);

    status = AmtPtpDeviceSpiKmCreateDevice(DeviceInit);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");

    return status;
}

VOID
AmtPtpDeviceSpiKmEvtDriverContextCleanup(
    _In_ WDFOBJECT DriverObject
    )
/*++
Routine Description:

    Free all the resources allocated in DriverEntry.

Arguments:

    DriverObject - handle to a WDF Driver object.

Return Value:

    VOID.

--*/
{
    UNREFERENCED_PARAMETER(DriverObject);
    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    //
    // Stop WPP Tracing
    //
    WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER) DriverObject));
}


================================================
FILE: src/AmtPtpDeviceSpiKm/Driver.h
================================================
/*++

Module Name:

    driver.h

Abstract:

    This file contains the driver definitions.

Environment:

    Kernel-mode Driver Framework

--*/

#include <ntddk.h>
#include <wdf.h>
#include <initguid.h>
#include <hidport.h>

#include "device.h"
#include "queue.h"
#include "trace.h"

#include "AppleDefinition.h"
#include "Hid.h"
#include "Input.h"

EXTERN_C_START

//
// WDFDRIVER Events
//

DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD AmtPtpDeviceSpiKmEvtDeviceAdd;
EVT_WDF_OBJECT_CONTEXT_CLEANUP AmtPtpDeviceSpiKmEvtDriverContextCleanup;

//
// Pool Tag
//
#define PTP_LIST_POOL_TAG 'LTPA'

//
// State Switch Max Retries
//
#define STATE_SWITCH_MAX_RETRIES 5

EXTERN_C_END


================================================
FILE: src/AmtPtpDeviceSpiKm/HID/SpiTrackpadSeries1.h
================================================
// Trackpad HID definition for MacBook8, 9, 10

#pragma once

#include "..\HidCommon.h"

#define AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_1 \
	BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
		/* Begin a byte */ \
		LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \
		USAGE, 0x47, /* Usage: Confidence */ \
		USAGE, 0x42, /* Usage: Tip switch */ \
		REPORT_COUNT, 0x02, /* Report Count: 2 */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x01, /* Report Count: 1 */ \
		REPORT_SIZE, 0x03, /* Report Size: 3 */ \
		LOGICAL_MAXIMUM, 0x03, /* Logical Maximum: 3 */ \
		USAGE, 0x51, /* Usage: Contract Identifier */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		/* End of a byte */ \
		/* Begin of 4 bytes */ \
		/* Size is hard-coded at this moment */ \
		/* This hard-coded size is designed for MacBook 8/9/10 */ \
		USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
		LOGICAL_MAXIMUM_2, 0xaa, 0x29, /* Logical Maximum: 10666 (See defintion) */ \
		REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \
		UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \
		UNIT, 0x11, /* Unit: SI Length (cm) */ \
		USAGE, 0x30, /* Usage: X */ \
		PHYSICAL_MAXIMUM_2, 0x5e, 0x04, /* Physical Maximum: 1118 (See Apple Spec) */ \
		REPORT_COUNT, 0x01, /* Report count: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM_2, 0xc7, 0x02, /* Physical Maximum: 711 (See Apple Spec) */ \
		LOGICAL_MAXIMUM_2, 0xaf, 0x1e, /* Logical Maximum: 7855 (See definition) */ \
		USAGE, 0x31, /* Usage: Y */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \
		UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \
		UNIT, 0x00, /* Unit: None */ \
		/* End of 4 bytes */ \
	END_COLLECTION /* End Collection */ \

#define AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_2 \
	BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
		/* Begin a byte */ \
		LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \
		USAGE, 0x47, /* Usage: Confidence */ \
		USAGE, 0x42, /* Usage: Tip switch */ \
		REPORT_COUNT, 0x02, /* Report Count: 2 */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x01, /* Report Count: 1 */ \
		REPORT_SIZE, 0x03, /* Report Size: 3 */ \
		LOGICAL_MAXIMUM, 0x03, /* Logical Maximum: 3 */ \
		USAGE, 0x51, /* Usage: Contract Identifier */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		/* End of a byte */ \
		/* Begin of 4 bytes */ \
		/* Size is hard-coded at this moment */ \
		USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
		LOGICAL_MAXIMUM_2, 0xaa, 0x29, /* Logical Maximum: 10666 (See defintion) */ \
		REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \
		UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \
		UNIT, 0x11, /* Unit: SI Length (cm) */ \
		USAGE, 0x30, /* Usage: X */ \
		PHYSICAL_MAXIMUM_2, 0x5e, 0x04, /* Physical Maximum: 1118 (See Apple Spec) */ \
		REPORT_COUNT, 0x01, /* Report count: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM_2, 0xc7, 0x02, /* Physical Maximum: 711 (See Apple Spec) */ \
		LOGICAL_MAXIMUM_2, 0xaf, 0x1e, /* Logical Maximum: 7855 (See definition) */ \
		USAGE, 0x31, /* Usage: Y */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		/* End of 4 bytes */ \
	END_COLLECTION /* End Collection */ \

#define AAPL_SPI_SERIES1_PTP_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x05, /* Usage: Touch Pad */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_1, /* 1 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_1, /* 2 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_2, /* 3 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_1, /* 4 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_2, /* 5 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \
		UNIT_2, 0x01, 0x10, /* Time: Second */ \
		PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		USAGE, 0x56, /* Usage: Scan Time */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE, 0x54, /* Usage: Contact Count */ \
		LOGICAL_MAXIMUM, 0x7f, \
		REPORT_SIZE, 0x08, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE_PAGE, 0x09, /* Usage Page: Button */ \
		USAGE, 0x01, /* Button 1 */ \
		LOGICAL_MAXIMUM, 0x01, \
		REPORT_SIZE, 0x01, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x07, \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		REPORT_ID, REPORTID_DEVICE_CAPS, \
		USAGE, 0x55, /* Usage: Maximum Contacts */ \
		USAGE, 0x59, /* Usage: Touchpad Button Type*/ \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT, 0x02, \
		FEATURE, 0x02, \
		USAGE_PAGE_1, 0x00, 0xff, \
		REPORT_ID, REPORTID_PTPHQA, \
		USAGE, 0xc5, \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT_2, 0x00, 0x01, \
		FEATURE, 0x02, \
	END_COLLECTION /* End Collection */

#define AAPL_SPI_SERIES1_TOUCHSCREEN_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x04, /* Usage: Touch Screen */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_1, /* 1 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_1, /* 2 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_2, /* 3 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_1, /* 4 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES1_PTP_FINGER_COLLECTION_2, /* 5 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \
		UNIT_2, 0x01, 0x10, /* Time: Second */ \
		PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		USAGE, 0x56, /* Usage: Scan Time */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE, 0x54, /* Usage: Contact Count */ \
		LOGICAL_MAXIMUM, 0x7f, \
		REPORT_SIZE, 0x08, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE_PAGE, 0x09, /* Usage Page: Button */ \
		USAGE, 0x01, /* Button 1 */ \
		LOGICAL_MAXIMUM, 0x01, \
		REPORT_SIZE, 0x01, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x07, \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		REPORT_ID, REPORTID_DEVICE_CAPS, \
		USAGE, 0x55, /* Usage: Maximum Contacts */ \
		USAGE, 0x59, /* Usage: Touchpad Button Type*/ \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT, 0x02, \
		FEATURE, 0x02, \
		USAGE_PAGE_1, 0x00, 0xff, \
		REPORT_ID, REPORTID_PTPHQA, \
		USAGE, 0xc5, \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT_2, 0x00, 0x01, \
		FEATURE, 0x02, \
	END_COLLECTION /* End Collection */

================================================
FILE: src/AmtPtpDeviceSpiKm/HID/SpiTrackpadSeries2.h
================================================
// Trackpad HID definition for MacBookPro 10, 11

#pragma once

#include "..\HidCommon.h"

#define AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_1 \
	BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
		/* Begin a byte */ \
		LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \
		USAGE, 0x47, /* Usage: Confidence */ \
		USAGE, 0x42, /* Usage: Tip switch */ \
		REPORT_COUNT, 0x02, /* Report Count: 2 */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x01, /* Report Count: 1 */ \
		REPORT_SIZE, 0x03, /* Report Size: 3 */ \
		LOGICAL_MAXIMUM, 0x03, /* Logical Maximum: 3 */ \
		USAGE, 0x51, /* Usage: Contract Identifier */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		/* End of a byte */ \
		/* Begin of 4 bytes */ \
		/* Size is hard-coded at this moment */ \
		/* This hard-coded size is designed for MacBookPro 11,1 */ \
		USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
		LOGICAL_MAXIMUM_2, 0x2e, 0x27, /* Logical Maximum: 10030 (See defintion) */ \
		REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \
		UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \
		UNIT, 0x11, /* Unit: SI Length (cm) */ \
		USAGE, 0x30, /* Usage: X */ \
		PHYSICAL_MAXIMUM_2, 0x28, 0x04, /* Physical Maximum: 1064 (See Apple Spec) */ \
		REPORT_COUNT, 0x01, /* Report count: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM_2, 0x05, 0x03, /* Physical Maximum: 773 (See Apple Spec) */ \
		LOGICAL_MAXIMUM_2, 0xe0, 0x1a, /* Logical Maximum: 6880 (See definition) */ \
		USAGE, 0x31, /* Usage: Y */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \
		UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \
		UNIT, 0x00, /* Unit: None */ \
		/* End of 4 bytes */ \
	END_COLLECTION /* End Collection */ \

#define AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_2 \
	BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
		/* Begin a byte */ \
		LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \
		USAGE, 0x47, /* Usage: Confidence */ \
		USAGE, 0x42, /* Usage: Tip switch */ \
		REPORT_COUNT, 0x02, /* Report Count: 2 */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x01, /* Report Count: 1 */ \
		REPORT_SIZE, 0x03, /* Report Size: 3 */ \
		LOGICAL_MAXIMUM, 0x03, /* Logical Maximum: 3 */ \
		USAGE, 0x51, /* Usage: Contract Identifier */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		/* End of a byte */ \
		/* Begin of 4 bytes */ \
		/* Size is hard-coded at this moment */ \
		USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
		LOGICAL_MAXIMUM_2, 0x2e, 0x27, /* Logical Maximum: 10030 (See defintion) */ \
		REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \
		UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \
		UNIT, 0x11, /* Unit: SI Length (cm) */ \
		USAGE, 0x30, /* Usage: X */ \
		PHYSICAL_MAXIMUM_2, 0x28, 0x04, /* Physical Maximum: 1064 (See Apple Spec) */ \
		REPORT_COUNT, 0x01, /* Report count: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM_2, 0x05, 0x03, /* Physical Maximum: 773 (See Apple Spec) */ \
		LOGICAL_MAXIMUM_2, 0xe0, 0x1a, /* Logical Maximum: 6880 (See definition) */ \
		USAGE, 0x31, /* Usage: Y */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		/* End of 4 bytes */ \
	END_COLLECTION /* End Collection */ \

#define AAPL_SPI_SERIES2_PTP_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x05, /* Usage: Touch Pad */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_1, /* 1 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_1, /* 2 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_2, /* 3 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_1, /* 4 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_2, /* 5 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \
		UNIT_2, 0x01, 0x10, /* Time: Second */ \
		PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		USAGE, 0x56, /* Usage: Scan Time */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE, 0x54, /* Usage: Contact Count */ \
		LOGICAL_MAXIMUM, 0x7f, \
		REPORT_SIZE, 0x08, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE_PAGE, 0x09, /* Usage Page: Button */ \
		USAGE, 0x01, /* Button 1 */ \
		LOGICAL_MAXIMUM, 0x01, \
		REPORT_SIZE, 0x01, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x07, \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		REPORT_ID, REPORTID_DEVICE_CAPS, \
		USAGE, 0x55, /* Usage: Maximum Contacts */ \
		USAGE, 0x59, /* Usage: Touchpad Button Type*/ \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT, 0x02, \
		FEATURE, 0x02, \
		USAGE_PAGE_1, 0x00, 0xff, \
		REPORT_ID, REPORTID_PTPHQA, \
		USAGE, 0xc5, \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT_2, 0x00, 0x01, \
		FEATURE, 0x02, \
	END_COLLECTION /* End Collection */

#define AAPL_SPI_SERIES2_TOUCHSCREEN_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x04, /* Usage: Touch Screen */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_1, /* 1 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_1, /* 2 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_2, /* 3 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_1, /* 4 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES2_PTP_FINGER_COLLECTION_2, /* 5 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \
		UNIT_2, 0x01, 0x10, /* Time: Second */ \
		PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		USAGE, 0x56, /* Usage: Scan Time */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE, 0x54, /* Usage: Contact Count */ \
		LOGICAL_MAXIMUM, 0x7f, \
		REPORT_SIZE, 0x08, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE_PAGE, 0x09, /* Usage Page: Button */ \
		USAGE, 0x01, /* Button 1 */ \
		LOGICAL_MAXIMUM, 0x01, \
		REPORT_SIZE, 0x01, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x07, \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		REPORT_ID, REPORTID_DEVICE_CAPS, \
		USAGE, 0x55, /* Usage: Maximum Contacts */ \
		USAGE, 0x59, /* Usage: Touchpad Button Type*/ \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT, 0x02, \
		FEATURE, 0x02, \
		USAGE_PAGE_1, 0x00, 0xff, \
		REPORT_ID, REPORTID_PTPHQA, \
		USAGE, 0xc5, \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT_2, 0x00, 0x01, \
		FEATURE, 0x02, \
	END_COLLECTION /* End Collection */

================================================
FILE: src/AmtPtpDeviceSpiKm/HID/SpiTrackpadSeries3.h
================================================
// Trackpad HID definition for MacBookPro 13, 14

#pragma once

#include "..\HidCommon.h"

#define AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_1 \
	BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
		/* Begin a byte */ \
		LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \
		USAGE, 0x47, /* Usage: Confidence */ \
		USAGE, 0x42, /* Usage: Tip switch */ \
		REPORT_COUNT, 0x02, /* Report Count: 2 */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x01, /* Report Count: 1 */ \
		REPORT_SIZE, 0x03, /* Report Size: 3 */ \
		LOGICAL_MAXIMUM, 0x03, /* Logical Maximum: 3 */ \
		USAGE, 0x51, /* Usage: Contract Identifier */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		/* End of a byte */ \
		/* Begin of 4 bytes */ \
		/* Size is hard-coded at this moment */ \
		/* This hard-coded size is designed for MacBookPro 13 / 14 */ \
		USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
		LOGICAL_MAXIMUM_2, 0xc0, 0x32, /* Logical Maximum: 12992 (See defintion) */ \
		REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \
		UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \
		UNIT, 0x11, /* Unit: SI Length (cm) */ \
		USAGE, 0x30, /* Usage: X */ \
		PHYSICAL_MAXIMUM_2, 0x48, 0x05, /* Physical Maximum: 1352 (See Apple Spec) */ \
		REPORT_COUNT, 0x01, /* Report count: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM_2, 0x44, 0x03, /* Physical Maximum: 836 (See Apple Spec) */ \
		LOGICAL_MAXIMUM_2, 0xaf, 0x1e, /* Logical Maximum: 7855 (See definition) */ \
		USAGE, 0x31, /* Usage: Y */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \
		UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \
		UNIT, 0x00, /* Unit: None */ \
		/* End of 4 bytes */ \
	END_COLLECTION /* End Collection */ \

#define AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_2 \
	BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
		/* Begin a byte */ \
		LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \
		USAGE, 0x47, /* Usage: Confidence */ \
		USAGE, 0x42, /* Usage: Tip switch */ \
		REPORT_COUNT, 0x02, /* Report Count: 2 */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x01, /* Report Count: 1 */ \
		REPORT_SIZE, 0x03, /* Report Size: 3 */ \
		LOGICAL_MAXIMUM, 0x03, /* Logical Maximum: 3 */ \
		USAGE, 0x51, /* Usage: Contract Identifier */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		/* End of a byte */ \
		/* Begin of 4 bytes */ \
		/* Size is hard-coded at this moment */ \
		USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
		LOGICAL_MAXIMUM_2, 0xc0, 0x32, /* Logical Maximum: 12992 (See defintion) */ \
		REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \
		UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \
		UNIT, 0x11, /* Unit: SI Length (cm) */ \
		USAGE, 0x30, /* Usage: X */ \
		PHYSICAL_MAXIMUM_2, 0x48, 0x05, /* Physical Maximum: 1352 (See Apple Spec) */ \
		REPORT_COUNT, 0x01, /* Report count: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM_2, 0x44, 0x03, /* Physical Maximum: 836 (See Apple Spec) */ \
		LOGICAL_MAXIMUM_2, 0xaf, 0x1e, /* Logical Maximum: 7855 (See definition) */ \
		USAGE, 0x31, /* Usage: Y */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		/* End of 4 bytes */ \
	END_COLLECTION /* End Collection */ \

#define AAPL_SPI_SERIES3_13_PTP_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x05, /* Usage: Touch Pad */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_1, /* 1 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_1, /* 2 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_2, /* 3 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_1, /* 4 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_2, /* 5 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \
		UNIT_2, 0x01, 0x10, /* Time: Second */ \
		PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		USAGE, 0x56, /* Usage: Scan Time */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE, 0x54, /* Usage: Contact Count */ \
		LOGICAL_MAXIMUM, 0x7f, \
		REPORT_SIZE, 0x08, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE_PAGE, 0x09, /* Usage Page: Button */ \
		USAGE, 0x01, /* Button 1 */ \
		LOGICAL_MAXIMUM, 0x01, \
		REPORT_SIZE, 0x01, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x07, \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		REPORT_ID, REPORTID_DEVICE_CAPS, \
		USAGE, 0x55, /* Usage: Maximum Contacts */ \
		USAGE, 0x59, /* Usage: Touchpad Button Type*/ \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT, 0x02, \
		FEATURE, 0x02, \
		USAGE_PAGE_1, 0x00, 0xff, \
		REPORT_ID, REPORTID_PTPHQA, \
		USAGE, 0xc5, \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT_2, 0x00, 0x01, \
		FEATURE, 0x02, \
	END_COLLECTION /* End Collection */

#define AAPL_SPI_SERIES3_13_TOUCHSCREEN_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x04, /* Usage: Touch Screen */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_1, /* 1 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_1, /* 2 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_2, /* 3 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_1, /* 4 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_13_PTP_FINGER_COLLECTION_2, /* 5 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \
		UNIT_2, 0x01, 0x10, /* Time: Second */ \
		PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		USAGE, 0x56, /* Usage: Scan Time */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE, 0x54, /* Usage: Contact Count */ \
		LOGICAL_MAXIMUM, 0x7f, \
		REPORT_SIZE, 0x08, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE_PAGE, 0x09, /* Usage Page: Button */ \
		USAGE, 0x01, /* Button 1 */ \
		LOGICAL_MAXIMUM, 0x01, \
		REPORT_SIZE, 0x01, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x07, \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		REPORT_ID, REPORTID_DEVICE_CAPS, \
		USAGE, 0x55, /* Usage: Maximum Contacts */ \
		USAGE, 0x59, /* Usage: Touchpad Button Type*/ \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT, 0x02, \
		FEATURE, 0x02, \
		USAGE_PAGE_1, 0x00, 0xff, \
		REPORT_ID, REPORTID_PTPHQA, \
		USAGE, 0xc5, \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT_2, 0x00, 0x01, \
		FEATURE, 0x02, \
	END_COLLECTION /* End Collection */

#define AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_1 \
	BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
		/* Begin a byte */ \
		LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \
		USAGE, 0x47, /* Usage: Confidence */ \
		USAGE, 0x42, /* Usage: Tip switch */ \
		REPORT_COUNT, 0x02, /* Report Count: 2 */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x01, /* Report Count: 1 */ \
		REPORT_SIZE, 0x03, /* Report Size: 3 */ \
		LOGICAL_MAXIMUM, 0x03, /* Logical Maximum: 3 */ \
		USAGE, 0x51, /* Usage: Contract Identifier */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		/* End of a byte */ \
		/* Begin of 4 bytes */ \
		/* Size is hard-coded at this moment */ \
		/* This hard-coded size is designed for MacBookPro 13 / 14 */ \
		USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
		LOGICAL_MAXIMUM_2, 0x48, 0x3c, /* Logical Maximum: 15432 (See defintion) */ \
		REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \
		UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \
		UNIT, 0x11, /* Unit: SI Length (cm) */ \
		USAGE, 0x30, /* Usage: X */ \
		PHYSICAL_MAXIMUM_2, 0x30, 0x06, /* Physical Maximum: 1584 (See Apple Spec) */ \
		REPORT_COUNT, 0x01, /* Report count: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM_2, 0xe0, 0x03, /* Physical Maximum: 992 (See Apple Spec) */ \
		LOGICAL_MAXIMUM_2, 0xe6, 0x24, /* Logical Maximum: 9446 (See definition) */ \
		USAGE, 0x31, /* Usage: Y */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \
		UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \
		UNIT, 0x00, /* Unit: None */ \
		/* End of 4 bytes */ \
	END_COLLECTION /* End Collection */ \

#define AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_2 \
	BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
		/* Begin a byte */ \
		LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \
		USAGE, 0x47, /* Usage: Confidence */ \
		USAGE, 0x42, /* Usage: Tip switch */ \
		REPORT_COUNT, 0x02, /* Report Count: 2 */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x01, /* Report Count: 1 */ \
		REPORT_SIZE, 0x03, /* Report Size: 3 */ \
		LOGICAL_MAXIMUM, 0x03, /* Logical Maximum: 3 */ \
		USAGE, 0x51, /* Usage: Contract Identifier */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_SIZE, 0x01, /* Report Size: 1 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		/* End of a byte */ \
		/* Begin of 4 bytes */ \
		/* Size is hard-coded at this moment */ \
		USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
		LOGICAL_MAXIMUM_2, 0x48, 0x3c, /* Logical Maximum: 15432 (See defintion) */ \
		REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \
		UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \
		UNIT, 0x11, /* Unit: SI Length (cm) */ \
		USAGE, 0x30, /* Usage: X */ \
		PHYSICAL_MAXIMUM_2, 0x30, 0x06, /* Physical Maximum: 1584 (See Apple Spec) */ \
		REPORT_COUNT, 0x01, /* Report count: 1 */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		PHYSICAL_MAXIMUM_2, 0xe0, 0x03, /* Physical Maximum: 992 (See Apple Spec) */ \
		LOGICAL_MAXIMUM_2, 0xe6, 0x24, /* Logical Maximum: 9446 (See definition) */ \
		USAGE, 0x31, /* Usage: Y */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		/* End of 4 bytes */ \
	END_COLLECTION /* End Collection */ \

#define AAPL_SPI_SERIES3_15_PTP_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x05, /* Usage: Touch Pad */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_1, /* 1 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_1, /* 2 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_2, /* 3 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_1, /* 4 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_2, /* 5 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \
		UNIT_2, 0x01, 0x10, /* Time: Second */ \
		PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		USAGE, 0x56, /* Usage: Scan Time */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE, 0x54, /* Usage: Contact Count */ \
		LOGICAL_MAXIMUM, 0x7f, \
		REPORT_SIZE, 0x08, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE_PAGE, 0x09, /* Usage Page: Button */ \
		USAGE, 0x01, /* Button 1 */ \
		LOGICAL_MAXIMUM, 0x01, \
		REPORT_SIZE, 0x01, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x07, \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		REPORT_ID, REPORTID_DEVICE_CAPS, \
		USAGE, 0x55, /* Usage: Maximum Contacts */ \
		USAGE, 0x59, /* Usage: Touchpad Button Type*/ \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT, 0x02, \
		FEATURE, 0x02, \
		USAGE_PAGE_1, 0x00, 0xff, \
		REPORT_ID, REPORTID_PTPHQA, \
		USAGE, 0xc5, \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT_2, 0x00, 0x01, \
		FEATURE, 0x02, \
	END_COLLECTION /* End Collection */

#define AAPL_SPI_SERIES3_15_TOUCHSCREEN_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x04, /* Usage: Touch Screen */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_1, /* 1 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_1, /* 2 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_2, /* 3 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_1, /* 4 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		USAGE, 0x22, /* Usage: Finger */ \
		AAPL_SPI_SERIES3_15_PTP_FINGER_COLLECTION_2, /* 5 */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \
		UNIT_2, 0x01, 0x10, /* Time: Second */ \
		PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \
		USAGE, 0x56, /* Usage: Scan Time */ \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE, 0x54, /* Usage: Contact Count */ \
		LOGICAL_MAXIMUM, 0x7f, \
		REPORT_SIZE, 0x08, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		USAGE_PAGE, 0x09, /* Usage Page: Button */ \
		USAGE, 0x01, /* Button 1 */ \
		LOGICAL_MAXIMUM, 0x01, \
		REPORT_SIZE, 0x01, \
		INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
		REPORT_COUNT, 0x07, \
		INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
		USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
		REPORT_ID, REPORTID_DEVICE_CAPS, \
		USAGE, 0x55, /* Usage: Maximum Contacts */ \
		USAGE, 0x59, /* Usage: Touchpad Button Type*/ \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT, 0x02, \
		FEATURE, 0x02, \
		USAGE_PAGE_1, 0x00, 0xff, \
		REPORT_ID, REPORTID_PTPHQA, \
		USAGE, 0xc5, \
		LOGICAL_MINIMUM, 0x00, \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, \
		REPORT_SIZE, 0x08, \
		REPORT_COUNT_2, 0x00, 0x01, \
		FEATURE, 0x02, \
	END_COLLECTION /* End Collection */

================================================
FILE: src/AmtPtpDeviceSpiKm/Hid.c
================================================
// Hid.c: HID-related routine

#include "Driver.h"
#include "Hid.tmh"

#ifndef __AAPL_HID_DESCRIPTOR_H__
#define __AAPL_HID_DESCRIPTOR_H__

HID_REPORT_DESCRIPTOR AmtPtpSpiFamily1ReportDescriptor[] = {
	AAPL_SPI_SERIES1_PTP_TLC,
	AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
	AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};

HID_REPORT_DESCRIPTOR AmtPtpSpiFamily1TouchscreenReportDescriptor[] = {
	AAPL_SPI_SERIES1_TOUCHSCREEN_TLC,
	AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
	AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};

CONST HID_DESCRIPTOR AmtPtpSpiFamily1DefaultHidDescriptor = {
	0x09,   // bLength
	0x21,   // bDescriptorType
	0x0100, // bcdHID
	0x00,   // bCountryCode
	0x01,   // bNumDescriptors
	{
		0x22,										// bDescriptorType
		sizeof(AmtPtpSpiFamily1ReportDescriptor)    // bDescriptorLength
	}
};

HID_REPORT_DESCRIPTOR AmtPtpSpiFamily2ReportDescriptor[] = {
	AAPL_SPI_SERIES2_PTP_TLC,
	AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
	AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};

HID_REPORT_DESCRIPTOR AmtPtpSpiFamily2TouchscreenReportDescriptor[] = {
	AAPL_SPI_SERIES2_TOUCHSCREEN_TLC,
	AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
	AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};

CONST HID_DESCRIPTOR AmtPtpSpiFamily2DefaultHidDescriptor = {
	0x09,   // bLength
	0x21,   // bDescriptorType
	0x0100, // bcdHID
	0x00,   // bCountryCode
	0x01,   // bNumDescriptors
	{
		0x22,										// bDescriptorType
		sizeof(AmtPtpSpiFamily2ReportDescriptor)    // bDescriptorLength
	}
};

HID_REPORT_DESCRIPTOR AmtPtpSpiFamily3aReportDescriptor[] = {
	AAPL_SPI_SERIES3_13_PTP_TLC,
	AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
	AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};

HID_REPORT_DESCRIPTOR AmtPtpSpiFamily3aTouchscreenReportDescriptor[] = {
	AAPL_SPI_SERIES3_13_TOUCHSCREEN_TLC,
	AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
	AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};

CONST HID_DESCRIPTOR AmtPtpSpiFamily3aDefaultHidDescriptor = {
	0x09,   // bLength
	0x21,   // bDescriptorType
	0x0100, // bcdHID
	0x00,   // bCountryCode
	0x01,   // bNumDescriptors
	{
		0x22,										// bDescriptorType
		sizeof(AmtPtpSpiFamily3aReportDescriptor)    // bDescriptorLength
	}
};

HID_REPORT_DESCRIPTOR AmtPtpSpiFamily3bReportDescriptor[] = {
	AAPL_SPI_SERIES3_15_PTP_TLC,
	AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
	AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};

HID_REPORT_DESCRIPTOR AmtPtpSpiFamily3bTouchscreenReportDescriptor[] = {
	AAPL_SPI_SERIES3_15_TOUCHSCREEN_TLC,
	AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
	AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};

CONST HID_DESCRIPTOR AmtPtpSpiFamily3bDefaultHidDescriptor = {
	0x09,   // bLength
	0x21,   // bDescriptorType
	0x0100, // bcdHID
	0x00,   // bCountryCode
	0x01,   // bNumDescriptors
	{
		0x22,										// bDescriptorType
		sizeof(AmtPtpSpiFamily3bReportDescriptor)    // bDescriptorLength
	}
};

#endif

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetHidDescriptor(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
)
{
	NTSTATUS Status = STATUS_SUCCESS;
	WDFMEMORY RequestMemory;
	size_t CopiedSize = 0;
	PDEVICE_CONTEXT pDeviceContext;
	BOOLEAN DescriptorFound = TRUE;

	PAGED_CODE();

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Entry"
	);

	pDeviceContext = DeviceGetContext(Device);
	Status = WdfRequestRetrieveOutputMemory(
		Request,
		&RequestMemory
	);

	if (!NT_SUCCESS(Status))
	{
		TraceEvents(
			TRACE_LEVEL_ERROR,
			TRACE_DRIVER,
			"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
			Status
		);

		goto exit;
	}

	// Get HID descriptor from registry
	switch (pDeviceContext->HidProductID)
	{
		// MacBook 9, 10
		case 0x0275:
		case 0x0279:
		// MacBookAir7,2 also use this fallback
		case 0x0290:
		case 0x0291:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Request HID Report Descriptor for Apple SPI Trackpad, Family 1"
			);

			CopiedSize = AmtPtpSpiFamily1DefaultHidDescriptor.bLength;
			Status = WdfMemoryCopyFromBuffer(
				RequestMemory,
				0,
				(PVOID)&AmtPtpSpiFamily1DefaultHidDescriptor,
				CopiedSize
			);

			if (!NT_SUCCESS(Status))
			{
				TraceEvents(
					TRACE_LEVEL_ERROR,
					TRACE_DRIVER,
					"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
					Status
				);
				return Status;
			}
			break;
		}
		// MacBookPro 11, 12 (13-inch). 15-inch is USB trackpad
		case 0x0272:
		case 0x0273:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Request HID Report Descriptor for Apple SPI Trackpad, Family 2"
			);

			CopiedSize = AmtPtpSpiFamily2DefaultHidDescriptor.bLength;
			Status = WdfMemoryCopyFromBuffer(
				RequestMemory,
				0,
				(PVOID)&AmtPtpSpiFamily2DefaultHidDescriptor,
				CopiedSize
			);

			if (!NT_SUCCESS(Status))
			{
				TraceEvents(
					TRACE_LEVEL_ERROR,
					TRACE_DRIVER,
					"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
					Status
				);
				return Status;
			}
			break;
		}
		// MacBookPro 13, 14 (13-inch)
		case 0x0276:
		case 0x0277:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Request HID Report Descriptor for Apple SPI Trackpad, Family 3A"
			);

			CopiedSize = AmtPtpSpiFamily3aDefaultHidDescriptor.bLength;
			Status = WdfMemoryCopyFromBuffer(
				RequestMemory,
				0,
				(PVOID)&AmtPtpSpiFamily3aDefaultHidDescriptor,
				CopiedSize
			);

			if (!NT_SUCCESS(Status))
			{
				TraceEvents(
					TRACE_LEVEL_ERROR,
					TRACE_DRIVER,
					"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
					Status
				);
				return Status;
			}
			break;
		}
		// MacBookPro 13, 14 (15-inch)
		case 0x0278:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Request HID Report Descriptor for Apple SPI Trackpad, Family 3B"
			);

			CopiedSize = AmtPtpSpiFamily3bDefaultHidDescriptor.bLength;
			Status = WdfMemoryCopyFromBuffer(
				RequestMemory,
				0,
				(PVOID)&AmtPtpSpiFamily3bDefaultHidDescriptor,
				CopiedSize
			);

			if (!NT_SUCCESS(Status))
			{
				TraceEvents(
					TRACE_LEVEL_ERROR,
					TRACE_DRIVER,
					"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
					Status
				);
				return Status;
			}
			break;
		}
		default:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Request HID Report Descriptor not found"
			);

			DescriptorFound = FALSE;
			break;
		}
	}

	if (DescriptorFound)
	{
		WdfRequestSetInformation(
			Request,
			CopiedSize
		);
	}
	else
	{
		Status = STATUS_NOT_FOUND;
	}

exit:
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Exit"
	);

	return Status;
}

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetDeviceAttribs(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_CONTEXT pDeviceContext = DeviceGetContext(Device);
	PHID_DEVICE_ATTRIBUTES pDeviceAttributes = NULL;

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Entry"
	);

	Status = WdfRequestRetrieveOutputBuffer(
		Request,
		sizeof(HID_DEVICE_ATTRIBUTES),
		&pDeviceAttributes,
		NULL
	);

	if (!NT_SUCCESS(Status)) 
	{
		TraceEvents(
			TRACE_LEVEL_ERROR,
			TRACE_DRIVER,
			"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
			Status
		);
		
		goto exit;
	}

	pDeviceAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES);
	// Okay here's one thing: we cannot report the real ID here, otherwise there's will be some great conflict with the USB/BT driver.
	// Therefore Vendor ID is changed to a hardcoded number
	pDeviceAttributes->VendorID = DEVICE_VID;
	pDeviceAttributes->ProductID = pDeviceContext->HidProductID;
	pDeviceAttributes->VersionNumber = pDeviceContext->HidVersionNumber;

	WdfRequestSetInformation(
		Request,
		sizeof(HID_DEVICE_ATTRIBUTES)
	);

exit:
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Exit"
	);

	return Status;
}

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetReportDescriptor(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
)
{
	NTSTATUS Status = STATUS_SUCCESS;
	size_t CopiedSize = 0;
	WDFMEMORY RequestMemory;
	PDEVICE_CONTEXT pDeviceContext;
	PVOID Descriptor = NULL;

	PAGED_CODE();

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Entry"
	);

	pDeviceContext = DeviceGetContext(Device);
	Status = WdfRequestRetrieveOutputMemory(
		Request,
		&RequestMemory
	);

	if (!NT_SUCCESS(Status))
	{
		TraceEvents(
			TRACE_LEVEL_ERROR,
			TRACE_DRIVER,
			"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
			Status
		);
		
		goto exit;
	}

	switch (pDeviceContext->HidProductID)
	{
		// MacBook 9, 10
		case 0x0275:
		case 0x0279:
		// MacBookAir7,2 also use this fallback
		case 0x0290:
		case 0x0291:
		{
			if (pDeviceContext->ReportType == PrecisionTouchpad)
			{
				CopiedSize = AmtPtpSpiFamily1DefaultHidDescriptor.DescriptorList[0].wReportLength;
				Descriptor = (PVOID) &AmtPtpSpiFamily1ReportDescriptor;
			}
			else if (pDeviceContext->ReportType == Touchscreen)
			{
				CopiedSize = AmtPtpSpiFamily1DefaultHidDescriptor.DescriptorList[0].wReportLength;
				Descriptor = (PVOID) &AmtPtpSpiFamily1TouchscreenReportDescriptor;
			}
			break;
		}
		// MacBookPro 11, 12 (13-inch)
		case 0x0272:
		case 0x0273:
		{
			if (pDeviceContext->ReportType == PrecisionTouchpad)
			{
				CopiedSize = AmtPtpSpiFamily2DefaultHidDescriptor.DescriptorList[0].wReportLength;
				Descriptor = (PVOID)&AmtPtpSpiFamily2ReportDescriptor;
			}
			else if (pDeviceContext->ReportType == Touchscreen)
			{
				CopiedSize = AmtPtpSpiFamily2DefaultHidDescriptor.DescriptorList[0].wReportLength;
				Descriptor = (PVOID)&AmtPtpSpiFamily2TouchscreenReportDescriptor;
			}
			break;
		}
		// MacBookPro 13, 14 (13-inch)
		case 0x0276:
		case 0x0277:
		{
			if (pDeviceContext->ReportType == PrecisionTouchpad)
			{
				CopiedSize = AmtPtpSpiFamily3aDefaultHidDescriptor.DescriptorList[0].wReportLength;
				Descriptor = (PVOID)&AmtPtpSpiFamily3aReportDescriptor;
			}
			else if (pDeviceContext->ReportType == Touchscreen)
			{
				CopiedSize = AmtPtpSpiFamily3aDefaultHidDescriptor.DescriptorList[0].wReportLength;
				Descriptor = (PVOID)&AmtPtpSpiFamily3aTouchscreenReportDescriptor;
			}
			break;
		}
		// MacBookPro 13, 14 (15-inch)
		case 0x0278:
		{
			if (pDeviceContext->ReportType == PrecisionTouchpad)
			{
				CopiedSize = AmtPtpSpiFamily3bDefaultHidDescriptor.DescriptorList[0].wReportLength;
				Descriptor = (PVOID)&AmtPtpSpiFamily3bReportDescriptor;
			}
			else if (pDeviceContext->ReportType == Touchscreen)
			{
				CopiedSize = AmtPtpSpiFamily3bDefaultHidDescriptor.DescriptorList[0].wReportLength;
				Descriptor = (PVOID)&AmtPtpSpiFamily3bTouchscreenReportDescriptor;
			}
			break;
		}
		default:
		{
			break;
		}
	}

	if (Descriptor == NULL)
	{
		Status = STATUS_NOT_FOUND;
		TraceEvents(
			TRACE_LEVEL_WARNING,
			TRACE_DRIVER,
			"%!FUNC! Device HID descriptor not found"
		);
		return Status;
	}

	if (CopiedSize == 0)
	{
		Status = STATUS_INVALID_DEVICE_STATE;
		TraceEvents(
			TRACE_LEVEL_WARNING,
			TRACE_DRIVER,
			"%!FUNC! Device HID report length is zero"
		);
		return Status;
	}

	Status = WdfMemoryCopyFromBuffer(
		RequestMemory,
		0,
		Descriptor,
		CopiedSize
	);

	if (!NT_SUCCESS(Status)) {

		TraceEvents(
			TRACE_LEVEL_ERROR,
			TRACE_DRIVER,
			"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
			Status
		);
		return Status;

	}

	WdfRequestSetInformation(
		Request,
		CopiedSize
	);

exit:
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Exit"
	);

	return Status;
}

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetStrings(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request,
	_Out_ BOOLEAN *Pending
)
{
	NTSTATUS Status = STATUS_SUCCESS;
	PDEVICE_CONTEXT pDeviceContext;
	BOOLEAN RequestSent;
	WDF_REQUEST_SEND_OPTIONS SendOptions;

	PAGED_CODE();

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! called"
	);

	pDeviceContext = DeviceGetContext(Device);

	// Forward the IRP to our upstream IO target
	// We don't really care about the content
	WdfRequestFormatRequestUsingCurrentType(Request);
	WDF_REQUEST_SEND_OPTIONS_INIT(
		&SendOptions,
		WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET
	);

	RequestSent = WdfRequestSend(
		Request,
		pDeviceContext->SpiTrackpadIoTarget,
		&SendOptions
	);

	*Pending = TRUE;

	if (!RequestSent)
	{
		Status = WdfRequestGetStatus(Request);
		*Pending = FALSE;
	}

	return Status;
}

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpReportFeatures(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
)
{
	NTSTATUS Status;
	PDEVICE_CONTEXT pDeviceContext;
	PHID_XFER_PACKET pHidPacket;
	WDF_REQUEST_PARAMETERS RequestParameters;
	size_t ReportSize;

	PAGED_CODE();

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Entry"
	);

	Status = STATUS_SUCCESS;
	pDeviceContext = DeviceGetContext(Device);

	WDF_REQUEST_PARAMETERS_INIT(&RequestParameters);
	WdfRequestGetParameters(Request, &RequestParameters);

	if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET))
	{
		Status = STATUS_BUFFER_TOO_SMALL;
		goto exit;
	}

	pHidPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(Request)->UserBuffer;
	if (pHidPacket == NULL)
	{
		Status = STATUS_INVALID_DEVICE_REQUEST;
		goto exit;
	}

	switch (pHidPacket->reportId)
	{
		case REPORTID_DEVICE_CAPS:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_DEVICE_CAPS is requested"
			);

			// Size sanity check
			ReportSize = sizeof(PTP_DEVICE_CAPS_FEATURE_REPORT);
			if (pHidPacket->reportBufferLen < ReportSize) {
				Status = STATUS_INVALID_BUFFER_SIZE;
				TraceEvents(
					TRACE_LEVEL_ERROR,
					TRACE_DRIVER,
					"%!FUNC! Report buffer is too small"
				);
				goto exit;
			}

			PPTP_DEVICE_CAPS_FEATURE_REPORT capsReport = (PPTP_DEVICE_CAPS_FEATURE_REPORT) pHidPacket->reportBuffer;

			capsReport->MaximumContactPoints = PTP_MAX_CONTACT_POINTS;
			capsReport->ButtonType = PTP_BUTTON_TYPE_CLICK_PAD;
			capsReport->ReportID = REPORTID_DEVICE_CAPS;

			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_DEVICE_CAPS has maximum contact points of %d",
				capsReport->MaximumContactPoints
			);
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_DEVICE_CAPS has touchpad type %d",
				capsReport->ButtonType
			);
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_DEVICE_CAPS is fulfilled"
			);

			break;
		}
		case REPORTID_PTPHQA:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_PTPHQA is requested"
			);

			// Size sanity check
			ReportSize = sizeof(PTP_DEVICE_HQA_CERTIFICATION_REPORT);
			if (pHidPacket->reportBufferLen < ReportSize) 
			{
				Status = STATUS_INVALID_BUFFER_SIZE;
				TraceEvents(
					TRACE_LEVEL_ERROR,
					TRACE_DRIVER,
					"%!FUNC! Report buffer is too small."
				);
				goto exit;
			}

			PPTP_DEVICE_HQA_CERTIFICATION_REPORT certReport = (PPTP_DEVICE_HQA_CERTIFICATION_REPORT) pHidPacket->reportBuffer;

			*certReport->CertificationBlob = DEFAULT_PTP_HQA_BLOB;
			certReport->ReportID = REPORTID_PTPHQA;

			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_PTPHQA is fulfilled"
			);

			break;
		}
		default:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Unsupported type %d is requested",
				pHidPacket->reportId
			);

			Status = STATUS_NOT_SUPPORTED;
			goto exit;
		}
	}

exit:
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Exit"
	);

	return Status;
}

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpSetFeatures(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
)
{
	NTSTATUS        Status;
	PHID_XFER_PACKET pHidPacket;
	WDF_REQUEST_PARAMETERS RequestParameters;
	PDEVICE_CONTEXT pDeviceContext;

	PAGED_CODE();

	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Entry"
	);

	Status = STATUS_SUCCESS;
	pDeviceContext = DeviceGetContext(Device);

	WDF_REQUEST_PARAMETERS_INIT(&RequestParameters);
	WdfRequestGetParameters(Request, &RequestParameters);

	if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET))
	{
		Status = STATUS_BUFFER_TOO_SMALL;
		goto exit;
	}

	pHidPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(Request)->UserBuffer;
	if (pHidPacket == NULL)
	{
		Status = STATUS_INVALID_DEVICE_REQUEST;
		goto exit;
	}

	switch (pHidPacket->reportId)
	{
		case REPORTID_REPORTMODE:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_REPORTMODE is requested"
			);

			PPTP_DEVICE_INPUT_MODE_REPORT DeviceInputMode = (PPTP_DEVICE_INPUT_MODE_REPORT) pHidPacket->reportBuffer;
			switch (DeviceInputMode->Mode)
			{
				case PTP_COLLECTION_MOUSE:
				{
					TraceEvents(
						TRACE_LEVEL_INFORMATION,
						TRACE_DRIVER,
						"%!FUNC! Report REPORTID_REPORTMODE requested Mouse Input"
					);

					pDeviceContext->PtpInputOn = FALSE;
					break;
				}
				case PTP_COLLECTION_WINDOWS:
				{

					TraceEvents(
						TRACE_LEVEL_INFORMATION,
						TRACE_DRIVER,
						"%!FUNC! Report REPORTID_REPORTMODE requested Windows PTP Input"
					);

					pDeviceContext->PtpInputOn = TRUE;
					break;
				}
			}

			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_REPORTMODE is fulfilled"
			);
			break;
		}
		case REPORTID_FUNCSWITCH:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_FUNCSWITCH is requested"
			);

			PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT InputSelection = (PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT) pHidPacket->reportBuffer;
			pDeviceContext->PtpReportButton = InputSelection->ButtonReport;
			pDeviceContext->PtpReportTouch = InputSelection->SurfaceReport;

			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_FUNCSWITCH requested Button = %d, Surface = %d",
				InputSelection->ButtonReport,
				InputSelection->SurfaceReport
			);

			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Report REPORTID_FUNCSWITCH is fulfilled"
			);

			break;
		}
		default:
		{
			TraceEvents(
				TRACE_LEVEL_INFORMATION,
				TRACE_DRIVER,
				"%!FUNC! Unsupported type %d is requested",
				pHidPacket->reportId
			);

			Status = STATUS_NOT_SUPPORTED;
			goto exit;
		}
	}

exit:
	TraceEvents(
		TRACE_LEVEL_INFORMATION,
		TRACE_DRIVER,
		"%!FUNC! Exit"
	);

	return Status;
}


================================================
FILE: src/AmtPtpDeviceSpiKm/Hid.h
================================================
#pragma once

#include <hidport.h>

#include "AppleDefinition.h"
#include "HidCommon.h"

// Device family metadata
#include "HID\SpiTrackpadSeries1.h"
#include "HID\SpiTrackpadSeries2.h"
#include "HID\SpiTrackpadSeries3.h"

typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR;

#define REPORT_BUFFER_SIZE   1024
#define DEVICE_VERSION 0x01
#define MAX_FINGERS	16

#define AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC \
	USAGE_PAGE_1, 0x00, 0xff, /* Usage Page: Vendor defined */ \
	USAGE, 0x01, /* Usage: Vendor Usage 0x01 */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_UMAPP_CONF, /* Report ID: User-mode Application configuration */ \
		USAGE, 0x01, /* Usage: Vendor Usage 0x01 */ \
		LOGICAL_MINIMUM, 0x00, /* Logical Minimum 0 */ \
		LOGICAL_MAXIMUM_2, 0xff, 0x00, /* Logical Maximum 255 */ \
		REPORT_SIZE, 0x08, /* Report Size: 8 */ \
		REPORT_COUNT, 0x03, /* Report Count: 3 */ \
		FEATURE, 0x02, /* Feature: (Data, Var, Abs) */ \
	END_COLLECTION

#define AAPL_PTP_WINDOWS_CONFIGURATION_TLC \
	USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
	USAGE, 0x0e, /* Usage: Configuration */ \
	BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \
		REPORT_ID, REPORTID_REPORTMODE, /* Report ID: Mode Selection */ \
		USAGE, 0x22, /* Usage: Finger */ \
		BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \
			USAGE, 0x52, /* Usage: Input Mode */ \
			LOGICAL_MINIMUM, 0x00, /* Logical Minumum: 0 finger */ \
			LOGICAL_MAXIMUM, MAX_FINGERS, /* Logical Maximum: MAX_TOUCH_COUNT fingers */ \
			REPORT_SIZE, 0x08, /* Report Size: 0x08 */ \
			REPORT_COUNT, 0x01, /* Report Count: 0x01 */ \
			FEATURE, 0x02, /* Feature: (Data, Var, Abs) */ \
		END_COLLECTION, /* End Collection */ \
		BEGIN_COLLECTION, 0x00, /* Begin Collection: Physical */ \
			REPORT_ID, REPORTID_FUNCSWITCH, /* Report ID: Function Switch */ \
			USAGE, BUTTON_SWITCH, /* Usage: Button Switch */ \
			USAGE, SURFACE_SWITCH, /* Usage: Surface Switch */ \
			REPORT_SIZE, 0x01, /* Report Size: 0x01 */ \
			REPORT_COUNT, 0x02, /* Report Count: 0x02 */ \
			LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 0x01 */ \
			FEATURE, 0x02, /* Feature: (Data, Var, Abs) */ \
			REPORT_COUNT, 0x06, /* Report Count: 0x06 */ \
			FEATURE, 0x03, /* Feature: (Const, Var, Abs) */ \
		END_COLLECTION, /* End Collection */ \
	END_COLLECTION /* End Collection */

#define DEFAULT_PTP_HQA_BLOB \
	0xfc, 0x28, 0xfe, 0x84, 0x40, 0xcb, 0x9a, 0x87, \
	0x0d, 0xbe, 0x57, 0x3c, 0xb6, 0x70, 0x09, 0x88, \
	0x07, 0x97, 0x2d, 0x2b, 0xe3, 0x38, 0x34, 0xb6, \
	0x6c, 0xed, 0xb0, 0xf7, 0xe5, 0x9c, 0xf6, 0xc2, \
	0x2e, 0x84, 0x1b, 0xe8, 0xb4, 0x51, 0x78, 0x43, \
	0x1f, 0x28, 0x4b, 0x7c, 0x2d, 0x53, 0xaf, 0xfc, \
	0x47, 0x70, 0x1b, 0x59, 0x6f, 0x74, 0x43, 0xc4, \
	0xf3, 0x47, 0x18, 0x53, 0x1a, 0xa2, 0xa1, 0x71, \
	0xc7, 0x95, 0x0e, 0x31, 0x55, 0x21, 0xd3, 0xb5, \
	0x1e, 0xe9, 0x0c, 0xba, 0xec, 0xb8, 0x89, 0x19, \
	0x3e, 0xb3, 0xaf, 0x75, 0x81, 0x9d, 0x53, 0xb9, \
	0x41, 0x57, 0xf4, 0x6d, 0x39, 0x25, 0x29, 0x7c, \
	0x87, 0xd9, 0xb4, 0x98, 0x45, 0x7d, 0xa7, 0x26, \
	0x9c, 0x65, 0x3b, 0x85, 0x68, 0x89, 0xd7, 0x3b, \
	0xbd, 0xff, 0x14, 0x67, 0xf2, 0x2b, 0xf0, 0x2a, \
	0x41, 0x54, 0xf0, 0xfd, 0x2c, 0x66, 0x7c, 0xf8, \
	0xc0, 0x8f, 0x33, 0x13, 0x03, 0xf1, 0xd3, 0xc1, \
	0x0b, 0x89, 0xd9, 0x1b, 0x62, 0xcd, 0x51, 0xb7, \
	0x80, 0xb8, 0xaf, 0x3a, 0x10, 0xc1, 0x8a, 0x5b, \
	0xe8, 0x8a, 0x56, 0xf0, 0x8c, 0xaa, 0xfa, 0x35, \
	0xe9, 0x42, 0xc4, 0xd8, 0x55, 0xc3, 0x38, 0xcc, \
	0x2b, 0x53, 0x5c, 0x69, 0x52, 0xd5, 0xc8, 0x73, \
	0x02, 0x38, 0x7c, 0x73, 0xb6, 0x41, 0xe7, 0xff, \
	0x05, 0xd8, 0x2b, 0x79, 0x9a, 0xe2, 0x34, 0x60, \
	0x8f, 0xa3, 0x32, 0x1f, 0x09, 0x78, 0x62, 0xbc, \
	0x80, 0xe3, 0x0f, 0xbd, 0x65, 0x20, 0x08, 0x13, \
	0xc1, 0xe2, 0xee, 0x53, 0x2d, 0x86, 0x7e, 0xa7, \
	0x5a, 0xc5, 0xd3, 0x7d, 0x98, 0xbe, 0x31, 0x48, \
	0x1f, 0xfb, 0xda, 0xaf, 0xa2, 0xa8, 0x6a, 0x89, \
	0xd6, 0xbf, 0xf2, 0xd3, 0x32, 0x2a, 0x9a, 0xe4, \
	0xcf, 0x17, 0xb7, 0xb8, 0xf4, 0xe1, 0x33, 0x08, \
	0x24, 0x8b, 0xc4, 0x43, 0xa5, 0xe5, 0x24, 0xc2

#define PTP_MAX_CONTACT_POINTS 5
#define PTP_BUTTON_TYPE_CLICK_PAD 0
#define PTP_BUTTON_TYPE_PRESSURE_PAD 1

#define PTP_COLLECTION_MOUSE 0
#define PTP_COLLECTION_WINDOWS 3

#define PTP_CONTACT_CONFIDENCE_BIT   1
#define PTP_CONTACT_TIPSWITCH_BIT    2

typedef struct _PTP_DEVICE_CAPS_FEATURE_REPORT {
	UCHAR ReportID;
	UCHAR MaximumContactPoints;
	UCHAR ButtonType;
} PTP_DEVICE_CAPS_FEATURE_REPORT, *PPTP_DEVICE_CAPS_FEATURE_REPORT;

typedef struct _PTP_DEVICE_HQA_CERTIFICATION_REPORT {
	UCHAR ReportID;
	UCHAR CertificationBlob[256];
} PTP_DEVICE_HQA_CERTIFICATION_REPORT, *PPTP_DEVICE_HQA_CERTIFICATION_REPORT;

typedef struct _PTP_DEVICE_INPUT_MODE_REPORT {
	UCHAR ReportID;
	UCHAR Mode;
} PTP_DEVICE_INPUT_MODE_REPORT, *PPTP_DEVICE_INPUT_MODE_REPORT;

#pragma pack(push)
#pragma pack(1)
typedef struct _PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT {
	UCHAR ReportID;
	UCHAR DeviceMode;
	UCHAR ButtonReport : 1;
	UCHAR SurfaceReport : 1;
	UCHAR Padding : 6;
} PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT, *PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT;
#pragma pack(pop)

#pragma pack(push)
#pragma pack(1)
typedef struct _PTP_CONTACT {
	UCHAR		Confidence : 1;
	UCHAR		TipSwitch : 1;
	UCHAR		ContactID : 3;
	UCHAR		Padding : 3;
	USHORT		X;
	USHORT		Y;
} PTP_CONTACT, *PPTP_CONTACT;
#pragma pack(pop)

enum CONTACT_STATE {
	CONTACT_NEW = 0,
	CONTACT_CONTINUED = 1,
	CONTACT_CONFIDENCE_CANCELLED = 2,
	CONTACT_INVALID = 3
};

// Used for defuzz - not report
typedef struct _PTP_CONTACT_RAW {
	USHORT				X;
	USHORT				Y;
	UCHAR				Pressure;
	UCHAR				Size;
	UCHAR				ContactId;
	USHORT				TouchMajor;
	USHORT				TouchMinor;
	USHORT				Orientation;
	enum CONTACT_STATE	State;
} PTP_CONTACT_RAW, *PPTP_CONTACT_RAW;

typedef struct _PTP_CONTACT_RAW_LL {
	PTP_CONTACT_RAW					ContactRaw;
	struct _PTP_CONTACT_RAW_LL		*pNext;
} PTP_CONTACT_RAW_LL, *PPTP_CONTACT_RAW_LL;

typedef struct _PTP_REPORT {
	UCHAR       ReportID;
	PTP_CONTACT Contacts[5];
	USHORT      ScanTime;
	UCHAR       ContactCount;
	UCHAR       IsButtonClicked;
} PTP_REPORT, *PPTP_REPORT;

typedef struct _PTP_USERMODEAPP_CONF_REPORT {
	UCHAR		ReportID;
	UCHAR		PressureQualificationLevel;
	UCHAR		SingleContactSizeQualificationLevel;
	UCHAR		MultipleContactSizeQualificationLevel;
} PTP_USERMODEAPP_CONF_REPORT, *PPTP_USERMODEAPP_CONF_REPORT;

// HID routines
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetHidDescriptor(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
);

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetDeviceAttribs(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
);

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetReportDescriptor(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
);

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetStrings(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request,
	_Out_ BOOLEAN *Pending
);

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpReportFeatures(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
);

_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpSetFeatures(
	_In_ WDFDEVICE Device,
	_In_ WDFREQUEST Request
);


================================================
FILE: src/AmtPtpDeviceSpiKm/HidCommon.h
================================================
#pragma once

#define REPORTID_STANDARDMOUSE 0x02
#define REPORTID_MULTITOUCH 0x05
#define REPORTID_REPORTMODE 0x04
#define REPORTID_PTPHQA 0x08
#define REPORTID_FUNCSWITCH 0x06
#define REPORTID_DEVICE_CAPS 0x07
#define REPORTID_UMAPP_CONF  0x09

#define BUTTON_SWITCH 0x57
#define SURFACE_SWITCH 0x58

#define USAGE_PAGE 0x05
#define USAGE_PAGE_1 0x06
#define USAGE      0x09
#define USAGE_MINIMUM 0x19
#define USAGE_MAXIMUM 0x29
#define LOGICAL_MINIMUM 0x15
#define LOGICAL_MAXIMUM 0x25
#define LOGICAL_MAXIMUM_2 0x26
#define LOGICAL_MAXIMUM_3 0x27
#define PHYSICAL_MINIMUM 0x35
#define PHYSICAL_MAXIMUM 0x45
#define PHYSICAL_MAXIMUM_2 0x46
#define PHYSICAL_MAXIMUM_3 0x47
#define UNIT_EXPONENT 0x55
#define UNIT 0x65
#define UNIT_2 0x66

#define REPORT_ID       0x85
#define REPORT_COUNT    0x95
#define REPORT_COUNT_2	0x96
#define REPORT_SIZE     0x75
#define INPUT           0x81
#define FEATURE         0xb1

#define BEGIN_COLLECTION 0xa1
#define END_COLLECTION   0xc0


================================================
FILE: src/AmtPtpDeviceSpiKm/Input.c
================================================
#include "driver.h"
#include "Input.tmh"

VOID
AmtPtpSpiInputRoutineWorker(
	WDFDEVICE Device,
	WDFREQUEST PtpRequest
)
{
	NTSTATUS Status;
	PDEVICE_CONTEXT pDeviceContext;
	pDeviceContext = DeviceGetContext(Device);

	Status = WdfRequestForwardToIoQueue(
		PtpRequest,
		pDeviceContext->HidQueue
	);

	if (!NT_SUCCESS(Status)) {
		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_DRIVER,
			"%!FUNC! WdfRequestForwardToIoQueue fails, status = %!STATUS!",
			Status
		);

		WdfRequestComplete(PtpRequest, Status);
		return;
	}

	// Only issue request when fully configured.
	// Otherwise we will let power recovery process to triage it
	if (pDeviceContext->DeviceStatus == D0ActiveAndConfigured) {
		AmtPtpSpiInputIssueRequest(Device);
	}
}

VOID
AmtPtpSpiInputIssueRequest(
	WDFDEVICE Device
)
{
	NTSTATUS Status;
	PDEVICE_CONTEXT pDeviceContext;
	WDF_OBJECT_ATTRIBUTES Attributes;
	BOOLEAN RequestStatus = FALSE;
	WDFREQUEST SpiHidReadRequest;
	WDFMEMORY SpiHidReadOutputMemory;
	PWORKER_REQUEST_CONTEXT RequestContext;
	pDeviceContext = DeviceGetContext(Device);

	WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attributes, WORKER_REQUEST_CONTEXT);
	Attributes.ParentObject = Device;

	Status = WdfRequestCreate(
		&Attributes,
		pDeviceContext->SpiTrackpadIoTarget,
		&SpiHidReadRequest
	);

	if (!NT_SUCCESS(Status))
	{
		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_DEVICE,
			"%!FUNC! WdfRequestCreate fails, status = %!STATUS!",
			Status
		);

		return;
	}

	Status = WdfMemoryCreateFromLookaside(
		pDeviceContext->HidReadBufferLookaside,
		&SpiHidReadOutputMemory
	);

	if (!NT_SUCCESS(Status))
	{
		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_DEVICE,
			"%!FUNC! WdfMemoryCreateFromLookaside fails, status = %!STATUS!",
			Status
		);

		WdfObjectDelete(SpiHidReadRequest);
		return;
	}

	// Assign context information
	RequestContext = WorkerRequestGetContext(SpiHidReadRequest);
	RequestContext->DeviceContext = pDeviceContext;
	RequestContext->RequestMemory = SpiHidReadOutputMemory;

	// Invoke HID read request to the device.
	Status = WdfIoTargetFormatRequestForInternalIoctl(
		pDeviceContext->SpiTrackpadIoTarget,
		SpiHidReadRequest,
		IOCTL_HID_READ_REPORT,
		NULL,
		0,
		SpiHidReadOutputMemory,
		0
	);

	if (!NT_SUCCESS(Status))
	{
		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_DEVICE,
			"%!FUNC! WdfIoTargetFormatRequestForInternalIoctl fails, status = %!STATUS!",
			Status
		);

		if (SpiHidReadOutputMemory != NULL) {
			WdfObjectDelete(SpiHidReadOutputMemory);
		}

		if (SpiHidReadRequest != NULL) {
			WdfObjectDelete(SpiHidReadRequest);
		}

		return;
	}

	WdfRequestSetCompletionRoutine(
		SpiHidReadRequest,
		AmtPtpRequestCompletionRoutine,
		RequestContext
	);

	RequestStatus = WdfRequestSend(
		SpiHidReadRequest,
		pDeviceContext->SpiTrackpadIoTarget,
		NULL
	);

	if (!RequestStatus)
	{
		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_DEVICE,
			"%!FUNC! AmtPtpSpiInputRoutineWorker request failed to sent"
		);

		if (SpiHidReadOutputMemory != NULL) {
			WdfObjectDelete(SpiHidReadOutputMemory);
		}

		if (SpiHidReadRequest != NULL) {
			WdfObjectDelete(SpiHidReadRequest);
		}
	}
}

VOID
AmtPtpRequestCompletionRoutine(
	WDFREQUEST SpiRequest,
	WDFIOTARGET Target,
	PWDF_REQUEST_COMPLETION_PARAMS Params,
	WDFCONTEXT Context
)
{
	NTSTATUS Status;
	PWORKER_REQUEST_CONTEXT RequestContext;
	PDEVICE_CONTEXT pDeviceContext;

	LONG SpiRequestLength;
	PSPI_TRACKPAD_PACKET pSpiTrackpadPacket;

	WDFREQUEST PtpRequest;
	PTP_REPORT PtpReport;
	WDFMEMORY PtpRequestMemory;

	LARGE_INTEGER CurrentCounter;
	LONGLONG CounterDelta;

	UNREFERENCED_PARAMETER(Target);

	// Get context
	RequestContext = (PWORKER_REQUEST_CONTEXT) Context;
	pDeviceContext = RequestContext->DeviceContext;

	// Read report and fulfill PTP request.
	// If no report is found, just exit.
	Status = WdfIoQueueRetrieveNextRequest(pDeviceContext->HidQueue, &PtpRequest);
	if (!NT_SUCCESS(Status)) {
		TraceEvents(
			TRACE_LEVEL_ERROR,
			TRACE_DRIVER,
			"%!FUNC! WdfIoQueueRetrieveNextRequest failed with %!STATUS!",
			Status
		);

		goto cleanup;
	}

	SpiRequestLength = (LONG) WdfRequestGetInformation(SpiRequest);
	pSpiTrackpadPacket = (PSPI_TRACKPAD_PACKET) WdfMemoryGetBuffer(Params->Parameters.Ioctl.Output.Buffer, NULL);

	// Safe measurement for buffer overrun and device state reset
	if (SpiRequestLength < 46) {
		TraceEvents(
			TRACE_LEVEL_ERROR,
			TRACE_DRIVER,
			"%!FUNC! Input too small: %d < 46. Attempt to re-enable the device.",
			SpiRequestLength
		);

		Status = STATUS_DEVICE_DATA_ERROR;
		goto exit;
	}

	// Get Counter
	KeQueryPerformanceCounter(
		&CurrentCounter
	);

	CounterDelta = (CurrentCounter.QuadPart - pDeviceContext->LastReportTime.QuadPart) / 100;
	pDeviceContext->LastReportTime.QuadPart = CurrentCounter.QuadPart;

	// Write report
	PtpReport.ReportID = REPORTID_MULTITOUCH;
	PtpReport.ContactCount = pSpiTrackpadPacket->NumOfFingers;
	PtpReport.IsButtonClicked = pSpiTrackpadPacket->ClickOccurred;

	UINT8 AdjustedCount = (pSpiTrackpadPacket->NumOfFingers > 5) ? 5 : pSpiTrackpadPacket->NumOfFingers;
	for (UINT8 Count = 0; Count < AdjustedCount; Count++)
	{
		PtpReport.Contacts[Count].ContactID = Count;
		PtpReport.Contacts[Count].X = ((pSpiTrackpadPacket->Fingers[Count].X - pDeviceContext->TrackpadInfo.XMin) > 0) ? 
			(USHORT)(pSpiTrackpadPacket->Fingers[Count].X - pDeviceContext->TrackpadInfo.XMin) : 0;
		PtpReport.Contacts[Count].Y = ((pDeviceContext->TrackpadInfo.YMax - pSpiTrackpadPacket->Fingers[Count].Y) > 0) ? 
			(USHORT)(pDeviceContext->TrackpadInfo.YMax - pSpiTrackpadPacket->Fingers[Count].Y) : 0;
		PtpReport.Contacts[Count].TipSwitch = (pSpiTrackpadPacket->Fingers[Count].Pressure > 0) ? 1 : 0;

		// $S = \pi * (Touch_{Major} * Touch_{Minor}) / 4$
		// $S = \pi * r^2$
		// $r^2 = (Touch_{Major} * Touch_{Minor}) / 4$
		// Using i386 in 2018 is evil
		PtpReport.Contacts[Count].Confidence = (pSpiTrackpadPacket->Fingers[Count].TouchMajor < 2500 &&
			pSpiTrackpadPacket->Fingers[Count].TouchMinor < 2500) ? 1 : 0;

		TraceEvents(
			TRACE_LEVEL_INFORMATION,
			TRACE_HID_INPUT,
			"%!FUNC! PTP Contact %d OX %d, OY %d, X %d, Y %d",
			Count,
			pSpiTrackpadPacket->Fingers[Count].OriginalX,
			pSpiTrackpadPacket->Fingers[Count].OriginalY,
			pSpiTrackpadPacket->Fingers[Count].X,
			pSpiTrackpadPacket->Fingers[Count].Y
		);
	}

	if (CounterDelta >= 0xFF)
	{
		PtpReport.ScanTime = 0xFF;
	}
	else
	{
		PtpReport.ScanTime = (USHORT) CounterDelta;
	}

	Status = WdfRequestRetri
Download .txt
gitextract_kok6b9fh/

├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       └── github-issue-sync.yml
├── .gitignore
├── AmtPtpDevice.Settings.sln
├── AmtPtpDriver.sln
├── LICENSE-GPL.md
├── LICENSE-MIT.md
├── LICENSE.md
├── README.md
├── es/
│   └── New-CabinetFile.ps1
└── src/
    ├── AmtPtpDevice.Settings/
    │   ├── AmtPtpDevice.Settings.csproj
    │   ├── App.xaml
    │   ├── App.xaml.cs
    │   ├── Comm/
    │   │   └── UsbHidDeviceAccessSubscription.cs
    │   ├── DataObjects/
    │   │   ├── Mt2BatteryStatusReport.cs
    │   │   └── PtpUserModeConfReport.cs
    │   ├── MainPage.xaml
    │   ├── MainPage.xaml.cs
    │   ├── Package.appxmanifest
    │   └── Properties/
    │       ├── AssemblyInfo.cs
    │       └── Default.rd.xml
    ├── AmtPtpDeviceSpiKm/
    │   ├── AmtPtpDeviceSpiKm.vcxproj
    │   ├── AmtPtpDeviceSpiKm.vcxproj.filters
    │   ├── AppleDefinition.h
    │   ├── Device.c
    │   ├── Device.h
    │   ├── Driver.c
    │   ├── Driver.h
    │   ├── HID/
    │   │   ├── SpiTrackpadSeries1.h
    │   │   ├── SpiTrackpadSeries2.h
    │   │   └── SpiTrackpadSeries3.h
    │   ├── Hid.c
    │   ├── Hid.h
    │   ├── HidCommon.h
    │   ├── Input.c
    │   ├── Input.h
    │   ├── Public.h
    │   ├── Queue.c
    │   ├── Queue.h
    │   └── Trace.h
    ├── AmtPtpDeviceUniversalPkg/
    │   ├── AmtPtpDevice.inf
    │   ├── AmtPtpDeviceUniversalPkg.vcxproj
    │   └── AmtPtpDeviceUniversalPkg.vcxproj.filters
    ├── AmtPtpDeviceUsbKm/
    │   ├── AmtPtpDeviceUsbKm.vcxproj
    │   ├── AmtPtpDeviceUsbKm.vcxproj.filters
    │   ├── DebugUtils.c
    │   ├── Device.c
    │   ├── Device.h
    │   ├── Driver.c
    │   ├── Driver.h
    │   ├── Hid.c
    │   ├── Interrupt.c
    │   ├── Public.h
    │   ├── Queue.c
    │   ├── Queue.h
    │   ├── Resource.rc
    │   ├── Trace.h
    │   ├── include/
    │   │   ├── AppleDefinition.h
    │   │   ├── Hid.h
    │   │   ├── hid/
    │   │   │   └── HidCommon.h
    │   │   └── metadata/
    │   │       └── WellspringT2.h
    │   └── resource.h
    ├── AmtPtpDeviceUsbUm/
    │   ├── AmtPtpDevice.wprp
    │   ├── Device.c
    │   ├── Driver.c
    │   ├── Hid.c
    │   ├── InputInterrupt.c
    │   ├── MagicTrackpad2PtpDevice.vcxproj
    │   ├── MagicTrackpad2PtpDevice.vcxproj.filters
    │   ├── Queue.c
    │   ├── Resource.rc
    │   └── include/
    │       ├── AppleDefinition.h
    │       ├── Device.h
    │       ├── DeviceFamily/
    │       │   ├── Wellspring3.h
    │       │   ├── Wellspring5.h
    │       │   ├── Wellspring6.h
    │       │   ├── Wellspring7A.h
    │       │   ├── Wellspring8.h
    │       │   └── WellspringMt2.h
    │       ├── Driver.h
    │       ├── Hid.h
    │       ├── HidCommon.h
    │       ├── ModernTrace.h
    │       ├── Queue.h
    │       ├── StaticHidRegistry.h
    │       ├── Trace.h
    │       └── resource.h
    └── AmtPtpHidFilter/
        ├── AmtPtpHidFilter.inf
        ├── AmtPtpHidFilter.vcxproj
        ├── AmtPtpHidFilter.vcxproj.filters
        ├── Detour.c
        ├── Device.c
        ├── Diagnostics.c
        ├── Driver.c
        ├── Hid.c
        ├── Input.c
        ├── Queue.c
        └── include/
            ├── Device.h
            ├── Diagnostics.h
            ├── Driver.h
            ├── Hac.h
            ├── HidCommon.h
            ├── HidDevice.h
            ├── HidMiniport.h
            ├── Input.h
            ├── Metadata/
            │   ├── MagicTrackpad2.h
            │   ├── StaticHidRegistry.h
            │   └── WindowsHID.h
            ├── Queue.h
            └── Trace.h
Download .txt
SYMBOL INDEX (230 symbols across 46 files)

FILE: src/AmtPtpDevice.Settings/App.xaml.cs
  class App (line 23) | sealed partial class App : Application
    method App (line 29) | public App()
    method OnLaunched (line 40) | protected override void OnLaunched(LaunchActivatedEventArgs e)
    method OnNavigationFailed (line 81) | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
    method OnSuspending (line 93) | private void OnSuspending(object sender, SuspendingEventArgs e)

FILE: src/AmtPtpDevice.Settings/Comm/UsbHidDeviceAccessSubscription.cs
  class UsbHidDeviceAccessSubscription (line 9) | public class UsbHidDeviceAccessSubscription : IDisposable
    method UsbHidDeviceAccessSubscription (line 55) | public UsbHidDeviceAccessSubscription(string aqsString)
    method SbDeviceRemoved (line 66) | private void SbDeviceRemoved(DeviceWatcher sender, DeviceInformationUp...
    method SbDeviceAdded (line 80) | private async void SbDeviceAdded(DeviceWatcher sender, DeviceInformati...
    method Dispose (line 90) | protected virtual void Dispose(bool disposing)
    method Dispose (line 110) | public void Dispose()

FILE: src/AmtPtpDevice.Settings/DataObjects/Mt2BatteryStatusReport.cs
  type Mt2BatteryStatusReport (line 5) | public struct Mt2BatteryStatusReport

FILE: src/AmtPtpDevice.Settings/DataObjects/PtpUserModeConfReport.cs
  type PtpUserModeConfReport (line 9) | public struct PtpUserModeConfReport

FILE: src/AmtPtpDevice.Settings/MainPage.xaml.cs
  class MainPage (line 20) | public sealed partial class MainPage : Page
    method MainPage (line 27) | public MainPage()
    method OnPageLoaded (line 37) | private void OnPageLoaded(object sender, RoutedEventArgs e)
    method SetupWatcher (line 56) | private void SetupWatcher()
    method OnBatteryAvailable (line 66) | private async void OnBatteryAvailable(object sender, EventArgs e)
    method OnInputDeviceLost (line 81) | private async void OnInputDeviceLost(object sender, EventArgs e)
    method OnInputDeviceAvailable (line 93) | private async void OnInputDeviceAvailable(object sender, EventArgs e)
    method ApplySettings (line 118) | private async void ApplySettings()
    method OnGestureButtonClicked (line 138) | private async void OnGestureButtonClicked(object sender, RoutedEventAr...
    method OnSliderValueChanged (line 143) | private void OnSliderValueChanged(object sender, Windows.UI.Xaml.Contr...
    method OnConfidenceSliderValueChanged (line 148) | private void OnConfidenceSliderValueChanged(object sender, Windows.UI....
    method OnMuConfidenceSliderValueChanged (line 153) | private void OnMuConfidenceSliderValueChanged(object sender, Windows.U...

FILE: src/AmtPtpDeviceSpiKm/AppleDefinition.h
  type SPI_TRACKPAD_FINGER (line 6) | typedef struct _SPI_TRACKPAD_FINGER
  type SPI_TRACKPAD_PACKET (line 25) | typedef struct _SPI_TRACKPAD_PACKET
  type SPI_SET_FEATURE (line 44) | typedef struct _SPI_SET_FEATURE {

FILE: src/AmtPtpDeviceSpiKm/Device.c
  function NTSTATUS (line 24) | NTSTATUS
  function NTSTATUS (line 166) | NTSTATUS
  function NTSTATUS (line 319) | NTSTATUS
  function NTSTATUS (line 353) | NTSTATUS
  function NTSTATUS (line 397) | NTSTATUS
  function PCHAR (line 429) | PCHAR
  function NTSTATUS (line 457) | NTSTATUS
  function AmtPtpPowerRecoveryTimerCallback (line 541) | void AmtPtpPowerRecoveryTimerCallback(

FILE: src/AmtPtpDeviceSpiKm/Device.h
  type _SPI_TRACKPAD_INFO (line 21) | struct _SPI_TRACKPAD_INFO {
  type PTP_AAPL_MAPPING (line 32) | typedef struct _PTP_AAPL_MAPPING {
  type REPORT_TYPE (line 40) | typedef enum _REPORT_TYPE {
  type PTP_AAPL_DEVICE_POWER_STATUS (line 46) | typedef enum _PTP_AAPL_DEVICE_POWER_STATUS {
  type DEVICE_CONTEXT (line 56) | typedef struct _DEVICE_CONTEXT
  type WORKER_REQUEST_CONTEXT (line 96) | typedef struct _WORKER_REQUEST_CONTEXT {

FILE: src/AmtPtpDeviceSpiKm/Driver.c
  function NTSTATUS (line 26) | NTSTATUS
  function NTSTATUS (line 100) | NTSTATUS
  function VOID (line 151) | VOID

FILE: src/AmtPtpDeviceSpiKm/Hid.c
  function AmtPtpGetHidDescriptor (line 107) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpGetDeviceAttribs (line 306) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpGetReportDescriptor (line 364) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpGetStrings (line 533) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpReportFeatures (line 581) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpSetFeatures (line 727) | _IRQL_requires_(PASSIVE_LEVEL)

FILE: src/AmtPtpDeviceSpiKm/Hid.h
  type UCHAR (line 13) | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR;
  type PTP_DEVICE_CAPS_FEATURE_REPORT (line 103) | typedef struct _PTP_DEVICE_CAPS_FEATURE_REPORT {
  type PTP_DEVICE_HQA_CERTIFICATION_REPORT (line 109) | typedef struct _PTP_DEVICE_HQA_CERTIFICATION_REPORT {
  type PTP_DEVICE_INPUT_MODE_REPORT (line 114) | typedef struct _PTP_DEVICE_INPUT_MODE_REPORT {
  type PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT (line 121) | typedef struct _PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT {
  type PTP_CONTACT (line 132) | typedef struct _PTP_CONTACT {
  type CONTACT_STATE (line 142) | enum CONTACT_STATE {
  type PTP_CONTACT_RAW (line 150) | typedef struct _PTP_CONTACT_RAW {
  type PTP_CONTACT_RAW_LL (line 162) | typedef struct _PTP_CONTACT_RAW_LL {
  type PTP_REPORT (line 167) | typedef struct _PTP_REPORT {
  type PTP_USERMODEAPP_CONF_REPORT (line 175) | typedef struct _PTP_USERMODEAPP_CONF_REPORT {

FILE: src/AmtPtpDeviceSpiKm/Input.c
  function VOID (line 4) | VOID
  function VOID (line 38) | VOID
  function VOID (line 157) | VOID

FILE: src/AmtPtpDeviceSpiKm/Queue.c
  function NTSTATUS (line 24) | NTSTATUS
  function PCHAR (line 90) | PCHAR
  function VOID (line 133) | VOID
  function VOID (line 224) | VOID

FILE: src/AmtPtpDeviceSpiKm/Queue.h
  type _QUEUE_CONTEXT (line 23) | struct _QUEUE_CONTEXT {

FILE: src/AmtPtpDeviceUsbKm/DebugUtils.c
  function PCHAR (line 3) | PCHAR
  function PCHAR (line 31) | PCHAR

FILE: src/AmtPtpDeviceUsbKm/Device.c
  function BCM5974_CONFIG (line 26) | BCM5974_CONFIG*
  function NTSTATUS (line 50) | NTSTATUS
  function NTSTATUS (line 130) | NTSTATUS
  function NTSTATUS (line 275) | NTSTATUS
  function NTSTATUS (line 361) | NTSTATUS
  function SelectInterruptInterface (line 418) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpSetWellspringMode (line 503) | _IRQL_requires_(PASSIVE_LEVEL)

FILE: src/AmtPtpDeviceUsbKm/Device.h
  type _DEVICE_CONTEXT (line 25) | struct _DEVICE_CONTEXT

FILE: src/AmtPtpDeviceUsbKm/Driver.c
  function NTSTATUS (line 27) | NTSTATUS
  function NTSTATUS (line 98) | NTSTATUS
  function VOID (line 145) | VOID

FILE: src/AmtPtpDeviceUsbKm/Hid.c
  function AmtPtpGetHidDescriptor (line 26) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpGetDeviceAttribs (line 121) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpGetReportDescriptor (line 169) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpReportFeatures (line 287) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpSetFeatures (line 420) | _IRQL_requires_(PASSIVE_LEVEL)

FILE: src/AmtPtpDeviceUsbKm/Interrupt.c
  function INT (line 7) | static inline INT AmtRawToInteger(
  function AmtPtpConfigContReaderForInterruptEndPoint (line 14) | _IRQL_requires_(PASSIVE_LEVEL)
  function VOID (line 89) | VOID
  function BOOLEAN (line 252) | BOOLEAN

FILE: src/AmtPtpDeviceUsbKm/Queue.c
  function NTSTATUS (line 24) | NTSTATUS
  function VOID (line 105) | VOID
  function NTSTATUS (line 184) | NTSTATUS
  function VOID (line 221) | VOID

FILE: src/AmtPtpDeviceUsbKm/Queue.h
  type _QUEUE_CONTEXT (line 23) | struct _QUEUE_CONTEXT {

FILE: src/AmtPtpDeviceUsbKm/include/AppleDefinition.h
  type TRACKPAD_BUTTON_DATA (line 13) | struct TRACKPAD_BUTTON_DATA {
  type TRACKPAD_TYPE (line 21) | enum TRACKPAD_TYPE {
  type TRACKPAD_FINGER (line 78) | struct TRACKPAD_FINGER {
  type BCM5974_PARAM (line 95) | struct BCM5974_PARAM {
  type BCM5974_CONFIG (line 102) | struct BCM5974_CONFIG {
  type BCM5974_CONFIG (line 149) | struct BCM5974_CONFIG
  type TRACKPAD_BUTTON_DATA (line 154) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 167) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 178) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 190) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 202) | struct TRACKPAD_BUTTON_DATA

FILE: src/AmtPtpDeviceUsbKm/include/Hid.h
  type UCHAR (line 12) | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR;
  type PTP_DEVICE_CAPS_FEATURE_REPORT (line 100) | typedef struct _PTP_DEVICE_CAPS_FEATURE_REPORT {
  type PTP_DEVICE_HQA_CERTIFICATION_REPORT (line 106) | typedef struct _PTP_DEVICE_HQA_CERTIFICATION_REPORT {
  type PTP_DEVICE_INPUT_MODE_REPORT (line 111) | typedef struct _PTP_DEVICE_INPUT_MODE_REPORT {
  type PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT (line 118) | typedef struct _PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT {
  type PTP_CONTACT (line 129) | typedef struct _PTP_CONTACT {
  type PTP_REPORT (line 139) | typedef struct _PTP_REPORT {
  type PTP_USERMODEAPP_CONF_REPORT (line 147) | typedef struct _PTP_USERMODEAPP_CONF_REPORT {

FILE: src/AmtPtpDeviceUsbUm/Device.c
  function BCM5974_CONFIG (line 7) | BCM5974_CONFIG*
  function AmtPtpCreateDevice (line 24) | _IRQL_requires_(PASSIVE_LEVEL)
  function NTSTATUS (line 120) | NTSTATUS
  function AmtPtpGetWellspringMode (line 255) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpSetWellspringMode (line 359) | _IRQL_requires_(PASSIVE_LEVEL)
  function NTSTATUS (line 498) | NTSTATUS
  function NTSTATUS (line 587) | NTSTATUS
  function SelectInterruptInterface (line 644) | _IRQL_requires_(PASSIVE_LEVEL)
  function DbgDevicePowerString (line 729) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpEmergResetDevice (line 758) | _IRQL_requires_(PASSIVE_LEVEL)

FILE: src/AmtPtpDeviceUsbUm/Driver.c
  function NTSTATUS (line 12) | NTSTATUS
  function VOID (line 80) | VOID
  function VOID (line 96) | VOID
  function NTSTATUS (line 108) | NTSTATUS
  function VOID (line 143) | VOID

FILE: src/AmtPtpDeviceUsbUm/Hid.c
  function AmtPtpGetHidDescriptor (line 7) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpGetDeviceAttribs (line 188) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpGetReportDescriptor (line 245) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpGetStrings (line 399) | _IRQL_requires_(PASSIVE_LEVEL)
  function RequestGetHidXferPacketToReadFromDevice (line 543) | _IRQL_requires_(PASSIVE_LEVEL)
  function RequestGetHidXferPacketToWriteToDevice (line 632) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpReportFeatures (line 711) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpSetFeatures (line 897) | _IRQL_requires_(PASSIVE_LEVEL)

FILE: src/AmtPtpDeviceUsbUm/InputInterrupt.c
  function AmtPtpConfigContReaderForInterruptEndPoint (line 6) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpEvtUsbInterruptPipeReadComplete (line 82) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpEvtUsbInterruptReadersFailed (line 213) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpServiceTouchInputInterrupt (line 228) | _IRQL_requires_(PASSIVE_LEVEL)
  function AmtPtpServiceTouchInputInterruptType5 (line 408) | _IRQL_requires_(PASSIVE_LEVEL)
  function INT (line 592) | static inline INT AmtRawToInteger(

FILE: src/AmtPtpDeviceUsbUm/Queue.c
  function NTSTATUS (line 6) | NTSTATUS
  function DbgIoControlGetString (line 77) | _IRQL_requires_(PASSIVE_LEVEL)
  function VOID (line 118) | VOID
  function VOID (line 215) | VOID
  function NTSTATUS (line 260) | NTSTATUS

FILE: src/AmtPtpDeviceUsbUm/include/AppleDefinition.h
  type TRACKPAD_BUTTON_DATA (line 63) | struct TRACKPAD_BUTTON_DATA {
  type TRACKPAD_TYPE (line 71) | enum TRACKPAD_TYPE {
  type TRACKPAD_FINGER (line 128) | struct TRACKPAD_FINGER {
  type TRACKPAD_FINGER_TYPE5 (line 145) | struct TRACKPAD_FINGER_TYPE5
  type BCM5974_PARAM (line 166) | struct BCM5974_PARAM {
  type BCM5974_CONFIG (line 173) | struct BCM5974_CONFIG {
  type BCM5974_CONFIG (line 221) | struct BCM5974_CONFIG
  type TRACKPAD_BUTTON_DATA (line 227) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 240) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 253) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 266) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 279) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 292) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 305) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 318) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 331) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 344) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 357) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 370) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 383) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 396) | struct TRACKPAD_BUTTON_DATA
  type TRACKPAD_BUTTON_DATA (line 409) | struct TRACKPAD_BUTTON_DATA

FILE: src/AmtPtpDeviceUsbUm/include/Device.h
  type _DEVICE_CONTEXT (line 6) | struct _DEVICE_CONTEXT

FILE: src/AmtPtpDeviceUsbUm/include/Hid.h
  type UCHAR (line 17) | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR;
  type HID_AAPL_MOUSE_REPORT (line 106) | typedef struct _HID_AAPL_MOUSE_REPORT {
  type HID_INPUT_REPORT (line 115) | typedef struct _HID_INPUT_REPORT {
  type PTP_DEVICE_CAPS_FEATURE_REPORT (line 120) | typedef struct _PTP_DEVICE_CAPS_FEATURE_REPORT {
  type PTP_DEVICE_HQA_CERTIFICATION_REPORT (line 126) | typedef struct _PTP_DEVICE_HQA_CERTIFICATION_REPORT {
  type PTP_DEVICE_INPUT_MODE_REPORT (line 131) | typedef struct _PTP_DEVICE_INPUT_MODE_REPORT {
  type PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT (line 137) | typedef struct _PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT {
  type PTP_CONTACT (line 146) | typedef struct _PTP_CONTACT {
  type PTP_REPORT (line 156) | typedef struct _PTP_REPORT {
  type PTP_USERMODEAPP_CONF_REPORT (line 164) | typedef struct _PTP_USERMODEAPP_CONF_REPORT {

FILE: src/AmtPtpDeviceUsbUm/include/Queue.h
  type _QUEUE_CONTEXT (line 9) | struct _QUEUE_CONTEXT {

FILE: src/AmtPtpHidFilter/Detour.c
  function NTSTATUS (line 6) | NTSTATUS

FILE: src/AmtPtpHidFilter/Device.c
  function NTSTATUS (line 10) | NTSTATUS
  function NTSTATUS (line 104) | NTSTATUS
  function NTSTATUS (line 132) | NTSTATUS
  function NTSTATUS (line 149) | NTSTATUS
  function NTSTATUS (line 184) | NTSTATUS
  function NTSTATUS (line 247) | NTSTATUS
  function NTSTATUS (line 286) | NTSTATUS
  function VOID (line 424) | VOID

FILE: src/AmtPtpHidFilter/Diagnostics.c
  function VOID (line 6) | VOID PtpFilterDiagnosticsInitializeContinuousRead(
  function VOID (line 20) | VOID
  function VOID (line 106) | VOID
  function PCHAR (line 141) | PCHAR

FILE: src/AmtPtpHidFilter/Driver.c
  function NTSTATUS (line 12) | NTSTATUS
  function NTSTATUS (line 45) | NTSTATUS
  function VOID (line 68) | VOID

FILE: src/AmtPtpHidFilter/Hid.c
  function NTSTATUS (line 6) | NTSTATUS
  function NTSTATUS (line 58) | NTSTATUS
  function NTSTATUS (line 91) | NTSTATUS
  function NTSTATUS (line 142) | NTSTATUS
  function NTSTATUS (line 176) | NTSTATUS
  function NTSTATUS (line 264) | NTSTATUS

FILE: src/AmtPtpHidFilter/Input.c
  function VOID (line 6) | VOID
  function VOID (line 30) | VOID
  function VOID (line 39) | VOID
  function VOID (line 119) | VOID

FILE: src/AmtPtpHidFilter/Queue.c
  function NTSTATUS (line 10) | NTSTATUS
  function VOID (line 56) | VOID
  function VOID (line 119) | VOID

FILE: src/AmtPtpHidFilter/include/Device.h
  type BCM5974_PARAM (line 19) | typedef struct _BCM5974_PARAM {
  type DEVICE_CONTEXT (line 26) | typedef struct _DEVICE_CONTEXT
  type WORKER_REQUEST_CONTEXT (line 65) | typedef struct _WORKER_REQUEST_CONTEXT {

FILE: src/AmtPtpHidFilter/include/Hac.h
  type _HIDCLASS_DRIVER_EXTENSION (line 7) | struct _HIDCLASS_DRIVER_EXTENSION {
  type IO_CLIENT_EXTENSION (line 19) | typedef struct _IO_CLIENT_EXTENSION
  type DRIVER_EXTENSION_EXT (line 25) | typedef struct _DRIVER_EXTENSION_EXT {

FILE: src/AmtPtpHidFilter/include/HidDevice.h
  type TRACKPAD_BUTTON_DATA (line 41) | typedef struct _TRACKPAD_BUTTON_DATA {
  type TRACKPAD_FINGER (line 50) | typedef struct _TRACKPAD_FINGER {
  type TRACKPAD_FINGER_TYPE5 (line 67) | typedef struct _TRACKPAD_FINGER_TYPE5

FILE: src/AmtPtpHidFilter/include/HidMiniport.h
  type PTP_DEVICE_CAPS_FEATURE_REPORT (line 7) | typedef struct _PTP_DEVICE_CAPS_FEATURE_REPORT {
  type PTP_DEVICE_HQA_CERTIFICATION_REPORT (line 14) | typedef struct _PTP_DEVICE_HQA_CERTIFICATION_REPORT {
  type PTP_DEVICE_INPUT_MODE_REPORT (line 20) | typedef struct _PTP_DEVICE_INPUT_MODE_REPORT {
  type PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT (line 26) | typedef struct _PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT {
  type PTP_CONTACT (line 34) | typedef struct _PTP_CONTACT {
  type PTP_REPORT (line 44) | typedef struct _PTP_REPORT {

FILE: src/AmtPtpHidFilter/include/Metadata/StaticHidRegistry.h
  type UCHAR (line 10) | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR;

FILE: src/AmtPtpHidFilter/include/Queue.h
  type QUEUE_CONTEXT (line 13) | typedef struct _QUEUE_CONTEXT {
Condensed preview — 112 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (619K chars).
[
  {
    "path": ".gitattributes",
    "chars": 2567,
    "preview": "###############################################################################\n# Set default behavior to automatically "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 698,
    "preview": "---\nname: Bug report\nabout: Create a report for driver defects or malfunctions\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 811,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Pr"
  },
  {
    "path": ".github/workflows/github-issue-sync.yml",
    "chars": 858,
    "preview": "# Synchronizes Github issue to Azure DevOps Board\n\nname: EngSys-ProjectManagement-GithubIssueOnewaySync\n\non:\n  issues:\n "
  },
  {
    "path": ".gitignore",
    "chars": 3779,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
  },
  {
    "path": "AmtPtpDevice.Settings.sln",
    "chars": 2492,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.26730.12\nMin"
  },
  {
    "path": "AmtPtpDriver.sln",
    "chars": 9856,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.2910"
  },
  {
    "path": "LICENSE-GPL.md",
    "chars": 15174,
    "preview": "The GNU General Public License, Version 2, June 1991 (GPLv2)\n==========================================================="
  },
  {
    "path": "LICENSE-MIT.md",
    "chars": 1099,
    "preview": "The MIT License (MIT)\n=====================\n\nCopyright  `2018` `Bingxing Wang`\n\nPermission is hereby granted, free of ch"
  },
  {
    "path": "LICENSE.md",
    "chars": 315,
    "preview": "Dual-licensed project notice\n=====================\n\nCopyright 2018-2019, Bingxing Wang and other project contributors.\n\n"
  },
  {
    "path": "README.md",
    "chars": 6373,
    "preview": "# Windows Precision Touchpad Implementation for Apple MacBook family/Magic Trackpad 2\n\n[![Build Status](https://ligstd.v"
  },
  {
    "path": "es/New-CabinetFile.ps1",
    "chars": 18010,
    "preview": " <#\n.SYNOPSIS\n    Creates a new cabinet .CAB file on disk.\n\n.DESCRIPTION\n    This cmdlet creates a new cabinet .CAB file"
  },
  {
    "path": "src/AmtPtpDevice.Settings/AmtPtpDevice.Settings.csproj",
    "chars": 7218,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "src/AmtPtpDevice.Settings/App.xaml",
    "chars": 273,
    "preview": "<Application\n    x:Class=\"AmtPtpDevice.Settings.App\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentati"
  },
  {
    "path": "src/AmtPtpDevice.Settings/App.xaml.cs",
    "chars": 3933,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Runtime.InteropService"
  },
  {
    "path": "src/AmtPtpDevice.Settings/Comm/UsbHidDeviceAccessSubscription.cs",
    "chars": 3387,
    "preview": "using System;\nusing System.Threading;\nusing Windows.Devices.Enumeration;\nusing Windows.Devices.HumanInterfaceDevice;\nus"
  },
  {
    "path": "src/AmtPtpDevice.Settings/DataObjects/Mt2BatteryStatusReport.cs",
    "chars": 239,
    "preview": "using System.Runtime.InteropServices;\n\nnamespace AmtPtpDevice.Settings.DataObjects\n{\n    public struct Mt2BatteryStatus"
  },
  {
    "path": "src/AmtPtpDevice.Settings/DataObjects/PtpUserModeConfReport.cs",
    "chars": 412,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nna"
  },
  {
    "path": "src/AmtPtpDevice.Settings/MainPage.xaml",
    "chars": 2487,
    "preview": "<Page\n    x:Class=\"AmtPtpDevice.Settings.MainPage\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  },
  {
    "path": "src/AmtPtpDevice.Settings/MainPage.xaml.cs",
    "chars": 6648,
    "preview": "using AmtPtpDevice.Settings.Comm;\nusing AmtPtpDevice.Settings.DataObjects;\nusing System;\nusing System.Linq;\nusing Syste"
  },
  {
    "path": "src/AmtPtpDevice.Settings/Package.appxmanifest",
    "chars": 1903,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Package xmlns=\"http://schemas.microsoft.com/appx/manifest/foundation/windows10\""
  },
  {
    "path": "src/AmtPtpDevice.Settings/Properties/AssemblyInfo.cs",
    "chars": 1059,
    "preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
  },
  {
    "path": "src/AmtPtpDevice.Settings/Properties/Default.rd.xml",
    "chars": 1243,
    "preview": "<!--\n    This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most\n    develope"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/AmtPtpDeviceSpiKm.vcxproj",
    "chars": 13499,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/AmtPtpDeviceSpiKm.vcxproj.filters",
    "chars": 2803,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/AppleDefinition.h",
    "chars": 1670,
    "preview": "#pragma once\n\n#define SPI_TRACKPAD_MAX_FINGERS 10\n#define DEVICE_VID 0x8910\n\ntypedef struct _SPI_TRACKPAD_FINGER\n{\n\tSHOR"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Device.c",
    "chars": 13156,
    "preview": "/*++\n\nModule Name:\n\n    device.c - Device handling events for example driver.\n\nAbstract:\n\n   This file contains the devi"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Device.h",
    "chars": 2691,
    "preview": "/*++\n\nModule Name:\n\n    device.h\n\nAbstract:\n\n    This file contains the device definitions.\n\nEnvironment:\n\n    Kernel-mo"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Driver.c",
    "chars": 4425,
    "preview": "/*++\n\nModule Name:\n\n    driver.c\n\nAbstract:\n\n    This file contains the driver entry points and callbacks.\n\nEnvironment:"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Driver.h",
    "chars": 692,
    "preview": "/*++\n\nModule Name:\n\n    driver.h\n\nAbstract:\n\n    This file contains the driver definitions.\n\nEnvironment:\n\n    Kernel-mo"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/HID/SpiTrackpadSeries1.h",
    "chars": 8009,
    "preview": "// Trackpad HID definition for MacBook8, 9, 10\n\n#pragma once\n\n#include \"..\\HidCommon.h\"\n\n#define AAPL_SPI_SERIES1_PTP_FI"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/HID/SpiTrackpadSeries2.h",
    "chars": 8012,
    "preview": "// Trackpad HID definition for MacBookPro 10, 11\n\n#pragma once\n\n#include \"..\\HidCommon.h\"\n\n#define AAPL_SPI_SERIES2_PTP_"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/HID/SpiTrackpadSeries3.h",
    "chars": 16025,
    "preview": "// Trackpad HID definition for MacBookPro 13, 14\n\n#pragma once\n\n#include \"..\\HidCommon.h\"\n\n#define AAPL_SPI_SERIES3_13_P"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Hid.c",
    "chars": 18412,
    "preview": "// Hid.c: HID-related routine\n\n#include \"Driver.h\"\n#include \"Hid.tmh\"\n\n#ifndef __AAPL_HID_DESCRIPTOR_H__\n#define __AAPL_"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Hid.h",
    "chars": 7061,
    "preview": "#pragma once\n\n#include <hidport.h>\n\n#include \"AppleDefinition.h\"\n#include \"HidCommon.h\"\n\n// Device family metadata\n#incl"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/HidCommon.h",
    "chars": 975,
    "preview": "#pragma once\n\n#define REPORTID_STANDARDMOUSE 0x02\n#define REPORTID_MULTITOUCH 0x05\n#define REPORTID_REPORTMODE 0x04\n#def"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Input.c",
    "chars": 7316,
    "preview": "#include \"driver.h\"\n#include \"Input.tmh\"\n\nVOID\nAmtPtpSpiInputRoutineWorker(\n\tWDFDEVICE Device,\n\tWDFREQUEST PtpRequest\n)\n"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Input.h",
    "chars": 216,
    "preview": "#pragma once\n\nEVT_WDF_REQUEST_COMPLETION_ROUTINE AmtPtpRequestCompletionRoutine;\n\nVOID\nAmtPtpSpiInputRoutineWorker(\n\tWDF"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Public.h",
    "chars": 427,
    "preview": "/*++\n\nModule Name:\n\n    public.h\n\nAbstract:\n\n    This module contains the common declarations shared by driver\n    and u"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Queue.c",
    "chars": 7153,
    "preview": "/*++\n\nModule Name:\n\n    queue.c\n\nAbstract:\n\n    This file contains the queue entry points and callbacks.\n\nEnvironment:\n\n"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Queue.h",
    "chars": 811,
    "preview": "/*++\n\nModule Name:\n\n    queue.h\n\nAbstract:\n\n    This file contains the queue definitions.\n\nEnvironment:\n\n    Kernel-mode"
  },
  {
    "path": "src/AmtPtpDeviceSpiKm/Trace.h",
    "chars": 2083,
    "preview": "/*++\n\nModule Name:\n\n    Trace.h\n\nAbstract:\n\n    Header file for the debug tracing related function defintions and macros"
  },
  {
    "path": "src/AmtPtpDeviceUniversalPkg/AmtPtpDevice.inf",
    "chars": 11038,
    "preview": ";\n; AmtPtpDevice.inf\n;\n\n[Version]\nSignature = \"$WINDOWS NT$\"\nClass = HIDClass\nClassGuid = {745a17a0-74d3-11d0-b6fe-00a0c"
  },
  {
    "path": "src/AmtPtpDeviceUniversalPkg/AmtPtpDeviceUniversalPkg.vcxproj",
    "chars": 11315,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsof"
  },
  {
    "path": "src/AmtPtpDeviceUniversalPkg/AmtPtpDeviceUniversalPkg.vcxproj.filters",
    "chars": 464,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/AmtPtpDeviceUsbKm.vcxproj",
    "chars": 14227,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/AmtPtpDeviceUsbKm.vcxproj.filters",
    "chars": 2247,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/DebugUtils.c",
    "chars": 1779,
    "preview": "#include \"Driver.h\"\n\nPCHAR\nDbgDevicePowerString(\n\t_In_ WDF_POWER_DEVICE_STATE Type\n)\n{\n\tswitch (Type)\n\t{\n\tcase WdfPowerD"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Device.c",
    "chars": 15723,
    "preview": "/*++\n\nModule Name:\n\n    device.c - Device handling events for example driver.\n\nAbstract:\n\n   This file contains the devi"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Device.h",
    "chars": 3013,
    "preview": "/*++\n\nModule Name:\n\n    device.h\n\nAbstract:\n\n    This file contains the device definitions.\n\nEnvironment:\n\n    Kernel-mo"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Driver.c",
    "chars": 4183,
    "preview": "/*++\n\nModule Name:\n\n    driver.c\n\nAbstract:\n\n    This file contains the driver entry points and callbacks.\n\nEnvironment:"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Driver.h",
    "chars": 559,
    "preview": "/*++\n\nModule Name:\n\n    driver.h\n\nAbstract:\n\n    This file contains the driver definitions.\n\nEnvironment:\n\n    Kernel-mo"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Hid.c",
    "chars": 12191,
    "preview": "#include \"Driver.h\"\n#include \"hid.tmh\"\n\n#ifndef _AAPL_HID_DESCRIPTOR_H_\n#define _AAPL_HID_DESCRIPTOR_H_\n\nHID_REPORT_DESC"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Interrupt.c",
    "chars": 6319,
    "preview": "// Interrupt.c: Handles device input event\n\n#include \"Driver.h\"\n#include \"Interrupt.tmh\"\n\n// Helper function for numberi"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Public.h",
    "chars": 426,
    "preview": "/*++\n\nModule Name:\n\n    public.h\n\nAbstract:\n\n    This module contains the common declarations shared by driver\n    and u"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Queue.c",
    "chars": 6871,
    "preview": "/*++\n\nModule Name:\n\n    queue.c\n\nAbstract:\n\n    This file contains the queue entry points and callbacks.\n\nEnvironment:\n\n"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Queue.h",
    "chars": 708,
    "preview": "/*++\n\nModule Name:\n\n    queue.h\n\nAbstract:\n\n    This file contains the queue definitions.\n\nEnvironment:\n\n    Kernel-mode"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/Trace.h",
    "chars": 2091,
    "preview": "/*++\n\nModule Name:\n\n    Trace.h\n\nAbstract:\n\n    Header file for the debug tracing related function defintions and macros"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/include/AppleDefinition.h",
    "chars": 7077,
    "preview": "#pragma once\n\n#define USB_VENDOR_ID_APPLE\t\t0x05ac\n\n/* Apple T2 USB trackpad */\n#define USB_DEVICE_ID_APPLE_T2_7A 0x027a\n"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/include/Hid.h",
    "chars": 5679,
    "preview": "// Hid.h: Device-related HID definitions\n#pragma once\n\n#include <hidport.h>\n\n#include <AppleDefinition.h>\n#include <hid/"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/include/hid/HidCommon.h",
    "chars": 975,
    "preview": "#pragma once\n\n#define REPORTID_STANDARDMOUSE 0x02\n#define REPORTID_MULTITOUCH 0x05\n#define REPORTID_REPORTMODE 0x04\n#def"
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/include/metadata/WellspringT2.h",
    "chars": 5912,
    "preview": "#pragma once\n\n#include <hid/HidCommon.h>\n\n#define AAPL_WELLSPRING_T2_PTP_FINGER_COLLECTION_1 \\\n\tBEGIN_COLLECTION, 0x02, "
  },
  {
    "path": "src/AmtPtpDeviceUsbKm/resource.h",
    "chars": 425,
    "preview": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by Resource.rc\n\n#define IDS_APP_TITLE     "
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/AmtPtpDevice.wprp",
    "chars": 1748,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<WindowsPerformanceRecorder Version=\"1.0\" Author=\"AmtPtpDevice Authors\" Copyright"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/Device.c",
    "chars": 18650,
    "preview": "// Device.c: Device handling events for driver.\n\n#include <driver.h>\n#include \"device.tmh\"\n\n_IRQL_requires_(PASSIVE_LEVE"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/Driver.c",
    "chars": 3005,
    "preview": "// Driver.c: This file contains the driver entry points and callbacks.\n\n#include <driver.h>\n#include \"driver.tmh\"\n\n// De"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/Hid.c",
    "chars": 25934,
    "preview": "// Hid.c: HID-related routine\n\n#include <driver.h>\n#include <StaticHidRegistry.h>\n#include \"Hid.tmh\"\n\n_IRQL_requires_(PA"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/InputInterrupt.c",
    "chars": 13321,
    "preview": "// InputInterrupt.c: Handles device input event\n\n#include <driver.h>\n#include \"InputInterrupt.tmh\"\n\n_IRQL_requires_(PASS"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/MagicTrackpad2PtpDevice.vcxproj",
    "chars": 12874,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/MagicTrackpad2PtpDevice.vcxproj.filters",
    "chars": 3680,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/Queue.c",
    "chars": 6834,
    "preview": "// Queue.c: This file contains the queue entry points and callbacks.\n\n#include <driver.h>\n#include \"queue.tmh\"\n\nNTSTATUS"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/AppleDefinition.h",
    "chars": 14296,
    "preview": "#pragma once\n\n#define USB_VENDOR_ID_APPLE\t\t0x05ac\n\n/* MacbookAir, aka wellspring */\n#define USB_DEVICE_ID_APPLE_WELLSPRI"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/Device.h",
    "chars": 3976,
    "preview": "// Device.h: Device definitions\n\nEXTERN_C_START\n\n// Device context struct\ntypedef struct _DEVICE_CONTEXT\n{\n\tWDFUSBDEVICE"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring3.h",
    "chars": 5958,
    "preview": "#pragma once\n\n#include <HidCommon.h>\n\n#define AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_1 \\\n\tBEGIN_COLLECTION, 0x02, /* Be"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring5.h",
    "chars": 5958,
    "preview": "#pragma once\n\n#include <HidCommon.h>\n\n#define AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_1 \\\n\tBEGIN_COLLECTION, 0x02, /* Be"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring6.h",
    "chars": 5957,
    "preview": "#pragma once\n\n#include <HidCommon.h>\n\n#define AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_1 \\\n\tBEGIN_COLLECTION, 0x02, /* Be"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring7A.h",
    "chars": 5969,
    "preview": "#pragma once\n\n#include <HidCommon.h>\n\n#define AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_1 \\\n\tBEGIN_COLLECTION, 0x02, /* B"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring8.h",
    "chars": 5958,
    "preview": "#pragma once\n\n#include <HidCommon.h>\n\n#define AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_1 \\\n\tBEGIN_COLLECTION, 0x02, /* Be"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/DeviceFamily/WellspringMt2.h",
    "chars": 5922,
    "preview": "#pragma once\n\n#include <HidCommon.h>\n\n#define AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1 \\\n\tBEGIN_COLLECTION, 0x02, /*"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/Driver.h",
    "chars": 774,
    "preview": "// Driver.h: Driver definitions\n\n#include <windows.h>\n#include <wdf.h>\n#include <usb.h>\n#include <wdfusb.h>\n#include <in"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/Hid.h",
    "chars": 6153,
    "preview": "// Hid.h: Device-related HID definitions\n#pragma once\n\n#include <hidport.h>\n\n#include <AppleDefinition.h>\n#include <HidC"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/HidCommon.h",
    "chars": 975,
    "preview": "#pragma once\n\n#define REPORTID_STANDARDMOUSE 0x02\n#define REPORTID_MULTITOUCH 0x05\n#define REPORTID_REPORTMODE 0x04\n#def"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/ModernTrace.h",
    "chars": 864,
    "preview": "#pragma once\n// This is the new Windows 10 trace logger provider\n#include <TraceLoggingProvider.h>\n\nEXTERN_C_START\n\n//\n/"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/Queue.h",
    "chars": 775,
    "preview": "// Queue.h: This file contains the queue definitions.\n\nEXTERN_C_START\n\n//\n// This is the context that can be placed per "
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/StaticHidRegistry.h",
    "chars": 2829,
    "preview": "#pragma once\n\n#ifndef _AAPL_HID_DESCRIPTOR_H_\n#define _AAPL_HID_DESCRIPTOR_H_\n\nHID_REPORT_DESCRIPTOR AmtPtp3ReportDescri"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/Trace.h",
    "chars": 1552,
    "preview": "// Trace.h: Local type definitions for tracing\n\n//\n// Device Interface GUID\n// 4a5064e5-7d39-41d1-a0e4-81097edce967\n//\nD"
  },
  {
    "path": "src/AmtPtpDeviceUsbUm/include/resource.h",
    "chars": 425,
    "preview": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by Resource.rc\n\n#define IDS_APP_TITLE     "
  },
  {
    "path": "src/AmtPtpHidFilter/AmtPtpHidFilter.inf",
    "chars": 4055,
    "preview": ";\n; AmtPtpHidFilter.inf\n;\n\n[Version]\nSignature=\"$WINDOWS NT$\"\nClass = HIDClass\nClassGuid = {745a17a0-74d3-11d0-b6fe-00a0"
  },
  {
    "path": "src/AmtPtpHidFilter/AmtPtpHidFilter.vcxproj",
    "chars": 12606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "src/AmtPtpHidFilter/AmtPtpHidFilter.vcxproj.filters",
    "chars": 3317,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "src/AmtPtpHidFilter/Detour.c",
    "chars": 4005,
    "preview": "// Detour.c: Windows HID detour facilities\n\n#include <Driver.h>\n#include \"Detour.tmh\"\n\nNTSTATUS\nPtpFilterDetourWindowsHI"
  },
  {
    "path": "src/AmtPtpHidFilter/Device.c",
    "chars": 16221,
    "preview": "// Device.c: Device-specific D0<->D3 handler and other misc procedures\n\n#include <Driver.h>\n#include \"Device.tmh\"\n\n#ifde"
  },
  {
    "path": "src/AmtPtpHidFilter/Diagnostics.c",
    "chars": 5215,
    "preview": "// Diagnostics.c: Debug and diagnostics facilities\n\n#include <Driver.h>\n#include \"Diagnostics.tmh\"\n\nVOID PtpFilterDiagno"
  },
  {
    "path": "src/AmtPtpHidFilter/Driver.c",
    "chars": 2046,
    "preview": "// Driver.c: Common entry point and WPP trace filter handler\n\n#include <Driver.h>\n#include \"Driver.tmh\"\n\n#ifdef ALLOC_PR"
  },
  {
    "path": "src/AmtPtpHidFilter/Hid.c",
    "chars": 10764,
    "preview": "// Hid.c: HID specific routines\n\n#include <Driver.h>\n#include \"Hid.tmh\"\n\nNTSTATUS\nPtpFilterGetHidDescriptor(\n\t_In_ WDFDE"
  },
  {
    "path": "src/AmtPtpHidFilter/Input.c",
    "chars": 9249,
    "preview": "// Input.c: Input handler routines\n\n#include <Driver.h>\n#include \"Input.tmh\"\n\nVOID\nPtpFilterInputProcessRequest(\n\t_In_ W"
  },
  {
    "path": "src/AmtPtpHidFilter/Queue.c",
    "chars": 4136,
    "preview": "// Queue.c: IO-queue related operations\n\n#include <Driver.h>\n#include \"Queue.tmh\"\n\n#ifdef ALLOC_PRAGMA\n#pragma alloc_tex"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Device.h",
    "chars": 2507,
    "preview": "// Device.h: Device-specific struct and routines\n\n#pragma once\n\nEXTERN_C_START\n\n// {FF969022-3111-4441-8F88-875440172C2E"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Diagnostics.h",
    "chars": 445,
    "preview": "#pragma once\n\nEXTERN_C_START\n\nVOID PtpFilterDiagnosticsInitializeContinuousRead(\n\t_In_ WDFDEVICE Device\n);\n\nVOID\nPtpFilt"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Driver.h",
    "chars": 698,
    "preview": "// Driver.h: common definition\n#pragma once\n\n#include <ntddk.h>\n#include <wdf.h>\n#include <usb.h>\n#include <usbdlib.h>\n#"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Hac.h",
    "chars": 1402,
    "preview": "// Hac.h: Yes, we have to hack Windows HID stack on the fly...\n#pragma once\n\nEXTERN_C_START\n\n// HACK: detour the HIDClas"
  },
  {
    "path": "src/AmtPtpHidFilter/include/HidCommon.h",
    "chars": 1068,
    "preview": "// HidCommon.h: HID common definition\n#pragma once\n\n#define REPORTID_STANDARDMOUSE 0x02\n#define REPORTID_MULTITOUCH 0x05"
  },
  {
    "path": "src/AmtPtpHidFilter/include/HidDevice.h",
    "chars": 3026,
    "preview": "// HidDevice.h: devicei-specific HID structures\n#pragma once\n\n/* Trackpad finger data offsets, le16-aligned */\n#define H"
  },
  {
    "path": "src/AmtPtpHidFilter/include/HidMiniport.h",
    "chars": 2000,
    "preview": "// Hidminiport.h: HID miniport communication structures\n#pragma once\n\n#include <pshpack1.h>\n\n// PTP device capabilites F"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Input.h",
    "chars": 457,
    "preview": "// Input.h: Input processing and device definitions\n#pragma once\n\nVOID\nPtpFilterInputProcessRequest(\n\t_In_ WDFDEVICE Dev"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Metadata/MagicTrackpad2.h",
    "chars": 5961,
    "preview": "// MagicTrackpad2.h: Magic Trackpad 2 specific HID information\n#pragma once\n\n#define AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COL"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Metadata/StaticHidRegistry.h",
    "chars": 763,
    "preview": "// StaticHidRegistry.h: Static HID collection information\n#pragma once\n\n#include <hidport.h>\n\n#include <HidCommon.h>\n#in"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Metadata/WindowsHID.h",
    "chars": 4009,
    "preview": "// WindowsHID.h: Windows specific HID Top Level Collections\n#pragma once\n\n#define MAX_FINGERS 16\n\n#define PTP_MAX_CONTAC"
  },
  {
    "path": "src/AmtPtpHidFilter/include/Queue.h",
    "chars": 505,
    "preview": "// Queue.h: IO queue bits\n#pragma once\n\nEXTERN_C_START\n\n// Initialization\nNTSTATUS\nPtpFilterIoQueueInitialize(\n    _In_ "
  },
  {
    "path": "src/AmtPtpHidFilter/include/Trace.h",
    "chars": 2031,
    "preview": "// Trace.h: Defines WPP tracing control bits.\n\n#pragma once\n\n//\n// Define the tracing flags.\n//\n// Tracing GUID - eeb348"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the imbushuo/mac-precision-touchpad GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 112 files (557.0 KB), approximately 179.2k tokens, and a symbol index with 230 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!