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
[](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)
[](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
================================================
Debug
x86
{8FF9D2F4-EC60-4AAE-865D-F11D1B4DEC2F}
AppContainerExe
Properties
AmtPtpDevice.Settings
AmtPtpDevice.Settings
en-US
UAP
10.0.15063.0
10.0.15063.0
14
512
{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
true
AmtPtpDevice.Settings_TemporaryKey.pfx
win10-arm;win10-arm-aot;win10-x86;win10-x86-aot;win10-x64;win10-x64-aot
True
Always
x86|x64|arm
true
bin\x86\Debug\
DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
;2008
full
x86
false
prompt
true
true
bin\x86\Release\
TRACE;NETFX_CORE;WINDOWS_UWP
true
;2008
pdbonly
x86
false
prompt
true
true
true
bin\ARM\Debug\
DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
;2008
full
ARM
false
prompt
true
bin\ARM\Release\
TRACE;NETFX_CORE;WINDOWS_UWP
true
;2008
pdbonly
ARM
false
prompt
true
true
true
bin\x64\Debug\
DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
;2008
full
x64
false
prompt
true
bin\x64\Release\
TRACE;NETFX_CORE;WINDOWS_UWP
true
;2008
pdbonly
x64
false
prompt
true
true
App.xaml
MainPage.xaml
Designer
MSBuild:Compile
Designer
MSBuild:Compile
Designer
5.4.2
4.4.0
14.0
================================================
FILE: src/AmtPtpDevice.Settings/App.xaml
================================================
================================================
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
{
///
/// Provides application-specific behavior to supplement the default Application class.
///
sealed partial class App : Application
{
///
/// 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().
///
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
///
/// 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.
///
/// Details about the launch request and process.
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();
}
}
///
/// Invoked when Navigation to a certain page fails
///
/// The Frame which failed navigation
/// Details about the navigation failure
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
///
/// 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.
///
/// The source of the suspend request.
/// Details about the suspend request.
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
================================================
Input Settings
================================================
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(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(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
================================================
AmtPtpDevice.Settings
imbushuo
Assets\StoreLogo.png
================================================
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
================================================
================================================
FILE: src/AmtPtpDeviceSpiKm/AmtPtpDeviceSpiKm.vcxproj
================================================
ReleaseSigned
ARM64
ReleaseSigned
x64
Debug
x64
Release
x64
Debug
ARM64
Release
ARM64
{FC08B706-5661-47FA-A840-053B06125750}
{497e31cb-056b-4f31-abb8-447fd55ee5a5}
v4.5
12.0
Debug
Win32
AmtPtpDeviceSpiKm
$(LatestTargetPlatformVersion)
10.0.19041.0
Windows10
true
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
<_NT_TARGET_VERSION>0xA000004
1
23
Windows10
false
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
<_NT_TARGET_VERSION>0xA000004
1
23
Windows10
false
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
<_NT_TARGET_VERSION>0xA000004
1
23
Windows10
true
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
<_NT_TARGET_VERSION>0xA000004
1
23
Windows10
false
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
<_NT_TARGET_VERSION>0xA000004
1
23
Windows10
false
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
<_NT_TARGET_VERSION>0xA000004
1
23
http://timestamp.digicert.com
$(ProductionCertPath)
ProductionSign
Off
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
http://timestamp.digicert.com
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
http://timestamp.digicert.com
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
http://timestamp.digicert.com
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
http://timestamp.digicert.com
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
true
true
trace.h
true
4214
sha256
true
true
trace.h
true
4214
sha256
true
true
trace.h
true
4214
sha256
true
true
trace.h
true
4214
true
true
trace.h
true
4214
true
true
trace.h
true
4214
================================================
FILE: src/AmtPtpDeviceSpiKm/AmtPtpDeviceSpiKm.vcxproj.filters
================================================
{93995380-89BD-4b04-88EB-625FBE52EBFB}
h;hpp;hxx;hm;inl;inc;xsd
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
{8E41214B-6785-4CFE-B992-037D68949A14}
inf;inv;inx;mof;mc;
{895871d8-b6bd-4578-bd98-bec2cb45183b}
{4FC737F1-C7A5-4376-A066-2A32D752A2FF}
cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Device Specific Metadata Files
Header Files
Header Files
Device Specific Metadata Files
Device Specific Metadata Files
Source Files
Source Files
Source Files
Source Files
Source Files
================================================
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
#include
#include
#include
#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
#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 = WdfRequestRetrieveOutputMemory(
PtpRequest,
&PtpRequestMemory
);
if (!NT_SUCCESS(Status))
{
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
Status
);
goto exit;
}
Status = WdfMemoryCopyFromBuffer(
PtpRequestMemory,
0,
(PVOID) &PtpReport,
sizeof(PTP_REPORT)
);
if (!NT_SUCCESS(Status))
{
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
Status
);
goto exit;
}
// Set information
WdfRequestSetInformation(
PtpRequest,
sizeof(PTP_REPORT)
);
exit:
WdfRequestComplete(
PtpRequest,
Status
);
cleanup:
// Clean up
pSpiTrackpadPacket = NULL;
WdfObjectDelete(SpiRequest);
if (RequestContext->RequestMemory != NULL) {
WdfObjectDelete(RequestContext->RequestMemory);
}
}
================================================
FILE: src/AmtPtpDeviceSpiKm/Input.h
================================================
#pragma once
EVT_WDF_REQUEST_COMPLETION_ROUTINE AmtPtpRequestCompletionRoutine;
VOID
AmtPtpSpiInputRoutineWorker(
WDFDEVICE Device,
WDFREQUEST PtpRequest
);
VOID
AmtPtpSpiInputIssueRequest(
WDFDEVICE Device
);
================================================
FILE: src/AmtPtpDeviceSpiKm/Public.h
================================================
/*++
Module Name:
public.h
Abstract:
This module contains the common declarations shared by driver
and user applications.
Environment:
user and kernel
--*/
//
// Define an Interface Guid so that apps can find the device and talk to it.
//
DEFINE_GUID (GUID_DEVINTERFACE_AmtPtpDeviceSpiKm,
0xf271e39d,0xd211,0x4a6e,0xa4,0x39,0x63,0xe5,0x19,0x40,0xd2,0x10);
// {f271e39d-d211-4a6e-a439-63e51940d210}
================================================
FILE: src/AmtPtpDeviceSpiKm/Queue.c
================================================
/*++
Module Name:
queue.c
Abstract:
This file contains the queue entry points and callbacks.
Environment:
Kernel-mode Driver Framework
--*/
#include "driver.h"
#include "queue.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, AmtPtpDeviceSpiKmQueueInitialize)
#endif
NTSTATUS
AmtPtpDeviceSpiKmQueueInitialize(
_In_ WDFDEVICE Device
)
{
WDFQUEUE Queue;
NTSTATUS Status;
WDF_IO_QUEUE_CONFIG QueueConfig;
PDEVICE_CONTEXT pDeviceContext;
PAGED_CODE();
// By the time this is being called, it should exist
pDeviceContext = DeviceGetContext(Device);
//
// Configure a default queue so that requests that are not
// configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
// other queues get dispatched here.
//
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
&QueueConfig,
WdfIoQueueDispatchParallel
);
QueueConfig.EvtIoInternalDeviceControl = AmtPtpDeviceSpiKmEvtIoInternalDeviceControl;
QueueConfig.EvtIoStop = AmtPtpDeviceSpiKmEvtIoStop;
Status = WdfIoQueueCreate(
Device,
&QueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&Queue
);
if(!NT_SUCCESS(Status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "WdfIoQueueCreate failed %!STATUS!", Status);
goto exit;
}
//
// Create secondary queues for touch read requests.
//
WDF_IO_QUEUE_CONFIG_INIT(&QueueConfig, WdfIoQueueDispatchManual);
QueueConfig.PowerManaged = WdfFalse;
Status = WdfIoQueueCreate(
Device,
&QueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&pDeviceContext->HidQueue
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_QUEUE,
"%!FUNC! WdfIoQueueCreate (Input) failed %!STATUS!",
Status
);
}
exit:
return Status;
}
PCHAR
DbgIoControlGetString(
_In_ ULONG IoControlCode
)
{
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
return "IOCTL_HID_GET_DEVICE_DESCRIPTOR";
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
return "IOCTL_HID_GET_DEVICE_ATTRIBUTES";
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
return "IOCTL_HID_GET_REPORT_DESCRIPTOR";
case IOCTL_HID_GET_STRING:
return "IOCTL_HID_GET_STRING";
case IOCTL_HID_READ_REPORT:
return "IOCTL_HID_READ_REPORT";
case IOCTL_HID_WRITE_REPORT:
return "IOCTL_HID_WRITE_REPORT";
case IOCTL_UMDF_HID_GET_INPUT_REPORT:
return "IOCTL_UMDF_HID_GET_INPUT_REPORT";
case IOCTL_UMDF_HID_SET_OUTPUT_REPORT:
return "IOCTL_UMDF_HID_SET_OUTPUT_REPORT";
case IOCTL_UMDF_HID_GET_FEATURE:
return "IOCTL_UMDF_HID_GET_FEATURE";
case IOCTL_UMDF_HID_SET_FEATURE:
return "IOCTL_UMDF_HID_SET_FEATURE";
case IOCTL_HID_ACTIVATE_DEVICE:
return "IOCTL_HID_ACTIVATE_DEVICE";
case IOCTL_HID_DEACTIVATE_DEVICE:
return "IOCTL_HID_DEACTIVATE_DEVICE";
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST";
case IOCTL_HID_GET_FEATURE:
return "IOCTL_HID_GET_FEATURE";
case IOCTL_HID_SET_FEATURE:
return "IOCTL_HID_SET_FEATURE";
default:
return "IOCTL_UNKNOWN";
}
}
VOID
AmtPtpDeviceSpiKmEvtIoInternalDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
{
UNREFERENCED_PARAMETER(InputBufferLength);
UNREFERENCED_PARAMETER(OutputBufferLength);
NTSTATUS Status = STATUS_SUCCESS;
WDFDEVICE Device = WdfIoQueueGetDevice(Queue);
BOOLEAN RequestPending = FALSE;
// Dispatch IOCTL to handler
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
Status = AmtPtpGetHidDescriptor(
Device,
Request
);
break;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
Status = AmtPtpGetDeviceAttribs(
Device,
Request
);
break;
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
Status = AmtPtpGetReportDescriptor(
Device,
Request
);
break;
case IOCTL_HID_GET_STRING:
Status = AmtPtpGetStrings(
Device,
Request,
&RequestPending
);
break;
case IOCTL_HID_READ_REPORT:
AmtPtpSpiInputRoutineWorker(
Device,
Request
);
RequestPending = TRUE;
break;
case IOCTL_HID_GET_FEATURE:
Status = AmtPtpReportFeatures(
Device,
Request
);
break;
case IOCTL_HID_SET_FEATURE:
Status = AmtPtpSetFeatures(
Device,
Request
);
break;
case IOCTL_HID_WRITE_REPORT:
case IOCTL_UMDF_HID_SET_OUTPUT_REPORT:
case IOCTL_UMDF_HID_GET_INPUT_REPORT:
case IOCTL_HID_ACTIVATE_DEVICE:
case IOCTL_HID_DEACTIVATE_DEVICE:
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
default:
Status = STATUS_NOT_SUPPORTED;
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_QUEUE,
"%!FUNC!: %s is not yet implemented",
DbgIoControlGetString(IoControlCode)
);
break;
}
if (RequestPending != TRUE)
{
WdfRequestComplete(
Request,
Status
);
}
return;
}
VOID
AmtPtpDeviceSpiKmEvtIoStop(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ ULONG ActionFlags
)
{
UNREFERENCED_PARAMETER(Queue);
UNREFERENCED_PARAMETER(Request);
UNREFERENCED_PARAMETER(ActionFlags);
//
// In most cases, the EvtIoStop callback function completes, cancels, or postpones
// further processing of the I/O request.
//
// Typically, the driver uses the following rules:
//
// - If the driver owns the I/O request, it calls WdfRequestUnmarkCancelable
// (if the request is cancelable) and either calls WdfRequestStopAcknowledge
// with a Requeue value of TRUE, or it calls WdfRequestComplete with a
// completion status value of STATUS_SUCCESS or STATUS_CANCELLED.
//
// Before it can call these methods safely, the driver must make sure that
// its implementation of EvtIoStop has exclusive access to the request.
//
// In order to do that, the driver must synchronize access to the request
// to prevent other threads from manipulating the request concurrently.
// The synchronization method you choose will depend on your driver's design.
//
// For example, if the request is held in a shared context, the EvtIoStop callback
// might acquire an internal driver lock, take the request from the shared context,
// and then release the lock. At this point, the EvtIoStop callback owns the request
// and can safely complete or requeue the request.
//
// - If the driver has forwarded the I/O request to an I/O target, it either calls
// WdfRequestCancelSentRequest to attempt to cancel the request, or it postpones
// further processing of the request and calls WdfRequestStopAcknowledge with
// a Requeue value of FALSE.
//
// A driver might choose to take no action in EvtIoStop for requests that are
// guaranteed to complete in a small amount of time.
//
// In this case, the framework waits until the specified request is complete
// before moving the device (or system) to a lower power state or removing the device.
// Potentially, this inaction can prevent a system from entering its hibernation state
// or another low system power state. In extreme cases, it can cause the system
// to crash with bugcheck code 9F.
//
return;
}
================================================
FILE: src/AmtPtpDeviceSpiKm/Queue.h
================================================
/*++
Module Name:
queue.h
Abstract:
This file contains the queue definitions.
Environment:
Kernel-mode Driver Framework
--*/
EXTERN_C_START
//
// This is the context that can be placed per queue
// and would contain per queue information.
//
typedef struct _QUEUE_CONTEXT {
ULONG PrivateDeviceData; // just a placeholder
} QUEUE_CONTEXT, *PQUEUE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext)
NTSTATUS
AmtPtpDeviceSpiKmQueueInitialize(
_In_ WDFDEVICE Device
);
_IRQL_requires_(PASSIVE_LEVEL)
PCHAR
DbgIoControlGetString(
_In_ ULONG IoControlCode
);
//
// Events from the IoQueue object
//
EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL AmtPtpDeviceSpiKmEvtIoInternalDeviceControl;
EVT_WDF_IO_QUEUE_IO_STOP AmtPtpDeviceSpiKmEvtIoStop;
EXTERN_C_END
================================================
FILE: src/AmtPtpDeviceSpiKm/Trace.h
================================================
/*++
Module Name:
Trace.h
Abstract:
Header file for the debug tracing related function defintions and macros.
Environment:
Kernel mode
--*/
//
// Define the tracing flags.
//
// Tracing GUID - 9b319d80-fe25-41e4-80ef-7d8528f7f1b5
//
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID( \
AmtPtpDeviceSpiKmTraceGuid, (9b319d80,fe25,41e4,80ef,7d8528f7f1b5), \
\
WPP_DEFINE_BIT(TRACE_DRIVER) \
WPP_DEFINE_BIT(TRACE_DEVICE) \
WPP_DEFINE_BIT(TRACE_QUEUE) \
WPP_DEFINE_BIT(TRACE_HID_INPUT) \
)
#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
WPP_LEVEL_LOGGER(flag)
#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
(WPP_LEVEL_ENABLED(flag) && \
WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
WPP_LEVEL_LOGGER(flags)
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
//
// WPP orders static parameters before dynamic parameters. To support the Trace function
// defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to
// reorder the arguments to what the .tpl configuration file expects.
//
#define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags)
#define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags)
//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC Trace{FLAGS=TRACE_DRIVER}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//
================================================
FILE: src/AmtPtpDeviceUniversalPkg/AmtPtpDevice.inf
================================================
;
; AmtPtpDevice.inf
;
[Version]
Signature = "$WINDOWS NT$"
Class = HIDClass
ClassGuid = {745a17a0-74d3-11d0-b6fe-00a0c90f57da}
Provider = %ManufacturerName%
CatalogFile = AmtPtpDevice.cat
DriverVer =
PnpLockdown = 1
[DestinationDirs]
DefaultDestDir = 13
PtpUmDrivers_Dir = 13
[SourceDisksNames]
1 = %DiskName%,,,""
[SourceDisksFiles]
AmtPtpDeviceUsbKm.sys = 1,,
AmtPtpDeviceUsbUm.dll = 1,,
AmtPtpDeviceSpiKm.sys = 1,,
AmtPtpHidFilter.sys = 1,,
[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$
[Standard.NT$ARCH$]
; Apple T2
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0273&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0274&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0277&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_027A&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_027B&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_027C&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_027D&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_027E&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_027F&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0280&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0290&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0291&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0340&MI_02
; Traditional Mac trackpad
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0236&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0237&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0238&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0245&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0246&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0247&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0249&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_024a&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_024b&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_024c&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_024d&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_024e&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0252&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0253&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0254&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0259&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_025a&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_025b&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0262&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0263&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0264&MI_01
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0272&MI_02
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0273&MI_02
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0274&MI_02
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0290&MI_02
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0291&MI_02
; SPI
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0272&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0273&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0275&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0276&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0277&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0278&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0279&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0280&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0290&MI_02
%AmtPtpDeviceSpiKm.DeviceDesc%=AmtPtpDeviceSpiKm_Device, SPI\VID_05ac&PID_0291&MI_02
; Magic Trackpad 2 USB
; Note: this will be a last few versions where Magic Trackpad 2 uses this old implementation
%AmtPtpDeviceUsbUm.DeviceDesc%=AmtPtpDeviceUsbUm_Install, USB\Vid_05ac&Pid_0265&MI_01
; Magic Trackpad 2 Bluetooth
%AmtPtpHidFilter.DeviceDesc%=AmtPtpHidFilter_MiniPortDevice, HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0001004c_PID&0265&Col01
%AmtPtpHidFilter.NullDeviceDesc%=AmtPtpHidFilter_NullDevice, HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0001004c_PID&0265&Col02
; Null Device
[AmtPtpHidFilter_NullDevice]
; Nothing!
[AmtPtpHidFilter_NullDevice.Services]
AddService = ,2 ; no value for the service name
; File paylods for each set of driver
[FilterDriver_Payload]
AmtPtpHidFilter.sys
[PtpKmDrivers_Dir]
AmtPtpDeviceUsbKm.sys
[PtpUmDrivers_Dir]
AmtPtpDeviceUsbUm.dll
[SpiKmDrivers_Dir]
AmtPtpDeviceSpiKm.sys
; Microsoft HID KMDF driver install sections
[mshidkmdf_Service_Inst]
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\mshidkmdf.sys
; PTP filter
[AmtPtpHidFilter_MiniPortDevice.NT]
CopyFiles=FilterDriver_Payload
[AmtPtpHidFilter_MiniPortDevice.NT.Services]
AddService = AmtPtpHidFilter,, AmtPtpHidFilter_Service_Inst
AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst
[AmtPtpHidFilter_MiniPortDevice.NT.HW]
AddReg=AmtPtpHidFilter_AddReg
[AmtPtpHidFilter_AddReg]
HKR,,FriendlyName,,%AmtPtpHidFilter.DeviceDesc%
HKR,,"LowerFilters",0x00010008,"AmtPtpHidFilter"
[AmtPtpHidFilter_MiniPortDevice.NT.Wdf]
KmdfService = AmtPtpHidFilter, AmtPtpHidFilter_wdfsect
[AmtPtpHidFilter_Service_Inst]
DisplayName = %AmtPtpHidFilter.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %13%\AmtPtpHidFilter.sys
[AmtPtpHidFilter_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$
; USB KM
[AmtPtpDeviceUsbKm_Device.NT]
CopyFiles=PtpKmDrivers_Dir
[AmtPtpDeviceUsbKm_Device.NT.Services]
AddService = AmtPtpDeviceUsbKm,, AmtPtpDeviceUsbKm_Service_Inst
AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst
[AmtPtpDeviceUsbKm_Device.NT.HW]
AddReg=AmtPtpDeviceUsbKm_AddReg
[AmtPtpDeviceUsbKm_AddReg]
HKR,,FriendlyName,,%AmtPtpDeviceUsbKm.DeviceDesc%
HKR,,"LowerFilters",0x00010008,"AmtPtpDeviceUsbKm"
; -------------- AmtPtpDeviceUsbKm driver install sections
[AmtPtpDeviceUsbKm_Service_Inst]
DisplayName = %AmtPtpDeviceUsbKm.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %13%\AmtPtpDeviceUsbKm.sys
[AmtPtpDeviceUsbKm_Device.NT.Wdf]
KmdfService = AmtPtpDeviceUsbKm, AmtPtpDeviceUsbKm_wdfsect
[AmtPtpDeviceUsbKm_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$
; USB UM
[AmtPtpDeviceUsbUm_Install.NT]
CopyFiles=PtpUmDrivers_Dir
[AmtPtpDeviceUsbUm_Install.NT.hw]
AddReg=AmtPtpDeviceUsbUm_AddReg
[AmtPtpDeviceUsbUm_Install.NT.Services]
AddService=mshidumdf, 0x000001fa, MSHIDUMDF_ServiceInstall ; flag 0x2 sets this as the service for the device
AddService=WUDFRd,0x000001f8,WUDFRD_ServiceInstall ; this service is installed because its a filter.
[AmtPtpDeviceUsbUm_Install.NT.Wdf]
UmdfDispatcher=NativeUSB
UmdfService=AmtPtpDeviceUsbUm,AmtPtpDeviceUsbUm_Install
UmdfServiceOrder=AmtPtpDeviceUsbUm
UmdfKernelModeClientPolicy=AllowKernelModeClients
UmdfFileObjectPolicy=AllowNullAndUnknownFileObjects
UmdfMethodNeitherAction=Copy
UmdfFsContextUsePolicy=CanUseFsContext2
UmdfHostPriority=PriorityHigh
[AmtPtpDeviceUsbUm_Install]
UmdfLibraryVersion=2.15.0
ServiceBinary=%13%\AmtPtpDeviceUsbUm.dll
[AmtPtpDeviceUsbUm_AddReg]
HKR,,FriendlyName,,%AmtPtpDeviceUsbUm.DeviceDesc%
HKR,,"LowerFilters",0x00010008,"WUDFRd" ; FLG_ADDREG_TYPE_MULTI_SZ | FLG_ADDREG_APPEND
[mshidumdf_ServiceInstall]
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\mshidumdf.sys
[WUDFRD_ServiceInstall]
DisplayName = %WudfRdDisplayName%
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %12%\WUDFRd.sys
; SPI KM
[AmtPtpDeviceSpiKm_Device.NT]
CopyFiles=SpiKmDrivers_Dir
[AmtPtpDeviceSpiKm_Device.NT.Services]
AddService = AmtPtpDeviceSpiKm,, AmtPtpDeviceSpiKm_Service_Inst
AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst ;flag 0x2 sets this as the service for the device
[AmtPtpDeviceSpiKm_Device.NT.HW]
AddReg = AmtPtpDeviceSpiKm_Device.NT.AddReg
[AmtPtpDeviceSpiKm_Device.NT.AddReg]
HKR,,"LowerFilters",0x00010008,"AmtPtpDeviceSpiKm"
[AmtPtpDeviceSpiKm_Service_Inst]
DisplayName = %AmtPtpDeviceSpiKm.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %13%\AmtPtpDeviceSpiKm.sys
LoadOrderGroup = Extended Base
[AmtPtpDeviceSpiKm_Device.NT.Wdf]
KmdfService = AmtPtpDeviceSpiKm, AmtPtpDeviceSpiKm_wdfsect
[AmtPtpDeviceSpiKm_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$
[Strings]
REG_MULTI_SZ = 0x00010000
SPSVCINST_ASSOCSERVICE = 0x00000002
ManufacturerName = "Bingxing Wang"
ClassName = "Universal Serial Bus devices"
DiskName = "AmtPtpDeviceUsbKm Installation Disk"
AmtPtpDeviceUsbKm.DeviceDesc = "Apple USB Precision Touchpad Device (Kernel-mode)"
AmtPtpDeviceUsbUm.DeviceDesc = "Apple USB Precision Touchpad Device (User-mode)"
AmtPtpDeviceSpiKm.DeviceDesc = "Apple SPI Precision Touchpad Device"
AmtPtpDeviceSpiKm.SVCDESC = "Apple SPI Precision Touchpad Driver Service"
AmtPtpDeviceUsbKm.SVCDESC = "Apple USB Precision Touchpad Service"
WudfRdDisplayName = "Windows Driver Foundation - User-mode Driver Framework Reflector"
AmtPtpHidRootDevice.DeviceDesc = "Apple Multi-touch Trackpad HID Device"
AmtPtpHidFilter.DeviceDesc = "Apple Multi-touch Trackpad HID Filter"
AmtPtpHidFilter.NullDeviceDesc = "Apple Multi-touch Auxiliary Services"
AmtPtpHidFilter.SVCDESC = "Apple Multi-touch Trackpad HID Filter Service"
================================================
FILE: src/AmtPtpDeviceUniversalPkg/AmtPtpDeviceUniversalPkg.vcxproj
================================================
ReleaseSigned
ARM64
ReleaseSigned
x64
Debug
x64
Release
x64
Debug
ARM64
Release
ARM64
{fc08b706-5661-47fa-a840-053b06125750}
{ab3e45e7-c524-47c1-9677-728ba2a19344}
{87efa31b-25eb-4944-a30a-300171bfff57}
{ee63c42b-f401-4f55-adbb-14c16bd3b18c}
{7AB0A246-AA1C-433B-9E16-88956C51A565}
{4605da2c-74a5-4865-98e1-152ef136825f}
v4.5
12.0
Debug
Win32
AmtPtpDeviceUniversalPkg
$(LatestTargetPlatformVersion)
10.0.19041.0
Windows10
true
WindowsKernelModeDriver10.0
Utility
Package
true
Windows10
false
WindowsKernelModeDriver10.0
Utility
Package
true
Windows10
false
WindowsKernelModeDriver10.0
Utility
Package
true
Windows10
true
WindowsKernelModeDriver10.0
Utility
Package
true
Windows10
false
WindowsKernelModeDriver10.0
Utility
Package
true
Windows10
false
WindowsKernelModeDriver10.0
Utility
Package
true
http://timestamp.digicert.com
TestSign
http://timestamp.digicert.com
TestSign
http://timestamp.digicert.com
$(ProductionCertPath)
ProductionSign
Off
sha256
2021.$(PipelineReleaseID).1.1000
*
DbgengKernelDebugger
False
False
True
133563
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
DbgengKernelDebugger
False
False
True
133563
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
DbgengKernelDebugger
False
False
True
133563
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
DbgengKernelDebugger
False
False
True
133563
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
DbgengKernelDebugger
False
False
True
133563
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
DbgengKernelDebugger
False
False
True
133563
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
================================================
FILE: src/AmtPtpDeviceUniversalPkg/AmtPtpDeviceUniversalPkg.vcxproj.filters
================================================
{8E41214B-6785-4CFE-B992-037D68949A14}
inf;inv;inx;mof;mc;
Driver Files
================================================
FILE: src/AmtPtpDeviceUsbKm/AmtPtpDeviceUsbKm.vcxproj
================================================
ReleaseSigned
ARM64
ReleaseSigned
x64
Debug
x64
Release
x64
Debug
ARM64
Release
ARM64
{AB3E45E7-C524-47C1-9677-728BA2A19344}
{8c0e3d8b-df43-455b-815a-4a0e72973bc6}
v4.5
12.0
Debug
Win32
AmtPtpDeviceUsbKm
$(LatestTargetPlatformVersion)
10.0.19041.0
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
Windows10
true
Windows10
false
Windows10
false
Windows10
true
Windows10
false
Windows10
false
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
http://timestamp.digicert.com
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
http://timestamp.digicert.com
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
http://timestamp.digicert.com
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
http://timestamp.digicert.com
DbgengKernelDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
http://timestamp.digicert.com
$(ProductionCertPath)
ProductionSign
Off
true
true
trace.h
true
4214;%(DisableSpecificWarnings)
%(AdditionalDependencies);usbdex.lib;ntstrsafe.lib
sha256
true
true
trace.h
true
4214;%(DisableSpecificWarnings)
%(AdditionalDependencies);usbdex.lib;ntstrsafe.lib
sha256
true
true
trace.h
true
4214;%(DisableSpecificWarnings)
%(AdditionalDependencies);usbdex.lib;ntstrsafe.lib
sha256
true
true
trace.h
true
4214;%(DisableSpecificWarnings)
%(AdditionalDependencies);usbdex.lib;ntstrsafe.lib
true
true
trace.h
true
4214;%(DisableSpecificWarnings)
%(AdditionalDependencies);usbdex.lib;ntstrsafe.lib
true
true
trace.h
true
4214;%(DisableSpecificWarnings)
%(AdditionalDependencies);usbdex.lib;ntstrsafe.lib
================================================
FILE: src/AmtPtpDeviceUsbKm/AmtPtpDeviceUsbKm.vcxproj.filters
================================================
{4FC737F1-C7A5-4376-A066-2A32D752A2FF}
cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
{93995380-89BD-4b04-88EB-625FBE52EBFB}
h;hpp;hxx;hm;inl;inc;xsd
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
{8E41214B-6785-4CFE-B992-037D68949A14}
inf;inv;inx;mof;mc;
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Source Files
Source Files
Source Files
Source Files
Source Files
Source Files
Resource Files
================================================
FILE: src/AmtPtpDeviceUsbKm/DebugUtils.c
================================================
#include "Driver.h"
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";
}
}
PCHAR
DbgIoControlGetString(
_In_ ULONG IoControlCode
)
{
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
return "IOCTL_HID_GET_DEVICE_DESCRIPTOR";
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
return "IOCTL_HID_GET_DEVICE_ATTRIBUTES";
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
return "IOCTL_HID_GET_REPORT_DESCRIPTOR";
case IOCTL_HID_GET_STRING:
return "IOCTL_HID_GET_STRING";
case IOCTL_HID_READ_REPORT:
return "IOCTL_HID_READ_REPORT";
case IOCTL_HID_WRITE_REPORT:
return "IOCTL_HID_WRITE_REPORT";
case IOCTL_UMDF_HID_GET_INPUT_REPORT:
return "IOCTL_UMDF_HID_GET_INPUT_REPORT";
case IOCTL_UMDF_HID_SET_OUTPUT_REPORT:
return "IOCTL_UMDF_HID_SET_OUTPUT_REPORT";
case IOCTL_UMDF_HID_GET_FEATURE:
return "IOCTL_UMDF_HID_GET_FEATURE";
case IOCTL_UMDF_HID_SET_FEATURE:
return "IOCTL_UMDF_HID_SET_FEATURE";
case IOCTL_HID_ACTIVATE_DEVICE:
return "IOCTL_HID_ACTIVATE_DEVICE";
case IOCTL_HID_DEACTIVATE_DEVICE:
return "IOCTL_HID_DEACTIVATE_DEVICE";
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST";
default:
return "IOCTL_UNKNOWN";
}
}
================================================
FILE: src/AmtPtpDeviceUsbKm/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, AmtPtpDeviceUsbKmCreateDevice)
#pragma alloc_text (PAGE, AmtPtpDeviceUsbKmEvtDevicePrepareHardware)
#endif
_IRQL_requires_(PASSIVE_LEVEL)
static const struct BCM5974_CONFIG*
AmtPtpGetDeviceConfig(
_In_ USB_DEVICE_DESCRIPTOR deviceInfo
)
{
USHORT id = deviceInfo.idProduct;
const struct BCM5974_CONFIG* cfg;
for (cfg = Bcm5974ConfigTable; cfg->identification; ++cfg) {
if (cfg->identification == id) {
return cfg;
}
}
// Generic fallback
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! Selected a generic fallback configuration"
);
return &Bcm5974ConfigTable[0];
}
NTSTATUS
AmtPtpDeviceUsbKmCreateDevice(
_Inout_ PWDFDEVICE_INIT DeviceInit
)
/*++
Routine Description:
Worker routine called to create a device and its software resources.
Arguments:
DeviceInit - Pointer to an opaque init structure. Memory for this
structure will be freed by the framework when the WdfDeviceCreate
succeeds. So don't access the structure after that point.
Return Value:
NTSTATUS
--*/
{
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_OBJECT_ATTRIBUTES deviceAttributes;
PDEVICE_CONTEXT deviceContext;
WDFDEVICE device;
NTSTATUS status;
PAGED_CODE();
// Initialize power callback (prep, D0 entry & exit)
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = AmtPtpDeviceUsbKmEvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDeviceD0Entry = AmtPtpEvtDeviceD0Entry;
pnpPowerCallbacks.EvtDeviceD0Exit = AmtPtpEvtDeviceD0Exit;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
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.
//
deviceContext = DeviceGetContext(device);
//
// Initialize the context.
//
deviceContext->PtpReportButton = TRUE;
deviceContext->PtpReportTouch = TRUE;
//
// Create a device interface so that applications can find and talk
// to us.
//
status = WdfDeviceCreateDeviceInterface(
device,
&GUID_DEVINTERFACE_AmtPtpDeviceUsbKm,
NULL // ReferenceString
);
if (NT_SUCCESS(status)) {
//
// Initialize the I/O Package and any Queues
//
status = AmtPtpDeviceUsbKmQueueInitialize(device);
}
}
return status;
}
NTSTATUS
AmtPtpDeviceUsbKmEvtDevicePrepareHardware(
_In_ WDFDEVICE Device,
_In_ WDFCMRESLIST ResourceList,
_In_ WDFCMRESLIST ResourceListTranslated
)
/*++
Routine Description:
In this callback, the driver does whatever is necessary to make the
hardware ready to use. In the case of a USB device, this involves
reading and selecting descriptors.
Arguments:
Device - handle to a device
Return Value:
NT status value
--*/
{
NTSTATUS status;
PDEVICE_CONTEXT pDeviceContext;
WDF_USB_DEVICE_INFORMATION deviceInfo;
ULONG waitWakeEnable = FALSE;
UNREFERENCED_PARAMETER(ResourceList);
UNREFERENCED_PARAMETER(ResourceListTranslated);
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
status = STATUS_SUCCESS;
pDeviceContext = DeviceGetContext(Device);
//
// Create a USB device handle so that we can communicate with the
// underlying USB stack. The WDFUSBDEVICE handle is used to query,
// configure, and manage all aspects of the USB device.
// These aspects include device properties, bus properties,
// and I/O creation and synchronization. We only create the device the first time
// PrepareHardware is called. If the device is restarted by pnp manager
// for resource rebalance, we will use the same device handle but then select
// the interfaces again because the USB stack could reconfigure the device on
// restart.
//
if (pDeviceContext->UsbDevice == NULL) {
status = WdfUsbTargetDeviceCreate(Device,
WDF_NO_OBJECT_ATTRIBUTES,
&pDeviceContext->UsbDevice
);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
"WdfUsbTargetDeviceCreate failed 0x%x", status);
return status;
}
}
// Retrieve device information
WdfUsbTargetDeviceGetDeviceDescriptor(
pDeviceContext->UsbDevice,
&pDeviceContext->DeviceDescriptor
);
// Get correct configuration from conf store
pDeviceContext->DeviceInfo = AmtPtpGetDeviceConfig(pDeviceContext->DeviceDescriptor);
if (pDeviceContext->DeviceInfo == NULL) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
"AmtPtpGetDeviceConfig failed to find the device config");
status = STATUS_INVALID_DEVICE_STATE;
return status;
}
//
// Retrieve USBD version information, port driver capabilites and device
// capabilites such as speed, power, etc.
//
WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo);
status = WdfUsbTargetDeviceRetrieveInformation(
pDeviceContext->UsbDevice,
&deviceInfo
);
if (NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DEVICE,
"%!FUNC! IsDeviceHighSpeed: %s",
(deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE");
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DEVICE,
"%!FUNC! IsDeviceSelfPowered: %s",
(deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE");
waitWakeEnable = deviceInfo.Traits &
WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DEVICE,
"%!FUNC! IsDeviceRemoteWakeable: %s",
waitWakeEnable ? "TRUE" : "FALSE");
//
// Save these for use later.
//
pDeviceContext->UsbDeviceTraits = deviceInfo.Traits;
}
else {
pDeviceContext->UsbDeviceTraits = 0;
}
// Select interface to use
status = SelectInterruptInterface(Device);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
"%!FUNC! SelectInterruptInterface failed with %!STATUS!", status);
return status;
}
// Set up interrupt
status = AmtPtpConfigContReaderForInterruptEndPoint(pDeviceContext);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
"%!FUNC! AmtPtpConfigContReaderForInterruptEndPoint failed with %!STATUS!", status);
return status;
}
// Set default settings
pDeviceContext->PtpReportButton = TRUE;
pDeviceContext->PtpReportTouch = TRUE;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
return status;
}
// D0 Entry & Exit
NTSTATUS
AmtPtpEvtDeviceD0Entry(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE PreviousState
)
{
PDEVICE_CONTEXT pDeviceContext;
NTSTATUS status;
BOOLEAN isTargetStarted;
pDeviceContext = DeviceGetContext(Device);
isTargetStarted = FALSE;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Entry - coming from %s",
DbgDevicePowerString(PreviousState)
);
// Check wellspring mode
if (pDeviceContext->PtpReportButton || pDeviceContext->IsWellspringModeOn) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Start Wellspring Mode"
);
status = AmtPtpSetWellspringMode(
pDeviceContext,
TRUE
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Start Wellspring Mode failed with %!STATUS!",
status
);
}
}
// Get current time counter
KeQueryPerformanceCounter(&pDeviceContext->LastReportTime);
//
// Since continuous reader is configured for this interrupt-pipe, we must explicitly start
// the I/O target to get the framework to post read requests.
//
status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe));
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Failed to start interrupt pipe %!STATUS!",
status
);
goto end;
}
isTargetStarted = TRUE;
end:
if (!NT_SUCCESS(status)) {
//
// Failure in D0Entry will lead to device being removed. So let us stop the continuous
// reader in preparation for the ensuing remove.
//
if (isTargetStarted) {
WdfIoTargetStop(
WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe),
WdfIoTargetCancelSentIo
);
}
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry"
);
return status;
}
NTSTATUS
AmtPtpEvtDeviceD0Exit(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE TargetState
)
{
PDEVICE_CONTEXT pDeviceContext;
NTSTATUS status;
PAGED_CODE();
status = STATUS_SUCCESS;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - moving to %s",
DbgDevicePowerString(TargetState)
);
pDeviceContext = DeviceGetContext(Device);
// Stop IO Pipe.
WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(
pDeviceContext->InterruptPipe),
WdfIoTargetCancelSentIo
);
// Cancel Wellspring mode.
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - Cancel Wellspring Mode"
);
status = AmtPtpSetWellspringMode(
pDeviceContext,
FALSE
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - Cancel Wellspring Mode failed with %!STATUS!",
status
);
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Exit"
);
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
SelectInterruptInterface(
_In_ WDFDEVICE Device
)
{
WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT pDeviceContext;
WDFUSBPIPE pipe;
WDF_USB_PIPE_INFORMATION pipeInfo;
UCHAR index;
UCHAR numberConfiguredPipes;
PAGED_CODE();
pDeviceContext = DeviceGetContext(Device);
WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);
// It is slightly different than UMDF
status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice,
WDF_NO_OBJECT_ATTRIBUTES,
&configParams);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
"WdfUsbTargetDeviceSelectConfig failed %!STATUS! ",
status);
return status;
}
pDeviceContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface;
numberConfiguredPipes = configParams.Types.SingleInterface.NumberConfiguredPipes;
//
// Get pipe handles
//
for (index = 0; index < numberConfiguredPipes; index++) {
WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
pipe = WdfUsbInterfaceGetConfiguredPipe(
pDeviceContext->UsbInterface,
index, //PipeIndex,
&pipeInfo
);
//
// Tell the framework that it's okay to read less than
// MaximumPacketSize
//
WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pipe);
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DEVICE,
"%!FUNC! Found USB pipe type %d",
pipeInfo.PipeType
);
if (WdfUsbPipeTypeInterrupt == pipeInfo.PipeType) {
pDeviceContext->InterruptPipe = pipe;
break;
}
}
//
// If we didn't find interrupt pipe, fail the start.
//
if (!pDeviceContext->InterruptPipe) {
status = STATUS_INVALID_DEVICE_STATE;
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! Device is not configured properly %!STATUS!",
status
);
return status;
}
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpSetWellspringMode(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ BOOLEAN IsWellspringModeOn
)
{
NTSTATUS status;
WDF_USB_CONTROL_SETUP_PACKET setupPacket;
WDF_MEMORY_DESCRIPTOR memoryDescriptor;
ULONG cbTransferred;
WDFMEMORY bufHandle = NULL;
unsigned char* buffer;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
// Type 3 does not need a mode switch.
// However, turn mode on or off as requested.
if (DeviceContext->DeviceInfo->tp_type == TYPE3) {
DeviceContext->IsWellspringModeOn = IsWellspringModeOn;
return STATUS_SUCCESS;
}
status = WdfMemoryCreate(
WDF_NO_OBJECT_ATTRIBUTES,
PagedPool,
POOL_TAG_PTP_CONTROL,
DeviceContext->DeviceInfo->um_size,
&bufHandle,
&buffer
);
if (!NT_SUCCESS(status)) {
goto cleanup;
}
RtlZeroMemory(
buffer,
DeviceContext->DeviceInfo->um_size
);
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
&memoryDescriptor,
buffer,
sizeof(DeviceContext->DeviceInfo->um_size)
);
WDF_USB_CONTROL_SETUP_PACKET_INIT(
&setupPacket,
BmRequestDeviceToHost,
BmRequestToInterface,
BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
(USHORT) DeviceContext->DeviceInfo->um_req_val,
(USHORT) DeviceContext->DeviceInfo->um_req_idx
);
// Set stuffs right
setupPacket.Packet.bm.Request.Type = BmRequestClass;
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
DeviceContext->UsbDevice,
WDF_NO_HANDLE,
NULL,
&setupPacket,
&memoryDescriptor,
&cbTransferred
);
// Behavior mismatch: Actual device does not transfer bytes as expected (in length)
// So we do not check um_size as a temporary workaround.
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Read) failed with %!STATUS!, cbTransferred = %llu, um_size = %d",
status,
cbTransferred,
DeviceContext->DeviceInfo->um_size
);
goto cleanup;
}
// Apply the mode switch
buffer[DeviceContext->DeviceInfo->um_switch_idx] = IsWellspringModeOn ?
(unsigned char)DeviceContext->DeviceInfo->um_switch_on :
(unsigned char)DeviceContext->DeviceInfo->um_switch_off;
// Write configuration
WDF_USB_CONTROL_SETUP_PACKET_INIT(
&setupPacket,
BmRequestHostToDevice,
BmRequestToInterface,
BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID,
(USHORT)DeviceContext->DeviceInfo->um_req_val,
(USHORT)DeviceContext->DeviceInfo->um_req_idx
);
// Set stuffs right
setupPacket.Packet.bm.Request.Type = BmRequestClass;
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
DeviceContext->UsbDevice,
WDF_NO_HANDLE,
NULL,
&setupPacket,
&memoryDescriptor,
&cbTransferred
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Write) failed with %!STATUS!",
status
);
goto cleanup;
}
// Set status
DeviceContext->IsWellspringModeOn = IsWellspringModeOn;
cleanup:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
WdfObjectDelete(bufHandle);
bufHandle = NULL;
return status;
}
================================================
FILE: src/AmtPtpDeviceUsbKm/Device.h
================================================
/*++
Module Name:
device.h
Abstract:
This file contains the device definitions.
Environment:
Kernel-mode Driver Framework
--*/
#include "public.h"
EXTERN_C_START
//
// The device context performs the same job as
// a WDM device extension in the driver frameworks
//
typedef struct _DEVICE_CONTEXT
{
// USB Things
WDFUSBDEVICE UsbDevice;
WDFUSBPIPE InterruptPipe;
WDFUSBINTERFACE UsbInterface;
WDFQUEUE InputQueue;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
ULONG UsbDeviceTraits;
// Device Config
const struct BCM5974_CONFIG* DeviceInfo;
BOOLEAN IsWellspringModeOn;
// PTP Status
BOOLEAN PtpInputOn;
BOOLEAN PtpReportTouch;
BOOLEAN PtpReportButton;
// Timer
LARGE_INTEGER LastReportTime;
} 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)
//
// Pool tags
//
#define POOL_TAG_PTP_CONTROL 'PTPC'
//
// Function to initialize the device's queues and callbacks
//
NTSTATUS
AmtPtpDeviceUsbKmCreateDevice(
_Inout_ PWDFDEVICE_INIT DeviceInit
);
//
// Function to select the device's USB configuration and get a WDFUSBDEVICE
// handle
//
EVT_WDF_DEVICE_PREPARE_HARDWARE AmtPtpDeviceUsbKmEvtDevicePrepareHardware;
EVT_WDF_DEVICE_D0_ENTRY AmtPtpEvtDeviceD0Entry;
EVT_WDF_DEVICE_D0_EXIT AmtPtpEvtDeviceD0Exit;
//
// Function to select interrupt interface
//
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
SelectInterruptInterface(
_In_ WDFDEVICE Device
);
//
// Function to configure interrupt
//
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpConfigContReaderForInterruptEndPoint(
_In_ PDEVICE_CONTEXT DeviceContext
);
//
// Functions to serve interrupt
//
EVT_WDF_USB_READER_COMPLETION_ROUTINE AmtPtpEvtUsbInterruptPipeReadComplete;
EVT_WDF_USB_READERS_FAILED AmtPtpEvtUsbInterruptReadersFailed;
//
// Debug utilities
//
PCHAR
DbgDevicePowerString(
_In_ WDF_POWER_DEVICE_STATE Type
);
PCHAR
DbgIoControlGetString(
_In_ ULONG IoControlCode
);
//
// Device functions
//
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpSetWellspringMode(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ BOOLEAN IsWellspringModeOn
);
//
// 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
);
NTSTATUS
AmtPtpDispatchReadReportRequests(
_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
);
EXTERN_C_END
================================================
FILE: src/AmtPtpDeviceUsbKm/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, AmtPtpDeviceUsbKmEvtDeviceAdd)
#pragma alloc_text (PAGE, AmtPtpDeviceUsbKmEvtDriverContextCleanup)
#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");
//
// 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 = AmtPtpDeviceUsbKmEvtDriverContextCleanup;
WDF_DRIVER_CONFIG_INIT(&config,
AmtPtpDeviceUsbKmEvtDeviceAdd
);
status = WdfDriverCreate(DriverObject,
RegistryPath,
&attributes,
&config,
WDF_NO_HANDLE
);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
WPP_CLEANUP(DriverObject);
return status;
}
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
return status;
}
NTSTATUS
AmtPtpDeviceUsbKmEvtDeviceAdd(
_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 = AmtPtpDeviceUsbKmCreateDevice(DeviceInit);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
return status;
}
VOID
AmtPtpDeviceUsbKmEvtDriverContextCleanup(
_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/AmtPtpDeviceUsbKm/Driver.h
================================================
/*++
Module Name:
driver.h
Abstract:
This file contains the driver definitions.
Environment:
Kernel-mode Driver Framework
--*/
#include
#include
#include
#include
#include
#include
#include "device.h"
#include "queue.h"
#include "trace.h"
#include
EXTERN_C_START
//
// WDFDRIVER Events
//
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD AmtPtpDeviceUsbKmEvtDeviceAdd;
EVT_WDF_OBJECT_CONTEXT_CLEANUP AmtPtpDeviceUsbKmEvtDriverContextCleanup;
EXTERN_C_END
================================================
FILE: src/AmtPtpDeviceUsbKm/Hid.c
================================================
#include "Driver.h"
#include "hid.tmh"
#ifndef _AAPL_HID_DESCRIPTOR_H_
#define _AAPL_HID_DESCRIPTOR_H_
HID_REPORT_DESCRIPTOR AmtPtpT2ReportDescriptor[] = {
AAPL_WELLSPRING_T2_PTP_TLC,
AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
};
CONST HID_DESCRIPTOR AmtPtpT2DefaultHidDescriptor = {
0x09, // bLength
0x21, // bDescriptorType
0x0100, // bcdHID
0x00, // bCountryCode
0x01, // bNumDescriptors
{
0x22, // bDescriptorType
sizeof(AmtPtpT2ReportDescriptor) // bDescriptorLength
},
};
#endif
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetHidDescriptor(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT pContext = DeviceGetContext(Device);
size_t szCopy = 0;
WDFMEMORY requestMemory;
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_DRIVER,
"%!FUNC! Entry"
);
status = WdfRequestRetrieveOutputMemory(
Request,
&requestMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
status
);
goto exit;
}
switch (pContext->DeviceDescriptor.idProduct) {
case USB_DEVICE_ID_APPLE_T2_7A:
case USB_DEVICE_ID_APPLE_T2_7B:
case USB_DEVICE_ID_APPLE_T2_7C:
case USB_DEVICE_ID_APPLE_T2_7D:
{
szCopy = AmtPtpT2DefaultHidDescriptor.bLength;
status = WdfMemoryCopyFromBuffer(
requestMemory,
0,
(PVOID) &AmtPtpT2DefaultHidDescriptor,
szCopy
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
status
);
goto exit;
}
WdfRequestSetInformation(Request,szCopy);
break;
}
default:
{
TraceEvents(
TRACE_LEVEL_WARNING, TRACE_DRIVER,
"%!FUNC! Device HID registry is not found, use a generic fallback"
);
szCopy = AmtPtpT2DefaultHidDescriptor.bLength;
status = WdfMemoryCopyFromBuffer(
requestMemory,
0,
(PVOID)&AmtPtpT2DefaultHidDescriptor,
szCopy
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
status
);
goto exit;
}
WdfRequestSetInformation(Request, szCopy);
break;
}
};
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 pContext = 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);
pDeviceAttributes->ProductID = pContext->DeviceDescriptor.idProduct;
pDeviceAttributes->VendorID = pContext->DeviceDescriptor.idVendor;
pDeviceAttributes->VersionNumber = DEVICE_VERSION;
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;
PDEVICE_CONTEXT pContext = DeviceGetContext(Device);
size_t szCopy = 0;
WDFMEMORY requestMemory;
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_DRIVER,
"%!FUNC! Entry"
);
status = WdfRequestRetrieveOutputMemory(
Request,
&requestMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
status
);
goto exit;
}
switch (pContext->DeviceDescriptor.idProduct) {
case USB_DEVICE_ID_APPLE_T2_7A:
case USB_DEVICE_ID_APPLE_T2_7B:
case USB_DEVICE_ID_APPLE_T2_7C:
case USB_DEVICE_ID_APPLE_T2_7D:
{
szCopy = AmtPtpT2DefaultHidDescriptor.DescriptorList[0].wReportLength;
if (szCopy == 0) {
status = STATUS_INVALID_DEVICE_STATE;
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! Device HID report length is zero"
);
goto exit;
}
status = WdfMemoryCopyFromBuffer(
requestMemory,
0,
(PVOID) &AmtPtpT2ReportDescriptor,
szCopy
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
status
);
goto exit;
}
WdfRequestSetInformation(Request, szCopy);
break;
}
default:
{
TraceEvents(
TRACE_LEVEL_WARNING, TRACE_DRIVER,
"%!FUNC! Device HID registry is not found, use a generic fallback"
);
szCopy = AmtPtpT2DefaultHidDescriptor.DescriptorList[0].wReportLength;
if (szCopy == 0) {
status = STATUS_INVALID_DEVICE_STATE;
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! Device HID report length is zero"
);
goto exit;
}
status = WdfMemoryCopyFromBuffer(
requestMemory,
0,
(PVOID)&AmtPtpT2ReportDescriptor,
szCopy
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
status
);
goto exit;
}
WdfRequestSetInformation(Request, szCopy);
break;
}
}
exit:
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_DRIVER,
"%!FUNC! Exit"
);
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;
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))
{
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! HID_XFER_PACKET buffer too small"
);
status = STATUS_BUFFER_TOO_SMALL;
goto exit;
}
pHidPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(Request)->UserBuffer;
if (pHidPacket == NULL)
{
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! HID_XFER_PACKET has no input packet"
);
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 devInputMode = (PPTP_DEVICE_INPUT_MODE_REPORT) pHidPacket->reportBuffer;
BOOLEAN bWellspringMode = pDeviceContext->IsWellspringModeOn;
switch (devInputMode->Mode)
{
case PTP_COLLECTION_MOUSE:
{
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_DRIVER,
"%!FUNC! Report REPORTID_REPORTMODE requested Mouse Input but not supported"
);
status = STATUS_NOT_SUPPORTED;
goto exit;
}
case PTP_COLLECTION_WINDOWS:
{
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_DRIVER,
"%!FUNC! Report REPORTID_REPORTMODE requested Windows PTP Input"
);
if (!bWellspringMode) {
status = AmtPtpSetWellspringMode(pDeviceContext, TRUE);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! -> AmtPtpSetWellspringMode failed with status %!STATUS!",
status
);
goto exit;
}
}
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 secInput = (PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT) pHidPacket->reportBuffer;
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_DRIVER,
"%!FUNC! Report REPORTID_FUNCSWITCH requested Button = %d, Surface = %d",
secInput->ButtonReport,
secInput->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/AmtPtpDeviceUsbKm/Interrupt.c
================================================
// Interrupt.c: Handles device input event
#include "Driver.h"
#include "Interrupt.tmh"
// Helper function for numberic operation
static inline INT AmtRawToInteger(
_In_ USHORT x
)
{
return (signed short)x;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpConfigContReaderForInterruptEndPoint(
_In_ PDEVICE_CONTEXT DeviceContext
)
{
WDF_USB_CONTINUOUS_READER_CONFIG contReaderConfig;
NTSTATUS status;
size_t transferLength = 0;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
switch (DeviceContext->DeviceInfo->tp_type)
{
case TYPE1:
transferLength = HEADER_TYPE1 + FSIZE_TYPE1 * MAX_FINGERS;
break;
case TYPE2:
transferLength = HEADER_TYPE2 + FSIZE_TYPE2 * MAX_FINGERS;
break;
case TYPE3:
transferLength = HEADER_TYPE3 + FSIZE_TYPE3 * MAX_FINGERS;
break;
case TYPE4:
transferLength = HEADER_TYPE4 + FSIZE_TYPE4 * MAX_FINGERS;
break;
case TYPE5:
transferLength = HEADER_TYPE5 + FSIZE_TYPE5 * MAX_FINGERS;
break;
}
if (transferLength <= 0) {
status = STATUS_UNKNOWN_REVISION;
goto exit;
}
WDF_USB_CONTINUOUS_READER_CONFIG_INIT(
&contReaderConfig,
AmtPtpEvtUsbInterruptPipeReadComplete,
DeviceContext, // Context
transferLength // Calculate transferred length by device information
);
contReaderConfig.EvtUsbTargetPipeReadersFailed = AmtPtpEvtUsbInterruptReadersFailed;
// Remember to turn it on in D0 entry
status = WdfUsbTargetPipeConfigContinuousReader(
DeviceContext->InterruptPipe,
&contReaderConfig
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! AmtPtpConfigContReaderForInterruptEndPoint failed with Status code %!STATUS!",
status
);
goto exit;
}
exit:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return STATUS_SUCCESS;
}
VOID
AmtPtpEvtUsbInterruptPipeReadComplete(
_In_ WDFUSBPIPE Pipe,
_In_ WDFMEMORY Buffer,
_In_ size_t NumBytesTransferred,
_In_ WDFCONTEXT Context
)
{
UNREFERENCED_PARAMETER(Pipe);
PDEVICE_CONTEXT pDeviceContext = Context;
size_t headerSize = (unsigned int)pDeviceContext->DeviceInfo->tp_header;
size_t fingerprintSize = (unsigned int)pDeviceContext->DeviceInfo->tp_fsize;
size_t raw_n, i;
USHORT x = 0, y = 0;
UCHAR* TouchBuffer = NULL;
const struct TRACKPAD_FINGER* f = NULL;
LONGLONG PerfCounterDelta;
LARGE_INTEGER CurrentPerfCounter;
NTSTATUS Status;
PTP_REPORT PtpReport;
WDFREQUEST Request;
WDFMEMORY RequestMemory;
if (NumBytesTransferred < headerSize || (NumBytesTransferred - headerSize) % fingerprintSize != 0) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Malformed input received. Length = %llu",
NumBytesTransferred
);
return;
}
// Retrieve packet
TouchBuffer = WdfMemoryGetBuffer(
Buffer,
NULL
);
if (TouchBuffer == NULL) {
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_DRIVER,
"%!FUNC! Failed to retrieve packet"
);
return;
}
// Retrieve next PTP touchpad request.
Status = WdfIoQueueRetrieveNextRequest(
pDeviceContext->InputQueue,
&Request
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_DRIVER,
"%!FUNC! No pending PTP request. Disposed"
);
return;
}
Status = WdfRequestRetrieveOutputMemory(
Request,
&RequestMemory
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputMemory failed with %!STATUS!",
Status
);
return;
}
// Prepare report
Status = STATUS_SUCCESS;
RtlZeroMemory(&PtpReport, sizeof(PTP_REPORT));
PtpReport.ReportID = REPORTID_MULTITOUCH;
PtpReport.IsButtonClicked = 0;
raw_n = (NumBytesTransferred - headerSize) / fingerprintSize;
UCHAR* f_base = TouchBuffer + headerSize + pDeviceContext->DeviceInfo->tp_delta;
// Scan time is in 100us
KeQueryPerformanceCounter(&CurrentPerfCounter);
PerfCounterDelta = (CurrentPerfCounter.QuadPart - pDeviceContext->LastReportTime.QuadPart) / 100;
if (PerfCounterDelta > 0xFF) {
PerfCounterDelta = 0xFF;
}
PtpReport.ScanTime = (USHORT) PerfCounterDelta;
if (pDeviceContext->PtpReportTouch) {
if (raw_n >= PTP_MAX_CONTACT_POINTS) raw_n = PTP_MAX_CONTACT_POINTS;
if (raw_n * fingerprintSize < (NumBytesTransferred - headerSize)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! Buffer may have a problem"
);
WdfRequestComplete(Request, STATUS_DATA_ERROR);
return;
}
PtpReport.ContactCount = (UCHAR) raw_n;
for (i = 0; i < raw_n; i++) {
f = (const struct TRACKPAD_FINGER*) (f_base + i * fingerprintSize);
// Translate X and Y
x = (AmtRawToInteger(f->abs_x) - pDeviceContext->DeviceInfo->x.min) > 0 ?
((USHORT)(AmtRawToInteger(f->abs_x) - pDeviceContext->DeviceInfo->x.min)) : 0;
y = (pDeviceContext->DeviceInfo->y.max - AmtRawToInteger(f->abs_y)) > 0 ?
((USHORT)(pDeviceContext->DeviceInfo->y.max - AmtRawToInteger(f->abs_y))) : 0;
// Defuzz functions remain the same
// TODO: Implement defuzz later
PtpReport.Contacts[i].ContactID = (UCHAR) i;
PtpReport.Contacts[i].X = x;
PtpReport.Contacts[i].Y = y;
PtpReport.Contacts[i].TipSwitch = (AmtRawToInteger(f->touch_major) << 1) >= 200 || (AmtRawToInteger(f->touch_minor) << 1) >= 150;
PtpReport.Contacts[i].Confidence = (AmtRawToInteger(f->touch_minor) << 1) > 0;
}
}
if (pDeviceContext->PtpReportButton) {
// Handles trackpad button input here.
if (TouchBuffer[pDeviceContext->DeviceInfo->tp_button]) {
PtpReport.IsButtonClicked = TRUE;
TraceEvents(
TRACE_LEVEL_INFORMATION, TRACE_INPUT,
"%!FUNC!: Trackpad button clicked"
);
}
}
// Compose final report and write it back
Status = WdfMemoryCopyFromBuffer(
RequestMemory,
0,
(PVOID) &PtpReport,
sizeof(PTP_REPORT)
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
Status
);
return;
}
// Set result
WdfRequestSetInformation(Request, sizeof(PTP_REPORT));
// Set completion flag
WdfRequestComplete(Request, Status);
}
BOOLEAN
AmtPtpEvtUsbInterruptReadersFailed(
_In_ WDFUSBPIPE Pipe,
_In_ NTSTATUS Status,
_In_ USBD_STATUS UsbdStatus
)
{
UNREFERENCED_PARAMETER(Pipe);
UNREFERENCED_PARAMETER(UsbdStatus);
UNREFERENCED_PARAMETER(Status);
return TRUE;
}
================================================
FILE: src/AmtPtpDeviceUsbKm/Public.h
================================================
/*++
Module Name:
public.h
Abstract:
This module contains the common declarations shared by driver
and user applications.
Environment:
user and kernel
--*/
//
// Define an Interface Guid so that app can find the device and talk to it.
//
DEFINE_GUID (GUID_DEVINTERFACE_AmtPtpDeviceUsbKm,
0x4aa332cc,0x5777,0x4afd,0xaa,0x4e,0x95,0x38,0x73,0x30,0x61,0x2a);
// {4aa332cc-5777-4afd-aa4e-95387330612a}
================================================
FILE: src/AmtPtpDeviceUsbKm/Queue.c
================================================
/*++
Module Name:
queue.c
Abstract:
This file contains the queue entry points and callbacks.
Environment:
Kernel-mode Driver Framework
--*/
#include "driver.h"
#include "queue.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, AmtPtpDeviceUsbKmQueueInitialize)
#endif
NTSTATUS
AmtPtpDeviceUsbKmQueueInitialize(
_In_ WDFDEVICE Device
)
/*++
Routine Description:
The I/O dispatch callbacks for the frameworks device object
are configured in this function.
A single default I/O Queue is configured for parallel request
processing, and a driver context memory allocation is created
to hold our structure QUEUE_CONTEXT.
Arguments:
Device - Handle to a framework device object.
Return Value:
VOID
--*/
{
WDFQUEUE queue;
NTSTATUS status;
WDF_IO_QUEUE_CONFIG queueConfig;
PDEVICE_CONTEXT pDeviceContext;
PAGED_CODE();
pDeviceContext = DeviceGetContext(Device);
//
// Configure a default queue so that requests that are not
// configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
// other queues get dispatched here.
//
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);
queueConfig.EvtIoInternalDeviceControl = AmtPtpDeviceUsbKmEvtIoDeviceControl;
queueConfig.EvtIoStop = AmtPtpDeviceUsbKmEvtIoStop;
status = WdfIoQueueCreate(
Device,
&queueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&queue
);
if( !NT_SUCCESS(status) ) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "WdfIoQueueCreate failed %!STATUS!", status);
return status;
}
//
// Create secondary queues for touch read requests.
//
WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual);
queueConfig.PowerManaged = WdfFalse;
status = WdfIoQueueCreate(
Device,
&queueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&pDeviceContext->InputQueue
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR, TRACE_QUEUE,
"%!FUNC! WdfIoQueueCreate (Input) failed %!STATUS!",
status
);
}
return status;
}
VOID
AmtPtpDeviceUsbKmEvtIoDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
/*++
Routine Description:
This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Request - Handle to a framework request object.
OutputBufferLength - Size of the output buffer in bytes
InputBufferLength - Size of the input buffer in bytes
IoControlCode - I/O control code.
Return Value:
VOID
--*/
{
NTSTATUS status;
WDFDEVICE device = WdfIoQueueGetDevice(Queue);
BOOLEAN requestPending = FALSE;
UNREFERENCED_PARAMETER(InputBufferLength);
UNREFERENCED_PARAMETER(OutputBufferLength);
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
status = AmtPtpGetHidDescriptor(device, Request);
break;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
status = AmtPtpGetDeviceAttribs(device, Request);
break;
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
status = AmtPtpGetReportDescriptor(device, Request);
break;
case IOCTL_HID_READ_REPORT:
status = AmtPtpDispatchReadReportRequests(device, Request, &requestPending);
break;
case IOCTL_HID_GET_FEATURE:
status = AmtPtpReportFeatures(device, Request);
break;
case IOCTL_HID_SET_FEATURE:
status = AmtPtpSetFeatures(device, Request);
break;
case IOCTL_HID_GET_STRING:
case IOCTL_HID_WRITE_REPORT:
case IOCTL_UMDF_HID_SET_OUTPUT_REPORT:
case IOCTL_UMDF_HID_GET_INPUT_REPORT:
case IOCTL_HID_ACTIVATE_DEVICE:
case IOCTL_HID_DEACTIVATE_DEVICE:
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
default:
status = STATUS_NOT_SUPPORTED;
break;
}
if (requestPending != TRUE) {
WdfRequestComplete(Request, status);
}
return;
}
NTSTATUS
AmtPtpDispatchReadReportRequests(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_Out_ BOOLEAN* Pending
)
{
NTSTATUS status;
PDEVICE_CONTEXT pDevContext;
status = STATUS_SUCCESS;
pDevContext = DeviceGetContext(Device);
status = WdfRequestForwardToIoQueue(
Request,
pDevContext->InputQueue
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestForwardToIoQueue failed with %!STATUS!",
status
);
goto exit;
}
if (NULL != Pending) {
*Pending = TRUE;
}
exit:
return status;
}
VOID
AmtPtpDeviceUsbKmEvtIoStop(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ ULONG ActionFlags
)
/*++
Routine Description:
This event is invoked for a power-managed queue before the device leaves the working state (D0).
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Request - Handle to a framework request object.
ActionFlags - A bitwise OR of one or more WDF_REQUEST_STOP_ACTION_FLAGS-typed flags
that identify the reason that the callback function is being called
and whether the request is cancelable.
Return Value:
VOID
--*/
{
TraceEvents(TRACE_LEVEL_INFORMATION,
TRACE_QUEUE,
"%!FUNC! Queue 0x%p, Request 0x%p ActionFlags %d",
Queue, Request, ActionFlags);
//
// In most cases, the EvtIoStop callback function completes, cancels, or postpones
// further processing of the I/O request.
//
// Typically, the driver uses the following rules:
//
// - If the driver owns the I/O request, it either postpones further processing
// of the request and calls WdfRequestStopAcknowledge, or it calls WdfRequestComplete
// with a completion status value of STATUS_SUCCESS or STATUS_CANCELLED.
//
// The driver must call WdfRequestComplete only once, to either complete or cancel
// the request. To ensure that another thread does not call WdfRequestComplete
// for the same request, the EvtIoStop callback must synchronize with the driver's
// other event callback functions, for instance by using interlocked operations.
//
// - If the driver has forwarded the I/O request to an I/O target, it either calls
// WdfRequestCancelSentRequest to attempt to cancel the request, or it postpones
// further processing of the request and calls WdfRequestStopAcknowledge.
//
// A driver might choose to take no action in EvtIoStop for requests that are
// guaranteed to complete in a small amount of time. For example, the driver might
// take no action for requests that are completed in one of the drivers request handlers.
//
return;
}
================================================
FILE: src/AmtPtpDeviceUsbKm/Queue.h
================================================
/*++
Module Name:
queue.h
Abstract:
This file contains the queue definitions.
Environment:
Kernel-mode Driver Framework
--*/
EXTERN_C_START
//
// This is the context that can be placed per queue
// and would contain per queue information.
//
typedef struct _QUEUE_CONTEXT {
ULONG PrivateDeviceData; // just a placeholder
} QUEUE_CONTEXT, *PQUEUE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext)
NTSTATUS
AmtPtpDeviceUsbKmQueueInitialize(
_In_ WDFDEVICE Device
);
//
// Events from the IoQueue object
//
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL AmtPtpDeviceUsbKmEvtIoDeviceControl;
EVT_WDF_IO_QUEUE_IO_STOP AmtPtpDeviceUsbKmEvtIoStop;
EXTERN_C_END
================================================
FILE: src/AmtPtpDeviceUsbKm/Trace.h
================================================
/*++
Module Name:
Trace.h
Abstract:
Header file for the debug tracing related function defintions and macros.
Environment:
Kernel mode
--*/
//
// Define the tracing flags.
//
// Tracing GUID - b409cf52-f41a-4193-98c2-bad95204203b
//
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID( \
AmtPtpDeviceUsbKmTraceGuid, (b409cf52,f41a,4193,98c2,bad95204203b), \
\
WPP_DEFINE_BIT(TRACE_DRIVER) \
WPP_DEFINE_BIT(TRACE_DEVICE) \
WPP_DEFINE_BIT(TRACE_QUEUE) \
WPP_DEFINE_BIT(TRACE_INPUT) \
)
#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
WPP_LEVEL_LOGGER(flag)
#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
(WPP_LEVEL_ENABLED(flag) && \
WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
WPP_LEVEL_LOGGER(flags)
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
//
// WPP orders static parameters before dynamic parameters. To support the Trace function
// defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to
// reorder the arguments to what the .tpl configuration file expects.
//
#define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags)
#define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags)
//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC Trace{FLAGS=TRACE_DRIVER}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//
================================================
FILE: src/AmtPtpDeviceUsbKm/include/AppleDefinition.h
================================================
#pragma once
#define USB_VENDOR_ID_APPLE 0x05ac
/* Apple T2 USB trackpad */
#define USB_DEVICE_ID_APPLE_T2_7A 0x027a
#define USB_DEVICE_ID_APPLE_T2_7B 0x027b
#define USB_DEVICE_ID_APPLE_T2_7C 0x027c
#define USB_DEVICE_ID_APPLE_T2_7D 0x027d
#define USB_DEVICE_ID_DEFAULT_FALLBACK 0xffff
/* button data structure */
struct TRACKPAD_BUTTON_DATA {
UCHAR unknown1; /* constant */
UCHAR button; /* left button */
UCHAR rel_x; /* relative x coordinate */
UCHAR rel_y; /* relative y coordinate */
};
/* trackpad header types */
enum TRACKPAD_TYPE {
TYPE1, /* plain trackpad */
TYPE2, /* button integrated in trackpad */
TYPE3, /* additional header fields since June 2013 */
TYPE4, /* additional header field for pressure data */
TYPE5 /* format for magic trackpad 2 */
};
/* Trackpad finger data offsets, le16-aligned */
#define HEADER_TYPE1 (13 * sizeof(USHORT))
#define HEADER_TYPE2 (15 * sizeof(USHORT))
#define HEADER_TYPE3 (19 * sizeof(USHORT))
#define HEADER_TYPE4 (23 * sizeof(USHORT))
#define HEADER_TYPE5 ( 6 * sizeof(USHORT))
/* Trackpad button data offsets */
#define BUTTON_TYPE1 0
#define BUTTON_TYPE2 15
#define BUTTON_TYPE3 23
#define BUTTON_TYPE4 31
#define BUTTON_TYPE5 1
/* List of device capability bits */
#define HAS_INTEGRATED_BUTTON 1
/* Trackpad finger data block size */
#define FSIZE_TYPE1 (14 * sizeof(USHORT))
#define FSIZE_TYPE2 (14 * sizeof(USHORT))
#define FSIZE_TYPE3 (14 * sizeof(USHORT))
#define FSIZE_TYPE4 (15 * sizeof(USHORT))
#define FSIZE_TYPE5 (9)
/* Offset from header to finger struct */
#define DELTA_TYPE1 (0 * sizeof(USHORT))
#define DELTA_TYPE2 (0 * sizeof(USHORT))
#define DELTA_TYPE3 (0 * sizeof(USHORT))
#define DELTA_TYPE4 (1 * sizeof(USHORT))
#define DELTA_TYPE5 (0 * sizeof(USHORT))
/* USB control message mode switch data */
#define USBMSG_TYPE1 8, 0x300, 0, 0, 0x1, 0x8
#define USBMSG_TYPE2 8, 0x300, 0, 0, 0x1, 0x8
#define USBMSG_TYPE3 8, 0x300, 0, 0, 0x1, 0x8
#define USBMSG_TYPE4 2, 0x302, 2, 1, 0x1, 0x0
#define USBMSG_TYPE5 2, 0x302, 1, 1, 0x1, 0x0
/* Wellspring initialization constants */
#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
/* Trackpad finger data size, empirically at least ten fingers */
#define MAX_FINGERS 16
#define MAX_FINGER_ORIENTATION 16384
#define BCM5974_MOUSE_SIZE 8
/* trackpad finger structure, le16-aligned */
__declspec(align(2)) struct TRACKPAD_FINGER {
USHORT origin; /* zero when switching track finger */
USHORT abs_x; /* absolute x coodinate */
USHORT abs_y; /* absolute y coodinate */
USHORT rel_x; /* relative x coodinate */
USHORT rel_y; /* relative y coodinate */
USHORT tool_major; /* tool area, major axis */
USHORT tool_minor; /* tool area, minor axis */
USHORT orientation; /* 16384 when point, else 15 bit angle */
USHORT touch_major; /* touch area, major axis */
USHORT touch_minor; /* touch area, minor axis */
USHORT unused[2]; /* zeros */
USHORT pressure; /* pressure on forcetouch touchpad */
USHORT multi; /* one finger: varies, more fingers: constant */
};
/* device-specific parameters */
struct BCM5974_PARAM {
int snratio; /* signal-to-noise ratio */
int min; /* device minimum reading */
int max; /* device maximum reading */
};
/* device-specific configuration */
struct BCM5974_CONFIG {
int identification; /* the product id of this device */
int caps; /* device capability bitmask */
int bt_ep; /* the endpoint of the button interface */
int bt_datalen; /* data length of the button interface */
int tp_ep; /* the endpoint of the trackpad interface */
enum TRACKPAD_TYPE tp_type; /* type of trackpad interface */
int tp_header; /* bytes in header block */
int tp_datalen; /* data length of the trackpad interface */
int tp_button; /* offset to button data */
int tp_fsize; /* bytes in single finger block */
int tp_delta; /* offset from header to finger struct */
int um_size; /* usb control message length */
int um_req_val; /* usb control message value */
int um_req_idx; /* usb control message index */
int um_switch_idx; /* usb control message mode switch index */
int um_switch_on; /* usb control message mode switch on */
int um_switch_off; /* usb control message mode switch off */
struct BCM5974_PARAM p; /* finger pressure limits */
struct BCM5974_PARAM w; /* finger width limits */
struct BCM5974_PARAM x; /* horizontal limits */
struct BCM5974_PARAM y; /* vertical limits */
struct BCM5974_PARAM o; /* orientation limits */
};
#define DATAFORMAT(type) \
type, \
HEADER_##type, \
HEADER_##type + (MAX_FINGERS) * (FSIZE_##type), \
BUTTON_##type, \
FSIZE_##type, \
DELTA_##type, \
USBMSG_##type
/* logical signal quality */
#define SN_PRESSURE 45 /* pressure signal-to-noise ratio */
#define SN_WIDTH 25 /* width signal-to-noise ratio */
#define SN_COORD 250 /* coordinate signal-to-noise ratio */
#define SN_ORIENT 10 /* orientation signal-to-noise ratio */
#define PRESSURE_QUALIFICATION_THRESHOLD 2
#define SIZE_QUALIFICATION_THRESHOLD 9
#define SIZE_MU_LOWER_THRESHOLD 5
#define PRESSURE_MU_QUALIFICATION_THRESHOLD_TOTAL 15
#define SIZE_MU_QUALIFICATION_THRESHOLD_TOTAL 25
static const struct BCM5974_CONFIG Bcm5974ConfigTable[] = {
/* New device? */
{
USB_DEVICE_ID_DEFAULT_FALLBACK,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE4),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
// Oversampled - this is fine for a trackpad
{ SN_COORD, -10000, 10000 },
{ SN_COORD, -2000, 10000 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
/* 13 inch */
{
USB_DEVICE_ID_APPLE_T2_7A,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE4),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -6243, 6749 },
{ SN_COORD, -170, 7685 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_T2_7B,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE4),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -6243, 6749 },
{ SN_COORD, -170, 7685 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
/* 15 inch */
{
USB_DEVICE_ID_APPLE_T2_7C,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE4),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
// Oversampled - this is fine for a trackpad
{ SN_COORD, -10000, 10000 },
{ SN_COORD, -2000, 10000 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_T2_7D,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE4),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
// Oversampled - this is fine for a trackpad
{ SN_COORD, -10000, 10000 },
{ SN_COORD, -2000, 10000 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
0
},
};
================================================
FILE: src/AmtPtpDeviceUsbKm/include/Hid.h
================================================
// Hid.h: Device-related HID definitions
#pragma once
#include
#include
#include
// Device family metadata
#include
typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR;
#define DEVICE_VERSION 0x01
#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 Padding : 6;
ULONG ContactID;
USHORT X;
USHORT Y;
} PTP_CONTACT, * PPTP_CONTACT;
#pragma pack(pop)
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;
================================================
FILE: src/AmtPtpDeviceUsbKm/include/hid/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/AmtPtpDeviceUsbKm/include/metadata/WellspringT2.h
================================================
#pragma once
#include
#define AAPL_WELLSPRING_T2_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x10 (2 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0x20, 0x4e, /* Logical Maximum: 20000 (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, 0x14, 0x05, /* Physical Maximum: 1300 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0x52, 0x03, /* Physical Maximum: 850 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0xe0, 0x2e, /* Logical Maximum: 12000 (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_WELLSPRING_T2_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x10 (2 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0x20, 0x4e, /* Logical Maximum: 20000 (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, 0x14, 0x05, /* Physical Maximum: 1045 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0x52, 0x03, /* Physical Maximum: 750 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0xe0, 0x2e, /* Logical Maximum: 12000 (See definition) */ \
USAGE, 0x31, /* Usage: Y */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
END_COLLECTION /* End Collection */ \
#define AAPL_WELLSPRING_T2_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_WELLSPRING_T2_PTP_FINGER_COLLECTION_1, /* 1 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_T2_PTP_FINGER_COLLECTION_1, /* 2 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_T2_PTP_FINGER_COLLECTION_2, /* 3 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_T2_PTP_FINGER_COLLECTION_1, /* 4 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_T2_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/AmtPtpDeviceUsbKm/resource.h
================================================
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
#define IDS_APP_TITLE 103
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
================================================
FILE: src/AmtPtpDeviceUsbUm/AmtPtpDevice.wprp
================================================
================================================
FILE: src/AmtPtpDeviceUsbUm/Device.c
================================================
// Device.c: Device handling events for driver.
#include
#include "device.tmh"
_IRQL_requires_(PASSIVE_LEVEL)
static const struct BCM5974_CONFIG*
AmtPtpGetDeviceConfig(
_In_ USB_DEVICE_DESCRIPTOR deviceInfo
)
{
USHORT id = deviceInfo.idProduct;
const struct BCM5974_CONFIG *cfg;
for (cfg = Bcm5974ConfigTable; cfg->ansi; ++cfg) {
if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) {
return cfg;
}
}
return NULL;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpCreateDevice(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
WDF_OBJECT_ATTRIBUTES deviceAttributes;
PDEVICE_CONTEXT deviceContext;
WDFDEVICE device;
NTSTATUS status;
UNREFERENCED_PARAMETER(Driver);
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;
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)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER,
"%!FUNC! WdfDeviceCreate failed with Status code %!STATUS!", status);
return 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.
//
deviceContext = DeviceGetContext(device);
//
// Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
// that you don't get the popup in usermode
// when you surprise remove the device.
//
WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
pnpCaps.SurpriseRemovalOK = WdfTrue;
WdfDeviceSetPnpCapabilities(
device,
&pnpCaps
);
//
// Create a device interface so that applications can find and talk
// to us.
//
status = WdfDeviceCreateDeviceInterface(
device,
&GUID_DEVINTERFACE_AmtPtpDevice,
NULL // ReferenceString
);
if (NT_SUCCESS(status)) {
//
// Initialize the I/O Package and any Queues
//
status = AmtPtpDeviceQueueInitialize(device);
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return status;
}
NTSTATUS
AmtPtpEvtDevicePrepareHardware(
_In_ WDFDEVICE Device,
_In_ WDFCMRESLIST ResourceList,
_In_ WDFCMRESLIST ResourceListTranslated
)
{
NTSTATUS status;
PDEVICE_CONTEXT pDeviceContext;
ULONG waitWakeEnable;
WDF_USB_DEVICE_INFORMATION deviceInfo;
waitWakeEnable = FALSE;
UNREFERENCED_PARAMETER(ResourceList);
UNREFERENCED_PARAMETER(ResourceListTranslated);
PAGED_CODE();
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
status = STATUS_SUCCESS;
pDeviceContext = DeviceGetContext(Device);
if (pDeviceContext->UsbDevice == NULL) {
status = WdfUsbTargetDeviceCreate(Device,
WDF_NO_OBJECT_ATTRIBUTES,
&pDeviceContext->UsbDevice
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfUsbTargetDeviceCreate failed with Status code %!STATUS!",
status
);
return status;
}
}
// Retrieve device information
WdfUsbTargetDeviceGetDeviceDescriptor(
pDeviceContext->UsbDevice,
&pDeviceContext->DeviceDescriptor
);
if (NT_SUCCESS(status)) {
// Get correct configuration from conf store
pDeviceContext->DeviceInfo = AmtPtpGetDeviceConfig(pDeviceContext->DeviceDescriptor);
if (pDeviceContext->DeviceInfo == NULL) {
status = STATUS_INVALID_DEVICE_STATE;
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! failed because device is not found in registry."
);
TraceLoggingWrite(
g_hAmtPtpDeviceTraceProvider,
EVENT_DEVICE_IDENTIFICATION,
TraceLoggingString("AmtPtpEvtDevicePrepareHardware", "Routine"),
TraceLoggingUInt16(pDeviceContext->DeviceDescriptor.idProduct, "idProduct"),
TraceLoggingUInt16(pDeviceContext->DeviceDescriptor.idVendor, "idVendor"),
TraceLoggingString(EVENT_DEVICE_ID_SUBTYPE_NOTFOUND, EVENT_DRIVER_FUNC_SUBTYPE)
);
return status;
}
}
//
// Retrieve USBD version information, port driver capabilites and device
// capabilites such as speed, power, etc.
//
WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo);
status = WdfUsbTargetDeviceRetrieveInformation(
pDeviceContext->UsbDevice,
&deviceInfo
);
if (NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DEVICE,
"%!FUNC! IsDeviceHighSpeed: %s",
(deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE");
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DEVICE,
"%!FUNC! IsDeviceSelfPowered: %s",
(deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE");
waitWakeEnable = deviceInfo.Traits &
WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DEVICE,
"%!FUNC! IsDeviceRemoteWakeable: %s",
waitWakeEnable ? "TRUE" : "FALSE");
//
// Save these for use later.
//
pDeviceContext->UsbDeviceTraits = deviceInfo.Traits;
} else {
pDeviceContext->UsbDeviceTraits = 0;
}
// Select interface to use
status = SelectInterruptInterface(Device);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! SelectInterruptInterface failed with %!STATUS!", status);
return status;
}
// Set up interrupt
status = AmtPtpConfigContReaderForInterruptEndPoint(pDeviceContext);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! AmtPtpConfigContReaderForInterruptEndPoint failed with %!STATUS!", status);
return status;
}
// Set default settings
pDeviceContext->IsButtonReportOn = TRUE;
pDeviceContext->IsSurfaceReportOn = TRUE;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetWellspringMode(
_In_ PDEVICE_CONTEXT DeviceContext,
_Out_ BOOL* IsWellspringModeOn
)
{
NTSTATUS status;
WDF_USB_CONTROL_SETUP_PACKET setupPacket;
WDF_MEMORY_DESCRIPTOR memoryDescriptor;
ULONG cbTransferred;
WDFMEMORY bufHandle = NULL;
unsigned char* buffer;
status = STATUS_SUCCESS;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
// Type 3 does not need a mode switch.
if (DeviceContext->DeviceInfo->tp_type == TYPE3) {
*IsWellspringModeOn = TRUE;
return STATUS_SUCCESS;
}
status = WdfMemoryCreate(
WDF_NO_OBJECT_ATTRIBUTES,
PagedPool,
POOL_TAG_PTP_CONTROL,
DeviceContext->DeviceInfo->um_size,
&bufHandle,
&buffer
);
if (!NT_SUCCESS(status)) {
goto cleanup;
}
RtlZeroMemory(
buffer,
DeviceContext->DeviceInfo->um_size
);
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
&memoryDescriptor,
buffer,
sizeof(DeviceContext->DeviceInfo->um_size)
);
WDF_USB_CONTROL_SETUP_PACKET_INIT(
&setupPacket,
BmRequestDeviceToHost,
BmRequestToInterface,
BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
(USHORT)DeviceContext->DeviceInfo->um_req_val,
(USHORT)DeviceContext->DeviceInfo->um_req_idx
);
// Set stuffs right
setupPacket.Packet.bm.Request.Type = BmRequestClass;
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
DeviceContext->UsbDevice,
WDF_NO_HANDLE,
NULL,
&setupPacket,
&memoryDescriptor,
&cbTransferred
);
// Behavior mismatch: Actual device does not transfer bytes as expected (in length)
// So we do not check um_size as a temporary workaround.
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Read) failed with %!STATUS!, cbTransferred = %llu, um_size = %d",
status,
cbTransferred,
DeviceContext->DeviceInfo->um_size
);
goto cleanup;
}
// Check mode switch
unsigned char wellspringBit = buffer[DeviceContext->DeviceInfo->um_switch_idx];
*IsWellspringModeOn = wellspringBit == DeviceContext->DeviceInfo->um_switch_on ? TRUE : FALSE;
cleanup:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
WdfObjectDelete(bufHandle);
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpSetWellspringMode(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ BOOL IsWellspringModeOn
)
{
NTSTATUS status;
WDF_USB_CONTROL_SETUP_PACKET setupPacket;
WDF_MEMORY_DESCRIPTOR memoryDescriptor;
ULONG cbTransferred;
WDFMEMORY bufHandle = NULL;
unsigned char* buffer;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
// Type 3 does not need a mode switch.
// However, turn mode on or off as requested.
if (DeviceContext->DeviceInfo->tp_type == TYPE3) {
DeviceContext->IsWellspringModeOn = IsWellspringModeOn;
return STATUS_SUCCESS;
}
status = WdfMemoryCreate(
WDF_NO_OBJECT_ATTRIBUTES,
PagedPool,
POOL_TAG_PTP_CONTROL,
DeviceContext->DeviceInfo->um_size,
&bufHandle,
&buffer
);
if (!NT_SUCCESS(status)) {
goto cleanup;
}
RtlZeroMemory(
buffer,
DeviceContext->DeviceInfo->um_size
);
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
&memoryDescriptor,
buffer,
sizeof(DeviceContext->DeviceInfo->um_size)
);
WDF_USB_CONTROL_SETUP_PACKET_INIT(
&setupPacket,
BmRequestDeviceToHost,
BmRequestToInterface,
BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
(USHORT) DeviceContext->DeviceInfo->um_req_val,
(USHORT) DeviceContext->DeviceInfo->um_req_idx
);
// Set stuffs right
setupPacket.Packet.bm.Request.Type = BmRequestClass;
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
DeviceContext->UsbDevice,
WDF_NO_HANDLE,
NULL,
&setupPacket,
&memoryDescriptor,
&cbTransferred
);
// Behavior mismatch: Actual device does not transfer bytes as expected (in length)
// So we do not check um_size as a temporary workaround.
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Read) failed with %!STATUS!, cbTransferred = %llu, um_size = %d",
status,
cbTransferred,
DeviceContext->DeviceInfo->um_size
);
goto cleanup;
}
// Apply the mode switch
buffer[DeviceContext->DeviceInfo->um_switch_idx] = IsWellspringModeOn ?
(unsigned char) DeviceContext->DeviceInfo->um_switch_on :
(unsigned char) DeviceContext->DeviceInfo->um_switch_off;
// Write configuration
WDF_USB_CONTROL_SETUP_PACKET_INIT(
&setupPacket,
BmRequestHostToDevice,
BmRequestToInterface,
BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID,
(USHORT) DeviceContext->DeviceInfo->um_req_val,
(USHORT) DeviceContext->DeviceInfo->um_req_idx
);
// Set stuffs right
setupPacket.Packet.bm.Request.Type = BmRequestClass;
status = WdfUsbTargetDeviceSendControlTransferSynchronously(
DeviceContext->UsbDevice,
WDF_NO_HANDLE,
NULL,
&setupPacket,
&memoryDescriptor,
&cbTransferred
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Write) failed with %!STATUS!",
status
);
goto cleanup;
}
// Set status
DeviceContext->IsWellspringModeOn = IsWellspringModeOn;
cleanup:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
WdfObjectDelete(bufHandle);
return status;
}
NTSTATUS
AmtPtpEvtDeviceD0Entry(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE PreviousState
)
{
PDEVICE_CONTEXT pDeviceContext;
NTSTATUS status;
BOOLEAN isTargetStarted;
pDeviceContext = DeviceGetContext(Device);
isTargetStarted = FALSE;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Entry - coming from %s",
DbgDevicePowerString(PreviousState)
);
// Check wellspring mode
if (pDeviceContext->IsButtonReportOn || pDeviceContext->IsWellspringModeOn) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Start Wellspring Mode"
);
status = AmtPtpSetWellspringMode(
pDeviceContext,
TRUE
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Start Wellspring Mode failed with %!STATUS!",
status
);
}
}
// Get current time counter
QueryPerformanceCounter(
&pDeviceContext->PerfCounter
);
//
// Since continuous reader is configured for this interrupt-pipe, we must explicitly start
// the I/O target to get the framework to post read requests.
//
status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe));
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Failed to start interrupt pipe %!STATUS!",
status
);
goto End;
}
isTargetStarted = TRUE;
End:
if (!NT_SUCCESS(status)) {
//
// Failure in D0Entry will lead to device being removed. So let us stop the continuous
// reader in preparation for the ensuing remove.
//
if (isTargetStarted) {
WdfIoTargetStop(
WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe),
WdfIoTargetCancelSentIo
);
}
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry"
);
return status;
}
NTSTATUS
AmtPtpEvtDeviceD0Exit(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE TargetState
)
{
PDEVICE_CONTEXT pDeviceContext;
NTSTATUS status;
PAGED_CODE();
status = STATUS_SUCCESS;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - moving to %s",
DbgDevicePowerString(TargetState)
);
pDeviceContext = DeviceGetContext(Device);
// Stop IO Pipe.
WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(
pDeviceContext->InterruptPipe),
WdfIoTargetCancelSentIo
);
// Cancel Wellspring mode.
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - Cancel Wellspring Mode"
);
status = AmtPtpSetWellspringMode(
pDeviceContext,
FALSE
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - Cancel Wellspring Mode failed with %!STATUS!",
status
);
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! <--AmtPtpDeviceEvtDeviceD0Exit"
);
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
SelectInterruptInterface(
_In_ WDFDEVICE Device
)
{
WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT pDeviceContext;
WDFUSBPIPE pipe;
WDF_USB_PIPE_INFORMATION pipeInfo;
UCHAR index;
UCHAR numberConfiguredPipes;
WDFUSBINTERFACE usbInterface;
PAGED_CODE();
pDeviceContext = DeviceGetContext(Device);
WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);
usbInterface = WdfUsbTargetDeviceGetInterface(
pDeviceContext->UsbDevice,
0
);
if (NULL == usbInterface) {
status = STATUS_UNSUCCESSFUL;
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! WdfUsbTargetDeviceGetInterface 0 failed %!STATUS!",
status
);
return status;
}
configParams.Types.SingleInterface.ConfiguredUsbInterface = usbInterface;
configParams.Types.SingleInterface.NumberConfiguredPipes = WdfUsbInterfaceGetNumConfiguredPipes(usbInterface);
pDeviceContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface;
numberConfiguredPipes = configParams.Types.SingleInterface.NumberConfiguredPipes;
//
// Get pipe handles
//
for (index = 0; index < numberConfiguredPipes; index++) {
WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
pipe = WdfUsbInterfaceGetConfiguredPipe(
pDeviceContext->UsbInterface,
index, //PipeIndex,
&pipeInfo
);
//
// Tell the framework that it's okay to read less than
// MaximumPacketSize
//
WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pipe);
if (WdfUsbPipeTypeInterrupt == pipeInfo.PipeType) {
pDeviceContext->InterruptPipe = pipe;
break;
}
}
//
// If we didn't find interrupt pipe, fail the start.
//
if (!pDeviceContext->InterruptPipe) {
status = STATUS_INVALID_DEVICE_STATE;
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! Device is not configured properly %!STATUS!",
status
);
return status;
}
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
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";
}
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpEmergResetDevice(
_In_ PDEVICE_CONTEXT DeviceContext
)
{
NTSTATUS status;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry");
status = AmtPtpSetWellspringMode(
DeviceContext,
FALSE);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! AmtPtpSetWellspringMode failed with %!STATUS!",
status);
}
status = AmtPtpSetWellspringMode(
DeviceContext,
TRUE);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DEVICE,
"%!FUNC! AmtPtpSetWellspringMode failed with %!STATUS!",
status);
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit");
return status;
}
================================================
FILE: src/AmtPtpDeviceUsbUm/Driver.c
================================================
// Driver.c: This file contains the driver entry points and callbacks.
#include
#include "driver.tmh"
// Declares Windows 10 TraceLogger provider here.
TRACELOGGING_DEFINE_PROVIDER(
g_hAmtPtpDeviceTraceProvider,
"AmtPtpDeviceTraceProvider",
(0x871b1e2d, 0xcc5a, 0x4ade, 0xb7, 0x4e, 0x6c, 0xf1, 0x0, 0x4e, 0xf1, 0x49));
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES attributes;
// Initialize tracing
DriverTraceInit(
DriverObject,
RegistryPath
);
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
//
// 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 = AmtPtpDeviceEvtDriverContextCleanup;
WDF_DRIVER_CONFIG_INIT(&config,
AmtPtpDeviceEvtDeviceAdd
);
status = WdfDriverCreate(DriverObject,
RegistryPath,
&attributes,
&config,
WDF_NO_HANDLE
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfDriverCreate failed %!STATUS!",
status
);
TraceLoggingWrite(
g_hAmtPtpDeviceTraceProvider,
EVENT_DRIVER_FUNCTIONAL,
TraceLoggingString("DriverEntry", "Routine"),
TraceLoggingString("WdfDriverCreate", "Context"),
TraceLoggingInt32(status, "Status"),
TraceLoggingString(EVENT_DRIVER_FUNC_SUBTYPE_CRITFAIL, EVENT_DRIVER_FUNC_SUBTYPE)
);
DriverTraceCleanup(DriverObject);
return status;
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return status;
}
VOID
DriverTraceInit(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
// Initialize WPP Tracing
WPP_INIT_TRACING(
DriverObject,
RegistryPath
);
// Initialize TraceLogger Tracing
TraceLoggingRegister(g_hAmtPtpDeviceTraceProvider);
}
VOID
DriverTraceCleanup(
_In_ WDFOBJECT DriverObject
)
{
UNREFERENCED_PARAMETER(DriverObject);
TraceLoggingUnregister(g_hAmtPtpDeviceTraceProvider);
// This actually directly calls WppCleanupUm() in UMDF drivers
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER) Driver));
}
NTSTATUS
AmtPtpDeviceEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
NTSTATUS status = STATUS_SUCCESS;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Set FDO driver filter"
);
WdfFdoInitSetFilter(DeviceInit);
status = AmtPtpCreateDevice(
Driver,
DeviceInit
);
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return status;
}
VOID
AmtPtpDeviceEvtDriverContextCleanup(
_In_ WDFOBJECT DriverObject
)
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
//
// Stop WPP Tracing
//
DriverTraceCleanup(DriverObject);
}
================================================
FILE: src/AmtPtpDeviceUsbUm/Hid.c
================================================
// Hid.c: HID-related routine
#include
#include
#include "Hid.tmh"
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetHidDescriptor(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT pContext = DeviceGetContext(Device);
size_t szHidDescriptor = 0;
WDFMEMORY RequestMemory;
PHID_DESCRIPTOR pSelectedHidDescriptor = NULL;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
status = WdfRequestRetrieveOutputMemory(
Request,
&RequestMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
status
);
return status;
}
switch (pContext->DeviceDescriptor.idProduct) {
case USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING3_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING3_JIS:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Request HID Report Descriptor for MacBook Family, Wellspring 3 Series"
);
szHidDescriptor = AmtPtp3DefaultHidDescriptor.bLength;
pSelectedHidDescriptor = &AmtPtp3DefaultHidDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING5_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING5_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Request HID Report Descriptor for MacBook Family, Wellspring 5/5A Series"
);
szHidDescriptor = AmtPtp5DefaultHidDescriptor.bLength;
pSelectedHidDescriptor = &AmtPtp5DefaultHidDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING6_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING6_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Request HID Report Descriptor for MacBook Family, Wellspring 6/6A Series"
);
szHidDescriptor = AmtPtp6DefaultHidDescriptor.bLength;
pSelectedHidDescriptor = &AmtPtp6DefaultHidDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING7_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING7_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Request HID Report Descriptor for MacBook Family, Wellspring 7/7A Series"
);
szHidDescriptor = AmtPtp7aDefaultHidDescriptor.bLength;
pSelectedHidDescriptor = &AmtPtp7aDefaultHidDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING8_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING8_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING9_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING9_ISO:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Request HID Report Descriptor for MacBook Family, Wellspring 8 Series"
);
szHidDescriptor = AmtPtp8DefaultHidDescriptor.bLength;
pSelectedHidDescriptor = &AmtPtp8DefaultHidDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Request HID Report Descriptor for Apple Magic Trackpad 2 Family"
);
szHidDescriptor = AmtPtpMt2DefaultHidDescriptor.bLength;
pSelectedHidDescriptor = &AmtPtpMt2DefaultHidDescriptor;
break;
}
}
if (pSelectedHidDescriptor != NULL && szHidDescriptor > 0) {
status = WdfMemoryCopyFromBuffer(
RequestMemory,
0,
(PVOID) pSelectedHidDescriptor,
szHidDescriptor
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
status
);
goto exit;
}
WdfRequestSetInformation(
Request,
szHidDescriptor
);
}
else {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! Device HID registry is not found"
);
TraceLoggingWrite(
g_hAmtPtpDeviceTraceProvider,
EVENT_DEVICE_IDENTIFICATION,
TraceLoggingString("AmtPtpGetHidDescriptor", "Routine"),
TraceLoggingUInt16(pContext->DeviceDescriptor.idProduct, "idProduct"),
TraceLoggingString(EVENT_DEVICE_ID_SUBTYPE_HIDREG_NOTFOUND, EVENT_DRIVER_FUNC_SUBTYPE)
);
status = STATUS_INVALID_DEVICE_STATE;
goto exit;
}
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 pContext = 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);
pDeviceAttributes->ProductID = pContext->DeviceDescriptor.idProduct;
// 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->VersionNumber = DEVICE_VERSION;
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;
PDEVICE_CONTEXT pContext = DeviceGetContext(Device);
size_t szHidDescriptor = 0;
WDFMEMORY RequestMemory;
PHID_REPORT_DESCRIPTOR pSelectedHidDescriptor = NULL;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
status = WdfRequestRetrieveOutputMemory(
Request,
&RequestMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
status
);
goto exit;
}
switch (pContext->DeviceDescriptor.idProduct) {
case USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING3_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING3_JIS:
{
szHidDescriptor = AmtPtp3DefaultHidDescriptor.DescriptorList[0].wReportLength;
pSelectedHidDescriptor = AmtPtp3ReportDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING5_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING5_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS:
{
szHidDescriptor = AmtPtp5DefaultHidDescriptor.DescriptorList[0].wReportLength;
pSelectedHidDescriptor = AmtPtp5ReportDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING6_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING6_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS:
{
szHidDescriptor = AmtPtp6DefaultHidDescriptor.DescriptorList[0].wReportLength;
pSelectedHidDescriptor = AmtPtp6ReportDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING7_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING7_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS:
{
szHidDescriptor = AmtPtp7aDefaultHidDescriptor.DescriptorList[0].wReportLength;
pSelectedHidDescriptor = AmtPtp7aReportDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING8_ISO:
case USB_DEVICE_ID_APPLE_WELLSPRING8_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING9_JIS:
case USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI:
case USB_DEVICE_ID_APPLE_WELLSPRING9_ISO:
{
szHidDescriptor = AmtPtp8DefaultHidDescriptor.DescriptorList[0].wReportLength;
pSelectedHidDescriptor = AmtPtp8ReportDescriptor;
break;
}
case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2:
{
szHidDescriptor = AmtPtpMt2DefaultHidDescriptor.DescriptorList[0].wReportLength;
pSelectedHidDescriptor = AmtPtpMt2ReportDescriptor;
break;
}
}
if (pSelectedHidDescriptor != NULL && szHidDescriptor > 0) {
status = WdfMemoryCopyFromBuffer(
RequestMemory,
0,
(PVOID) pSelectedHidDescriptor,
szHidDescriptor
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
status
);
return status;
}
WdfRequestSetInformation(
Request,
szHidDescriptor
);
}
else if (szHidDescriptor == 0) {
status = STATUS_INVALID_DEVICE_STATE;
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! Device HID report length is zero"
);
goto exit;
}
else {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! Device HID registry is not found"
);
TraceLoggingWrite(
g_hAmtPtpDeviceTraceProvider,
EVENT_DEVICE_IDENTIFICATION,
TraceLoggingString("AmtPtpGetReportDescriptor", "Routine"),
TraceLoggingUInt16(pContext->DeviceDescriptor.idProduct, "idProduct"),
TraceLoggingString(EVENT_DEVICE_ID_SUBTYPE_HIDREG_NOTFOUND, EVENT_DRIVER_FUNC_SUBTYPE)
);
status = STATUS_INVALID_DEVICE_STATE;
goto exit;
}
exit:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetStrings(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT pContext = DeviceGetContext(Device);
void *pStringBuffer = NULL;
WDFMEMORY memHandle;
USHORT wcharCount;
size_t actualSize;
UCHAR strIndex;
ULONG inputValue;
WDFMEMORY inputMemory;
size_t inputBufferLength;
PVOID inputBuffer;
ULONG languageId, stringId;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
status = WdfRequestRetrieveInputMemory(
Request,
&inputMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveInputMemory failed with status %!STATUS!",
status
);
return status;
}
inputBuffer = WdfMemoryGetBuffer(
inputMemory,
&inputBufferLength
);
//
// make sure buffer is big enough.
//
if (inputBufferLength < sizeof(ULONG)) {
status = STATUS_INVALID_BUFFER_SIZE;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! GetStringId: invalid input buffer. size %d, expect %d",
(int)inputBufferLength,
(int) sizeof(ULONG)
);
return status;
}
inputValue = (*(PULONG)inputBuffer);
stringId = (inputValue & 0x0ffff);
languageId = (inputValue >> 16);
// Get actual string from USB device
switch (stringId)
{
case HID_STRING_ID_IMANUFACTURER:
strIndex = pContext->DeviceDescriptor.iManufacturer;
break;
case HID_STRING_ID_IPRODUCT:
strIndex = pContext->DeviceDescriptor.iProduct;
break;
case HID_STRING_ID_ISERIALNUMBER:
strIndex = pContext->DeviceDescriptor.iSerialNumber;
break;
default:
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! gets invalid string type"
);
return status;
}
status = WdfUsbTargetDeviceAllocAndQueryString(
pContext->UsbDevice,
WDF_NO_OBJECT_ATTRIBUTES,
&memHandle,
&wcharCount,
strIndex,
(USHORT) languageId
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER, "%!FUNC! WdfUsbTargetDeviceAllocAndQueryString failed with %!STATUS!",
status
);
return status;
}
status = WdfRequestRetrieveOutputBuffer(
Request,
wcharCount * sizeof(WCHAR),
&pStringBuffer,
&actualSize
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
status
);
return status;
}
WdfMemoryCopyToBuffer(
memHandle,
0,
&pStringBuffer,
actualSize
);
WdfRequestSetInformation(
Request,
actualSize
);
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
RequestGetHidXferPacketToReadFromDevice(
_In_ WDFREQUEST Request,
_Out_ HID_XFER_PACKET *Packet
)
{
//
// Driver need to write to the output buffer (so that App can read from it)
//
// Report Buffer: Output Buffer
// Report Id : Input Buffer
//
NTSTATUS status;
WDFMEMORY inputMemory;
WDFMEMORY outputMemory;
size_t inputBufferLength;
size_t outputBufferLength;
PVOID inputBuffer;
PVOID outputBuffer;
//
// Get report Id from input buffer
//
status = WdfRequestRetrieveInputMemory(
Request,
&inputMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveInputMemory failed with %!STATUS!",
status
);
return status;
}
inputBuffer = WdfMemoryGetBuffer(
inputMemory,
&inputBufferLength
);
if (inputBufferLength < sizeof(UCHAR)) {
status = STATUS_INVALID_BUFFER_SIZE;
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveInputMemory: invalid input buffer. size %d, expect %d",
(int) inputBufferLength,
(int) sizeof(UCHAR)
);
return status;
}
Packet->reportId = *(PUCHAR) inputBuffer;
//
// Get report buffer from output buffer
//
status = WdfRequestRetrieveOutputMemory(
Request,
&outputMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputMemory failed with %!STATUS!",
status
);
return status;
}
outputBuffer = WdfMemoryGetBuffer(
outputMemory,
&outputBufferLength
);
Packet->reportBuffer = (PUCHAR) outputBuffer;
Packet->reportBufferLen = (ULONG) outputBufferLength;
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
RequestGetHidXferPacketToWriteToDevice(
_In_ WDFREQUEST Request,
_Out_ HID_XFER_PACKET *Packet
)
{
//
// Driver need to read from the input buffer (which was written by App)
//
// Report Buffer: Input Buffer
// Report Id : Output Buffer Length
//
// Note that the report id is not stored inside the output buffer, as the
// driver has no read-access right to the output buffer, and trying to read
// from the buffer will cause an access violation error.
//
// The workaround is to store the report id in the OutputBufferLength field,
// to which the driver does have read-access right.
//
NTSTATUS status;
WDFMEMORY inputMemory;
WDFMEMORY outputMemory;
size_t inputBufferLength;
size_t outputBufferLength;
PVOID inputBuffer;
//
// Get report Id from output buffer length
//
status = WdfRequestRetrieveOutputMemory(
Request,
&outputMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputMemory failed with %!STATUS!",
status
);
return status;
}
WdfMemoryGetBuffer(
outputMemory,
&outputBufferLength
);
Packet->reportId = (UCHAR) outputBufferLength;
//
// Get report buffer from input buffer
//
status = WdfRequestRetrieveInputMemory(
Request,
&inputMemory
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveInputMemory failed with %!STATUS!",
status
);
return status;
}
inputBuffer = WdfMemoryGetBuffer(
inputMemory,
&inputBufferLength
);
Packet->reportBuffer = (PUCHAR) inputBuffer;
Packet->reportBufferLen = (ULONG) inputBufferLength;
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpReportFeatures(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status;
PDEVICE_CONTEXT deviceContext;
HID_XFER_PACKET packet;
size_t reportSize;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
status = STATUS_SUCCESS;
deviceContext = DeviceGetContext(Device);
status = RequestGetHidXferPacketToReadFromDevice(
Request,
&packet
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! RequestGetHidXferPacketToReadFromDevice failed with status %!STATUS!",
status
);
goto exit;
}
switch (packet.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 (packet.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) packet.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"
);
WdfRequestSetInformation(
Request,
reportSize
);
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 (packet.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) packet.reportBuffer;
*certReport->CertificationBlob = DEFAULT_PTP_HQA_BLOB;
certReport->ReportID = REPORTID_PTPHQA;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_PTPHQA is fulfilled"
);
WdfRequestSetInformation(
Request,
reportSize
);
break;
}
case REPORTID_UMAPP_CONF:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_UMAPP_CONF is requested"
);
// Size sanity check
reportSize = sizeof(PTP_USERMODEAPP_CONF_REPORT);
if (packet.reportBufferLen < reportSize) {
status = STATUS_INVALID_BUFFER_SIZE;
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! Report buffer is too small."
);
goto exit;
}
PPTP_USERMODEAPP_CONF_REPORT confReport = (PPTP_USERMODEAPP_CONF_REPORT)packet.reportBuffer;
confReport->ReportID = REPORTID_UMAPP_CONF;
confReport->MultipleContactSizeQualificationLevel = deviceContext->MuContactSizeQualLevel;
confReport->SingleContactSizeQualificationLevel = deviceContext->SgContactSizeQualLevel;
confReport->PressureQualificationLevel = deviceContext->PressureQualLevel;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_UMAPP_CONF is fulfilled"
);
WdfRequestSetInformation(
Request,
reportSize
);
break;
}
default:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Unsupported type %d is requested",
packet.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;
HID_XFER_PACKET packet;
PDEVICE_CONTEXT deviceContext;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
status = STATUS_SUCCESS;
deviceContext = DeviceGetContext(Device);
status = RequestGetHidXferPacketToWriteToDevice(
Request,
&packet
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! RequestGetHidXferPacketToWriteToDevice failed with status %!STATUS!",
status
);
goto exit;
}
switch (packet.reportId)
{
case REPORTID_REPORTMODE:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_REPORTMODE is requested"
);
PPTP_DEVICE_INPUT_MODE_REPORT devInputMode = (PPTP_DEVICE_INPUT_MODE_REPORT) packet.reportBuffer;
// Get current WellSpring mode
BOOL bWellspringMode = FALSE;
status = AmtPtpGetWellspringMode(
deviceContext,
&bWellspringMode
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! -> AmtPtpGetWellspringMode failed with status %!STATUS!",
status
);
goto exit;
}
switch (devInputMode->Mode)
{
case PTP_COLLECTION_MOUSE:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_REPORTMODE requested Mouse Input"
);
if (bWellspringMode) {
status = AmtPtpSetWellspringMode(
deviceContext,
FALSE
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! -> AmtPtpSetWellspringMode failed with status %!STATUS!",
status
);
goto exit;
}
}
break;
}
case PTP_COLLECTION_WINDOWS:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_REPORTMODE requested Windows PTP Input"
);
if (!bWellspringMode) {
status = AmtPtpSetWellspringMode(
deviceContext,
TRUE
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! -> AmtPtpSetWellspringMode failed with status %!STATUS!",
status
);
goto exit;
}
}
break;
}
}
WdfRequestSetInformation(
Request,
sizeof(PTP_DEVICE_INPUT_MODE_REPORT)
);
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 secInput = (PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT) packet.reportBuffer;
deviceContext->IsButtonReportOn = secInput->ButtonReport;
deviceContext->IsSurfaceReportOn = secInput->SurfaceReport;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_FUNCSWITCH requested Button = %d, Surface = %d",
secInput->ButtonReport,
secInput->SurfaceReport
);
WdfRequestSetInformation(
Request,
sizeof(PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT)
);
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_FUNCSWITCH is fulfilled"
);
break;
}
case REPORTID_UMAPP_CONF:
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_UMAPP_CONF is requested"
);
PPTP_USERMODEAPP_CONF_REPORT umConfInput = (PPTP_USERMODEAPP_CONF_REPORT) packet.reportBuffer;
// Set value
deviceContext->SgContactSizeQualLevel = umConfInput->SingleContactSizeQualificationLevel;
deviceContext->MuContactSizeQualLevel = umConfInput->MultipleContactSizeQualificationLevel;
deviceContext->PressureQualLevel = umConfInput->PressureQualificationLevel;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_UMAPP_CONF requested PressureQual = %d, SgSize = %d, MuSize = %d",
umConfInput->PressureQualificationLevel,
umConfInput->SingleContactSizeQualificationLevel,
umConfInput->MultipleContactSizeQualificationLevel
);
// Report back
WdfRequestSetInformation(
Request,
sizeof(PTP_USERMODEAPP_CONF_REPORT)
);
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Report REPORTID_UMAPP_CONF is fulfilled"
);
break;
}
default:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Unsupported type %d is requested",
packet.reportId
);
status = STATUS_NOT_SUPPORTED;
goto exit;
}
exit:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return STATUS_SUCCESS;
}
================================================
FILE: src/AmtPtpDeviceUsbUm/InputInterrupt.c
================================================
// InputInterrupt.c: Handles device input event
#include
#include "InputInterrupt.tmh"
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpConfigContReaderForInterruptEndPoint(
_In_ PDEVICE_CONTEXT DeviceContext
)
{
WDF_USB_CONTINUOUS_READER_CONFIG contReaderConfig;
NTSTATUS status;
size_t transferLength = 0;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
switch (DeviceContext->DeviceInfo->tp_type)
{
case TYPE1:
transferLength = HEADER_TYPE1 + FSIZE_TYPE1 * MAX_FINGERS;
break;
case TYPE2:
transferLength = HEADER_TYPE2 + FSIZE_TYPE2 * MAX_FINGERS;
break;
case TYPE3:
transferLength = HEADER_TYPE3 + FSIZE_TYPE3 * MAX_FINGERS;
break;
case TYPE4:
transferLength = HEADER_TYPE4 + FSIZE_TYPE4 * MAX_FINGERS;
break;
case TYPE5:
transferLength = HEADER_TYPE5 + FSIZE_TYPE5 * MAX_FINGERS;
break;
}
if (transferLength <= 0) {
status = STATUS_UNKNOWN_REVISION;
return status;
}
WDF_USB_CONTINUOUS_READER_CONFIG_INIT(
&contReaderConfig,
AmtPtpEvtUsbInterruptPipeReadComplete,
DeviceContext, // Context
transferLength // Calculate transferred length by device information
);
contReaderConfig.EvtUsbTargetPipeReadersFailed = AmtPtpEvtUsbInterruptReadersFailed;
// Remember to turn it on in D0 entry
status = WdfUsbTargetPipeConfigContinuousReader(
DeviceContext->InterruptPipe,
&contReaderConfig
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! AmtPtpConfigContReaderForInterruptEndPoint failed with Status code %!STATUS!",
status
);
return status;
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return STATUS_SUCCESS;
}
_IRQL_requires_(PASSIVE_LEVEL)
VOID
AmtPtpEvtUsbInterruptPipeReadComplete(
_In_ WDFUSBPIPE Pipe,
_In_ WDFMEMORY Buffer,
_In_ size_t NumBytesTransferred,
_In_ WDFCONTEXT Context
)
{
UNREFERENCED_PARAMETER(Pipe);
WDFDEVICE device;
PDEVICE_CONTEXT pDeviceContext = Context;
UCHAR* pBuffer = NULL;
NTSTATUS status;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
device = WdfObjectContextGetObject(pDeviceContext);
size_t headerSize = (unsigned int) pDeviceContext->DeviceInfo->tp_header;
size_t fingerprintSize = (unsigned int) pDeviceContext->DeviceInfo->tp_fsize;
if (NumBytesTransferred < headerSize || (NumBytesTransferred - headerSize) % fingerprintSize != 0) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Malformed input received. Length = %llu. Attempt to reset device.",
NumBytesTransferred
);
status = AmtPtpEmergResetDevice(pDeviceContext);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! AmtPtpEmergResetDevice failed with %!STATUS!",
status
);
}
return;
}
if (!pDeviceContext->IsWellspringModeOn) {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! Routine is called without enabling Wellspring mode"
);
return;
}
// Dispatch USB Interrupt routine by device family
switch (pDeviceContext->DeviceInfo->tp_type) {
case TYPE1:
{
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! Mode not yet supported"
);
break;
}
// Universal routine handler
case TYPE2:
case TYPE3:
case TYPE4:
{
pBuffer = WdfMemoryGetBuffer(
Buffer,
NULL
);
status = AmtPtpServiceTouchInputInterrupt(
pDeviceContext,
pBuffer,
NumBytesTransferred
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! AmtPtpServiceTouchInputInterrupt failed with %!STATUS!",
status
);
}
break;
}
// Magic Trackpad 2
case TYPE5:
{
pBuffer = WdfMemoryGetBuffer(
Buffer,
NULL
);
status = AmtPtpServiceTouchInputInterruptType5(
pDeviceContext,
pBuffer,
NumBytesTransferred
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_DRIVER,
"%!FUNC! AmtPtpServiceTouchInputInterrupt5 failed with %!STATUS!",
status
);
}
break;
}
}
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
}
_IRQL_requires_(PASSIVE_LEVEL)
BOOLEAN
AmtPtpEvtUsbInterruptReadersFailed(
_In_ WDFUSBPIPE Pipe,
_In_ NTSTATUS Status,
_In_ USBD_STATUS UsbdStatus
)
{
UNREFERENCED_PARAMETER(Pipe);
UNREFERENCED_PARAMETER(UsbdStatus);
UNREFERENCED_PARAMETER(Status);
return TRUE;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpServiceTouchInputInterrupt(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ UCHAR* Buffer,
_In_ size_t NumBytesTransferred
)
{
NTSTATUS Status;
WDFREQUEST Request;
WDFMEMORY RequestMemory;
PTP_REPORT PtpReport;
LARGE_INTEGER CurrentPerfCounter;
LONGLONG PerfCounterDelta;
const struct TRACKPAD_FINGER *f;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
size_t raw_n, i = 0;
size_t headerSize = (unsigned int) DeviceContext->DeviceInfo->tp_header;
size_t fingerprintSize = (unsigned int) DeviceContext->DeviceInfo->tp_fsize;
USHORT x = 0, y = 0;
Status = STATUS_SUCCESS;
PtpReport.ReportID = REPORTID_MULTITOUCH;
PtpReport.IsButtonClicked = 0;
// Retrieve next PTP touchpad request.
Status = WdfIoQueueRetrieveNextRequest(
DeviceContext->InputQueue,
&Request
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! No pending PTP request. Interrupt disposed"
);
goto exit;
}
QueryPerformanceCounter(
&CurrentPerfCounter
);
// Scan time is in 100us
PerfCounterDelta = (CurrentPerfCounter.QuadPart - DeviceContext->PerfCounter.QuadPart) / 100;
// Only two bytes allocated
if (PerfCounterDelta > 0xFF)
{
PerfCounterDelta = 0xFF;
}
PtpReport.ScanTime = (USHORT) PerfCounterDelta;
// Allocate output memory.
Status = WdfRequestRetrieveOutputMemory(
Request,
&RequestMemory
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputMemory failed with %!STATUS!",
Status
);
goto exit;
}
// Type 2 touchpad surface report
if (DeviceContext->IsSurfaceReportOn) {
// Handles trackpad surface report here.
raw_n = (NumBytesTransferred - headerSize) / fingerprintSize;
if (raw_n >= PTP_MAX_CONTACT_POINTS) raw_n = PTP_MAX_CONTACT_POINTS;
PtpReport.ContactCount = (UCHAR) raw_n;
#ifdef INPUT_CONTENT_TRACE
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! with %llu points.",
raw_n
);
#endif
// Fingers
for (i = 0; i < raw_n; i++) {
UCHAR *f_base = Buffer + headerSize + DeviceContext->DeviceInfo->tp_delta;
f = (const struct TRACKPAD_FINGER*) (f_base + i * fingerprintSize);
// Translate X and Y
x = (AmtRawToInteger(f->abs_x) - DeviceContext->DeviceInfo->x.min) > 0 ?
((USHORT)(AmtRawToInteger(f->abs_x) - DeviceContext->DeviceInfo->x.min)) : 0;
y = (DeviceContext->DeviceInfo->y.max - AmtRawToInteger(f->abs_y)) > 0 ?
((USHORT)(DeviceContext->DeviceInfo->y.max - AmtRawToInteger(f->abs_y))) : 0;
// Defuzz functions remain the same
// TODO: Implement defuzz later
PtpReport.Contacts[i].ContactID = (UCHAR) i;
PtpReport.Contacts[i].X = x;
PtpReport.Contacts[i].Y = y;
PtpReport.Contacts[i].TipSwitch = (AmtRawToInteger(f->touch_major) << 1) >= 200;
PtpReport.Contacts[i].Confidence = (AmtRawToInteger(f->touch_minor) << 1) > 0;
#ifdef INPUT_CONTENT_TRACE
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_INPUT,
"%!FUNC!: Point %llu, X = %d, Y = %d, TipSwitch = %d, Confidence = %d, tMajor = %d, tMinor = %d, origin = %d, PTP Origin = %d",
i,
PtpReport.Contacts[i].X,
PtpReport.Contacts[i].Y,
PtpReport.Contacts[i].TipSwitch,
PtpReport.Contacts[i].Confidence,
AmtRawToInteger(f->touch_major) << 1,
AmtRawToInteger(f->touch_minor) << 1,
AmtRawToInteger(f->origin),
(UCHAR) i
);
#endif
}
}
// Type 2 touchpad contains integrated trackpad buttons
if (DeviceContext->IsButtonReportOn) {
// Handles trackpad button input here.
if (Buffer[DeviceContext->DeviceInfo->tp_button]) {
PtpReport.IsButtonClicked = TRUE;
}
}
// Compose final report and write it back
Status = WdfMemoryCopyFromBuffer(
RequestMemory,
0,
(PVOID) &PtpReport,
sizeof(PTP_REPORT)
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
Status
);
goto exit;
}
// Set result
WdfRequestSetInformation(
Request,
sizeof(PTP_REPORT)
);
// Set completion flag
WdfRequestComplete(
Request,
Status
);
exit:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return Status;
}
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpServiceTouchInputInterruptType5(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ UCHAR* Buffer,
_In_ size_t NumBytesTransferred
)
{
NTSTATUS Status;
WDFREQUEST Request;
WDFMEMORY RequestMemory;
PTP_REPORT PtpReport;
LARGE_INTEGER CurrentPerfCounter;
LONGLONG PerfCounterDelta;
const struct TRACKPAD_FINGER *f;
const struct TRACKPAD_FINGER_TYPE5 *f_type5;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Entry"
);
Status = STATUS_SUCCESS;
PtpReport.ReportID = REPORTID_MULTITOUCH;
PtpReport.IsButtonClicked = 0;
INT x, y = 0;
size_t raw_n, i = 0;
size_t headerSize = (unsigned int) DeviceContext->DeviceInfo->tp_header;
size_t fingerprintSize = (unsigned int) DeviceContext->DeviceInfo->tp_fsize;
Status = WdfIoQueueRetrieveNextRequest(
DeviceContext->InputQueue,
&Request
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! No pending PTP request. Interrupt disposed"
);
goto exit;
}
Status = WdfRequestRetrieveOutputMemory(
Request,
&RequestMemory
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!",
Status
);
goto exit;
}
QueryPerformanceCounter(
&CurrentPerfCounter
);
// Scan time is in 100us
PerfCounterDelta = (CurrentPerfCounter.QuadPart - DeviceContext->PerfCounter.QuadPart) / 100;
// Only two bytes allocated
if (PerfCounterDelta > 0xFF)
{
PerfCounterDelta = 0xFF;
}
PtpReport.ScanTime = (USHORT) PerfCounterDelta;
// Type 5 finger report
if (DeviceContext->IsSurfaceReportOn) {
raw_n = (NumBytesTransferred - headerSize) / fingerprintSize;
if (raw_n >= PTP_MAX_CONTACT_POINTS) raw_n = PTP_MAX_CONTACT_POINTS;
PtpReport.ContactCount = (UCHAR)raw_n;
#ifdef INPUT_CONTENT_TRACE
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! with %llu points.",
raw_n
);
#endif
// Fingers to array
for (i = 0; i < raw_n; i++) {
UCHAR *f_base = Buffer + headerSize + DeviceContext->DeviceInfo->tp_delta;
f = (const struct TRACKPAD_FINGER*) (f_base + i * fingerprintSize);
f_type5 = (const struct TRACKPAD_FINGER_TYPE5*) f;
USHORT tmp_x = (*((USHORT*)f_type5)) & 0x1fff;
UINT tmp_y = (INT)(*((UINT*)f_type5));
x = (SHORT) (tmp_x << 3) >> 3;
y = -(INT) (tmp_y << 6) >> 19;
x = (x - DeviceContext->DeviceInfo->x.min) > 0 ? (x - DeviceContext->DeviceInfo->x.min) : 0;
y = (y - DeviceContext->DeviceInfo->y.min) > 0 ? (y - DeviceContext->DeviceInfo->y.min) : 0;
PtpReport.Contacts[i].ContactID = f_type5->ContactIdentifier.Id;
PtpReport.Contacts[i].X = (USHORT) x;
PtpReport.Contacts[i].Y = (USHORT) y;
PtpReport.Contacts[i].TipSwitch = (AmtRawToInteger(f_type5->TouchMajor) << 1) > 0;
// The Microsoft spec says reject any input larger than 25mm. This is not ideal
// for Magic Trackpad 2 - so we raised the threshold a bit higher.
// Or maybe I used the wrong unit? IDK
PtpReport.Contacts[i].Confidence = (AmtRawToInteger(f_type5->TouchMinor) << 1) < 345 &&
(AmtRawToInteger(f_type5->TouchMinor) << 1) < 345;
#ifdef INPUT_CONTENT_TRACE
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_INPUT,
"%!FUNC!: Point %llu, X = %d, Y = %d, TipSwitch = %d, Confidence = %d, tMajor = %d, tMinor = %d, origin = %d",
i,
PtpReport.Contacts[i].X,
PtpReport.Contacts[i].Y,
PtpReport.Contacts[i].TipSwitch,
PtpReport.Contacts[i].Confidence,
AmtRawToInteger(f_type5->TouchMajor) << 1,
AmtRawToInteger(f_type5->TouchMinor) << 1,
f_type5->ContactIdentifier.Id
);
#endif
}
}
// Button
if (DeviceContext->IsButtonReportOn) {
if (Buffer[DeviceContext->DeviceInfo->tp_button]) {
PtpReport.IsButtonClicked = TRUE;
}
}
// Write output
Status = WdfMemoryCopyFromBuffer(
RequestMemory,
0,
(PVOID) &PtpReport,
sizeof(PTP_REPORT)
);
if (!NT_SUCCESS(Status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!",
Status
);
goto exit;
}
// Set result
WdfRequestSetInformation(
Request,
sizeof(PTP_REPORT)
);
// Set completion flag
WdfRequestComplete(
Request,
Status
);
exit:
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! Exit"
);
return Status;
}
// Helper function for numberic operation
static inline INT AmtRawToInteger(
_In_ USHORT x
)
{
return (signed short) x;
}
================================================
FILE: src/AmtPtpDeviceUsbUm/MagicTrackpad2PtpDevice.vcxproj
================================================
ReleaseSigned
ARM64
ReleaseSigned
x64
Debug
x64
Release
x64
Debug
ARM64
Release
ARM64
{87EFA31B-25EB-4944-A30A-300171BFFF57}
{9181db3b-298d-4e39-a572-55bca4e4ac89}
v4.5
12.0
Debug
Win32
MagicTrackpad2PtpDevice
AmtPtpDeviceUsbUm
$(LatestTargetPlatformVersion)
10.0.19041.0
Windows10
true
WindowsUserModeDriver10.0
DynamicLibrary
2
Universal
Windows10
false
WindowsUserModeDriver10.0
DynamicLibrary
2
Universal
Windows10
false
WindowsUserModeDriver10.0
DynamicLibrary
2
Universal
Windows10
true
WindowsUserModeDriver10.0
DynamicLibrary
2
Universal
Windows10
false
WindowsUserModeDriver10.0
DynamicLibrary
2
Universal
Windows10
false
WindowsUserModeDriver10.0
DynamicLibrary
2
Universal
DbgengRemoteDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengRemoteDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengRemoteDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
DbgengRemoteDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengRemoteDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengRemoteDebugger
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath)
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
$(ProductionCertPath)
ProductionSign
Off
true
true
include\trace.h
sha256
true
true
include\trace.h
sha256
true
true
include\trace.h
sha256
true
true
include\trace.h
true
true
include\trace.h
true
true
include\trace.h
================================================
FILE: src/AmtPtpDeviceUsbUm/MagicTrackpad2PtpDevice.vcxproj.filters
================================================
{4FC737F1-C7A5-4376-A066-2A32D752A2FF}
cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
{93995380-89BD-4b04-88EB-625FBE52EBFB}
h;hpp;hxx;hm;inl;inc;xsd
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
{8E41214B-6785-4CFE-B992-037D68949A14}
inf;inv;inx;mof;mc;
{d3b4239b-c0e3-4d91-a6ee-730df7a15240}
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Device Specific Metadata Files
Device Specific Metadata Files
Device Specific Metadata Files
Device Specific Metadata Files
Device Specific Metadata Files
Device Specific Metadata Files
Source Files
Source Files
Source Files
Source Files
Source Files
Resource Files
Resource Files
================================================
FILE: src/AmtPtpDeviceUsbUm/Queue.c
================================================
// Queue.c: This file contains the queue entry points and callbacks.
#include
#include "queue.tmh"
NTSTATUS
AmtPtpDeviceQueueInitialize(
_In_ WDFDEVICE Device
)
{
WDFQUEUE queue;
NTSTATUS status;
WDF_IO_QUEUE_CONFIG queueConfig;
PDEVICE_CONTEXT deviceContext;
deviceContext = DeviceGetContext(Device);
//
// Configure a default queue so that requests that are not
// configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
// other queues get dispatched here.
//
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
&queueConfig,
WdfIoQueueDispatchParallel
);
queueConfig.EvtIoDeviceControl = AmtPtpDeviceEvtIoDeviceControl;
queueConfig.EvtIoStop = AmtPtpDeviceEvtIoStop;
status = WdfIoQueueCreate(
Device,
&queueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&queue
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_QUEUE,
"%!FUNC! WdfIoQueueCreate (Primary) failed %!STATUS!",
status
);
return status;
}
//
// Create secondary queues for touch and mouse read requests.
//
WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual);
queueConfig.PowerManaged = WdfFalse;
status = WdfIoQueueCreate(
Device,
&queueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&deviceContext->InputQueue
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_QUEUE,
"%!FUNC! WdfIoQueueCreate (Input) failed %!STATUS!",
status
);
return status;
}
return status;
}
_IRQL_requires_(PASSIVE_LEVEL)
PCHAR
DbgIoControlGetString(
_In_ ULONG IoControlCode
)
{
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
return "IOCTL_HID_GET_DEVICE_DESCRIPTOR";
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
return "IOCTL_HID_GET_DEVICE_ATTRIBUTES";
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
return "IOCTL_HID_GET_REPORT_DESCRIPTOR";
case IOCTL_HID_GET_STRING:
return "IOCTL_HID_GET_STRING";
case IOCTL_HID_READ_REPORT:
return "IOCTL_HID_READ_REPORT";
case IOCTL_HID_WRITE_REPORT:
return "IOCTL_HID_WRITE_REPORT";
case IOCTL_UMDF_HID_GET_INPUT_REPORT:
return "IOCTL_UMDF_HID_GET_INPUT_REPORT";
case IOCTL_UMDF_HID_SET_OUTPUT_REPORT:
return "IOCTL_UMDF_HID_SET_OUTPUT_REPORT";
case IOCTL_UMDF_HID_GET_FEATURE:
return "IOCTL_UMDF_HID_GET_FEATURE";
case IOCTL_UMDF_HID_SET_FEATURE:
return "IOCTL_UMDF_HID_SET_FEATURE";
case IOCTL_HID_ACTIVATE_DEVICE:
return "IOCTL_HID_ACTIVATE_DEVICE";
case IOCTL_HID_DEACTIVATE_DEVICE:
return "IOCTL_HID_DEACTIVATE_DEVICE";
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST";
default:
return "IOCTL_UNKNOWN";
}
}
VOID
AmtPtpDeviceEvtIoDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
{
NTSTATUS status = STATUS_SUCCESS;
WDFDEVICE device = WdfIoQueueGetDevice(Queue);
BOOLEAN requestPending = FALSE;
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_QUEUE,
"%!FUNC!: Queue 0x%p, Request 0x%p OutputBufferLength %d InputBufferLength %d IoControlCode %d",
Queue,
Request,
(int) OutputBufferLength,
(int) InputBufferLength,
IoControlCode
);
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
status = AmtPtpGetHidDescriptor(
device,
Request
);
break;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
status = AmtPtpGetDeviceAttribs(
device,
Request
);
break;
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
status = AmtPtpGetReportDescriptor(
device,
Request
);
break;
case IOCTL_HID_GET_STRING:
status = AmtPtpGetStrings(
device,
Request
);
break;
case IOCTL_HID_READ_REPORT:
status = AmtPtpDispatchReadReportRequests(
device,
Request,
&requestPending
);
break;
case IOCTL_UMDF_HID_GET_FEATURE:
status = AmtPtpReportFeatures(
device,
Request
);
break;
case IOCTL_UMDF_HID_SET_FEATURE:
status = AmtPtpSetFeatures(
device,
Request
);
break;
case IOCTL_HID_WRITE_REPORT:
case IOCTL_UMDF_HID_SET_OUTPUT_REPORT:
case IOCTL_UMDF_HID_GET_INPUT_REPORT:
case IOCTL_HID_ACTIVATE_DEVICE:
case IOCTL_HID_DEACTIVATE_DEVICE:
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
default:
status = STATUS_NOT_SUPPORTED;
TraceEvents(
TRACE_LEVEL_WARNING,
TRACE_QUEUE,
"%!FUNC!: %s is not yet implemented",
DbgIoControlGetString(IoControlCode)
);
break;
}
if (requestPending != TRUE) {
WdfRequestComplete(
Request,
status
);
}
return;
}
VOID
AmtPtpDeviceEvtIoStop(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ ULONG ActionFlags
)
{
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_QUEUE,
"%!FUNC! Queue 0x%p, Request 0x%p ActionFlags %d",
Queue,
Request,
ActionFlags
);
//
// In most cases, the EvtIoStop callback function completes, cancels, or postpones
// further processing of the I/O request.
//
// Typically, the driver uses the following rules:
//
// - If the driver owns the I/O request, it either postpones further processing
// of the request and calls WdfRequestStopAcknowledge, or it calls WdfRequestComplete
// with a completion status value of STATUS_SUCCESS or STATUS_CANCELLED.
//
// The driver must call WdfRequestComplete only once, to either complete or cancel
// the request. To ensure that another thread does not call WdfRequestComplete
// for the same request, the EvtIoStop callback must synchronize with the driver's
// other event callback functions, for instance by using interlocked operations.
//
// - If the driver has forwarded the I/O request to an I/O target, it either calls
// WdfRequestCancelSentRequest to attempt to cancel the request, or it postpones
// further processing of the request and calls WdfRequestStopAcknowledge.
//
// A driver might choose to take no action in EvtIoStop for requests that are
// guaranteed to complete in a small amount of time. For example, the driver might
// take no action for requests that are completed in one of the drivers request handlers.
//
return;
}
NTSTATUS
AmtPtpDispatchReadReportRequests(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_Out_ BOOLEAN *Pending
)
{
NTSTATUS status;
PDEVICE_CONTEXT devContext;
status = STATUS_SUCCESS;
devContext = DeviceGetContext(Device);
status = WdfRequestForwardToIoQueue(
Request,
devContext->InputQueue
);
if (!NT_SUCCESS(status)) {
TraceEvents(
TRACE_LEVEL_ERROR,
TRACE_DRIVER,
"%!FUNC! WdfRequestForwardToIoQueue failed with %!STATUS!",
status
);
return status;
} else {
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_DRIVER,
"%!FUNC! A report has been forwarded to input queue"
);
}
if (NULL != Pending) {
*Pending = TRUE;
}
return status;
}
================================================
FILE: src/AmtPtpDeviceUsbUm/include/AppleDefinition.h
================================================
#pragma once
#define USB_VENDOR_ID_APPLE 0x05ac
/* MacbookAir, aka wellspring */
#define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223
#define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224
#define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225
/* MacbookProPenryn, aka wellspring2 */
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
/* Macbook5,1 (unibody), aka wellspring3 */
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
/* MacbookAir3,2 (unibody), aka wellspring5 */
#define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f
#define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240
#define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241
/* MacbookAir3,1 (unibody), aka wellspring4 */
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243
#define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244
/* Macbook8 (unibody, March 2011) */
#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245
#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246
#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247
/* MacbookAir4,1 (unibody, July 2011) */
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b
/* MacbookAir4,2 (unibody, July 2011) */
#define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c
#define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d
#define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e
/* Macbook8,2 (unibody) */
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254
/* MacbookPro10,1 (unibody, June 2012) */
#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262
#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263
#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264
/* MacbookPro10,2 (unibody, October 2012) */
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b
/* MacbookAir6,2 (unibody, June 2013) */
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291
#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292
/* MacbookPro12,1 (2015) */
#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272
#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273
#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274
/* MagicTrackpad2 (2015) */
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 0x0265
/* Apple T2 USB trackpad */
#define USB_DEVICE_ID_APPLE_T2 0x027d
/* button data structure */
struct TRACKPAD_BUTTON_DATA {
UCHAR unknown1; /* constant */
UCHAR button; /* left button */
UCHAR rel_x; /* relative x coordinate */
UCHAR rel_y; /* relative y coordinate */
};
/* trackpad header types */
enum TRACKPAD_TYPE {
TYPE1, /* plain trackpad */
TYPE2, /* button integrated in trackpad */
TYPE3, /* additional header fields since June 2013 */
TYPE4, /* additional header field for pressure data */
TYPE5 /* format for magic trackpad 2 */
};
/* Trackpad finger data offsets, le16-aligned */
#define HEADER_TYPE1 (13 * sizeof(USHORT))
#define HEADER_TYPE2 (15 * sizeof(USHORT))
#define HEADER_TYPE3 (19 * sizeof(USHORT))
#define HEADER_TYPE4 (23 * sizeof(USHORT))
#define HEADER_TYPE5 ( 6 * sizeof(USHORT))
/* Trackpad button data offsets */
#define BUTTON_TYPE1 0
#define BUTTON_TYPE2 15
#define BUTTON_TYPE3 23
#define BUTTON_TYPE4 31
#define BUTTON_TYPE5 1
/* List of device capability bits */
#define HAS_INTEGRATED_BUTTON 1
/* Trackpad finger data block size */
#define FSIZE_TYPE1 (14 * sizeof(USHORT))
#define FSIZE_TYPE2 (14 * sizeof(USHORT))
#define FSIZE_TYPE3 (14 * sizeof(USHORT))
#define FSIZE_TYPE4 (15 * sizeof(USHORT))
#define FSIZE_TYPE5 (9)
/* Offset from header to finger struct */
#define DELTA_TYPE1 (0 * sizeof(USHORT))
#define DELTA_TYPE2 (0 * sizeof(USHORT))
#define DELTA_TYPE3 (0 * sizeof(USHORT))
#define DELTA_TYPE4 (1 * sizeof(USHORT))
#define DELTA_TYPE5 (0 * sizeof(USHORT))
/* USB control message mode switch data */
#define USBMSG_TYPE1 8, 0x300, 0, 0, 0x1, 0x8
#define USBMSG_TYPE2 8, 0x300, 0, 0, 0x1, 0x8
#define USBMSG_TYPE3 8, 0x300, 0, 0, 0x1, 0x8
#define USBMSG_TYPE4 2, 0x302, 2, 1, 0x1, 0x0
#define USBMSG_TYPE5 2, 0x302, 1, 1, 0x1, 0x0
/* Wellspring initialization constants */
#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
/* Trackpad finger data size, empirically at least ten fingers */
#define MAX_FINGERS 16
#define MAX_FINGER_ORIENTATION 16384
#define BCM5974_MOUSE_SIZE 8
/* trackpad finger structure, le16-aligned */
__declspec(align(2)) struct TRACKPAD_FINGER {
USHORT origin; /* zero when switching track finger */
USHORT abs_x; /* absolute x coodinate */
USHORT abs_y; /* absolute y coodinate */
USHORT rel_x; /* relative x coodinate */
USHORT rel_y; /* relative y coodinate */
USHORT tool_major; /* tool area, major axis */
USHORT tool_minor; /* tool area, minor axis */
USHORT orientation; /* 16384 when point, else 15 bit angle */
USHORT touch_major; /* touch area, major axis */
USHORT touch_minor; /* touch area, minor axis */
USHORT unused[2]; /* zeros */
USHORT pressure; /* pressure on forcetouch touchpad */
USHORT multi; /* one finger: varies, more fingers: constant */
};
/* Trackpad finger structure for type5 (magic trackpad), le16-aligned */
__declspec(align(2)) struct TRACKPAD_FINGER_TYPE5
{
UCHAR AbsoluteX; /* absolute x coodinate */
UCHAR AbsoluteXY; /* absolute x,y coodinate */
UCHAR AbsoluteY[2]; /* absolute y coodinate */
UCHAR TouchMajor; /* touch area, major axis */
UCHAR TouchMinor; /* touch area, minor axis */
UCHAR Size; /* tool area, size */
UCHAR Pressure; /* pressure on forcetouch touchpad */
union
{
struct
{
UCHAR Id : 4;
UCHAR Orientation : 4;
} ContactIdentifier;
UCHAR RawOrientationAndOrigin;
};
};
/* device-specific parameters */
struct BCM5974_PARAM {
int snratio; /* signal-to-noise ratio */
int min; /* device minimum reading */
int max; /* device maximum reading */
};
/* device-specific configuration */
struct BCM5974_CONFIG {
int ansi, iso, jis; /* the product id of this device */
int caps; /* device capability bitmask */
int bt_ep; /* the endpoint of the button interface */
int bt_datalen; /* data length of the button interface */
int tp_ep; /* the endpoint of the trackpad interface */
enum TRACKPAD_TYPE tp_type; /* type of trackpad interface */
int tp_header; /* bytes in header block */
int tp_datalen; /* data length of the trackpad interface */
int tp_button; /* offset to button data */
int tp_fsize; /* bytes in single finger block */
int tp_delta; /* offset from header to finger struct */
int um_size; /* usb control message length */
int um_req_val; /* usb control message value */
int um_req_idx; /* usb control message index */
int um_switch_idx; /* usb control message mode switch index */
int um_switch_on; /* usb control message mode switch on */
int um_switch_off; /* usb control message mode switch off */
struct BCM5974_PARAM p; /* finger pressure limits */
struct BCM5974_PARAM w; /* finger width limits */
struct BCM5974_PARAM x; /* horizontal limits */
struct BCM5974_PARAM y; /* vertical limits */
struct BCM5974_PARAM o; /* orientation limits */
};
#define DATAFORMAT(type) \
type, \
HEADER_##type, \
HEADER_##type + (MAX_FINGERS) * (FSIZE_##type), \
BUTTON_##type, \
FSIZE_##type, \
DELTA_##type, \
USBMSG_##type
/* logical signal quality */
#define SN_PRESSURE 45 /* pressure signal-to-noise ratio */
#define SN_WIDTH 25 /* width signal-to-noise ratio */
#define SN_COORD 250 /* coordinate signal-to-noise ratio */
#define SN_ORIENT 10 /* orientation signal-to-noise ratio */
#define PRESSURE_QUALIFICATION_THRESHOLD 2
#define SIZE_QUALIFICATION_THRESHOLD 9
#define SIZE_MU_LOWER_THRESHOLD 5
#define PRESSURE_MU_QUALIFICATION_THRESHOLD_TOTAL 15
#define SIZE_MU_QUALIFICATION_THRESHOLD_TOTAL 25
/* device constants */
static const struct BCM5974_CONFIG Bcm5974ConfigTable[] = {
{
USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
0,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE1),
{ SN_PRESSURE, 0, 256 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4824, 5342 },
{ SN_COORD, -172, 5820 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
0,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE1),
{ SN_PRESSURE, 0, 256 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4824, 4824 },
{ SN_COORD, -172, 4290 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING3_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING3_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4460, 5166 },
{ SN_COORD, -75, 6700 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING4_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING4_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4620, 5140 },
{ SN_COORD, -150, 6600 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4616, 5112 },
{ SN_COORD, -142, 5234 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING5_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING5_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4415, 5050 },
{ SN_COORD, -55, 6680 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING6_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING6_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4620, 5140 },
{ SN_COORD, -150, 6600 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4750, 5280 },
{ SN_COORD, -150, 6730 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4620, 5140 },
{ SN_COORD, -150, 6600 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING7_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING7_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4750, 5280 },
{ SN_COORD, -150, 6730 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct TRACKPAD_BUTTON_DATA),
0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4750, 5280 },
{ SN_COORD, -150, 6730 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING8_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING8_JIS,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE3),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4620, 5140 },
{ SN_COORD, -150, 6600 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING9_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING9_JIS,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE4),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4828, 5345 },
{ SN_COORD, -203, 6803 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2,
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2,
USB_DEVICE_ID_APPLE_MAGICTRACKPAD2,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE5),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -3678, 3934 },
{ SN_COORD, -2479, 2586 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{
USB_DEVICE_ID_APPLE_T2,
USB_DEVICE_ID_APPLE_T2,
USB_DEVICE_ID_APPLE_T2,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct TRACKPAD_BUTTON_DATA),
0x83, DATAFORMAT(TYPE4),
{ SN_PRESSURE, 0, 300 },
/* This is incorrect; check actual data later */
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4828, 5345 },
{ SN_COORD, -203, 6803 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
};
================================================
FILE: src/AmtPtpDeviceUsbUm/include/Device.h
================================================
// Device.h: Device definitions
EXTERN_C_START
// Device context struct
typedef struct _DEVICE_CONTEXT
{
WDFUSBDEVICE UsbDevice;
WDFUSBPIPE InterruptPipe;
WDFUSBINTERFACE UsbInterface;
WDFQUEUE InputQueue;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
const struct BCM5974_CONFIG *DeviceInfo;
ULONG UsbDeviceTraits;
UCHAR PressureQualLevel;
UCHAR SgContactSizeQualLevel;
UCHAR MuContactSizeQualLevel;
BOOL IsWellspringModeOn;
BOOL IsSurfaceReportOn;
BOOL IsButtonReportOn;
LARGE_INTEGER PerfCounter;
} 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)
//
// Pool tags
//
#define POOL_TAG_PTP_CONTROL 'PTPC'
//
// Function to initialize the device's queues and callbacks
//
NTSTATUS
AmtPtpCreateDevice(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
);
//
// Function to select the device's USB configuration and get a WDFUSBDEVICE
// handle
//
EVT_WDF_DEVICE_PREPARE_HARDWARE AmtPtpEvtDevicePrepareHardware;
EVT_WDF_DEVICE_D0_ENTRY AmtPtpEvtDeviceD0Entry;
EVT_WDF_DEVICE_D0_EXIT AmtPtpEvtDeviceD0Exit;
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpConfigContReaderForInterruptEndPoint(
_In_ PDEVICE_CONTEXT DeviceContext
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpGetWellspringMode(
_In_ PDEVICE_CONTEXT DeviceContext,
_Out_ BOOL* IsWellspringModeOn
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
SelectInterruptInterface(
_In_ WDFDEVICE Device
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpSetWellspringMode(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ BOOL IsWellspringModeOn
);
_IRQL_requires_(PASSIVE_LEVEL)
PCHAR
DbgDevicePowerString(
_In_ WDF_POWER_DEVICE_STATE Type
);
_IRQL_requires_(PASSIVE_LEVEL)
VOID
AmtPtpEvtUsbInterruptPipeReadComplete(
_In_ WDFUSBPIPE Pipe,
_In_ WDFMEMORY Buffer,
_In_ size_t NumBytesTransferred,
_In_ WDFCONTEXT Context
);
_IRQL_requires_(PASSIVE_LEVEL)
BOOLEAN
AmtPtpEvtUsbInterruptReadersFailed(
_In_ WDFUSBPIPE Pipe,
_In_ NTSTATUS Status,
_In_ USBD_STATUS UsbdStatus
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpServiceTouchInputInterrupt(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ UCHAR* Buffer,
_In_ size_t NumBytesTransferred
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpServiceTouchInputInterruptType5(
_In_ PDEVICE_CONTEXT DeviceContext,
_In_ UCHAR* Buffer,
_In_ size_t NumBytesTransferred
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpEmergResetDevice(
_In_ PDEVICE_CONTEXT DeviceContext
);
///
/// HID sections
///
_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
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpReportFeatures(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
AmtPtpSetFeatures(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
//
// Utils
//
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
RequestGetHidXferPacketToReadFromDevice(
_In_ WDFREQUEST Request,
_Out_ HID_XFER_PACKET *Packet
);
_IRQL_requires_(PASSIVE_LEVEL)
NTSTATUS
RequestGetHidXferPacketToWriteToDevice(
_In_ WDFREQUEST Request,
_Out_ HID_XFER_PACKET *Packet
);
// Helper function for numberic operation
static inline INT AmtRawToInteger(
_In_ USHORT x
);
EXTERN_C_END
================================================
FILE: src/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring3.h
================================================
#pragma once
#include
#define AAPL_WELLSPRING_3_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
/* This hard-coded size is designed for MacBookAir 7,2 */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0x9a, 0x25, /* Logical Maximum: 9626 (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, 0x1a, 0x04, /* Physical Maximum: 1050 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0xf8, 0x02, /* Physical Maximum: 760 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0x77, 0x1a, /* Logical Maximum: 6775 (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_WELLSPRING_3_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0x9a, 0x25, /* Logical Maximum: 9626 (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, 0x1a, 0x04, /* Physical Maximum: 1050 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0xf8, 0x02, /* Physical Maximum: 760 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0x77, 0x1a, /* Logical Maximum: 6775 (See definition) */ \
USAGE, 0x31, /* Usage: Y */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
END_COLLECTION /* End Collection */ \
#define AAPL_WELLSPRING_3_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_WELLSPRING_3_PTP_FINGER_COLLECTION_1, /* 1 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_1, /* 2 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_2, /* 3 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_1, /* 4 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_3_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/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring5.h
================================================
#pragma once
#include
#define AAPL_WELLSPRING_5_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
/* This hard-coded size is designed for MacBookAir 7,2 */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0xf9, 0x24, /* Logical Maximum: 9465 (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, 0x1a, 0x04, /* Physical Maximum: 1050 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0x2a, 0x03, /* Physical Maximum: 810 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0x4f, 0x1a, /* Logical Maximum: 6735 (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_WELLSPRING_5_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0xf9, 0x24, /* Logical Maximum: 9465 (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, 0x1a, 0x04, /* Physical Maximum: 1050 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0x2a, 0x03, /* Physical Maximum: 810 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0x4f, 0x1a, /* Logical Maximum: 6735 (See definition) */ \
USAGE, 0x31, /* Usage: Y */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
END_COLLECTION /* End Collection */ \
#define AAPL_WELLSPRING_5_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_WELLSPRING_5_PTP_FINGER_COLLECTION_1, /* 1 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_1, /* 2 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_2, /* 3 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_1, /* 4 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_5_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/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring6.h
================================================
#pragma once
#include
#define AAPL_WELLSPRING_6_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
/* This hard-coded size is designed for MacBookAir 7,2 */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0x20, 0x26, /* Logical Maximum: 9760 (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, 0x2b, 0x04, /* Physical Maximum: 1067 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0xfa, 0x02, /* Physical Maximum: 762 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0x5e, 0x1a, /* Logical Maximum: 6750 (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_WELLSPRING_6_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0x20, 0x26, /* Logical Maximum: 9760 (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, 0x2b, 0x04, /* Physical Maximum: 1067 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0xfa, 0x02, /* Physical Maximum: 762 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0x5e, 0x1a, /* Logical Maximum: 6750 (See definition) */ \
USAGE, 0x31, /* Usage: Y */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
END_COLLECTION /* End Collection */ \
#define AAPL_WELLSPRING_6_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_WELLSPRING_6_PTP_FINGER_COLLECTION_1, /* 1 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_1, /* 2 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_2, /* 3 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_1, /* 4 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_6_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/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring7A.h
================================================
#pragma once
#include
#define AAPL_WELLSPRING_7A_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* 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_WELLSPRING_7A_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* 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_WELLSPRING_7A_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_WELLSPRING_7A_PTP_FINGER_COLLECTION_1, /* 1 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_1, /* 2 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_2, /* 3 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_1, /* 4 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_7A_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/AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring8.h
================================================
#pragma once
#include
#define AAPL_WELLSPRING_8_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
/* This hard-coded size is designed for MacBookAir 7,2 */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0x20, 0x26, /* Logical Maximum: 9760 (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, 0x15, 0x04, /* Physical Maximum: 1045 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0xee, 0x02, /* Physical Maximum: 750 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0x5e, 0x1a, /* Logical Maximum: 6750 (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_WELLSPRING_8_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0x20, 0x26, /* Logical Maximum: 9760 (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, 0x15, 0x04, /* Physical Maximum: 1045 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0xee, 0x02, /* Physical Maximum: 750 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0x5e, 0x1a, /* Logical Maximum: 6750 (See definition) */ \
USAGE, 0x31, /* Usage: Y */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
END_COLLECTION /* End Collection */ \
#define AAPL_WELLSPRING_8_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_WELLSPRING_8_PTP_FINGER_COLLECTION_1, /* 1 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_1, /* 2 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_2, /* 3 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_1, /* 4 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_WELLSPRING_8_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/AmtPtpDeviceUsbUm/include/DeviceFamily/WellspringMt2.h
================================================
#pragma once
#include
#define AAPL_MAGIC_TRACKPAD2_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0xbc, 0x1d, /* Logical Maximum: 7612 (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, 0x40, 0x06, /* Physical Maximum: 1600 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0x7d, 0x04, /* Physical Maximum: 1149 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0xc9, 0x13, /* Logical Maximum: 5065 (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_MAGIC_TRACKPAD2_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0xbc, 0x1d, /* Logical Maximum: 7612 (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, 0x40, 0x06, /* Physical Maximum: 1600 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0x7d, 0x04, /* Physical Maximum: 1149 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0xc9, 0x13, /* Logical Maximum: 5065 (See definition) */ \
USAGE, 0x31, /* Usage: Y */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
END_COLLECTION /* End Collection */ \
#define AAPL_MAGIC_TRACKPAD2_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_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 1 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 2 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_2, /* 3 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 4 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_MAGIC_TRACKPAD2_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/AmtPtpDeviceUsbUm/include/Driver.h
================================================
// Driver.h: Driver definitions
#include
#include
#include
#include
#include
#include
// ModernTrace is for runtime debugging
// Trace is WPP-based, development debugging
#include
#include
#include
#include
#include
#include
EXTERN_C_START
//
// WDFDRIVER Events
//
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD AmtPtpDeviceEvtDeviceAdd;
EVT_WDF_OBJECT_CONTEXT_CLEANUP AmtPtpDeviceEvtDriverContextCleanup;
//
// Driver initialization routines
//
VOID
DriverTraceInit(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
);
VOID
DriverTraceCleanup(
_In_ WDFOBJECT DriverObject
);
EXTERN_C_END
================================================
FILE: src/AmtPtpDeviceUsbUm/include/Hid.h
================================================
// Hid.h: Device-related HID definitions
#pragma once
#include
#include
#include
// Device family metadata
#include "DeviceFamily/Wellspring3.h"
#include "DeviceFamily/Wellspring5.h"
#include "DeviceFamily/Wellspring6.h"
#include "DeviceFamily/Wellspring7A.h"
#include "DeviceFamily/Wellspring8.h"
#include "DeviceFamily/WellspringMt2.h"
typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR;
#define DEVICE_VERSION 0x01
#define DEVICE_VID 0x8910
#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 _HID_AAPL_MOUSE_REPORT {
struct {
UCHAR bButtons;
UCHAR wXData;
UCHAR wYData;
UINT Padding;
} InputReport;
} HID_AAPL_MOUSE_REPORT, *PHID_AAPL_MOUSE_REPORT;
typedef struct _HID_INPUT_REPORT {
UCHAR ReportID;
HID_AAPL_MOUSE_REPORT MouseReport;
} HID_INPUT_REPORT, *PHID_INPUT_REPORT;
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(1)
typedef struct _PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT {
UCHAR ReportID;
UCHAR ButtonReport : 1;
UCHAR SurfaceReport : 1;
UCHAR Padding : 6;
} PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT, *PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT;
#pragma pack()
#pragma pack(1)
typedef struct _PTP_CONTACT {
UCHAR Confidence : 1;
UCHAR TipSwitch : 1;
UCHAR Padding : 6;
ULONG ContactID;
USHORT X;
USHORT Y;
} PTP_CONTACT, *PPTP_CONTACT;
#pragma pack()
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;
================================================
FILE: src/AmtPtpDeviceUsbUm/include/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/AmtPtpDeviceUsbUm/include/ModernTrace.h
================================================
#pragma once
// This is the new Windows 10 trace logger provider
#include
EXTERN_C_START
//
// Declare TraceLogger Handler
// TraceLogger GUID {871B1E2D-CC5A-4ADE-B74E-6CF1004EF149}
// Do not confuse with WPP tracing
//
TRACELOGGING_DECLARE_PROVIDER(g_hAmtPtpDeviceTraceProvider);
EXTERN_C_END
//
// Defines a set of events to use
//
#define EVENT_DRIVER_FUNCTIONAL "DriverFunctionalEvent"
#define EVENT_DEVICE_IDENTIFICATION "DeviceIdentificationEvent"
#define EVENT_DEVICE_USBOPERATION "DeviceUsbOperationEvent"
#define EVENT_INPUT_DIAGNOSTICS "InputDiagnosticsEvent"
#define EVENT_DRIVER_FUNC_SUBTYPE "Subtype"
#define EVENT_DRIVER_FUNC_SUBTYPE_CRITFAIL "CriticalFailure"
#define EVENT_DEVICE_ID_SUBTYPE_NOTFOUND "DeviceNotFoundInRegistry"
#define EVENT_DEVICE_ID_SUBTYPE_HIDREG_NOTFOUND "DeviceDescriptorNotFoundInRegistry"
================================================
FILE: src/AmtPtpDeviceUsbUm/include/Queue.h
================================================
// Queue.h: This file contains the queue definitions.
EXTERN_C_START
//
// This is the context that can be placed per queue
// and would contain per queue information.
//
typedef struct _QUEUE_CONTEXT {
ULONG placeholder;
} QUEUE_CONTEXT, *PQUEUE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext)
_IRQL_requires_(PASSIVE_LEVEL)
PCHAR
DbgIoControlGetString(
_In_ ULONG IoControlCode
);
NTSTATUS
AmtPtpDeviceQueueInitialize(
_In_ WDFDEVICE Device
);
NTSTATUS
AmtPtpDispatchReadReportRequests(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_Out_ BOOLEAN *Pending
);
//
// Events from the IoQueue object
//
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL AmtPtpDeviceEvtIoDeviceControl;
EVT_WDF_IO_QUEUE_IO_STOP AmtPtpDeviceEvtIoStop;
EXTERN_C_END
================================================
FILE: src/AmtPtpDeviceUsbUm/include/StaticHidRegistry.h
================================================
#pragma once
#ifndef _AAPL_HID_DESCRIPTOR_H_
#define _AAPL_HID_DESCRIPTOR_H_
HID_REPORT_DESCRIPTOR AmtPtp3ReportDescriptor[] = {
AAPL_WELLSPRING_3_PTP_TLC,
AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};
HID_REPORT_DESCRIPTOR AmtPtp5ReportDescriptor[] = {
AAPL_WELLSPRING_5_PTP_TLC,
AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};
HID_REPORT_DESCRIPTOR AmtPtp6ReportDescriptor[] = {
AAPL_WELLSPRING_6_PTP_TLC,
AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};
HID_REPORT_DESCRIPTOR AmtPtp7aReportDescriptor[] = {
AAPL_WELLSPRING_7A_PTP_TLC,
AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};
HID_REPORT_DESCRIPTOR AmtPtp8ReportDescriptor[] = {
AAPL_WELLSPRING_8_PTP_TLC,
AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};
HID_REPORT_DESCRIPTOR AmtPtpMt2ReportDescriptor[] = {
AAPL_MAGIC_TRACKPAD2_PTP_TLC,
AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC
};
HID_DESCRIPTOR AmtPtp3DefaultHidDescriptor = {
0x09, // bLength
0x21, // bDescriptorType
0x0100, // bcdHID
0x00, // bCountryCode
0x01, // bNumDescriptors
{
0x22, // bDescriptorType
sizeof(AmtPtp3ReportDescriptor) // bDescriptorLength
},
};
HID_DESCRIPTOR AmtPtp5DefaultHidDescriptor = {
0x09, // bLength
0x21, // bDescriptorType
0x0100, // bcdHID
0x00, // bCountryCode
0x01, // bNumDescriptors
{
0x22, // bDescriptorType
sizeof(AmtPtp5ReportDescriptor) // bDescriptorLength
},
};
HID_DESCRIPTOR AmtPtp6DefaultHidDescriptor = {
0x09, // bLength
0x21, // bDescriptorType
0x0100, // bcdHID
0x00, // bCountryCode
0x01, // bNumDescriptors
{
0x22, // bDescriptorType
sizeof(AmtPtp6ReportDescriptor) // bDescriptorLength
},
};
HID_DESCRIPTOR AmtPtp7aDefaultHidDescriptor = {
0x09, // bLength
0x21, // bDescriptorType
0x0100, // bcdHID
0x00, // bCountryCode
0x01, // bNumDescriptors
{
0x22, // bDescriptorType
sizeof(AmtPtp7aReportDescriptor) // bDescriptorLength
},
};
HID_DESCRIPTOR AmtPtp8DefaultHidDescriptor = {
0x09, // bLength
0x21, // bDescriptorType
0x0100, // bcdHID
0x00, // bCountryCode
0x01, // bNumDescriptors
{
0x22, // bDescriptorType
sizeof(AmtPtp8ReportDescriptor) // bDescriptorLength
},
};
HID_DESCRIPTOR AmtPtpMt2DefaultHidDescriptor = {
0x09, // bLength
0x21, // bDescriptorType
0x0100, // bcdHID
0x00, // bCountryCode
0x01, // bNumDescriptors
{
0x22, // bDescriptorType
sizeof(AmtPtpMt2ReportDescriptor) // bDescriptorLength
},
};
#endif
================================================
FILE: src/AmtPtpDeviceUsbUm/include/Trace.h
================================================
// Trace.h: Local type definitions for tracing
//
// Device Interface GUID
// 4a5064e5-7d39-41d1-a0e4-81097edce967
//
DEFINE_GUID(GUID_DEVINTERFACE_AmtPtpDevice,
0x4a5064e5, 0x7d39, 0x41d1, 0xa0, 0xe4, 0x81, 0x09, 0x7e, 0xdc, 0xe9, 0x67);
//
// Define the tracing flags.
//
// Tracing GUID - efc3ce99-43ff-4b59-afe4-c856e1afd8b0
//
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID( \
AmtPtpDriverTraceGuid, (efc3ce99,43ff,4b59,afe4,c856e1afd8b0), \
\
WPP_DEFINE_BIT(AMTPTPDRIVER_ALL_INFO) \
WPP_DEFINE_BIT(TRACE_DRIVER) \
WPP_DEFINE_BIT(TRACE_DEVICE) \
WPP_DEFINE_BIT(TRACE_QUEUE) \
WPP_DEFINE_BIT(TRACE_INPUT) \
)
#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
WPP_LEVEL_LOGGER(flag)
#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
(WPP_LEVEL_ENABLED(flag) && \
WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
WPP_LEVEL_LOGGER(flags)
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//
================================================
FILE: src/AmtPtpDeviceUsbUm/include/resource.h
================================================
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
#define IDS_APP_TITLE 103
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
================================================
FILE: src/AmtPtpHidFilter/AmtPtpHidFilter.inf
================================================
;
; AmtPtpHidFilter.inf
;
[Version]
Signature="$WINDOWS NT$"
Class = HIDClass
ClassGuid = {745a17a0-74d3-11d0-b6fe-00a0c90f57da}
Provider=%ManufacturerName%
CatalogFile=AmtPtpHidFilter.cat
DriverVer= ; TODO: set DriverVer in stampinf property pages
PnpLockdown=1
[DestinationDirs]
DefaultDestDir = 13
[ControlFlags]
; We don't want our device to be installable via the non-PnP hardware dialogs
ExcludeFromSelect = *
[SourceDisksNames]
1 = %DiskName%,,,""
[SourceDisksFiles]
AmtPtpHidFilter.sys = 1,,
;*****************************************
; Install Section
;*****************************************
[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$.10.0
[Standard.NT$ARCH$.10.0]
; Driver migration: if this user installed the old Precision Touch Driver, install the generic HID USB driver for them
%AmtPtpHidRootDevice.DeviceDesc%=StandardUsbHid_Device, USB\Vid_05ac&Pid_0265&MI_01
; The fact is, you can't filter HIDUSB or friends directly, because they load the export driver called
; HIDCLASS which overrides their IO Major Function pointers. Therefore we still implement our own HID miniport
; transport, but in fact reusing the underlying HID transport (either Bluetooth or USB).
; Some high-level patches involved to modify the underlying driver IO handlers.
%AmtPtpHidFilter.DeviceDesc%=AmtPtpHidFilter_MiniPortDevice, HID\VID_05AC&PID_0265&REV_0855&MI_01&Col01
%AmtPtpHidFilter.DeviceDesc%=AmtPtpHidFilter_MiniPortDevice, HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0001004c_PID&0265&Col01
; To avoid confusions to OS, disable any other collections.
%AmtPtpHidFilter.NullDeviceDesc%=AmtPtpHidFilter_NullDevice, HID\VID_05AC&PID_0265&REV_0855&MI_01&Col02
%AmtPtpHidFilter.NullDeviceDesc%=AmtPtpHidFilter_NullDevice, HID\VID_05AC&PID_0265&REV_0855&MI_01&Col03
%AmtPtpHidFilter.NullDeviceDesc%=AmtPtpHidFilter_NullDevice, HID\{00001124-0000-1000-8000-00805f9b34fb}_VID&0001004c_PID&0265&Col02
[FilterDriver_Payload]
AmtPtpHidFilter.sys
[StandardUsbHid_Device.NT]
Include = input.inf
Needs = HID_Inst.NT
[StandardUsbHid_Device.NT.HW]
Include = input.inf
Needs = HID_Inst.NT.HW
[StandardUsbHid_Device.NT.Services]
Include = input.inf
Needs = HID_Inst.NT.Services
[AmtPtpHidFilter_MiniPortDevice.NT]
CopyFiles=FilterDriver_Payload
[AmtPtpHidFilter_NullDevice]
; Nothing!
[AmtPtpHidFilter_NullDevice.Services]
AddService = ,2 ; no value for the service name
;-------------- Service installation
[AmtPtpHidFilter_MiniPortDevice.NT.Services]
AddService = AmtPtpHidFilter,, AmtPtpHidFilter_Service_Inst
AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst
[AmtPtpHidFilter_MiniPortDevice.NT.HW]
AddReg=AmtPtpHidFilter_AddReg
[AmtPtpHidFilter_AddReg]
HKR,,FriendlyName,,%AmtPtpHidFilter.DeviceDesc%
HKR,,"LowerFilters",0x00010008,"AmtPtpHidFilter"
[AmtPtpHidFilter_MiniPortDevice.NT.Wdf]
KmdfService = AmtPtpHidFilter, AmtPtpHidFilter_wdfsect
; -------------- Microsoft HID KMDF driver install sections
[mshidkmdf_Service_Inst]
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\mshidkmdf.sys
; -------------- AmtPtpHidFilter driver install sections
[AmtPtpHidFilter_Service_Inst]
DisplayName = %AmtPtpHidFilter.SVCDESC%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %13%\AmtPtpHidFilter.sys
[AmtPtpHidFilter_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$
[Strings]
SPSVCINST_ASSOCSERVICE= 0x00000002
ManufacturerName = "Bingxing Wang"
DiskName = "Precision Touchpad for Apple Trackpad Installation Disk"
AmtPtpHidRootDevice.DeviceDesc = "Apple Multi-touch Trackpad HID Device"
AmtPtpHidFilter.DeviceDesc = "Apple Multi-touch Trackpad HID Filter"
AmtPtpHidFilter.NullDeviceDesc = "Apple Multi-touch Auxiliary Services"
AmtPtpHidFilter.SVCDESC = "Apple Multi-touch Trackpad HID Filter Service"
================================================
FILE: src/AmtPtpHidFilter/AmtPtpHidFilter.vcxproj
================================================
ReleaseSigned
ARM64
ReleaseSigned
x64
Debug
x64
Release
x64
Debug
ARM64
Release
ARM64
{EE63C42B-F401-4F55-ADBB-14C16BD3B18C}
{1bc93793-694f-48fe-9372-81e2b05556fd}
v4.5
12.0
Debug
Win32
AmtPtpHidFilter
$(LatestTargetPlatformVersion)
Windows10
true
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
Windows10
false
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
Windows10
false
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
Windows10
true
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
Windows10
false
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
Windows10
false
WindowsKernelModeDriver10.0
Driver
KMDF
Universal
DbgengKernelDebugger
$(ProjectDir)include;$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengKernelDebugger
$(ProjectDir)include;$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengKernelDebugger
$(ProjectDir)include;$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengKernelDebugger
$(ProjectDir)include;$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengKernelDebugger
$(ProjectDir)include;$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
DbgengKernelDebugger
$(ProjectDir)include;$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\;$(IncludePath)
$(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\
$(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\
http://timestamp.digicert.com
true
true
$(ProjectDir)include\Trace.h
stdcpplatest
stdc17
true
true
$(ProjectDir)include\Trace.h
stdcpplatest
stdc17
true
true
$(ProjectDir)include\Trace.h
stdcpplatest
stdc17
true
true
$(ProjectDir)include\Trace.h
stdcpplatest
stdc17
sha256
true
true
$(ProjectDir)include\Trace.h
stdcpplatest
stdc17
sha256
true
true
$(ProjectDir)include\Trace.h
stdcpplatest
stdc17
sha256
================================================
FILE: src/AmtPtpHidFilter/AmtPtpHidFilter.vcxproj.filters
================================================
{4FC737F1-C7A5-4376-A066-2A32D752A2FF}
cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
{93995380-89BD-4b04-88EB-625FBE52EBFB}
h;hpp;hxx;hm;inl;inc;xsd
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
{8E41214B-6785-4CFE-B992-037D68949A14}
inf;inv;inx;mof;mc;
{cccbe0e8-fadd-4a3c-bd83-cbd350127d11}
Driver Files
Source Files
Source Files
Source Files
Source Files
Source Files
Source Files
Source Files
Header Files
Header Files
Header Files
Header Files
Header Files
Header Files
Device Specific Metadata Files
Header Files
Device Specific Metadata Files
Device Specific Metadata Files
Header Files
Header Files
Header Files
================================================
FILE: src/AmtPtpHidFilter/Detour.c
================================================
// Detour.c: Windows HID detour facilities
#include
#include "Detour.tmh"
NTSTATUS
PtpFilterDetourWindowsHIDStack(
_In_ WDFDEVICE Device
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
PDEVICE_OBJECT hidTransportWdmDeviceObject = NULL;
PDRIVER_OBJECT hidTransportWdmDriverObject = NULL;
PIO_CLIENT_EXTENSION hidTransportIoClientExtension = NULL;
PHIDCLASS_DRIVER_EXTENSION hidTransportClassExtension = NULL;
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
if (deviceContext->WdmDeviceObject == NULL || deviceContext->WdmDeviceObject->DriverObject == NULL) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WDM Device Object or Driver Object is null, can't continue");
status = STATUS_UNSUCCESSFUL;
goto exit;
}
// Access the driver object to find next low-level device (in our case, we expect it to be HID transport driver)
hidTransportWdmDeviceObject = IoGetLowerDeviceObject(deviceContext->WdmDeviceObject);
if (hidTransportWdmDeviceObject == NULL) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! IoGetLowerDeviceObject returns null, can't continue");
status = STATUS_UNSUCCESSFUL;
goto exit;
}
hidTransportWdmDriverObject = hidTransportWdmDeviceObject->DriverObject;
if (hidTransportWdmDriverObject == NULL) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! DriverObject of HID transport Device Object is null, can't continue");
status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
// Verify if the driver extension is what we expected.
if (hidTransportWdmDriverObject->DriverExtension == NULL) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! DriverExtension of HID transport Driver Object is null, can't continue");
status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
// Just two more check...
hidTransportIoClientExtension = ((PDRIVER_EXTENSION_EXT)hidTransportWdmDriverObject->DriverExtension)->IoClientExtension;
if (hidTransportIoClientExtension == NULL) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! IO Extension is NULL, can't continue");
status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
if (strncmp(HID_CLASS_EXTENSION_LITERAL_ID, hidTransportIoClientExtension->ClientIdentificationAddress, sizeof(HID_CLASS_EXTENSION_LITERAL_ID)) != 0) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! IO Extension mistmatch, can't continue");
status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
hidTransportClassExtension = (PHIDCLASS_DRIVER_EXTENSION)(hidTransportIoClientExtension + 1);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Sanity check seems okay, safe to patch IO handler routines");
// HIDClass overrides:
// IRP_MJ_SYSTEM_CONTROL, IRP_MJ_WRITE, IRP_MJ_READ, IRP_MJ_POWER, IRP_MJ_PNP, IRP_MJ_INTERNAL_DEVICE_CONTROL, IRP_MJ_DEVICE_CONTROL
// IRP_MJ_CREATE, IRP_MJ_CLOSE
// For us, overriding IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL might be sufficient.
// Details: https://ligstd.visualstudio.com/Apple%20PTP%20Trackpad/_wiki/wikis/Apple-PTP-Trackpad.wiki/47/Hijack-HIDCLASS
hidTransportWdmDriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = hidTransportClassExtension->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL];
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! IRP_MJ_INTERNAL_DEVICE_CONTROL patched");
// Mark detour as completed.
deviceContext->IsHidIoDetourCompleted = TRUE;
deviceContext->HidIoTarget = WdfDeviceGetIoTarget(Device);
cleanup:
if (hidTransportWdmDeviceObject != NULL) {
ObDereferenceObject(hidTransportWdmDeviceObject);
}
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", status);
return status;
}
================================================
FILE: src/AmtPtpHidFilter/Device.c
================================================
// Device.c: Device-specific D0<->D3 handler and other misc procedures
#include
#include "Device.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, PtpFilterCreateDevice)
#endif
NTSTATUS
PtpFilterCreateDevice(
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
WDF_OBJECT_ATTRIBUTES deviceAttributes;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_TIMER_CONFIG timerConfig;
WDF_WORKITEM_CONFIG workitemConfig;
WDFDEVICE device;
PDEVICE_CONTEXT deviceContext;
NTSTATUS status;
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
// Initialize Power Callback
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = PtpFilterPrepareHardware;
pnpPowerCallbacks.EvtDeviceD0Entry = PtpFilterDeviceD0Entry;
pnpPowerCallbacks.EvtDeviceD0Exit = PtpFilterDeviceD0Exit;
pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = PtpFilterSelfManagedIoInit;
pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = PtpFilterSelfManagedIoRestart;
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)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "WdfDeviceCreate failed: %!STATUS!", status);
goto exit;
}
// Initialize context and interface
deviceContext = PtpFilterGetContext(device);
deviceContext->Device = device;
deviceContext->WdmDeviceObject = WdfDeviceWdmGetDeviceObject(device);
if (deviceContext->WdmDeviceObject == NULL) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "WdfDeviceWdmGetDeviceObject failed");
goto exit;
}
status = WdfDeviceCreateDeviceInterface(device,&GUID_DEVICEINTERFACE_AmtPtpHidFilter, NULL);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "WdfDeviceCreateDeviceInterface failed: %!STATUS!", status);
goto exit;
}
// Initialize read buffer
status = WdfLookasideListCreate(WDF_NO_OBJECT_ATTRIBUTES, REPORT_BUFFER_SIZE,
NonPagedPoolNx, WDF_NO_OBJECT_ATTRIBUTES, PTP_LIST_POOL_TAG,
&deviceContext->HidReadBufferLookaside
);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "WdfLookasideListCreate failed: %!STATUS!", status);
}
// Initialize HID recovery timer
WDF_TIMER_CONFIG_INIT(&timerConfig, PtpFilterRecoveryTimerCallback);
timerConfig.AutomaticSerialization = TRUE;
WDF_OBJECT_ATTRIBUTES_INIT(&deviceAttributes);
deviceAttributes.ParentObject = device;
deviceAttributes.ExecutionLevel = WdfExecutionLevelPassive;
status = WdfTimerCreate(&timerConfig, &deviceAttributes, &deviceContext->HidTransportRecoveryTimer);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "WdfTimerCreate failed: %!STATUS!", status);
}
// Initialize HID recovery workitem
WDF_WORKITEM_CONFIG_INIT(&workitemConfig, PtpFilterWorkItemCallback);
WDF_OBJECT_ATTRIBUTES_INIT(&deviceAttributes);
deviceAttributes.ParentObject = device;
status = WdfWorkItemCreate(&workitemConfig, &deviceAttributes, &deviceContext->HidTransportRecoveryWorkItem);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "HidTransportRecoveryWorkItem failed: %!STATUS!", status);
}
// Set initial state
deviceContext->VendorID = 0;
deviceContext->ProductID = 0;
deviceContext->VersionNumber = 0;
deviceContext->DeviceConfigured = FALSE;
// Initialize IO queue
status = PtpFilterIoQueueInitialize(device);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "PtpFilterIoQueueInitialize failed: %!STATUS!", status);
}
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", status);
return status;
}
NTSTATUS
PtpFilterPrepareHardware(
_In_ WDFDEVICE Device,
_In_ WDFCMRESLIST ResourceList,
_In_ WDFCMRESLIST ResourceListTranslated
)
{
PDEVICE_CONTEXT deviceContext;
NTSTATUS status = STATUS_SUCCESS;
// We don't need to retrieve resources since this works as a filter now
UNREFERENCED_PARAMETER(ResourceList);
UNREFERENCED_PARAMETER(ResourceListTranslated);
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
// Initialize IDs, set to zero
deviceContext->VendorID = 0;
deviceContext->ProductID = 0;
deviceContext->VersionNumber = 0;
deviceContext->DeviceConfigured = FALSE;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", status);
return status;
}
NTSTATUS
PtpFilterDeviceD0Entry(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE PreviousState
)
{
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
UNREFERENCED_PARAMETER(Device);
UNREFERENCED_PARAMETER(PreviousState);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", status);
return status;
}
NTSTATUS
PtpFilterDeviceD0Exit(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE TargetState
)
{
PDEVICE_CONTEXT deviceContext;
NTSTATUS status = STATUS_SUCCESS;
WDFREQUEST outstandingRequest;
UNREFERENCED_PARAMETER(TargetState);
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
// Reset device state
deviceContext->DeviceConfigured = FALSE;
// Cancelling all outstanding requests
while (NT_SUCCESS(status)) {
status = WdfIoQueueRetrieveNextRequest(
deviceContext->HidReadQueue,
&outstandingRequest
);
if (NT_SUCCESS(status)) {
WdfRequestComplete(outstandingRequest, STATUS_CANCELLED);
}
}
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", STATUS_SUCCESS);
return STATUS_SUCCESS;
}
NTSTATUS
PtpFilterSelfManagedIoInit(
_In_ WDFDEVICE Device
)
{
NTSTATUS status;
PDEVICE_CONTEXT deviceContext;
WDF_MEMORY_DESCRIPTOR hidAttributeMemoryDescriptor;
HID_DEVICE_ATTRIBUTES deviceAttributes;
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
status = PtpFilterDetourWindowsHIDStack(Device);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! PtpFilterDetourWindowsHIDStack failed, Status = %!STATUS!", status);
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(
deviceContext->HidIoTarget, NULL,
IOCTL_HID_GET_DEVICE_ATTRIBUTES,
NULL, &hidAttributeMemoryDescriptor, NULL, NULL);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfIoTargetSendInternalIoctlSynchronously failed, Status = %!STATUS!", status);
goto exit;
}
deviceContext->VendorID = deviceAttributes.VendorID;
deviceContext->ProductID = deviceAttributes.ProductID;
deviceContext->VersionNumber = deviceAttributes.VersionNumber;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Device %x:%x, Version 0x%x", deviceContext->VendorID,
deviceContext->ProductID, deviceContext->VersionNumber);
status = PtpFilterConfigureMultiTouch(Device);
if (!NT_SUCCESS(status)) {
// If this failed, we will retry after 2 seconds (and pretend nothing happens)
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! PtpFilterConfigureMultiTouch failed, Status = %!STATUS!", status);
status = STATUS_SUCCESS;
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(2));
goto exit;
}
// Stamp last query performance counter
KeQueryPerformanceCounter(&deviceContext->LastReportTime);
// Set device state
deviceContext->DeviceConfigured = TRUE;
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", status);
return status;
}
NTSTATUS
PtpFilterSelfManagedIoRestart(
_In_ WDFDEVICE Device
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
// If this is first D0, it will be done in self-managed IO init.
if (deviceContext->IsHidIoDetourCompleted) {
status = PtpFilterConfigureMultiTouch(Device);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! PtpFilterConfigureMultiTouch failed, Status = %!STATUS!", status);
// If this failed, we will retry after 2 seconds (and pretend nothing happens)
status = STATUS_SUCCESS;
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(2));
goto exit;
}
}
else {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! HID detour should already complete here");
status = STATUS_INVALID_STATE_TRANSITION;
}
// Stamp last query performance counter
KeQueryPerformanceCounter(&deviceContext->LastReportTime);
// Set device state
deviceContext->DeviceConfigured = TRUE;
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", status);
return status;
}
NTSTATUS
PtpFilterConfigureMultiTouch(
_In_ WDFDEVICE Device
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
UCHAR hidPacketBuffer[HID_XFER_PACKET_SIZE];
PHID_XFER_PACKET pHidPacket;
WDFMEMORY hidMemory;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_REQUEST_SEND_OPTIONS configRequestSendOptions;
WDFREQUEST configRequest;
PIRP pConfigIrp = NULL;
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
// Check if this device is supported for configuration.
// So far in this prototype, we support Magic Trackpad 2 in USB (05AC:0265) or Bluetooth mode (004c:0265)
if (deviceContext->VendorID != HID_VID_APPLE_USB && deviceContext->VendorID != HID_VID_APPLE_BT) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! Vendor not supported: 0x%x", deviceContext->VendorID);
status = STATUS_NOT_SUPPORTED;
goto exit;
}
if (deviceContext->ProductID != HID_PID_MAGIC_TRACKPAD_2) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! Product not supported: 0x%x", deviceContext->ProductID);
status = STATUS_NOT_SUPPORTED;
goto exit;
}
RtlZeroMemory(hidPacketBuffer, sizeof(hidPacketBuffer));
pHidPacket = (PHID_XFER_PACKET) &hidPacketBuffer;
if (deviceContext->VendorID == HID_VID_APPLE_USB) {
deviceContext->InputFingerSize = FSIZE_TYPE5;
deviceContext->InputHeaderSize = HOFFSET_TYPE_USB_5;
deviceContext->InputFingerDelta = FDELTA_TYPE5;
deviceContext->InputButtonDelta = BOFFSET_TYPE5;
deviceContext->X.snratio = 250;
deviceContext->X.min = -3678;
deviceContext->X.max = 3934;
deviceContext->Y.snratio = 250;
deviceContext->Y.min = -2479;
deviceContext->Y.max = 2586;
pHidPacket->reportId = 0x02;
pHidPacket->reportBufferLen = 0x04;
pHidPacket->reportBuffer = (PUCHAR)pHidPacket + sizeof(HID_XFER_PACKET);
pHidPacket->reportBuffer[0] = 0x02;
pHidPacket->reportBuffer[1] = 0x01;
pHidPacket->reportBuffer[2] = 0x00;
pHidPacket->reportBuffer[3] = 0x00;
}
else if (deviceContext->VendorID == HID_VID_APPLE_BT) {
deviceContext->InputFingerSize = FSIZE_TYPE5;
deviceContext->InputHeaderSize = HOFFSET_TYPE_BTH_5;
deviceContext->InputFingerDelta = FDELTA_TYPE5;
deviceContext->InputButtonDelta = BOFFSET_TYPE5;
deviceContext->X.snratio = 250;
deviceContext->X.min = -3678;
deviceContext->X.max = 3934;
deviceContext->Y.snratio = 250;
deviceContext->Y.min = -2479;
deviceContext->Y.max = 2586;
pHidPacket->reportId = 0xF1;
pHidPacket->reportBufferLen = 0x03;
pHidPacket->reportBuffer = (PUCHAR)pHidPacket + sizeof(HID_XFER_PACKET);
pHidPacket->reportBuffer[0] = 0xF1;
pHidPacket->reportBuffer[1] = 0x02;
pHidPacket->reportBuffer[2] = 0x01;
}
else {
// Something we don't support yet.
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! Unrecognized device detected");
status = STATUS_NOT_SUPPORTED;
goto exit;
}
// Init a request entity.
// Because we bypassed HIDCLASS driver, there's a few things that we need to manually take care of.
status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, deviceContext->HidIoTarget, &configRequest);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfRequestCreate failed, Status = %!STATUS!", status);
goto exit;
}
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.ParentObject = configRequest;
status = WdfMemoryCreatePreallocated(&attributes, (PVOID) pHidPacket, HID_XFER_PACKET_SIZE, &hidMemory);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfMemoryCreatePreallocated failed, Status = %!STATUS!", status);
goto cleanup;
}
status = WdfIoTargetFormatRequestForInternalIoctl(deviceContext->HidIoTarget,
configRequest, IOCTL_HID_SET_FEATURE,
hidMemory, NULL, NULL, NULL);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfIoTargetFormatRequestForInternalIoctl failed, Status = %!STATUS!", status);
goto cleanup;
}
// Manually take care of IRP to meet requirements of mini drivers.
pConfigIrp = WdfRequestWdmGetIrp(configRequest);
if (pConfigIrp == NULL) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfRequestWdmGetIrp failed");
status = STATUS_UNSUCCESSFUL;
goto cleanup;
}
// God-damn-it we have to configure it by ourselves :)
pConfigIrp->UserBuffer = pHidPacket;
WDF_REQUEST_SEND_OPTIONS_INIT(&configRequestSendOptions, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);
if (WdfRequestSend(configRequest, deviceContext->HidIoTarget, &configRequestSendOptions) == FALSE) {
status = WdfRequestGetStatus(configRequest);
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfRequestSend failed, Status = %!STATUS!", status);
goto cleanup;
} else {
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Changed trackpad status to multitouch mode");
status = STATUS_SUCCESS;
}
cleanup:
if (configRequest != NULL) {
WdfObjectDelete(configRequest);
}
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", status);
return status;
}
VOID
PtpFilterRecoveryTimerCallback(
WDFTIMER Timer
)
{
WDFDEVICE device;
PDEVICE_CONTEXT deviceContext;
NTSTATUS status;
device = WdfTimerGetParentObject(Timer);
deviceContext = PtpFilterGetContext(device);
// We will try to reinitialize the device
status = PtpFilterSelfManagedIoRestart(device);
if (NT_SUCCESS(status)) {
// If succeeded, proceed to reissue the request.
// Otherwise it will retry the process after a few seconds.
PtpFilterInputIssueTransportRequest(device);
}
}
================================================
FILE: src/AmtPtpHidFilter/Diagnostics.c
================================================
// Diagnostics.c: Debug and diagnostics facilities
#include
#include "Diagnostics.tmh"
VOID PtpFilterDiagnosticsInitializeContinuousRead(
_In_ WDFDEVICE Device
)
{
NTSTATUS status = STATUS_SUCCESS;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Entry");
// Issue a request to underlying HID target. Then start to have a continus stream reading it
PtpFilterDiagnosticsInputIssueRequest(Device);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "%!FUNC! Exit, Status = %!STATUS!", status);
}
VOID
PtpFilterDiagnosticsInputIssueRequest(
_In_ WDFDEVICE Device
)
{
NTSTATUS status;
PDEVICE_CONTEXT deviceContext;
WDF_OBJECT_ATTRIBUTES attributes;
BOOLEAN requestStatus = FALSE;
WDFREQUEST hidReadRequest;
WDFMEMORY hidReadOutputMemory;
PWORKER_REQUEST_CONTEXT requestContext;
deviceContext = PtpFilterGetContext(Device);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WORKER_REQUEST_CONTEXT);
attributes.ParentObject = Device;
status = WdfRequestCreate(&attributes, deviceContext->HidIoTarget, &hidReadRequest);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfRequestCreate fails, status = %!STATUS!",status);
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_US(200));
return;
}
status = WdfMemoryCreateFromLookaside(deviceContext->HidReadBufferLookaside, &hidReadOutputMemory);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfMemoryCreateFromLookaside fails, status = %!STATUS!", status);
WdfObjectDelete(hidReadRequest);
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_US(200));
return;
}
// Assign context information
requestContext = WorkerRequestGetContext(hidReadRequest);
requestContext->DeviceContext = deviceContext;
requestContext->RequestMemory = hidReadOutputMemory;
// Invoke HID read request to the device.
status = WdfIoTargetFormatRequestForInternalIoctl(deviceContext->HidIoTarget, hidReadRequest,
IOCTL_HID_READ_REPORT, NULL, 0, hidReadOutputMemory, 0);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfIoTargetFormatRequestForInternalIoctl fails, status = %!STATUS!", status);
if (hidReadOutputMemory != NULL) {
WdfObjectDelete(hidReadOutputMemory);
}
if (hidReadRequest != NULL) {
WdfObjectDelete(hidReadRequest);
}
return;
}
WdfRequestSetCompletionRoutine(
hidReadRequest,
PtpFilterDiagnosticsRequestCompletionRoutine,
requestContext
);
requestStatus = WdfRequestSend(
hidReadRequest,
deviceContext->HidIoTarget,
NULL
);
if (!requestStatus)
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! AmtPtpSpiInputRoutineWorker request failed to sent");
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_US(50));
if (hidReadOutputMemory != NULL) {
WdfObjectDelete(hidReadOutputMemory);
}
if (hidReadRequest != NULL) {
WdfObjectDelete(hidReadRequest);
}
}
}
VOID
PtpFilterDiagnosticsRequestCompletionRoutine(
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS Params,
_In_ WDFCONTEXT Context
)
{
PWORKER_REQUEST_CONTEXT requestContext;
PDEVICE_CONTEXT deviceContext;
LONG responseLength;
UNREFERENCED_PARAMETER(Request);
UNREFERENCED_PARAMETER(Target);
UNREFERENCED_PARAMETER(Params);
requestContext = (PWORKER_REQUEST_CONTEXT)Context;
deviceContext = requestContext->DeviceContext;
// Decode request
responseLength = (LONG) WdfRequestGetInformation(Request);
if (responseLength > 0) {
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_INPUT, "Request received with size %d", responseLength);
}
// Cleanup
WdfObjectDelete(Request);
if (requestContext->RequestMemory != NULL) {
WdfObjectDelete(requestContext->RequestMemory);
}
// Issue next request
PtpFilterDiagnosticsInputIssueRequest(requestContext->DeviceContext->Device);
}
PCHAR
PtpFilterDiagnosticsIoControlGetString(
_In_ ULONG IoControlCode
)
{
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
return "IOCTL_HID_GET_DEVICE_DESCRIPTOR";
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
return "IOCTL_HID_GET_DEVICE_ATTRIBUTES";
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
return "IOCTL_HID_GET_REPORT_DESCRIPTOR";
case IOCTL_HID_GET_STRING:
return "IOCTL_HID_GET_STRING";
case IOCTL_HID_READ_REPORT:
return "IOCTL_HID_READ_REPORT";
case IOCTL_HID_WRITE_REPORT:
return "IOCTL_HID_WRITE_REPORT";
case IOCTL_UMDF_HID_GET_INPUT_REPORT:
return "IOCTL_UMDF_HID_GET_INPUT_REPORT";
case IOCTL_UMDF_HID_SET_OUTPUT_REPORT:
return "IOCTL_UMDF_HID_SET_OUTPUT_REPORT";
case IOCTL_UMDF_HID_GET_FEATURE:
return "IOCTL_UMDF_HID_GET_FEATURE";
case IOCTL_UMDF_HID_SET_FEATURE:
return "IOCTL_UMDF_HID_SET_FEATURE";
case IOCTL_HID_ACTIVATE_DEVICE:
return "IOCTL_HID_ACTIVATE_DEVICE";
case IOCTL_HID_DEACTIVATE_DEVICE:
return "IOCTL_HID_DEACTIVATE_DEVICE";
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST";
case IOCTL_HID_GET_FEATURE:
return "IOCTL_HID_GET_FEATURE";
case IOCTL_HID_SET_FEATURE:
return "IOCTL_HID_SET_FEATURE";
default:
return "IOCTL_UNKNOWN";
}
}
================================================
FILE: src/AmtPtpHidFilter/Driver.c
================================================
// Driver.c: Common entry point and WPP trace filter handler
#include
#include "Driver.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, PtpFilterEvtDeviceAdd)
#pragma alloc_text (PAGE, PtpFilterEvtDriverContextCleanup)
#endif
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
WDF_DRIVER_CONFIG config;
WDF_OBJECT_ATTRIBUTES attributes;
PAGED_CODE();
// Initialize WPP
WPP_INIT_TRACING(DriverObject, RegistryPath);
// Register a cleanup callback
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.EvtCleanupCallback = PtpFilterEvtDriverContextCleanup;
// Register WDF driver
WDF_DRIVER_CONFIG_INIT(&config, PtpFilterEvtDeviceAdd);
status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, WDF_NO_HANDLE);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
WPP_CLEANUP(DriverObject);
return status;
}
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Driver Initialized");
return STATUS_SUCCESS;
}
NTSTATUS
PtpFilterEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
NTSTATUS status;
UNREFERENCED_PARAMETER(Driver);
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
// We do not own power control.
// In addition we do not own every I/O request.
WdfFdoInitSetFilter(DeviceInit);
// Create the device.
status = PtpFilterCreateDevice(DeviceInit);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
return status;
}
VOID
PtpFilterEvtDriverContextCleanup(
_In_ WDFOBJECT DriverObject
)
{
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Cleanup");
//
// Stop WPP Tracing
//
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
}
================================================
FILE: src/AmtPtpHidFilter/Hid.c
================================================
// Hid.c: HID specific routines
#include
#include "Hid.tmh"
NTSTATUS
PtpFilterGetHidDescriptor(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
size_t hidDescriptorSize = 0;
WDFMEMORY requestMemory;
PHID_DESCRIPTOR pSelectedHidDescriptor = NULL;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
status = WdfRequestRetrieveOutputMemory(Request, &requestMemory);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_HID, "%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!", status);
goto exit;
}
switch (deviceContext->ProductID) {
case HID_PID_MAGIC_TRACKPAD_2:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Request HID Report Descriptor for Apple Magic Trackpad 2 Family");
hidDescriptorSize = PtpDefaultHidDescriptorMagicTrackpad2.bLength;
pSelectedHidDescriptor = &PtpDefaultHidDescriptorMagicTrackpad2;
break;
}
}
if (pSelectedHidDescriptor != NULL && hidDescriptorSize > 0) {
status = WdfMemoryCopyFromBuffer(requestMemory, 0, (PVOID)pSelectedHidDescriptor, hidDescriptorSize);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_HID, "%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!", status);
goto exit;
}
WdfRequestSetInformation(Request, hidDescriptorSize);
}
else {
TraceEvents(TRACE_LEVEL_WARNING, TRACE_HID, "%!FUNC! Device HID registry is not found");
status = STATUS_NOT_SUPPORTED;
goto exit;
}
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Exit");
return status;
}
NTSTATUS
PtpFilterGetDeviceAttribs(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
PHID_DEVICE_ATTRIBUTES pDeviceAttributes = NULL;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
status = WdfRequestRetrieveOutputBuffer(Request, sizeof(HID_DEVICE_ATTRIBUTES), &pDeviceAttributes, NULL);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_HID, "%!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->ProductID = deviceContext->ProductID;
pDeviceAttributes->VendorID = DEVICE_VID;
pDeviceAttributes->VersionNumber = DEVICE_VERSION;
WdfRequestSetInformation(Request, sizeof(HID_DEVICE_ATTRIBUTES));
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Exit");
return status;
}
NTSTATUS
PtpFilterGetReportDescriptor(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
size_t hidDescriptorSize = 0;
WDFMEMORY requestMemory;
PHID_REPORT_DESCRIPTOR selectedHidDescriptor = NULL;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
status = WdfRequestRetrieveOutputMemory(Request, &requestMemory);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_HID, "%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!", status);
goto exit;
}
switch (deviceContext->ProductID) {
case HID_PID_MAGIC_TRACKPAD_2:
{
hidDescriptorSize = PtpDefaultHidDescriptorMagicTrackpad2.DescriptorList[0].wReportLength;
selectedHidDescriptor = PtpReportDescriptorMagicTrackpad2;
break;
}
}
if (selectedHidDescriptor != NULL && hidDescriptorSize > 0) {
status = WdfMemoryCopyFromBuffer(requestMemory, 0, (PVOID)selectedHidDescriptor, hidDescriptorSize);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_HID, "%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!", status);
goto exit;
}
WdfRequestSetInformation(Request, hidDescriptorSize);
}
else {
TraceEvents(TRACE_LEVEL_WARNING, TRACE_HID, "%!FUNC! Device HID registry is not found");
status = STATUS_NOT_SUPPORTED;
goto exit;
}
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Exit");
return status;
}
NTSTATUS
PtpFilterGetStrings(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_Out_ BOOLEAN* Pending
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
BOOLEAN requestSent;
WDF_REQUEST_SEND_OPTIONS sendOptions;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(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);
// This IOCTL is METHOD_NEITHER, so we just send it without IRP modification
requestSent = WdfRequestSend(Request, deviceContext->HidIoTarget, &sendOptions);
*Pending = TRUE;
if (!requestSent)
{
status = WdfRequestGetStatus(Request);
*Pending = FALSE;
}
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Exit");
return status;
}
NTSTATUS
PtpFilterGetHidFeatures(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
WDF_REQUEST_PARAMETERS requestParameters;
size_t reportSize;
PHID_XFER_PACKET hidContent;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(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;
}
hidContent = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer;
if (hidContent == NULL)
{
status = STATUS_INVALID_DEVICE_REQUEST;
goto exit;
}
switch (hidContent->reportId)
{
case REPORTID_DEVICE_CAPS:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_DEVICE_CAPS is requested");
// Size sanity check
reportSize = sizeof(PTP_DEVICE_CAPS_FEATURE_REPORT);
if (hidContent->reportBufferLen < reportSize) {
status = STATUS_INVALID_BUFFER_SIZE;
TraceEvents(TRACE_LEVEL_ERROR, TRACE_HID, "%!FUNC! Report buffer is too small");
goto exit;
}
PPTP_DEVICE_CAPS_FEATURE_REPORT capsReport = (PPTP_DEVICE_CAPS_FEATURE_REPORT)hidContent->reportBuffer;
capsReport->MaximumContactPoints = PTP_MAX_CONTACT_POINTS;
capsReport->ButtonType = PTP_BUTTON_TYPE_CLICK_PAD;
capsReport->ReportID = REPORTID_DEVICE_CAPS;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_DEVICE_CAPS has maximum contact points of %d", capsReport->MaximumContactPoints);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_DEVICE_CAPS has touchpad type %d", capsReport->ButtonType);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_DEVICE_CAPS is fulfilled");
break;
}
case REPORTID_PTPHQA:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_PTPHQA is requested");
// Size sanity check
reportSize = sizeof(PTP_DEVICE_HQA_CERTIFICATION_REPORT);
if (hidContent->reportBufferLen < reportSize)
{
status = STATUS_INVALID_BUFFER_SIZE;
TraceEvents(TRACE_LEVEL_ERROR, TRACE_HID, "%!FUNC! Report buffer is too small.");
goto exit;
}
PPTP_DEVICE_HQA_CERTIFICATION_REPORT certReport = (PPTP_DEVICE_HQA_CERTIFICATION_REPORT)hidContent->reportBuffer;
*certReport->CertificationBlob = DEFAULT_PTP_HQA_BLOB;
certReport->ReportID = REPORTID_PTPHQA;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_PTPHQA is fulfilled");
break;
}
default:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Unsupported type %d is requested", hidContent->reportId);
status = STATUS_NOT_SUPPORTED;
goto exit;
}
}
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Exit");
return status;
}
NTSTATUS
PtpFilterSetHidFeatures(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT deviceContext;
PHID_XFER_PACKET hidPacket;
WDF_REQUEST_PARAMETERS requestParameters;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(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;
}
hidPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer;
if (hidPacket == NULL)
{
status = STATUS_INVALID_DEVICE_REQUEST;
goto exit;
}
switch (hidPacket->reportId)
{
case REPORTID_REPORTMODE:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_REPORTMODE is requested");
PPTP_DEVICE_INPUT_MODE_REPORT DeviceInputMode = (PPTP_DEVICE_INPUT_MODE_REPORT)hidPacket->reportBuffer;
switch (DeviceInputMode->Mode)
{
case PTP_COLLECTION_MOUSE:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_REPORTMODE requested Mouse Input");
deviceContext->PtpInputOn = FALSE;
break;
}
case PTP_COLLECTION_WINDOWS:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_REPORTMODE requested Windows PTP Input");
deviceContext->PtpInputOn = TRUE;
break;
}
}
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_REPORTMODE is fulfilled");
break;
}
case REPORTID_FUNCSWITCH:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_FUNCSWITCH is requested");
PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT InputSelection = (PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT)hidPacket->reportBuffer;
deviceContext->PtpReportButton = InputSelection->ButtonReport;
deviceContext->PtpReportTouch = InputSelection->SurfaceReport;
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_FUNCSWITCH requested Button = %d, Surface = %d",
InputSelection->ButtonReport, InputSelection->SurfaceReport);
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Report REPORTID_FUNCSWITCH is fulfilled");
break;
}
default:
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Unsupported type %d is requested", hidPacket->reportId);
status = STATUS_NOT_SUPPORTED;
goto exit;
}
}
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_HID, "%!FUNC! Exit");
return status;
}
================================================
FILE: src/AmtPtpHidFilter/Input.c
================================================
// Input.c: Input handler routines
#include
#include "Input.tmh"
VOID
PtpFilterInputProcessRequest(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
)
{
NTSTATUS status;
PDEVICE_CONTEXT deviceContext;
deviceContext = PtpFilterGetContext(Device);
status = WdfRequestForwardToIoQueue(Request, deviceContext->HidReadQueue);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! WdfRequestForwardToIoQueue fails, status = %!STATUS!", status);
WdfRequestComplete(Request, status);
return;
}
// Only issue request when fully configured.
// Otherwise we will let power recovery process to triage it
if (deviceContext->DeviceConfigured == TRUE) {
PtpFilterInputIssueTransportRequest(Device);
}
}
VOID
PtpFilterWorkItemCallback(
_In_ WDFWORKITEM WorkItem
)
{
WDFDEVICE Device = WdfWorkItemGetParentObject(WorkItem);
PtpFilterInputIssueTransportRequest(Device);
}
VOID
PtpFilterInputIssueTransportRequest(
_In_ WDFDEVICE Device
)
{
NTSTATUS status;
PDEVICE_CONTEXT deviceContext;
WDF_OBJECT_ATTRIBUTES attributes;
WDFREQUEST hidReadRequest;
WDFMEMORY hidReadOutputMemory;
PWORKER_REQUEST_CONTEXT requestContext;
BOOLEAN requestStatus = FALSE;
deviceContext = PtpFilterGetContext(Device);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, WORKER_REQUEST_CONTEXT);
attributes.ParentObject = Device;
status = WdfRequestCreate(&attributes, deviceContext->HidIoTarget, &hidReadRequest);
if (!NT_SUCCESS(status)) {
// This can fail for Bluetooth devices. We will set up a 3 second timer for retry triage.
// Typically this should not fail for USB transport.
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfRequestCreate fails, status = %!STATUS!", status);
deviceContext->DeviceConfigured = FALSE;
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(3));
return;
}
status = WdfMemoryCreateFromLookaside(deviceContext->HidReadBufferLookaside, &hidReadOutputMemory);
if (!NT_SUCCESS(status)) {
// tbh if you fail here, something seriously went wrong...request a restart.
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfMemoryCreateFromLookaside fails, status = %!STATUS!", status);
WdfObjectDelete(hidReadRequest);
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedAttemptRestart);
return;
}
// Assign context information
// And format HID read request.
requestContext = WorkerRequestGetContext(hidReadRequest);
requestContext->DeviceContext = deviceContext;
requestContext->RequestMemory = hidReadOutputMemory;
status = WdfIoTargetFormatRequestForInternalIoctl(deviceContext->HidIoTarget, hidReadRequest,
IOCTL_HID_READ_REPORT, NULL, 0, hidReadOutputMemory, 0);
if (!NT_SUCCESS(status)) {
// tbh if you fail here, something seriously went wrong...request a restart.
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! WdfIoTargetFormatRequestForInternalIoctl fails, status = %!STATUS!", status);
if (hidReadOutputMemory != NULL) {
WdfObjectDelete(hidReadOutputMemory);
}
if (hidReadRequest != NULL) {
WdfObjectDelete(hidReadRequest);
}
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedAttemptRestart);
return;
}
// Set callback
WdfRequestSetCompletionRoutine(hidReadRequest, PtpFilterInputRequestCompletionCallback, requestContext);
requestStatus = WdfRequestSend(hidReadRequest, deviceContext->HidIoTarget, NULL);
if (!requestStatus) {
// Retry after 3 seconds, in case this is a transportation issue.
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! PtpFilterInputIssueTransportRequest request failed to sent");
deviceContext->DeviceConfigured = FALSE;
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(3));
if (hidReadOutputMemory != NULL) {
WdfObjectDelete(hidReadOutputMemory);
}
if (hidReadRequest != NULL) {
WdfObjectDelete(hidReadRequest);
}
}
}
VOID
PtpFilterInputRequestCompletionCallback(
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS Params,
_In_ WDFCONTEXT Context
)
{
PWORKER_REQUEST_CONTEXT requestContext;
PDEVICE_CONTEXT deviceContext;
NTSTATUS status;
WDFREQUEST ptpRequest;
PTP_REPORT ptpOutputReport;
WDFMEMORY ptpRequestMemory;
size_t responseLength;
PUCHAR responseBuffer;
LARGE_INTEGER currentTSC;
LONGLONG tSCDelta;
const TRACKPAD_FINGER* f;
const TRACKPAD_FINGER_TYPE5* f_type5;
size_t raw_n, headerSize, fingerprintSize = 0;
INT x, y = 0;
UNREFERENCED_PARAMETER(Target);
requestContext = (PWORKER_REQUEST_CONTEXT)Context;
deviceContext = requestContext->DeviceContext;
responseLength = (size_t)(LONG)WdfRequestGetInformation(Request);
responseBuffer = WdfMemoryGetBuffer(Params->Parameters.Ioctl.Output.Buffer, NULL);
headerSize = deviceContext->InputHeaderSize;
fingerprintSize = deviceContext->InputFingerSize;
// Pre-flight check 0: Right now we only have Magic Trackpad 2 (BT and USB)
if (deviceContext->VendorID != HID_VID_APPLE_USB && deviceContext->VendorID != HID_VID_APPLE_BT) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! Unsupported device entered this routine");
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedNoRestart);
goto cleanup;
}
// Pre-flight check 1: if size is 0, this is not something we need. Ignore the read, and issue next request.
if (responseLength <= 0) {
WdfWorkItemEnqueue(requestContext->DeviceContext->HidTransportRecoveryWorkItem);
goto cleanup;
}
// Pre-flight check 2: the response size should be sane
if (responseLength < deviceContext->InputHeaderSize || (responseLength - deviceContext->InputHeaderSize) % deviceContext->InputFingerSize != 0) {
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_INPUT, "%!FUNC! Malformed input received. Length = %llu. Attempt to reconfigure the device.", responseLength);
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(3));
goto cleanup;
}
// Read report and fulfill PTP request. If no report is found, just exit.
status = WdfIoQueueRetrieveNextRequest(deviceContext->HidReadQueue, &ptpRequest);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! WdfIoQueueRetrieveNextRequest failed with %!STATUS!", status);
goto cleanup;
}
// Report header
ptpOutputReport.ReportID = REPORTID_MULTITOUCH;
ptpOutputReport.IsButtonClicked = 0;
// Capture current timestamp and get input delta in 100us unit
KeQueryPerformanceCounter(¤tTSC);
tSCDelta = (currentTSC.QuadPart - deviceContext->LastReportTime.QuadPart) / 100;
ptpOutputReport.ScanTime = (tSCDelta >= 0xFF) ? 0xFF : (USHORT)tSCDelta;
deviceContext->LastReportTime.QuadPart = currentTSC.QuadPart;
// Report required content
// Touch
raw_n = (responseLength - headerSize) / fingerprintSize;
if (raw_n >= PTP_MAX_CONTACT_POINTS) raw_n = PTP_MAX_CONTACT_POINTS;
ptpOutputReport.ContactCount = (UCHAR) raw_n;
for (size_t i = 0; i < raw_n; i++) {
PUCHAR f_base = responseBuffer + headerSize + deviceContext->InputFingerDelta;
f = (const TRACKPAD_FINGER*)(f_base + i * fingerprintSize);
f_type5 = (const TRACKPAD_FINGER_TYPE5*)f;
USHORT tmp_x = (*((USHORT*)f_type5)) & 0x1fff;
unsigned int tmp_y = (INT)(*((unsigned int*) f_type5));
x = (SHORT)(tmp_x << 3) >> 3;
y = -(INT)(tmp_y << 6) >> 19;
x = (x - deviceContext->X.min) > 0 ? (x - deviceContext->X.min) : 0;
y = (y - deviceContext->Y.min) > 0 ? (y - deviceContext->Y.min) : 0;
ptpOutputReport.Contacts[i].ContactID = f_type5->OrientationAndOrigin.ContactIdentifier.Id;
ptpOutputReport.Contacts[i].X = (USHORT)x;
ptpOutputReport.Contacts[i].Y = (USHORT)y;
ptpOutputReport.Contacts[i].TipSwitch = ((signed short) (f_type5->TouchMajor) << 1) > 0;
// The Microsoft spec says reject any input larger than 25mm. This is not ideal
// for Magic Trackpad 2 - so we raised the threshold a bit higher.
// Or maybe I used the wrong unit? IDK
ptpOutputReport.Contacts[i].Confidence = ((signed short) (f_type5->TouchMinor) << 1) < 345 && ((signed short) (f_type5->TouchMinor) << 1) < 345;
}
// Button
if ((responseBuffer[deviceContext->InputButtonDelta] & 1) != 0) {
ptpOutputReport.IsButtonClicked = TRUE;
}
status = WdfRequestRetrieveOutputMemory(ptpRequest, &ptpRequestMemory);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!", status);
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedAttemptRestart);
goto cleanup;
}
status = WdfMemoryCopyFromBuffer(ptpRequestMemory, 0, (PVOID) &ptpOutputReport, sizeof(PTP_REPORT));
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!", status);
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedAttemptRestart);
goto cleanup;
}
WdfRequestSetInformation(ptpRequest, sizeof(PTP_REPORT));
WdfRequestComplete(ptpRequest, status);
cleanup:
// Cleanup
WdfObjectDelete(Request);
if (requestContext->RequestMemory != NULL) {
WdfObjectDelete(requestContext->RequestMemory);
}
// We don't issue new request here (unless it's a spurious request - which is handled earlier) to
// keep the request pipe go through one-way.
}
================================================
FILE: src/AmtPtpHidFilter/Queue.c
================================================
// Queue.c: IO-queue related operations
#include
#include "Queue.tmh"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, PtpFilterIoQueueInitialize)
#endif
NTSTATUS
PtpFilterIoQueueInitialize(
_In_ WDFDEVICE Device
)
{
WDFQUEUE queue;
WDF_IO_QUEUE_CONFIG queueConfig;
WDF_OBJECT_ATTRIBUTES queueAttributes;
PDEVICE_CONTEXT deviceContext;
PQUEUE_CONTEXT queueContext;
NTSTATUS status;
PAGED_CODE();
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
deviceContext = PtpFilterGetContext(Device);
// First queue for system-wide HID controls
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_CONTEXT);
queueConfig.EvtIoInternalDeviceControl = FilterEvtIoIntDeviceControl;
queueConfig.EvtIoStop = FilterEvtIoStop;
status = WdfIoQueueCreate(Device, &queueConfig, &queueAttributes, &queue);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "%!FUNC! WdfIoQueueCreate failed %!STATUS!", status);
goto exit;
}
queueContext = PtpFilterQueueGetContext(queue);
queueContext->Device = deviceContext->Device;
queueContext->DeviceIoTarget = deviceContext->HidIoTarget;
// Second queue for HID read requests
WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual);
queueConfig.PowerManaged = WdfFalse;
status = WdfIoQueueCreate(Device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceContext->HidReadQueue);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "%!FUNC! WdfIoQueueCreate (Input) failed %!STATUS!", status);
}
exit:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit, Status = %!STATUS!", status);
return status;
}
VOID
FilterEvtIoIntDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
{
PQUEUE_CONTEXT queueContext;
PDEVICE_CONTEXT deviceContext;
BOOLEAN requestPending = FALSE;
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNREFERENCED_PARAMETER(InputBufferLength);
UNREFERENCED_PARAMETER(OutputBufferLength);
queueContext = PtpFilterQueueGetContext(Queue);
deviceContext = PtpFilterGetContext(queueContext->Device);
switch (IoControlCode)
{
case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
status = PtpFilterGetHidDescriptor(queueContext->Device, Request);
break;
case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
status = PtpFilterGetDeviceAttribs(queueContext->Device, Request);
break;
case IOCTL_HID_GET_REPORT_DESCRIPTOR:
status = PtpFilterGetReportDescriptor(queueContext->Device, Request);
break;
case IOCTL_HID_GET_STRING:
status = PtpFilterGetStrings(queueContext->Device, Request, &requestPending);
break;
case IOCTL_HID_READ_REPORT:
PtpFilterInputProcessRequest(queueContext->Device, Request);
requestPending = TRUE;
break;
case IOCTL_HID_GET_FEATURE:
status = PtpFilterGetHidFeatures(queueContext->Device, Request);
break;
case IOCTL_HID_SET_FEATURE:
status = PtpFilterSetHidFeatures(queueContext->Device, Request);
break;
case IOCTL_HID_WRITE_REPORT:
case IOCTL_UMDF_HID_SET_OUTPUT_REPORT:
case IOCTL_UMDF_HID_GET_INPUT_REPORT:
case IOCTL_HID_ACTIVATE_DEVICE:
case IOCTL_HID_DEACTIVATE_DEVICE:
case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST:
default:
status = STATUS_NOT_SUPPORTED;
TraceEvents(TRACE_LEVEL_WARNING, TRACE_QUEUE, "%!FUNC!: %s is not yet implemented", PtpFilterDiagnosticsIoControlGetString(IoControlCode));
break;
}
if (requestPending != TRUE)
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC!: %s, Status = %!STATUS!", PtpFilterDiagnosticsIoControlGetString(IoControlCode), status);
WdfRequestComplete(Request, status);
}
}
VOID
FilterEvtIoStop(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ ULONG ActionFlags
)
{
UNREFERENCED_PARAMETER(Queue);
UNREFERENCED_PARAMETER(Request);
UNREFERENCED_PARAMETER(ActionFlags);
}
================================================
FILE: src/AmtPtpHidFilter/include/Device.h
================================================
// Device.h: Device-specific struct and routines
#pragma once
EXTERN_C_START
// {FF969022-3111-4441-8F88-875440172C2E} for the device interface
DEFINE_GUID(GUID_DEVICEINTERFACE_AmtPtpHidFilter,
0xff969022, 0x3111, 0x4441, 0x8f, 0x88, 0x87, 0x54, 0x40, 0x17, 0x2c, 0x2e);
// Definition
#define HID_XFER_PACKET_SIZE 32
#define HID_VID_APPLE_USB 0x05ac
#define HID_VID_APPLE_BT 0x004c
#define HID_PID_MAGIC_TRACKPAD_2 0x0265
/* device-specific parameters */
typedef struct _BCM5974_PARAM {
int snratio; /* signal-to-noise ratio */
int min; /* device minimum reading */
int max; /* device maximum reading */
} BCM5974_PARAM, *PBCM5974_PARAM;
// Device Context
typedef struct _DEVICE_CONTEXT
{
PDEVICE_OBJECT WdmDeviceObject;
WDFDEVICE Device;
WDFQUEUE HidReadQueue;
// Device identification
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
size_t InputHeaderSize;
size_t InputFingerSize;
size_t InputFingerDelta;
size_t InputButtonDelta;
BCM5974_PARAM X;
BCM5974_PARAM Y;
// List of buffers
WDFLOOKASIDE HidReadBufferLookaside;
// System HID transport
WDFIOTARGET HidIoTarget;
BOOLEAN IsHidIoDetourCompleted;
WDFTIMER HidTransportRecoveryTimer;
WDFWORKITEM HidTransportRecoveryWorkItem;
// Device State
BOOLEAN DeviceConfigured;
// PTP report specific
LARGE_INTEGER LastReportTime;
BOOLEAN PtpInputOn;
BOOLEAN PtpReportTouch;
BOOLEAN PtpReportButton;
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, PtpFilterGetContext)
// 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)
// Initialization routines
NTSTATUS
PtpFilterCreateDevice(
_Inout_ PWDFDEVICE_INIT DeviceInit
);
// Power Management Handlers
EVT_WDF_DEVICE_PREPARE_HARDWARE PtpFilterPrepareHardware;
EVT_WDF_DEVICE_D0_ENTRY PtpFilterDeviceD0Entry;
EVT_WDF_DEVICE_D0_EXIT PtpFilterDeviceD0Exit;
EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT PtpFilterSelfManagedIoInit;
EVT_WDF_DEVICE_SELF_MANAGED_IO_RESTART PtpFilterSelfManagedIoRestart;
// Device Management routines
NTSTATUS
PtpFilterConfigureMultiTouch(
_In_ WDFDEVICE Device
);
VOID
PtpFilterRecoveryTimerCallback(
WDFTIMER Timer
);
EXTERN_C_END
================================================
FILE: src/AmtPtpHidFilter/include/Diagnostics.h
================================================
#pragma once
EXTERN_C_START
VOID PtpFilterDiagnosticsInitializeContinuousRead(
_In_ WDFDEVICE Device
);
VOID
PtpFilterDiagnosticsInputIssueRequest(
_In_ WDFDEVICE Device
);
VOID
PtpFilterDiagnosticsRequestCompletionRoutine(
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS Params,
_In_ WDFCONTEXT Context
);
PCHAR
PtpFilterDiagnosticsIoControlGetString(
_In_ ULONG IoControlCode
);
EXTERN_C_END
================================================
FILE: src/AmtPtpHidFilter/include/Driver.h
================================================
// Driver.h: common definition
#pragma once
#include
#include
#include
#include
#include
#include
#include
#include "Trace.h"
EXTERN_C_START
// Common entry points
DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD PtpFilterEvtDeviceAdd;
EVT_WDF_OBJECT_CONTEXT_CLEANUP PtpFilterEvtDriverContextCleanup;
// Device specific routines
#include "Device.h"
#include "Queue.h"
#include "Hac.h"
#include "Diagnostics.h"
#include "Metadata/StaticHidRegistry.h"
#include "HidMiniport.h"
#include "HidDevice.h"
#include "Input.h"
// Pool Tag
#define PTP_LIST_POOL_TAG 'LTPA'
#define REPORT_BUFFER_SIZE 1024
EXTERN_C_END
================================================
FILE: src/AmtPtpHidFilter/include/Hac.h
================================================
// Hac.h: Yes, we have to hack Windows HID stack on the fly...
#pragma once
EXTERN_C_START
// HACK: detour the HIDClass extension
typedef struct _HIDCLASS_DRIVER_EXTENSION {
PDRIVER_OBJECT MinidriverObject;
UNICODE_STRING RegistryPath;
ULONG DeviceExtensionSize;
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
PDRIVER_ADD_DEVICE AddDevice;
PDRIVER_UNLOAD DriverUnload;
LONG ReferenceCount;
LIST_ENTRY ListEntry;
BOOLEAN DevicesArePolled;
} HIDCLASS_DRIVER_EXTENSION, * PHIDCLASS_DRIVER_EXTENSION;
typedef struct _IO_CLIENT_EXTENSION
{
struct _IO_CLIENT_EXTENSION* NextExtension;
PVOID ClientIdentificationAddress;
} IO_CLIENT_EXTENSION, * PIO_CLIENT_EXTENSION, ** PPIO_CLIENT_EXTENSION;
typedef struct _DRIVER_EXTENSION_EXT {
struct _DRIVER_OBJECT* DriverObject;
PDRIVER_ADD_DEVICE AddDevice;
ULONG Count;
UNICODE_STRING ServiceKeyName;
PIO_CLIENT_EXTENSION IoClientExtension;
} DRIVER_EXTENSION_EXT, * PDRIVER_EXTENSION_EXT;
#define HID_CLASS_EXTENSION_LITERAL_ID "HIDCLASS"
#define HID_USB_SERVICE_NAME L"HidUsb"
// Hack: import from ntifs.h
extern NTKERNELAPI
PDEVICE_OBJECT
IoGetLowerDeviceObject(
_In_ PDEVICE_OBJECT DeviceObject
);
// Detour routines
NTSTATUS
PtpFilterDetourWindowsHIDStack(
_In_ WDFDEVICE Device
);
EXTERN_C_END
================================================
FILE: src/AmtPtpHidFilter/include/HidCommon.h
================================================
// HidCommon.h: HID common definition
#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
#define DEVICE_VID 0x8910
#define DEVICE_VERSION 0x100
================================================
FILE: src/AmtPtpHidFilter/include/HidDevice.h
================================================
// HidDevice.h: devicei-specific HID structures
#pragma once
/* Trackpad finger data offsets, le16-aligned */
#define HOFFSET_TYPE_USB_1 (13 * sizeof(USHORT))
#define HOFFSET_TYPE_USB_2 (15 * sizeof(USHORT))
#define HOFFSET_TYPE_USB_3 (19 * sizeof(USHORT))
#define HOFFSET_TYPE_USB_4 (23 * sizeof(USHORT))
#define HOFFSET_TYPE_USB_5 ( 6 * sizeof(USHORT))
#define HOFFSET_TYPE_BTH_5 ( 2 * sizeof(USHORT))
/* Trackpad button data offsets */
#define BOFFSET_TYPE1 0
#define BOFFSET_TYPE2 15
#define BOFFSET_TYPE3 23
#define BOFFSET_TYPE4 31
#define BOFFSET_TYPE5 1
/* Trackpad finger data block size */
#define FSIZE_TYPE1 (14 * sizeof(USHORT))
#define FSIZE_TYPE2 (14 * sizeof(USHORT))
#define FSIZE_TYPE3 (14 * sizeof(USHORT))
#define FSIZE_TYPE4 (15 * sizeof(USHORT))
#define FSIZE_TYPE5 (9)
/* List of device capability bits */
#define HAS_INTEGRATED_BUTTON 1
/* Offset from header to finger struct */
#define FDELTA_TYPE1 (0 * sizeof(USHORT))
#define FDELTA_TYPE2 (0 * sizeof(USHORT))
#define FDELTA_TYPE3 (0 * sizeof(USHORT))
#define FDELTA_TYPE4 (1 * sizeof(USHORT))
#define FDELTA_TYPE5 (0 * sizeof(USHORT))
/* Trackpad finger data size, empirically at least ten fingers */
#define MAX_FINGERS 16
#define MAX_FINGER_ORIENTATION 16384
/* button data structure */
typedef struct _TRACKPAD_BUTTON_DATA {
UCHAR unknown1; /* constant */
UCHAR button; /* left button */
UCHAR rel_x; /* relative x coordinate */
UCHAR rel_y; /* relative y coordinate */
} TRACKPAD_BUTTON_DATA, *PTRACKPAD_BUTTON_DATA;
#include
/* trackpad finger structure, le16-aligned */
typedef struct _TRACKPAD_FINGER {
USHORT origin; /* zero when switching track finger */
USHORT abs_x; /* absolute x coodinate */
USHORT abs_y; /* absolute y coodinate */
USHORT rel_x; /* relative x coodinate */
USHORT rel_y; /* relative y coodinate */
USHORT tool_major; /* tool area, major axis */
USHORT tool_minor; /* tool area, minor axis */
USHORT orientation; /* 16384 when point, else 15 bit angle */
USHORT touch_major; /* touch area, major axis */
USHORT touch_minor; /* touch area, minor axis */
USHORT unused[2]; /* zeros */
USHORT pressure; /* pressure on forcetouch touchpad */
USHORT multi; /* one finger: varies, more fingers: constant */
} TRACKPAD_FINGER, *PTRACKPAD_FINGER;
/* Trackpad finger structure for type5 (magic trackpad), le16-aligned */
typedef struct _TRACKPAD_FINGER_TYPE5
{
UCHAR AbsoluteX; /* absolute x coodinate */
UCHAR AbsoluteXY; /* absolute x,y coodinate */
UCHAR AbsoluteY[2]; /* absolute y coodinate */
UCHAR TouchMajor; /* touch area, major axis */
UCHAR TouchMinor; /* touch area, minor axis */
UCHAR Size; /* tool area, size */
UCHAR Pressure; /* pressure on forcetouch touchpad */
union _ORIDENTATION_AND_ORIGIN
{
struct _CONTACT_IDENTIFIER
{
UCHAR Id : 4;
UCHAR Orientation : 4;
} ContactIdentifier;
UCHAR RawValue;
} OrientationAndOrigin;
} TRACKPAD_FINGER_TYPE5, *PTRACKPAD_FINGER_TYPE5;
#include
================================================
FILE: src/AmtPtpHidFilter/include/HidMiniport.h
================================================
// Hidminiport.h: HID miniport communication structures
#pragma once
#include
// PTP device capabilites Feature Report
typedef struct _PTP_DEVICE_CAPS_FEATURE_REPORT {
UCHAR ReportID;
UCHAR MaximumContactPoints;
UCHAR ButtonType;
} PTP_DEVICE_CAPS_FEATURE_REPORT, * PPTP_DEVICE_CAPS_FEATURE_REPORT;
// PTP device certification Feature Report
typedef struct _PTP_DEVICE_HQA_CERTIFICATION_REPORT {
UCHAR ReportID;
UCHAR CertificationBlob[256];
} PTP_DEVICE_HQA_CERTIFICATION_REPORT, * PPTP_DEVICE_HQA_CERTIFICATION_REPORT;
// PTP input mode Feature Report
typedef struct _PTP_DEVICE_INPUT_MODE_REPORT {
UCHAR ReportID;
UCHAR Mode;
} PTP_DEVICE_INPUT_MODE_REPORT, * PPTP_DEVICE_INPUT_MODE_REPORT;
// PTP input selection Feature Report
typedef struct _PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT {
UCHAR ReportID;
UCHAR ButtonReport : 1;
UCHAR SurfaceReport : 1;
UCHAR Padding : 6;
} PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT, * PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT;
// PTP single finger
typedef struct _PTP_CONTACT {
UCHAR Confidence : 1;
UCHAR TipSwitch : 1;
UCHAR Padding : 6;
ULONG ContactID;
USHORT X;
USHORT Y;
} PTP_CONTACT, * PPTP_CONTACT;
// PTP single scan frame Input Report
typedef struct _PTP_REPORT {
UCHAR ReportID;
PTP_CONTACT Contacts[5];
USHORT ScanTime;
UCHAR ContactCount;
UCHAR IsButtonClicked;
} PTP_REPORT, * PPTP_REPORT;
#include
// HID routines
NTSTATUS
PtpFilterGetHidDescriptor(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
NTSTATUS
PtpFilterGetDeviceAttribs(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
NTSTATUS
PtpFilterGetReportDescriptor(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
NTSTATUS
PtpFilterGetStrings(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request,
_Out_ BOOLEAN* Pending
);
NTSTATUS
PtpFilterGetHidFeatures(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
NTSTATUS
PtpFilterSetHidFeatures(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
================================================
FILE: src/AmtPtpHidFilter/include/Input.h
================================================
// Input.h: Input processing and device definitions
#pragma once
VOID
PtpFilterInputProcessRequest(
_In_ WDFDEVICE Device,
_In_ WDFREQUEST Request
);
VOID
PtpFilterWorkItemCallback(
_In_ WDFWORKITEM WorkItem
);
VOID
PtpFilterInputIssueTransportRequest(
_In_ WDFDEVICE Device
);
VOID
PtpFilterInputRequestCompletionCallback(
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS Params,
_In_ WDFCONTEXT Context
);
================================================
FILE: src/AmtPtpHidFilter/include/Metadata/MagicTrackpad2.h
================================================
// MagicTrackpad2.h: Magic Trackpad 2 specific HID information
#pragma once
#define AAPL_MAGIC_TRACKPAD2_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0xbc, 0x1d, /* Logical Maximum: 7612 (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, 0x40, 0x06, /* Physical Maximum: 1600 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0x7d, 0x04, /* Physical Maximum: 1149 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0xc9, 0x13, /* Logical Maximum: 5065 (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_MAGIC_TRACKPAD2_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_SIZE, 0x01, /* Report Size: 1 */ \
REPORT_COUNT, 0x06, /* Report Count: 6 */ \
INPUT, 0x03, /* Input: (Const, Var, Abs) */ \
/* End of a byte */ \
/* Begin of 4 bytes */ \
REPORT_COUNT, 0x01, /* Report Count: 1 */ \
REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \
LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \
USAGE, 0x51, /* Usage: Contract Identifier */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
/* Begin of 4 bytes */ \
/* Size is hard-coded at this moment */ \
USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \
LOGICAL_MAXIMUM_2, 0xbc, 0x1d, /* Logical Maximum: 7612 (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, 0x40, 0x06, /* Physical Maximum: 1600 (See Apple Spec) */ \
REPORT_COUNT, 0x01, /* Report count: 1 */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
PHYSICAL_MAXIMUM_2, 0x7d, 0x04, /* Physical Maximum: 1149 (See Apple Spec) */ \
LOGICAL_MAXIMUM_2, 0xc9, 0x13, /* Logical Maximum: 5065 (See definition) */ \
USAGE, 0x31, /* Usage: Y */ \
INPUT, 0x02, /* Input: (Data, Var, Abs) */ \
/* End of 4 bytes */ \
END_COLLECTION /* End Collection */ \
#define AAPL_MAGIC_TRACKPAD2_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_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 1 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 2 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_2, /* 3 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 4 */ \
USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \
USAGE, 0x22, /* Usage: Finger */ \
AAPL_MAGIC_TRACKPAD2_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/AmtPtpHidFilter/include/Metadata/StaticHidRegistry.h
================================================
// StaticHidRegistry.h: Static HID collection information
#pragma once
#include
#include
#include
#include
typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR;
#ifndef _STATIC_HID_REGISTRY_H_
#define _STATIC_HID_REGISTRY_H_
static HID_REPORT_DESCRIPTOR PtpReportDescriptorMagicTrackpad2[] = {
AAPL_MAGIC_TRACKPAD2_PTP_TLC,
AAPL_PTP_WINDOWS_CONFIGURATION_TLC,
};
static HID_DESCRIPTOR PtpDefaultHidDescriptorMagicTrackpad2 = {
0x09, // bLength
0x21, // bDescriptorType
0x0100, // bcdHID
0x00, // bCountryCode
0x01, // bNumDescriptors
{
0x22, // bDescriptorType
sizeof(PtpReportDescriptorMagicTrackpad2), // bDescriptorLength
},
};
#endif
================================================
FILE: src/AmtPtpHidFilter/include/Metadata/WindowsHID.h
================================================
// WindowsHID.h: Windows specific HID Top Level Collections
#pragma once
#define MAX_FINGERS 16
#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
#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
================================================
FILE: src/AmtPtpHidFilter/include/Queue.h
================================================
// Queue.h: IO queue bits
#pragma once
EXTERN_C_START
// Initialization
NTSTATUS
PtpFilterIoQueueInitialize(
_In_ WDFDEVICE Device
);
// Queue context
typedef struct _QUEUE_CONTEXT {
WDFDEVICE Device;
WDFIOTARGET DeviceIoTarget;
} QUEUE_CONTEXT, *PQUEUE_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, PtpFilterQueueGetContext)
// Event handlers
EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL FilterEvtIoIntDeviceControl;
EVT_WDF_IO_QUEUE_IO_STOP FilterEvtIoStop;
EXTERN_C_END
================================================
FILE: src/AmtPtpHidFilter/include/Trace.h
================================================
// Trace.h: Defines WPP tracing control bits.
#pragma once
//
// Define the tracing flags.
//
// Tracing GUID - eeb34803-f3ec-4bb1-97ce-b42405d7f3c2
//
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID( \
AmtPtpHidFilterTraceGuid, (eeb34803,f3ec,4bb1,97ce,b42405d7f3c2), \
\
WPP_DEFINE_BIT(TRACE_DRIVER) \
WPP_DEFINE_BIT(TRACE_DEVICE) \
WPP_DEFINE_BIT(TRACE_QUEUE) \
WPP_DEFINE_BIT(TRACE_HID) \
WPP_DEFINE_BIT(TRACE_INPUT) \
)
#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
WPP_LEVEL_LOGGER(flag)
#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
(WPP_LEVEL_ENABLED(flag) && \
WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
WPP_LEVEL_LOGGER(flags)
#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
//
// WPP orders static parameters before dynamic parameters. To support the Trace function
// defined below which sets FLAGS=MYDRIVER_ALL_INFO, a custom macro must be defined to
// reorder the arguments to what the .tpl configuration file expects.
//
#define WPP_RECORDER_FLAGS_LEVEL_ARGS(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_ARGS(lvl, flags)
#define WPP_RECORDER_FLAGS_LEVEL_FILTER(flags, lvl) WPP_RECORDER_LEVEL_FLAGS_FILTER(lvl, flags)
//
// This comment block is scanned by the trace preprocessor to define our
// Trace function.
//
// begin_wpp config
// FUNC Trace{FLAGS=TRACE_DRIVER}(LEVEL, MSG, ...);
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//