├── .gitignore ├── AmtPtpControlPanel ├── AmtPtpControlPanel.csproj ├── AmtPtpControlPanel.sln ├── App.config ├── Main.Designer.cs ├── Main.cs ├── Main.resx ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ └── Icon1.ico └── app.manifest ├── AmtPtpDeviceUsbUm ├── AmtPtpDevice.wprp ├── Device.c ├── Driver.c ├── Hid.c ├── InputInterrupt.c ├── MagicTrackpad2PtpDevice.sln ├── 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 ├── README.md └── assets └── ControlPanel.png /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | bin/ 3 | obj/ 4 | build/ 5 | intermediate/ 6 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/AmtPtpControlPanel.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB} 8 | WinExe 9 | AmtPtpControlPanel 10 | AmtPtpControlPanel 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | true 37 | bin\x64\Debug\ 38 | DEBUG;TRACE 39 | full 40 | x64 41 | 7.3 42 | prompt 43 | true 44 | 45 | 46 | bin\x64\Release\ 47 | TRACE 48 | true 49 | pdbonly 50 | x64 51 | 7.3 52 | prompt 53 | true 54 | 55 | 56 | app.manifest 57 | 58 | 59 | Resources\Icon1.ico 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Form 77 | 78 | 79 | Main.cs 80 | 81 | 82 | 83 | 84 | Main.cs 85 | 86 | 87 | ResXFileCodeGenerator 88 | Resources.Designer.cs 89 | Designer 90 | 91 | 92 | True 93 | Resources.resx 94 | True 95 | 96 | 97 | 98 | SettingsSingleFileGenerator 99 | Settings.Designer.cs 100 | 101 | 102 | True 103 | Settings.settings 104 | True 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/AmtPtpControlPanel.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.33801.447 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AmtPtpControlPanel", "AmtPtpControlPanel.csproj", "{EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Release|Any CPU = Release|Any CPU 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}.Debug|x64.ActiveCfg = Debug|x64 19 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}.Debug|x64.Build.0 = Debug|x64 20 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}.Release|x64.ActiveCfg = Release|x64 23 | {EE1C7A99-9593-4D6A-889B-D75EEA2DE6AB}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {EF892ED6-EFF6-4552-89C8-4A58160848EC} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/Main.Designer.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace AmtPtpControlPanel 3 | { 4 | partial class Main 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Main)); 33 | this.ctlInstallDriver = new System.Windows.Forms.Button(); 34 | this.ctlApply = new System.Windows.Forms.Button(); 35 | this.ctlFeedback = new System.Windows.Forms.TrackBar(); 36 | this.ctlLightLabel = new System.Windows.Forms.Label(); 37 | this.ctlMediumLabel = new System.Windows.Forms.Label(); 38 | this.ctlFirmLabel = new System.Windows.Forms.Label(); 39 | this.ctlSilentClicking = new System.Windows.Forms.CheckBox(); 40 | this.ctlMacOSClickOptions = new System.Windows.Forms.RadioButton(); 41 | this.groupBox1 = new System.Windows.Forms.GroupBox(); 42 | this.groupBox2 = new System.Windows.Forms.GroupBox(); 43 | this.ctlMaximumFeedback = new System.Windows.Forms.RadioButton(); 44 | this.ctlDisableFeedback = new System.Windows.Forms.RadioButton(); 45 | this.ctlFocusHack = new System.Windows.Forms.TextBox(); 46 | this.groupBox3 = new System.Windows.Forms.GroupBox(); 47 | this.ctlStopSizeLabel = new System.Windows.Forms.Label(); 48 | this.ctlStopSizeValue = new System.Windows.Forms.TextBox(); 49 | this.ctlStopPressureLabel = new System.Windows.Forms.Label(); 50 | this.ctlStopPressureValue = new System.Windows.Forms.TextBox(); 51 | this.ctlStopSize = new System.Windows.Forms.RadioButton(); 52 | this.ctlStopPressure = new System.Windows.Forms.RadioButton(); 53 | this.ctlStopDoNothing = new System.Windows.Forms.RadioButton(); 54 | this.groupBox4 = new System.Windows.Forms.GroupBox(); 55 | this.ctlIgnoreNearFingers = new System.Windows.Forms.CheckBox(); 56 | this.ctlIgnoreButtonFinger = new System.Windows.Forms.CheckBox(); 57 | this.ctlPalmRejection = new System.Windows.Forms.CheckBox(); 58 | ((System.ComponentModel.ISupportInitialize)(this.ctlFeedback)).BeginInit(); 59 | this.groupBox1.SuspendLayout(); 60 | this.groupBox2.SuspendLayout(); 61 | this.groupBox3.SuspendLayout(); 62 | this.groupBox4.SuspendLayout(); 63 | this.SuspendLayout(); 64 | // 65 | // ctlInstallDriver 66 | // 67 | this.ctlInstallDriver.Location = new System.Drawing.Point(13, 537); 68 | this.ctlInstallDriver.Name = "ctlInstallDriver"; 69 | this.ctlInstallDriver.Size = new System.Drawing.Size(195, 33); 70 | this.ctlInstallDriver.TabIndex = 5; 71 | this.ctlInstallDriver.Text = "Install Driver"; 72 | this.ctlInstallDriver.UseVisualStyleBackColor = true; 73 | this.ctlInstallDriver.Click += new System.EventHandler(this.ctlInstallDriver_Click); 74 | // 75 | // ctlApply 76 | // 77 | this.ctlApply.Location = new System.Drawing.Point(608, 537); 78 | this.ctlApply.Name = "ctlApply"; 79 | this.ctlApply.Size = new System.Drawing.Size(195, 33); 80 | this.ctlApply.TabIndex = 0; 81 | this.ctlApply.Text = "Apply"; 82 | this.ctlApply.UseVisualStyleBackColor = true; 83 | this.ctlApply.Click += new System.EventHandler(this.ctlApply_Click); 84 | // 85 | // ctlFeedback 86 | // 87 | this.ctlFeedback.Location = new System.Drawing.Point(53, 106); 88 | this.ctlFeedback.Maximum = 2; 89 | this.ctlFeedback.Name = "ctlFeedback"; 90 | this.ctlFeedback.Size = new System.Drawing.Size(227, 56); 91 | this.ctlFeedback.TabIndex = 2; 92 | this.ctlFeedback.Value = 1; 93 | // 94 | // ctlLightLabel 95 | // 96 | this.ctlLightLabel.AutoSize = true; 97 | this.ctlLightLabel.Location = new System.Drawing.Point(50, 145); 98 | this.ctlLightLabel.Name = "ctlLightLabel"; 99 | this.ctlLightLabel.Size = new System.Drawing.Size(39, 17); 100 | this.ctlLightLabel.TabIndex = 3; 101 | this.ctlLightLabel.Text = "Light"; 102 | // 103 | // ctlMediumLabel 104 | // 105 | this.ctlMediumLabel.AutoSize = true; 106 | this.ctlMediumLabel.Location = new System.Drawing.Point(139, 145); 107 | this.ctlMediumLabel.Name = "ctlMediumLabel"; 108 | this.ctlMediumLabel.Size = new System.Drawing.Size(57, 17); 109 | this.ctlMediumLabel.TabIndex = 4; 110 | this.ctlMediumLabel.Text = "Medium"; 111 | // 112 | // ctlFirmLabel 113 | // 114 | this.ctlFirmLabel.AutoSize = true; 115 | this.ctlFirmLabel.Location = new System.Drawing.Point(245, 145); 116 | this.ctlFirmLabel.Name = "ctlFirmLabel"; 117 | this.ctlFirmLabel.Size = new System.Drawing.Size(35, 17); 118 | this.ctlFirmLabel.TabIndex = 5; 119 | this.ctlFirmLabel.Text = "Firm"; 120 | // 121 | // ctlSilentClicking 122 | // 123 | this.ctlSilentClicking.AutoSize = true; 124 | this.ctlSilentClicking.Location = new System.Drawing.Point(112, 68); 125 | this.ctlSilentClicking.Name = "ctlSilentClicking"; 126 | this.ctlSilentClicking.Size = new System.Drawing.Size(115, 21); 127 | this.ctlSilentClicking.TabIndex = 1; 128 | this.ctlSilentClicking.Text = "Silent clicking"; 129 | this.ctlSilentClicking.UseVisualStyleBackColor = true; 130 | // 131 | // ctlMacOSClickOptions 132 | // 133 | this.ctlMacOSClickOptions.AutoSize = true; 134 | this.ctlMacOSClickOptions.Location = new System.Drawing.Point(17, 21); 135 | this.ctlMacOSClickOptions.Name = "ctlMacOSClickOptions"; 136 | this.ctlMacOSClickOptions.Size = new System.Drawing.Size(194, 21); 137 | this.ctlMacOSClickOptions.TabIndex = 0; 138 | this.ctlMacOSClickOptions.TabStop = true; 139 | this.ctlMacOSClickOptions.Text = "Use macOS Click Options:"; 140 | this.ctlMacOSClickOptions.UseVisualStyleBackColor = true; 141 | this.ctlMacOSClickOptions.CheckedChanged += new System.EventHandler(this.ctlClickOptions_CheckedChanged); 142 | // 143 | // groupBox1 144 | // 145 | this.groupBox1.Controls.Add(this.ctlLightLabel); 146 | this.groupBox1.Controls.Add(this.ctlMacOSClickOptions); 147 | this.groupBox1.Controls.Add(this.ctlSilentClicking); 148 | this.groupBox1.Controls.Add(this.ctlFirmLabel); 149 | this.groupBox1.Controls.Add(this.ctlMediumLabel); 150 | this.groupBox1.Controls.Add(this.ctlFeedback); 151 | this.groupBox1.Location = new System.Drawing.Point(12, 12); 152 | this.groupBox1.Name = "groupBox1"; 153 | this.groupBox1.Size = new System.Drawing.Size(340, 194); 154 | this.groupBox1.TabIndex = 1; 155 | this.groupBox1.TabStop = false; 156 | // 157 | // groupBox2 158 | // 159 | this.groupBox2.Controls.Add(this.ctlMaximumFeedback); 160 | this.groupBox2.Controls.Add(this.ctlDisableFeedback); 161 | this.groupBox2.Location = new System.Drawing.Point(358, 12); 162 | this.groupBox2.Name = "groupBox2"; 163 | this.groupBox2.Size = new System.Drawing.Size(445, 194); 164 | this.groupBox2.TabIndex = 2; 165 | this.groupBox2.TabStop = false; 166 | this.groupBox2.Text = "Click Options NOT available in macOS:"; 167 | // 168 | // ctlMaximumFeedback 169 | // 170 | this.ctlMaximumFeedback.AutoSize = true; 171 | this.ctlMaximumFeedback.Location = new System.Drawing.Point(28, 98); 172 | this.ctlMaximumFeedback.Name = "ctlMaximumFeedback"; 173 | this.ctlMaximumFeedback.Size = new System.Drawing.Size(332, 21); 174 | this.ctlMaximumFeedback.TabIndex = 1; 175 | this.ctlMaximumFeedback.TabStop = true; 176 | this.ctlMaximumFeedback.Text = "Maximum haptic feedback (very clicky and loud!)"; 177 | this.ctlMaximumFeedback.UseVisualStyleBackColor = true; 178 | this.ctlMaximumFeedback.CheckedChanged += new System.EventHandler(this.ctlClickOptions_CheckedChanged); 179 | // 180 | // ctlDisableFeedback 181 | // 182 | this.ctlDisableFeedback.AutoSize = true; 183 | this.ctlDisableFeedback.Location = new System.Drawing.Point(28, 61); 184 | this.ctlDisableFeedback.Name = "ctlDisableFeedback"; 185 | this.ctlDisableFeedback.Size = new System.Drawing.Size(398, 21); 186 | this.ctlDisableFeedback.TabIndex = 0; 187 | this.ctlDisableFeedback.TabStop = true; 188 | this.ctlDisableFeedback.Text = "Disable haptic feedback and force touch button completely"; 189 | this.ctlDisableFeedback.UseVisualStyleBackColor = true; 190 | this.ctlDisableFeedback.CheckedChanged += new System.EventHandler(this.ctlClickOptions_CheckedChanged); 191 | // 192 | // ctlFocusHack 193 | // 194 | this.ctlFocusHack.Location = new System.Drawing.Point(-32, -32); 195 | this.ctlFocusHack.Name = "ctlFocusHack"; 196 | this.ctlFocusHack.Size = new System.Drawing.Size(22, 22); 197 | this.ctlFocusHack.TabIndex = 10; 198 | this.ctlFocusHack.TabStop = false; 199 | // 200 | // groupBox3 201 | // 202 | this.groupBox3.Controls.Add(this.ctlStopSizeLabel); 203 | this.groupBox3.Controls.Add(this.ctlStopSizeValue); 204 | this.groupBox3.Controls.Add(this.ctlStopPressureLabel); 205 | this.groupBox3.Controls.Add(this.ctlStopPressureValue); 206 | this.groupBox3.Controls.Add(this.ctlStopSize); 207 | this.groupBox3.Controls.Add(this.ctlStopPressure); 208 | this.groupBox3.Controls.Add(this.ctlStopDoNothing); 209 | this.groupBox3.Location = new System.Drawing.Point(12, 212); 210 | this.groupBox3.Name = "groupBox3"; 211 | this.groupBox3.Size = new System.Drawing.Size(791, 147); 212 | this.groupBox3.TabIndex = 3; 213 | this.groupBox3.TabStop = false; 214 | this.groupBox3.Text = "When you lift your finger from the trackpad:"; 215 | // 216 | // ctlStopSizeLabel 217 | // 218 | this.ctlStopSizeLabel.AutoSize = true; 219 | this.ctlStopSizeLabel.Location = new System.Drawing.Point(491, 108); 220 | this.ctlStopSizeLabel.Name = "ctlStopSizeLabel"; 221 | this.ctlStopSizeLabel.Size = new System.Drawing.Size(164, 17); 222 | this.ctlStopSizeLabel.TabIndex = 6; 223 | this.ctlStopSizeLabel.Text = "units. (7 is a good value)"; 224 | this.ctlStopSizeLabel.Click += new System.EventHandler(this.ctlStop_Click); 225 | // 226 | // ctlStopSizeValue 227 | // 228 | this.ctlStopSizeValue.Location = new System.Drawing.Point(434, 106); 229 | this.ctlStopSizeValue.Name = "ctlStopSizeValue"; 230 | this.ctlStopSizeValue.Size = new System.Drawing.Size(51, 22); 231 | this.ctlStopSizeValue.TabIndex = 5; 232 | this.ctlStopSizeValue.Text = "7"; 233 | this.ctlStopSizeValue.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; 234 | // 235 | // ctlStopPressureLabel 236 | // 237 | this.ctlStopPressureLabel.AutoSize = true; 238 | this.ctlStopPressureLabel.Location = new System.Drawing.Point(419, 71); 239 | this.ctlStopPressureLabel.Name = "ctlStopPressureLabel"; 240 | this.ctlStopPressureLabel.Size = new System.Drawing.Size(306, 17); 241 | this.ctlStopPressureLabel.TabIndex = 3; 242 | this.ctlStopPressureLabel.Text = "units. (0 means no pressure; 0 is a good value)"; 243 | this.ctlStopPressureLabel.Click += new System.EventHandler(this.ctlStop_Click); 244 | // 245 | // ctlStopPressureValue 246 | // 247 | this.ctlStopPressureValue.Location = new System.Drawing.Point(362, 69); 248 | this.ctlStopPressureValue.Name = "ctlStopPressureValue"; 249 | this.ctlStopPressureValue.Size = new System.Drawing.Size(51, 22); 250 | this.ctlStopPressureValue.TabIndex = 2; 251 | this.ctlStopPressureValue.Text = "0"; 252 | this.ctlStopPressureValue.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; 253 | // 254 | // ctlStopSize 255 | // 256 | this.ctlStopSize.AutoSize = true; 257 | this.ctlStopSize.Location = new System.Drawing.Point(17, 106); 258 | this.ctlStopSize.Name = "ctlStopSize"; 259 | this.ctlStopSize.Size = new System.Drawing.Size(453, 21); 260 | this.ctlStopSize.TabIndex = 4; 261 | this.ctlStopSize.TabStop = true; 262 | this.ctlStopSize.Text = "Stop the pointer if the size of the touch area is less than or equal to"; 263 | this.ctlStopSize.UseVisualStyleBackColor = true; 264 | this.ctlStopSize.CheckedChanged += new System.EventHandler(this.ctlStop_CheckedChanged); 265 | // 266 | // ctlStopPressure 267 | // 268 | this.ctlStopPressure.AutoSize = true; 269 | this.ctlStopPressure.Location = new System.Drawing.Point(17, 69); 270 | this.ctlStopPressure.Name = "ctlStopPressure"; 271 | this.ctlStopPressure.Size = new System.Drawing.Size(372, 21); 272 | this.ctlStopPressure.TabIndex = 1; 273 | this.ctlStopPressure.TabStop = true; 274 | this.ctlStopPressure.Text = "Stop the pointer if the pressure is less than or equal to"; 275 | this.ctlStopPressure.UseVisualStyleBackColor = true; 276 | this.ctlStopPressure.CheckedChanged += new System.EventHandler(this.ctlStop_CheckedChanged); 277 | // 278 | // ctlStopDoNothing 279 | // 280 | this.ctlStopDoNothing.AutoSize = true; 281 | this.ctlStopDoNothing.Location = new System.Drawing.Point(17, 32); 282 | this.ctlStopDoNothing.Name = "ctlStopDoNothing"; 283 | this.ctlStopDoNothing.Size = new System.Drawing.Size(98, 21); 284 | this.ctlStopDoNothing.TabIndex = 0; 285 | this.ctlStopDoNothing.TabStop = true; 286 | this.ctlStopDoNothing.Text = "Do nothing"; 287 | this.ctlStopDoNothing.UseVisualStyleBackColor = true; 288 | this.ctlStopDoNothing.CheckedChanged += new System.EventHandler(this.ctlStop_CheckedChanged); 289 | // 290 | // groupBox4 291 | // 292 | this.groupBox4.Controls.Add(this.ctlPalmRejection); 293 | this.groupBox4.Controls.Add(this.ctlIgnoreButtonFinger); 294 | this.groupBox4.Controls.Add(this.ctlIgnoreNearFingers); 295 | this.groupBox4.Location = new System.Drawing.Point(12, 365); 296 | this.groupBox4.Name = "groupBox4"; 297 | this.groupBox4.Size = new System.Drawing.Size(791, 147); 298 | this.groupBox4.TabIndex = 4; 299 | this.groupBox4.TabStop = false; 300 | this.groupBox4.Text = "Other options:"; 301 | // 302 | // ctlIgnoreNearFingers 303 | // 304 | this.ctlIgnoreNearFingers.AutoSize = true; 305 | this.ctlIgnoreNearFingers.Location = new System.Drawing.Point(17, 32); 306 | this.ctlIgnoreNearFingers.Name = "ctlIgnoreNearFingers"; 307 | this.ctlIgnoreNearFingers.Size = new System.Drawing.Size(400, 21); 308 | this.ctlIgnoreNearFingers.TabIndex = 0; 309 | this.ctlIgnoreNearFingers.Text = "Ignore input from fingers not touching the trackpad surface"; 310 | this.ctlIgnoreNearFingers.UseVisualStyleBackColor = true; 311 | // 312 | // ctlIgnoreButtonFinger 313 | // 314 | this.ctlIgnoreButtonFinger.Location = new System.Drawing.Point(17, 58); 315 | this.ctlIgnoreButtonFinger.Name = "ctlIgnoreButtonFinger"; 316 | this.ctlIgnoreButtonFinger.Size = new System.Drawing.Size(755, 41); 317 | this.ctlIgnoreButtonFinger.TabIndex = 1; 318 | this.ctlIgnoreButtonFinger.Text = "Ignore input from the finger used to click the force touch button (useful for dra" + 319 | "gging, if you use your thumb to click the button and your index finger to move t" + 320 | "he pointer, for example)"; 321 | this.ctlIgnoreButtonFinger.UseVisualStyleBackColor = true; 322 | // 323 | // ctlPalmRejection 324 | // 325 | this.ctlPalmRejection.AutoSize = true; 326 | this.ctlPalmRejection.Location = new System.Drawing.Point(17, 106); 327 | this.ctlPalmRejection.Name = "ctlPalmRejection"; 328 | this.ctlPalmRejection.Size = new System.Drawing.Size(124, 21); 329 | this.ctlPalmRejection.TabIndex = 2; 330 | this.ctlPalmRejection.Text = "Palm Rejection"; 331 | this.ctlPalmRejection.UseVisualStyleBackColor = true; 332 | // 333 | // Main 334 | // 335 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); 336 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 337 | this.ClientSize = new System.Drawing.Size(815, 582); 338 | this.Controls.Add(this.groupBox4); 339 | this.Controls.Add(this.groupBox3); 340 | this.Controls.Add(this.ctlFocusHack); 341 | this.Controls.Add(this.groupBox2); 342 | this.Controls.Add(this.groupBox1); 343 | this.Controls.Add(this.ctlApply); 344 | this.Controls.Add(this.ctlInstallDriver); 345 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 346 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 347 | this.MaximizeBox = false; 348 | this.Name = "Main"; 349 | this.Text = "Magic Trackpad 2 Control Panel"; 350 | this.Load += new System.EventHandler(this.Main_Load); 351 | ((System.ComponentModel.ISupportInitialize)(this.ctlFeedback)).EndInit(); 352 | this.groupBox1.ResumeLayout(false); 353 | this.groupBox1.PerformLayout(); 354 | this.groupBox2.ResumeLayout(false); 355 | this.groupBox2.PerformLayout(); 356 | this.groupBox3.ResumeLayout(false); 357 | this.groupBox3.PerformLayout(); 358 | this.groupBox4.ResumeLayout(false); 359 | this.groupBox4.PerformLayout(); 360 | this.ResumeLayout(false); 361 | this.PerformLayout(); 362 | 363 | } 364 | 365 | #endregion 366 | 367 | private System.Windows.Forms.Button ctlInstallDriver; 368 | private System.Windows.Forms.Button ctlApply; 369 | private System.Windows.Forms.TrackBar ctlFeedback; 370 | private System.Windows.Forms.Label ctlLightLabel; 371 | private System.Windows.Forms.Label ctlMediumLabel; 372 | private System.Windows.Forms.Label ctlFirmLabel; 373 | private System.Windows.Forms.CheckBox ctlSilentClicking; 374 | private System.Windows.Forms.RadioButton ctlMacOSClickOptions; 375 | private System.Windows.Forms.GroupBox groupBox1; 376 | private System.Windows.Forms.GroupBox groupBox2; 377 | private System.Windows.Forms.RadioButton ctlMaximumFeedback; 378 | private System.Windows.Forms.RadioButton ctlDisableFeedback; 379 | private System.Windows.Forms.TextBox ctlFocusHack; 380 | private System.Windows.Forms.GroupBox groupBox3; 381 | private System.Windows.Forms.Label ctlStopSizeLabel; 382 | private System.Windows.Forms.TextBox ctlStopSizeValue; 383 | private System.Windows.Forms.Label ctlStopPressureLabel; 384 | private System.Windows.Forms.TextBox ctlStopPressureValue; 385 | private System.Windows.Forms.RadioButton ctlStopSize; 386 | private System.Windows.Forms.RadioButton ctlStopPressure; 387 | private System.Windows.Forms.RadioButton ctlStopDoNothing; 388 | private System.Windows.Forms.GroupBox groupBox4; 389 | private System.Windows.Forms.CheckBox ctlIgnoreButtonFinger; 390 | private System.Windows.Forms.CheckBox ctlIgnoreNearFingers; 391 | private System.Windows.Forms.CheckBox ctlPalmRejection; 392 | } 393 | } 394 | 395 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace AmtPtpControlPanel 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new Main()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AmtPtpControlPanel")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AmtPtpControlPanel")] 13 | [assembly: AssemblyCopyright("Copyright © 2024")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ee1c7a99-9593-4d6a-889b-d75eea2de6ab")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace AmtPtpControlPanel.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AmtPtpControlPanel.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 65 | /// 66 | internal static System.Drawing.Icon Icon1 { 67 | get { 68 | object obj = ResourceManager.GetObject("Icon1", resourceCulture); 69 | return ((System.Drawing.Icon)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\Icon1.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | 12 | namespace AmtPtpControlPanel.Properties 13 | { 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 17 | { 18 | 19 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 20 | 21 | public static Settings Default 22 | { 23 | get 24 | { 25 | return defaultInstance; 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AmtPtpControlPanel/Resources/Icon1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maashrafh/MagicTrackpad2ForWindows/971609319bd85e80e667ae8445b9b1053fadef66/AmtPtpControlPanel/Resources/Icon1.ico -------------------------------------------------------------------------------- /AmtPtpControlPanel/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 54 | 55 | 56 | 57 | true 58 | true 59 | 60 | 61 | 62 | 63 | 64 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/AmtPtpDevice.wprp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 25 | 28 | 29 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/Device.c: -------------------------------------------------------------------------------- 1 | // Device.c: Device handling events for driver. 2 | 3 | #include 4 | #include "device.tmh" 5 | 6 | _IRQL_requires_(PASSIVE_LEVEL) 7 | static const struct BCM5974_CONFIG* 8 | AmtPtpGetDeviceConfig( 9 | _In_ USB_DEVICE_DESCRIPTOR deviceInfo 10 | ) 11 | { 12 | USHORT id = deviceInfo.idProduct; 13 | const struct BCM5974_CONFIG *cfg; 14 | 15 | for (cfg = Bcm5974ConfigTable; cfg->ansi; ++cfg) { 16 | if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) { 17 | return cfg; 18 | } 19 | } 20 | 21 | return NULL; 22 | } 23 | 24 | _IRQL_requires_(PASSIVE_LEVEL) 25 | NTSTATUS 26 | AmtPtpCreateDevice( 27 | _In_ WDFDRIVER Driver, 28 | _Inout_ PWDFDEVICE_INIT DeviceInit 29 | ) 30 | { 31 | WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; 32 | WDF_DEVICE_PNP_CAPABILITIES pnpCaps; 33 | WDF_OBJECT_ATTRIBUTES deviceAttributes; 34 | PDEVICE_CONTEXT deviceContext; 35 | WDFDEVICE device; 36 | NTSTATUS status; 37 | 38 | UNREFERENCED_PARAMETER(Driver); 39 | PAGED_CODE(); 40 | 41 | TraceEvents( 42 | TRACE_LEVEL_INFORMATION, 43 | TRACE_DRIVER, 44 | "%!FUNC! Entry" 45 | ); 46 | 47 | // Initialize Power Callback 48 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); 49 | 50 | // Initialize PNP power event callbacks 51 | pnpPowerCallbacks.EvtDevicePrepareHardware = AmtPtpEvtDevicePrepareHardware; 52 | pnpPowerCallbacks.EvtDeviceD0Entry = AmtPtpEvtDeviceD0Entry; 53 | pnpPowerCallbacks.EvtDeviceD0Exit = AmtPtpEvtDeviceD0Exit; 54 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); 55 | 56 | // Create WDF device object 57 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); 58 | 59 | status = WdfDeviceCreate( 60 | &DeviceInit, 61 | &deviceAttributes, 62 | &device 63 | ); 64 | 65 | if (!NT_SUCCESS(status)) { 66 | TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, 67 | "%!FUNC! WdfDeviceCreate failed with Status code %!STATUS!", status); 68 | return status; 69 | } 70 | 71 | // 72 | // Get a pointer to the device context structure that we just associated 73 | // with the device object. We define this structure in the device.h 74 | // header file. DeviceGetContext is an inline function generated by 75 | // using the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro in device.h. 76 | // This function will do the type checking and return the device context. 77 | // If you pass a wrong object handle it will return NULL and assert if 78 | // run under framework verifier mode. 79 | // 80 | deviceContext = DeviceGetContext(device); 81 | 82 | // 83 | // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so 84 | // that you don't get the popup in usermode 85 | // when you surprise remove the device. 86 | // 87 | WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); 88 | pnpCaps.SurpriseRemovalOK = WdfTrue; 89 | WdfDeviceSetPnpCapabilities( 90 | device, 91 | &pnpCaps 92 | ); 93 | 94 | // 95 | // Create a device interface so that applications can find and talk 96 | // to us. 97 | // 98 | status = WdfDeviceCreateDeviceInterface( 99 | device, 100 | &GUID_DEVINTERFACE_AmtPtpDevice, 101 | NULL // ReferenceString 102 | ); 103 | 104 | if (NT_SUCCESS(status)) { 105 | // 106 | // Initialize the I/O Package and any Queues 107 | // 108 | status = AmtPtpDeviceQueueInitialize(device); 109 | } 110 | 111 | TraceEvents( 112 | TRACE_LEVEL_INFORMATION, 113 | TRACE_DRIVER, 114 | "%!FUNC! Exit" 115 | ); 116 | 117 | return status; 118 | } 119 | 120 | NTSTATUS 121 | AmtPtpEvtDevicePrepareHardware( 122 | _In_ WDFDEVICE Device, 123 | _In_ WDFCMRESLIST ResourceList, 124 | _In_ WDFCMRESLIST ResourceListTranslated 125 | ) 126 | { 127 | 128 | NTSTATUS status; 129 | PDEVICE_CONTEXT pDeviceContext; 130 | ULONG waitWakeEnable; 131 | WDF_USB_DEVICE_INFORMATION deviceInfo; 132 | 133 | waitWakeEnable = FALSE; 134 | 135 | UNREFERENCED_PARAMETER(ResourceList); 136 | UNREFERENCED_PARAMETER(ResourceListTranslated); 137 | PAGED_CODE(); 138 | 139 | TraceEvents( 140 | TRACE_LEVEL_INFORMATION, 141 | TRACE_DRIVER, 142 | "%!FUNC! Entry" 143 | ); 144 | 145 | status = STATUS_SUCCESS; 146 | pDeviceContext = DeviceGetContext(Device); 147 | 148 | if (pDeviceContext->UsbDevice == NULL) { 149 | status = WdfUsbTargetDeviceCreate(Device, 150 | WDF_NO_OBJECT_ATTRIBUTES, 151 | &pDeviceContext->UsbDevice 152 | ); 153 | 154 | if (!NT_SUCCESS(status)) { 155 | TraceEvents( 156 | TRACE_LEVEL_ERROR, 157 | TRACE_DRIVER, 158 | "%!FUNC! WdfUsbTargetDeviceCreate failed with Status code %!STATUS!", 159 | status 160 | ); 161 | return status; 162 | } 163 | } 164 | 165 | // Retrieve device information 166 | WdfUsbTargetDeviceGetDeviceDescriptor( 167 | pDeviceContext->UsbDevice, 168 | &pDeviceContext->DeviceDescriptor 169 | ); 170 | 171 | if (NT_SUCCESS(status)) { 172 | // Get correct configuration from conf store 173 | pDeviceContext->DeviceInfo = AmtPtpGetDeviceConfig(pDeviceContext->DeviceDescriptor); 174 | if (pDeviceContext->DeviceInfo == NULL) { 175 | status = STATUS_INVALID_DEVICE_STATE; 176 | TraceEvents( 177 | TRACE_LEVEL_ERROR, 178 | TRACE_DEVICE, 179 | "%!FUNC! failed because device is not found in registry." 180 | ); 181 | TraceLoggingWrite( 182 | g_hAmtPtpDeviceTraceProvider, 183 | EVENT_DEVICE_IDENTIFICATION, 184 | TraceLoggingString("AmtPtpEvtDevicePrepareHardware", "Routine"), 185 | TraceLoggingUInt16(pDeviceContext->DeviceDescriptor.idProduct, "idProduct"), 186 | TraceLoggingUInt16(pDeviceContext->DeviceDescriptor.idVendor, "idVendor"), 187 | TraceLoggingString(EVENT_DEVICE_ID_SUBTYPE_NOTFOUND, EVENT_DRIVER_FUNC_SUBTYPE) 188 | ); 189 | return status; 190 | } 191 | } 192 | 193 | // 194 | // Retrieve USBD version information, port driver capabilites and device 195 | // capabilites such as speed, power, etc. 196 | // 197 | WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo); 198 | status = WdfUsbTargetDeviceRetrieveInformation( 199 | pDeviceContext->UsbDevice, 200 | &deviceInfo 201 | ); 202 | 203 | if (NT_SUCCESS(status)) { 204 | TraceEvents( 205 | TRACE_LEVEL_INFORMATION, 206 | TRACE_DEVICE, 207 | "%!FUNC! IsDeviceHighSpeed: %s", 208 | (deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE"); 209 | 210 | TraceEvents( 211 | TRACE_LEVEL_INFORMATION, 212 | TRACE_DEVICE, 213 | "%!FUNC! IsDeviceSelfPowered: %s", 214 | (deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE"); 215 | 216 | waitWakeEnable = deviceInfo.Traits & 217 | WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE; 218 | 219 | TraceEvents( 220 | TRACE_LEVEL_INFORMATION, 221 | TRACE_DEVICE, 222 | "%!FUNC! IsDeviceRemoteWakeable: %s", 223 | waitWakeEnable ? "TRUE" : "FALSE"); 224 | 225 | // 226 | // Save these for use later. 227 | // 228 | pDeviceContext->UsbDeviceTraits = deviceInfo.Traits; 229 | } else { 230 | pDeviceContext->UsbDeviceTraits = 0; 231 | } 232 | 233 | // Select interface to use 234 | status = SelectInterruptInterface(Device); 235 | if (!NT_SUCCESS(status)) { 236 | TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! SelectInterruptInterface failed with %!STATUS!", status); 237 | return status; 238 | } 239 | 240 | // Set up interrupt 241 | status = AmtPtpConfigContReaderForInterruptEndPoint(pDeviceContext); 242 | if (!NT_SUCCESS(status)) { 243 | TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, "%!FUNC! AmtPtpConfigContReaderForInterruptEndPoint failed with %!STATUS!", status); 244 | return status; 245 | } 246 | 247 | // Set default settings 248 | pDeviceContext->IsButtonReportOn = TRUE; 249 | pDeviceContext->IsSurfaceReportOn = TRUE; 250 | 251 | TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit"); 252 | return status; 253 | } 254 | 255 | _IRQL_requires_(PASSIVE_LEVEL) 256 | NTSTATUS 257 | AmtPtpGetWellspringMode( 258 | _In_ PDEVICE_CONTEXT DeviceContext, 259 | _Out_ BOOL* IsWellspringModeOn 260 | ) 261 | { 262 | 263 | NTSTATUS status; 264 | WDF_USB_CONTROL_SETUP_PACKET setupPacket; 265 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 266 | ULONG cbTransferred; 267 | WDFMEMORY bufHandle = NULL; 268 | unsigned char* buffer; 269 | 270 | status = STATUS_SUCCESS; 271 | 272 | TraceEvents( 273 | TRACE_LEVEL_INFORMATION, 274 | TRACE_DRIVER, 275 | "%!FUNC! Entry" 276 | ); 277 | 278 | // Type 3 does not need a mode switch. 279 | if (DeviceContext->DeviceInfo->tp_type == TYPE3) { 280 | *IsWellspringModeOn = TRUE; 281 | return STATUS_SUCCESS; 282 | } 283 | 284 | status = WdfMemoryCreate( 285 | WDF_NO_OBJECT_ATTRIBUTES, 286 | PagedPool, 287 | POOL_TAG_PTP_CONTROL, 288 | DeviceContext->DeviceInfo->um_size, 289 | &bufHandle, 290 | &buffer 291 | ); 292 | 293 | if (!NT_SUCCESS(status)) { 294 | goto cleanup; 295 | } 296 | 297 | RtlZeroMemory( 298 | buffer, 299 | DeviceContext->DeviceInfo->um_size 300 | ); 301 | 302 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 303 | &memoryDescriptor, 304 | buffer, 305 | sizeof(DeviceContext->DeviceInfo->um_size) 306 | ); 307 | 308 | WDF_USB_CONTROL_SETUP_PACKET_INIT( 309 | &setupPacket, 310 | BmRequestDeviceToHost, 311 | BmRequestToInterface, 312 | BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, 313 | (USHORT)DeviceContext->DeviceInfo->um_req_val, 314 | (USHORT)DeviceContext->DeviceInfo->um_req_idx 315 | ); 316 | 317 | // Set stuffs right 318 | setupPacket.Packet.bm.Request.Type = BmRequestClass; 319 | 320 | status = WdfUsbTargetDeviceSendControlTransferSynchronously( 321 | DeviceContext->UsbDevice, 322 | WDF_NO_HANDLE, 323 | NULL, 324 | &setupPacket, 325 | &memoryDescriptor, 326 | &cbTransferred 327 | ); 328 | 329 | // Behavior mismatch: Actual device does not transfer bytes as expected (in length) 330 | // So we do not check um_size as a temporary workaround. 331 | if (!NT_SUCCESS(status)) { 332 | TraceEvents( 333 | TRACE_LEVEL_ERROR, 334 | TRACE_DEVICE, 335 | "%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Read) failed with %!STATUS!, cbTransferred = %llu, um_size = %d", 336 | status, 337 | cbTransferred, 338 | DeviceContext->DeviceInfo->um_size 339 | ); 340 | goto cleanup; 341 | } 342 | 343 | // Check mode switch 344 | unsigned char wellspringBit = buffer[DeviceContext->DeviceInfo->um_switch_idx]; 345 | *IsWellspringModeOn = wellspringBit == DeviceContext->DeviceInfo->um_switch_on ? TRUE : FALSE; 346 | 347 | cleanup: 348 | TraceEvents( 349 | TRACE_LEVEL_INFORMATION, 350 | TRACE_DRIVER, 351 | "%!FUNC! Exit" 352 | ); 353 | 354 | WdfObjectDelete(bufHandle); 355 | return status; 356 | 357 | } 358 | 359 | _IRQL_requires_(PASSIVE_LEVEL) 360 | ULONG ReadSettingValue( 361 | _In_ PWCHAR SettingName, 362 | _In_ ULONG DefaultValue 363 | ) 364 | { 365 | WDFKEY key = NULL; 366 | NTSTATUS status; 367 | ULONG value = DefaultValue; 368 | UNICODE_STRING valueName; 369 | 370 | TraceEvents( 371 | TRACE_LEVEL_INFORMATION, 372 | TRACE_DRIVER, 373 | "%!FUNC! Entry (%ws)", 374 | SettingName 375 | ); 376 | 377 | status = WdfDriverOpenParametersRegistryKey( 378 | WdfGetDriver(), 379 | KEY_READ, 380 | WDF_NO_OBJECT_ATTRIBUTES, 381 | &key); 382 | 383 | if (!NT_SUCCESS(status)) 384 | { 385 | key = NULL; 386 | TraceEvents( 387 | TRACE_LEVEL_ERROR, 388 | TRACE_DEVICE, 389 | "%!FUNC! WdfDriverOpenParametersRegistryKey failed with %!STATUS!", 390 | status 391 | ); 392 | goto cleanup; 393 | } 394 | 395 | RtlInitUnicodeString(&valueName, SettingName); 396 | 397 | status = WdfRegistryQueryULong(key, &valueName, &value); 398 | if (!NT_SUCCESS(status)) 399 | { 400 | value = DefaultValue; 401 | TraceEvents( 402 | TRACE_LEVEL_ERROR, 403 | TRACE_DEVICE, 404 | "%!FUNC! WdfRegistryQueryULong failed with %!STATUS!", 405 | status 406 | ); 407 | goto cleanup; 408 | } 409 | 410 | TraceEvents( 411 | TRACE_LEVEL_INFORMATION, 412 | TRACE_DRIVER, 413 | "%!FUNC! read value of %ws is %u", 414 | SettingName, 415 | value 416 | ); 417 | 418 | cleanup: 419 | if (key != NULL) 420 | { 421 | WdfRegistryClose(key); 422 | } 423 | 424 | TraceEvents( 425 | TRACE_LEVEL_INFORMATION, 426 | TRACE_DRIVER, 427 | "%!FUNC! Exit" 428 | ); 429 | 430 | return value; 431 | } 432 | 433 | _IRQL_requires_(PASSIVE_LEVEL) 434 | NTSTATUS 435 | AmtPtpSetWellspringMode( 436 | _In_ PDEVICE_CONTEXT DeviceContext, 437 | _In_ BOOL IsWellspringModeOn 438 | ) 439 | { 440 | 441 | NTSTATUS status; 442 | WDF_USB_CONTROL_SETUP_PACKET setupPacket; 443 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 444 | ULONG cbTransferred; 445 | WDFMEMORY bufHandle = NULL; 446 | unsigned char* buffer; 447 | 448 | if (IsWellspringModeOn) 449 | { 450 | ULONG feedbackClick = ReadSettingValue(L"FeedbackClick", 0x08081E); 451 | ULONG feedbackRelease = ReadSettingValue(L"FeedbackRelease", 0x020218); 452 | 453 | AmtPtpSetHapticFeedback(DeviceContext, feedbackClick, feedbackRelease); 454 | } 455 | 456 | TraceEvents( 457 | TRACE_LEVEL_INFORMATION, 458 | TRACE_DRIVER, 459 | "%!FUNC! Entry" 460 | ); 461 | 462 | // Type 3 does not need a mode switch. 463 | // However, turn mode on or off as requested. 464 | if (DeviceContext->DeviceInfo->tp_type == TYPE3) { 465 | DeviceContext->IsWellspringModeOn = IsWellspringModeOn; 466 | return STATUS_SUCCESS; 467 | } 468 | 469 | status = WdfMemoryCreate( 470 | WDF_NO_OBJECT_ATTRIBUTES, 471 | PagedPool, 472 | POOL_TAG_PTP_CONTROL, 473 | DeviceContext->DeviceInfo->um_size, 474 | &bufHandle, 475 | &buffer 476 | ); 477 | 478 | if (!NT_SUCCESS(status)) { 479 | goto cleanup; 480 | } 481 | 482 | RtlZeroMemory( 483 | buffer, 484 | DeviceContext->DeviceInfo->um_size 485 | ); 486 | 487 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 488 | &memoryDescriptor, 489 | buffer, 490 | sizeof(DeviceContext->DeviceInfo->um_size) 491 | ); 492 | 493 | WDF_USB_CONTROL_SETUP_PACKET_INIT( 494 | &setupPacket, 495 | BmRequestDeviceToHost, 496 | BmRequestToInterface, 497 | BCM5974_WELLSPRING_MODE_READ_REQUEST_ID, 498 | (USHORT) DeviceContext->DeviceInfo->um_req_val, 499 | (USHORT) DeviceContext->DeviceInfo->um_req_idx 500 | ); 501 | 502 | // Set stuffs right 503 | setupPacket.Packet.bm.Request.Type = BmRequestClass; 504 | 505 | status = WdfUsbTargetDeviceSendControlTransferSynchronously( 506 | DeviceContext->UsbDevice, 507 | WDF_NO_HANDLE, 508 | NULL, 509 | &setupPacket, 510 | &memoryDescriptor, 511 | &cbTransferred 512 | ); 513 | 514 | // Behavior mismatch: Actual device does not transfer bytes as expected (in length) 515 | // So we do not check um_size as a temporary workaround. 516 | if (!NT_SUCCESS(status)) { 517 | TraceEvents( 518 | TRACE_LEVEL_ERROR, 519 | TRACE_DEVICE, 520 | "%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Read) failed with %!STATUS!, cbTransferred = %llu, um_size = %d", 521 | status, 522 | cbTransferred, 523 | DeviceContext->DeviceInfo->um_size 524 | ); 525 | goto cleanup; 526 | } 527 | 528 | // Apply the mode switch 529 | buffer[DeviceContext->DeviceInfo->um_switch_idx] = IsWellspringModeOn ? 530 | (unsigned char) DeviceContext->DeviceInfo->um_switch_on : 531 | (unsigned char) DeviceContext->DeviceInfo->um_switch_off; 532 | 533 | // Write configuration 534 | WDF_USB_CONTROL_SETUP_PACKET_INIT( 535 | &setupPacket, 536 | BmRequestHostToDevice, 537 | BmRequestToInterface, 538 | BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID, 539 | (USHORT) DeviceContext->DeviceInfo->um_req_val, 540 | (USHORT) DeviceContext->DeviceInfo->um_req_idx 541 | ); 542 | 543 | // Set stuffs right 544 | setupPacket.Packet.bm.Request.Type = BmRequestClass; 545 | 546 | status = WdfUsbTargetDeviceSendControlTransferSynchronously( 547 | DeviceContext->UsbDevice, 548 | WDF_NO_HANDLE, 549 | NULL, 550 | &setupPacket, 551 | &memoryDescriptor, 552 | &cbTransferred 553 | ); 554 | 555 | if (!NT_SUCCESS(status)) { 556 | TraceEvents( 557 | TRACE_LEVEL_ERROR, 558 | TRACE_DEVICE, 559 | "%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Write) failed with %!STATUS!", 560 | status 561 | ); 562 | goto cleanup; 563 | } 564 | 565 | // Set status 566 | DeviceContext->IsWellspringModeOn = IsWellspringModeOn; 567 | 568 | cleanup: 569 | TraceEvents( 570 | TRACE_LEVEL_INFORMATION, 571 | TRACE_DRIVER, 572 | "%!FUNC! Exit" 573 | ); 574 | 575 | WdfObjectDelete(bufHandle); 576 | return status; 577 | 578 | } 579 | 580 | _IRQL_requires_(PASSIVE_LEVEL) 581 | NTSTATUS 582 | AmtPtpSetHapticFeedback( // --> Based on: https://github.com/dos1/Linux-Magic-Trackpad-2-Driver/blob/master/linux/drivers/hid/hid-magicmouse.c 583 | _In_ PDEVICE_CONTEXT DeviceContext, 584 | _In_ ULONG FeedbackClick, 585 | _In_ ULONG FeedbackRelease 586 | ) 587 | { 588 | NTSTATUS status = STATUS_UNSUCCESSFUL; 589 | WDFMEMORY bufHandle = NULL; 590 | PBYTE buffer; 591 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 592 | WDF_USB_CONTROL_SETUP_PACKET setupPacket; 593 | ULONG cbTransferred; 594 | CONST BYTE mt2Click[] = { 0x22, 0x01, 0x00, 0x78, 0x02, 0x00, 0x24, 0x30, 0x06, 0x01, 0x00, 0x18, 0x48, 0x13 }; 595 | CONST BYTE mt2Release[] = { 0x23, 0x01, 0x00, 0x78, 0x02, 0x00, 0x24, 0x30, 0x06, 0x01, 0x00, 0x18, 0x48, 0x13 }; // WARNING: sizeof(mt2Release) MUST BE == TO sizeof(mt2Click)! 596 | 597 | TraceEvents( 598 | TRACE_LEVEL_INFORMATION, 599 | TRACE_DRIVER, 600 | "%!FUNC! Entry" 601 | ); 602 | 603 | status = WdfMemoryCreate( 604 | WDF_NO_OBJECT_ATTRIBUTES, 605 | PagedPool, 606 | POOL_TAG_PTP_CONTROL, 607 | sizeof(mt2Click), 608 | &bufHandle, 609 | &buffer 610 | ); 611 | 612 | if (!NT_SUCCESS(status)) { 613 | goto cleanup; 614 | } 615 | 616 | RtlCopyMemory( 617 | buffer, 618 | mt2Click, 619 | sizeof(mt2Click) 620 | ); 621 | 622 | buffer[2] = (BYTE)(FeedbackClick >> 0); 623 | buffer[5] = (BYTE)(FeedbackClick >> 8); 624 | buffer[10] = (BYTE)(FeedbackClick >> 16); 625 | 626 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 627 | &memoryDescriptor, 628 | buffer, 629 | sizeof(mt2Click) 630 | ); 631 | 632 | WDF_USB_CONTROL_SETUP_PACKET_INIT( 633 | &setupPacket, 634 | BmRequestHostToDevice, 635 | BmRequestToInterface, 636 | 9, 637 | 0x0322, 638 | 2 639 | ); 640 | 641 | setupPacket.Packet.bm.Request.Type = BmRequestClass; 642 | 643 | status = WdfUsbTargetDeviceSendControlTransferSynchronously( 644 | DeviceContext->UsbDevice, 645 | WDF_NO_HANDLE, 646 | NULL, 647 | &setupPacket, 648 | &memoryDescriptor, 649 | &cbTransferred 650 | ); 651 | 652 | if (!NT_SUCCESS(status)) { 653 | TraceEvents( 654 | TRACE_LEVEL_ERROR, 655 | TRACE_DEVICE, 656 | "%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Write) failed with %!STATUS!", 657 | status 658 | ); 659 | goto cleanup; 660 | } 661 | 662 | RtlCopyMemory( 663 | buffer, 664 | mt2Release, 665 | sizeof(mt2Release) 666 | ); 667 | 668 | buffer[2] = (BYTE)(FeedbackRelease >> 0); 669 | buffer[5] = (BYTE)(FeedbackRelease >> 8); 670 | buffer[10] = (BYTE)(FeedbackRelease >> 16); 671 | 672 | WDF_USB_CONTROL_SETUP_PACKET_INIT( 673 | &setupPacket, 674 | BmRequestHostToDevice, 675 | BmRequestToInterface, 676 | 9, 677 | 0x0323, 678 | 2 679 | ); 680 | 681 | setupPacket.Packet.bm.Request.Type = BmRequestClass; 682 | 683 | status = WdfUsbTargetDeviceSendControlTransferSynchronously( 684 | DeviceContext->UsbDevice, 685 | WDF_NO_HANDLE, 686 | NULL, 687 | &setupPacket, 688 | &memoryDescriptor, 689 | &cbTransferred 690 | ); 691 | 692 | if (!NT_SUCCESS(status)) { 693 | TraceEvents( 694 | TRACE_LEVEL_ERROR, 695 | TRACE_DEVICE, 696 | "%!FUNC! WdfUsbTargetDeviceSendControlTransferSynchronously (Write) failed with %!STATUS!", 697 | status 698 | ); 699 | goto cleanup; 700 | } 701 | 702 | cleanup: 703 | TraceEvents( 704 | TRACE_LEVEL_INFORMATION, 705 | TRACE_DRIVER, 706 | "%!FUNC! Exit" 707 | ); 708 | 709 | WdfObjectDelete(bufHandle); 710 | return status; 711 | } 712 | 713 | NTSTATUS 714 | AmtPtpEvtDeviceD0Entry( 715 | _In_ WDFDEVICE Device, 716 | _In_ WDF_POWER_DEVICE_STATE PreviousState 717 | ) 718 | { 719 | PDEVICE_CONTEXT pDeviceContext; 720 | NTSTATUS status; 721 | BOOLEAN isTargetStarted; 722 | 723 | pDeviceContext = DeviceGetContext(Device); 724 | isTargetStarted = FALSE; 725 | 726 | TraceEvents( 727 | TRACE_LEVEL_INFORMATION, 728 | TRACE_DRIVER, 729 | "%!FUNC! -->AmtPtpDeviceEvtDeviceD0Entry - coming from %s", 730 | DbgDevicePowerString(PreviousState) 731 | ); 732 | 733 | // Check wellspring mode 734 | if (pDeviceContext->IsButtonReportOn || pDeviceContext->IsWellspringModeOn) { 735 | TraceEvents( 736 | TRACE_LEVEL_INFORMATION, 737 | TRACE_DRIVER, 738 | "%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Start Wellspring Mode" 739 | ); 740 | 741 | status = AmtPtpSetWellspringMode( 742 | pDeviceContext, 743 | TRUE 744 | ); 745 | 746 | if (!NT_SUCCESS(status)) { 747 | TraceEvents( 748 | TRACE_LEVEL_WARNING, 749 | TRACE_DRIVER, 750 | "%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Start Wellspring Mode failed with %!STATUS!", 751 | status 752 | ); 753 | } 754 | } 755 | 756 | // Get current time counter 757 | QueryPerformanceCounter( 758 | &pDeviceContext->PerfCounter 759 | ); 760 | 761 | // 762 | // Since continuous reader is configured for this interrupt-pipe, we must explicitly start 763 | // the I/O target to get the framework to post read requests. 764 | // 765 | status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe)); 766 | if (!NT_SUCCESS(status)) { 767 | TraceEvents( 768 | TRACE_LEVEL_ERROR, 769 | TRACE_DRIVER, 770 | "%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry - Failed to start interrupt pipe %!STATUS!", 771 | status 772 | ); 773 | goto End; 774 | } 775 | 776 | isTargetStarted = TRUE; 777 | 778 | End: 779 | 780 | if (!NT_SUCCESS(status)) { 781 | // 782 | // Failure in D0Entry will lead to device being removed. So let us stop the continuous 783 | // reader in preparation for the ensuing remove. 784 | // 785 | if (isTargetStarted) { 786 | WdfIoTargetStop( 787 | WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe), 788 | WdfIoTargetCancelSentIo 789 | ); 790 | } 791 | } 792 | 793 | TraceEvents( 794 | TRACE_LEVEL_INFORMATION, 795 | TRACE_DRIVER, 796 | "%!FUNC! <--AmtPtpDeviceEvtDeviceD0Entry" 797 | ); 798 | 799 | return status; 800 | } 801 | 802 | NTSTATUS 803 | AmtPtpEvtDeviceD0Exit( 804 | _In_ WDFDEVICE Device, 805 | _In_ WDF_POWER_DEVICE_STATE TargetState 806 | ) 807 | { 808 | PDEVICE_CONTEXT pDeviceContext; 809 | NTSTATUS status; 810 | 811 | PAGED_CODE(); 812 | status = STATUS_SUCCESS; 813 | 814 | TraceEvents( 815 | TRACE_LEVEL_INFORMATION, 816 | TRACE_DRIVER, 817 | "%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - moving to %s", 818 | DbgDevicePowerString(TargetState) 819 | ); 820 | 821 | pDeviceContext = DeviceGetContext(Device); 822 | 823 | // Stop IO Pipe. 824 | WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget( 825 | pDeviceContext->InterruptPipe), 826 | WdfIoTargetCancelSentIo 827 | ); 828 | 829 | // Cancel Wellspring mode. 830 | TraceEvents( 831 | TRACE_LEVEL_INFORMATION, 832 | TRACE_DRIVER, 833 | "%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - Cancel Wellspring Mode" 834 | ); 835 | 836 | status = AmtPtpSetWellspringMode( 837 | pDeviceContext, 838 | FALSE 839 | ); 840 | 841 | if (!NT_SUCCESS(status)) { 842 | TraceEvents( 843 | TRACE_LEVEL_WARNING, 844 | TRACE_DRIVER, 845 | "%!FUNC! -->AmtPtpDeviceEvtDeviceD0Exit - Cancel Wellspring Mode failed with %!STATUS!", 846 | status 847 | ); 848 | } 849 | 850 | TraceEvents( 851 | TRACE_LEVEL_INFORMATION, 852 | TRACE_DRIVER, 853 | "%!FUNC! <--AmtPtpDeviceEvtDeviceD0Exit" 854 | ); 855 | 856 | return status; 857 | } 858 | 859 | _IRQL_requires_(PASSIVE_LEVEL) 860 | NTSTATUS 861 | SelectInterruptInterface( 862 | _In_ WDFDEVICE Device 863 | ) 864 | { 865 | WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams; 866 | NTSTATUS status = STATUS_SUCCESS; 867 | PDEVICE_CONTEXT pDeviceContext; 868 | WDFUSBPIPE pipe; 869 | WDF_USB_PIPE_INFORMATION pipeInfo; 870 | UCHAR index; 871 | UCHAR numberConfiguredPipes; 872 | WDFUSBINTERFACE usbInterface; 873 | 874 | PAGED_CODE(); 875 | 876 | pDeviceContext = DeviceGetContext(Device); 877 | WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams); 878 | usbInterface = WdfUsbTargetDeviceGetInterface( 879 | pDeviceContext->UsbDevice, 880 | 0 881 | ); 882 | 883 | if (NULL == usbInterface) { 884 | status = STATUS_UNSUCCESSFUL; 885 | TraceEvents( 886 | TRACE_LEVEL_ERROR, 887 | TRACE_DEVICE, 888 | "%!FUNC! WdfUsbTargetDeviceGetInterface 0 failed %!STATUS!", 889 | status 890 | ); 891 | return status; 892 | } 893 | 894 | configParams.Types.SingleInterface.ConfiguredUsbInterface = usbInterface; 895 | configParams.Types.SingleInterface.NumberConfiguredPipes = WdfUsbInterfaceGetNumConfiguredPipes(usbInterface); 896 | 897 | pDeviceContext->UsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface; 898 | numberConfiguredPipes = configParams.Types.SingleInterface.NumberConfiguredPipes; 899 | 900 | // 901 | // Get pipe handles 902 | // 903 | for (index = 0; index < numberConfiguredPipes; index++) { 904 | 905 | WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); 906 | 907 | pipe = WdfUsbInterfaceGetConfiguredPipe( 908 | pDeviceContext->UsbInterface, 909 | index, //PipeIndex, 910 | &pipeInfo 911 | ); 912 | 913 | // 914 | // Tell the framework that it's okay to read less than 915 | // MaximumPacketSize 916 | // 917 | WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pipe); 918 | 919 | if (WdfUsbPipeTypeInterrupt == pipeInfo.PipeType) { 920 | pDeviceContext->InterruptPipe = pipe; 921 | break; 922 | } 923 | 924 | } 925 | 926 | // 927 | // If we didn't find interrupt pipe, fail the start. 928 | // 929 | if (!pDeviceContext->InterruptPipe) { 930 | status = STATUS_INVALID_DEVICE_STATE; 931 | TraceEvents( 932 | TRACE_LEVEL_ERROR, 933 | TRACE_DEVICE, 934 | "%!FUNC! Device is not configured properly %!STATUS!", 935 | status 936 | ); 937 | 938 | return status; 939 | } 940 | 941 | return status; 942 | } 943 | 944 | _IRQL_requires_(PASSIVE_LEVEL) 945 | PCHAR 946 | DbgDevicePowerString( 947 | _In_ WDF_POWER_DEVICE_STATE Type 948 | ) 949 | { 950 | switch (Type) 951 | { 952 | case WdfPowerDeviceInvalid: 953 | return "WdfPowerDeviceInvalid"; 954 | case WdfPowerDeviceD0: 955 | return "WdfPowerDeviceD0"; 956 | case WdfPowerDeviceD1: 957 | return "WdfPowerDeviceD1"; 958 | case WdfPowerDeviceD2: 959 | return "WdfPowerDeviceD2"; 960 | case WdfPowerDeviceD3: 961 | return "WdfPowerDeviceD3"; 962 | case WdfPowerDeviceD3Final: 963 | return "WdfPowerDeviceD3Final"; 964 | case WdfPowerDevicePrepareForHibernation: 965 | return "WdfPowerDevicePrepareForHibernation"; 966 | case WdfPowerDeviceMaximum: 967 | return "WdfPowerDeviceMaximum"; 968 | default: 969 | return "UnKnown Device Power State"; 970 | } 971 | } 972 | 973 | _IRQL_requires_(PASSIVE_LEVEL) 974 | NTSTATUS 975 | AmtPtpEmergResetDevice( 976 | _In_ PDEVICE_CONTEXT DeviceContext 977 | ) 978 | { 979 | 980 | NTSTATUS status; 981 | TraceEvents( 982 | TRACE_LEVEL_INFORMATION, 983 | TRACE_DRIVER, 984 | "%!FUNC! Entry"); 985 | 986 | status = AmtPtpSetWellspringMode( 987 | DeviceContext, 988 | FALSE); 989 | 990 | if (!NT_SUCCESS(status)) { 991 | TraceEvents( 992 | TRACE_LEVEL_ERROR, 993 | TRACE_DEVICE, 994 | "%!FUNC! AmtPtpSetWellspringMode failed with %!STATUS!", 995 | status); 996 | } 997 | 998 | status = AmtPtpSetWellspringMode( 999 | DeviceContext, 1000 | TRUE); 1001 | 1002 | if (!NT_SUCCESS(status)) { 1003 | TraceEvents( 1004 | TRACE_LEVEL_ERROR, 1005 | TRACE_DEVICE, 1006 | "%!FUNC! AmtPtpSetWellspringMode failed with %!STATUS!", 1007 | status); 1008 | } 1009 | 1010 | TraceEvents( 1011 | TRACE_LEVEL_INFORMATION, 1012 | TRACE_DRIVER, 1013 | "%!FUNC! Exit"); 1014 | 1015 | return status; 1016 | 1017 | } 1018 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/Driver.c: -------------------------------------------------------------------------------- 1 | // Driver.c: This file contains the driver entry points and callbacks. 2 | 3 | #include 4 | #include "driver.tmh" 5 | 6 | // Declares Windows 10 TraceLogger provider here. 7 | TRACELOGGING_DEFINE_PROVIDER( 8 | g_hAmtPtpDeviceTraceProvider, 9 | "AmtPtpDeviceTraceProvider", 10 | (0x871b1e2d, 0xcc5a, 0x4ade, 0xb7, 0x4e, 0x6c, 0xf1, 0x0, 0x4e, 0xf1, 0x49)); 11 | 12 | NTSTATUS 13 | DriverEntry( 14 | _In_ PDRIVER_OBJECT DriverObject, 15 | _In_ PUNICODE_STRING RegistryPath 16 | ) 17 | { 18 | WDF_DRIVER_CONFIG config; 19 | NTSTATUS status; 20 | WDF_OBJECT_ATTRIBUTES attributes; 21 | 22 | // Initialize tracing 23 | DriverTraceInit( 24 | DriverObject, 25 | RegistryPath 26 | ); 27 | 28 | TraceEvents( 29 | TRACE_LEVEL_INFORMATION, 30 | TRACE_DRIVER, 31 | "%!FUNC! Entry" 32 | ); 33 | 34 | // 35 | // Register a cleanup callback so that we can call WPP_CLEANUP when 36 | // the framework driver object is deleted during driver unload. 37 | // 38 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 39 | attributes.EvtCleanupCallback = AmtPtpDeviceEvtDriverContextCleanup; 40 | 41 | WDF_DRIVER_CONFIG_INIT(&config, 42 | AmtPtpDeviceEvtDeviceAdd 43 | ); 44 | 45 | status = WdfDriverCreate(DriverObject, 46 | RegistryPath, 47 | &attributes, 48 | &config, 49 | WDF_NO_HANDLE 50 | ); 51 | 52 | if (!NT_SUCCESS(status)) { 53 | TraceEvents( 54 | TRACE_LEVEL_ERROR, 55 | TRACE_DRIVER, 56 | "%!FUNC! WdfDriverCreate failed %!STATUS!", 57 | status 58 | ); 59 | TraceLoggingWrite( 60 | g_hAmtPtpDeviceTraceProvider, 61 | EVENT_DRIVER_FUNCTIONAL, 62 | TraceLoggingString("DriverEntry", "Routine"), 63 | TraceLoggingString("WdfDriverCreate", "Context"), 64 | TraceLoggingInt32(status, "Status"), 65 | TraceLoggingString(EVENT_DRIVER_FUNC_SUBTYPE_CRITFAIL, EVENT_DRIVER_FUNC_SUBTYPE) 66 | ); 67 | DriverTraceCleanup(DriverObject); 68 | return status; 69 | } 70 | 71 | TraceEvents( 72 | TRACE_LEVEL_INFORMATION, 73 | TRACE_DRIVER, 74 | "%!FUNC! Exit" 75 | ); 76 | 77 | return status; 78 | } 79 | 80 | VOID 81 | DriverTraceInit( 82 | _In_ PDRIVER_OBJECT DriverObject, 83 | _In_ PUNICODE_STRING RegistryPath 84 | ) 85 | { 86 | // Initialize WPP Tracing 87 | WPP_INIT_TRACING( 88 | DriverObject, 89 | RegistryPath 90 | ); 91 | 92 | // Initialize TraceLogger Tracing 93 | TraceLoggingRegister(g_hAmtPtpDeviceTraceProvider); 94 | } 95 | 96 | VOID 97 | DriverTraceCleanup( 98 | _In_ WDFOBJECT DriverObject 99 | ) 100 | { 101 | UNREFERENCED_PARAMETER(DriverObject); 102 | 103 | TraceLoggingUnregister(g_hAmtPtpDeviceTraceProvider); 104 | // This actually directly calls WppCleanupUm() in UMDF drivers 105 | WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER) Driver)); 106 | } 107 | 108 | NTSTATUS 109 | AmtPtpDeviceEvtDeviceAdd( 110 | _In_ WDFDRIVER Driver, 111 | _Inout_ PWDFDEVICE_INIT DeviceInit 112 | ) 113 | { 114 | NTSTATUS status = STATUS_SUCCESS; 115 | 116 | TraceEvents( 117 | TRACE_LEVEL_INFORMATION, 118 | TRACE_DRIVER, 119 | "%!FUNC! Entry" 120 | ); 121 | 122 | TraceEvents( 123 | TRACE_LEVEL_INFORMATION, 124 | TRACE_DRIVER, 125 | "%!FUNC! Set FDO driver filter" 126 | ); 127 | 128 | WdfFdoInitSetFilter(DeviceInit); 129 | 130 | status = AmtPtpCreateDevice( 131 | Driver, 132 | DeviceInit 133 | ); 134 | 135 | TraceEvents( 136 | TRACE_LEVEL_INFORMATION, 137 | TRACE_DRIVER, 138 | "%!FUNC! Exit" 139 | ); 140 | return status; 141 | } 142 | 143 | VOID 144 | AmtPtpDeviceEvtDriverContextCleanup( 145 | _In_ WDFOBJECT DriverObject 146 | ) 147 | { 148 | TraceEvents( 149 | TRACE_LEVEL_INFORMATION, 150 | TRACE_DRIVER, 151 | "%!FUNC! Entry" 152 | ); 153 | 154 | // 155 | // Stop WPP Tracing 156 | // 157 | DriverTraceCleanup(DriverObject); 158 | } 159 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/InputInterrupt.c: -------------------------------------------------------------------------------- 1 | // InputInterrupt.c: Handles device input event 2 | 3 | #include 4 | #include "InputInterrupt.tmh" 5 | 6 | _IRQL_requires_(PASSIVE_LEVEL) 7 | NTSTATUS 8 | AmtPtpConfigContReaderForInterruptEndPoint( 9 | _In_ PDEVICE_CONTEXT DeviceContext 10 | ) 11 | { 12 | 13 | WDF_USB_CONTINUOUS_READER_CONFIG contReaderConfig; 14 | NTSTATUS status; 15 | size_t transferLength = 0; 16 | 17 | TraceEvents( 18 | TRACE_LEVEL_INFORMATION, 19 | TRACE_DRIVER, 20 | "%!FUNC! Entry" 21 | ); 22 | 23 | switch (DeviceContext->DeviceInfo->tp_type) 24 | { 25 | case TYPE1: 26 | transferLength = HEADER_TYPE1 + FSIZE_TYPE1 * MAX_FINGERS; 27 | break; 28 | case TYPE2: 29 | transferLength = HEADER_TYPE2 + FSIZE_TYPE2 * MAX_FINGERS; 30 | break; 31 | case TYPE3: 32 | transferLength = HEADER_TYPE3 + FSIZE_TYPE3 * MAX_FINGERS; 33 | break; 34 | case TYPE4: 35 | transferLength = HEADER_TYPE4 + FSIZE_TYPE4 * MAX_FINGERS; 36 | break; 37 | case TYPE5: 38 | transferLength = HEADER_TYPE5 + FSIZE_TYPE5 * MAX_FINGERS; 39 | break; 40 | } 41 | 42 | if (transferLength <= 0) { 43 | status = STATUS_UNKNOWN_REVISION; 44 | return status; 45 | } 46 | 47 | WDF_USB_CONTINUOUS_READER_CONFIG_INIT( 48 | &contReaderConfig, 49 | AmtPtpEvtUsbInterruptPipeReadComplete, 50 | DeviceContext, // Context 51 | transferLength // Calculate transferred length by device information 52 | ); 53 | 54 | contReaderConfig.EvtUsbTargetPipeReadersFailed = AmtPtpEvtUsbInterruptReadersFailed; 55 | 56 | // Remember to turn it on in D0 entry 57 | status = WdfUsbTargetPipeConfigContinuousReader( 58 | DeviceContext->InterruptPipe, 59 | &contReaderConfig 60 | ); 61 | 62 | if (!NT_SUCCESS(status)) { 63 | TraceEvents( 64 | TRACE_LEVEL_ERROR, 65 | TRACE_DRIVER, 66 | "%!FUNC! AmtPtpConfigContReaderForInterruptEndPoint failed with Status code %!STATUS!", 67 | status 68 | ); 69 | return status; 70 | } 71 | 72 | TraceEvents( 73 | TRACE_LEVEL_INFORMATION, 74 | TRACE_DRIVER, 75 | "%!FUNC! Exit" 76 | ); 77 | 78 | return STATUS_SUCCESS; 79 | 80 | } 81 | 82 | _IRQL_requires_(PASSIVE_LEVEL) 83 | VOID 84 | AmtPtpEvtUsbInterruptPipeReadComplete( 85 | _In_ WDFUSBPIPE Pipe, 86 | _In_ WDFMEMORY Buffer, 87 | _In_ size_t NumBytesTransferred, 88 | _In_ WDFCONTEXT Context 89 | ) 90 | { 91 | UNREFERENCED_PARAMETER(Pipe); 92 | 93 | WDFDEVICE device; 94 | PDEVICE_CONTEXT pDeviceContext = Context; 95 | UCHAR* pBuffer = NULL; 96 | NTSTATUS status; 97 | 98 | TraceEvents( 99 | TRACE_LEVEL_INFORMATION, 100 | TRACE_DRIVER, 101 | "%!FUNC! Entry" 102 | ); 103 | 104 | device = WdfObjectContextGetObject(pDeviceContext); 105 | size_t headerSize = (unsigned int) pDeviceContext->DeviceInfo->tp_header; 106 | size_t fingerprintSize = (unsigned int) pDeviceContext->DeviceInfo->tp_fsize; 107 | 108 | if (NumBytesTransferred < headerSize || (NumBytesTransferred - headerSize) % fingerprintSize != 0) { 109 | 110 | TraceEvents( 111 | TRACE_LEVEL_INFORMATION, 112 | TRACE_DRIVER, 113 | "%!FUNC! Malformed input received. Length = %llu. Attempt to reset device.", 114 | NumBytesTransferred 115 | ); 116 | 117 | status = AmtPtpEmergResetDevice(pDeviceContext); 118 | if (!NT_SUCCESS(status)) { 119 | 120 | TraceEvents( 121 | TRACE_LEVEL_INFORMATION, 122 | TRACE_DRIVER, 123 | "%!FUNC! AmtPtpEmergResetDevice failed with %!STATUS!", 124 | status 125 | ); 126 | 127 | } 128 | 129 | return; 130 | } 131 | 132 | if (!pDeviceContext->IsWellspringModeOn) { 133 | 134 | TraceEvents( 135 | TRACE_LEVEL_WARNING, 136 | TRACE_DRIVER, 137 | "%!FUNC! Routine is called without enabling Wellspring mode" 138 | ); 139 | 140 | return; 141 | } 142 | 143 | // Dispatch USB Interrupt routine by device family 144 | switch (pDeviceContext->DeviceInfo->tp_type) { 145 | case TYPE1: 146 | { 147 | TraceEvents( 148 | TRACE_LEVEL_WARNING, 149 | TRACE_DRIVER, 150 | "%!FUNC! Mode not yet supported" 151 | ); 152 | break; 153 | } 154 | // Universal routine handler 155 | case TYPE2: 156 | case TYPE3: 157 | case TYPE4: 158 | { 159 | pBuffer = WdfMemoryGetBuffer( 160 | Buffer, 161 | NULL 162 | ); 163 | 164 | status = AmtPtpServiceTouchInputInterrupt( 165 | pDeviceContext, 166 | pBuffer, 167 | NumBytesTransferred 168 | ); 169 | 170 | if (!NT_SUCCESS(status)) { 171 | TraceEvents( 172 | TRACE_LEVEL_WARNING, 173 | TRACE_DRIVER, 174 | "%!FUNC! AmtPtpServiceTouchInputInterrupt failed with %!STATUS!", 175 | status 176 | ); 177 | } 178 | break; 179 | } 180 | // Magic Trackpad 2 181 | case TYPE5: 182 | { 183 | pBuffer = WdfMemoryGetBuffer( 184 | Buffer, 185 | NULL 186 | ); 187 | status = AmtPtpServiceTouchInputInterruptType5( 188 | pDeviceContext, 189 | pBuffer, 190 | NumBytesTransferred 191 | ); 192 | 193 | if (!NT_SUCCESS(status)) { 194 | TraceEvents( 195 | TRACE_LEVEL_WARNING, 196 | TRACE_DRIVER, 197 | "%!FUNC! AmtPtpServiceTouchInputInterrupt5 failed with %!STATUS!", 198 | status 199 | ); 200 | } 201 | break; 202 | } 203 | } 204 | 205 | TraceEvents( 206 | TRACE_LEVEL_INFORMATION, 207 | TRACE_DRIVER, 208 | "%!FUNC! Exit" 209 | ); 210 | 211 | } 212 | 213 | _IRQL_requires_(PASSIVE_LEVEL) 214 | BOOLEAN 215 | AmtPtpEvtUsbInterruptReadersFailed( 216 | _In_ WDFUSBPIPE Pipe, 217 | _In_ NTSTATUS Status, 218 | _In_ USBD_STATUS UsbdStatus 219 | ) 220 | { 221 | UNREFERENCED_PARAMETER(Pipe); 222 | UNREFERENCED_PARAMETER(UsbdStatus); 223 | UNREFERENCED_PARAMETER(Status); 224 | 225 | return TRUE; 226 | } 227 | 228 | _IRQL_requires_(PASSIVE_LEVEL) 229 | NTSTATUS 230 | AmtPtpServiceTouchInputInterrupt( 231 | _In_ PDEVICE_CONTEXT DeviceContext, 232 | _In_ UCHAR* Buffer, 233 | _In_ size_t NumBytesTransferred 234 | ) 235 | { 236 | NTSTATUS Status; 237 | WDFREQUEST Request; 238 | WDFMEMORY RequestMemory; 239 | PTP_REPORT PtpReport; 240 | LARGE_INTEGER CurrentPerfCounter; 241 | LONGLONG PerfCounterDelta; 242 | 243 | const struct TRACKPAD_FINGER *f; 244 | 245 | TraceEvents( 246 | TRACE_LEVEL_INFORMATION, 247 | TRACE_DRIVER, 248 | "%!FUNC! Entry" 249 | ); 250 | 251 | size_t raw_n, i = 0; 252 | size_t headerSize = (unsigned int) DeviceContext->DeviceInfo->tp_header; 253 | size_t fingerprintSize = (unsigned int) DeviceContext->DeviceInfo->tp_fsize; 254 | USHORT x = 0, y = 0; 255 | 256 | Status = STATUS_SUCCESS; 257 | PtpReport.ReportID = REPORTID_MULTITOUCH; 258 | PtpReport.IsButtonClicked = 0; 259 | 260 | // Retrieve next PTP touchpad request. 261 | Status = WdfIoQueueRetrieveNextRequest( 262 | DeviceContext->InputQueue, 263 | &Request 264 | ); 265 | 266 | if (!NT_SUCCESS(Status)) { 267 | TraceEvents( 268 | TRACE_LEVEL_INFORMATION, 269 | TRACE_DRIVER, 270 | "%!FUNC! No pending PTP request. Interrupt disposed" 271 | ); 272 | goto exit; 273 | } 274 | 275 | QueryPerformanceCounter( 276 | &CurrentPerfCounter 277 | ); 278 | 279 | // Scan time is in 100us 280 | PerfCounterDelta = (CurrentPerfCounter.QuadPart - DeviceContext->PerfCounter.QuadPart) / 100; 281 | // Only two bytes allocated 282 | if (PerfCounterDelta > 0xFF) 283 | { 284 | PerfCounterDelta = 0xFF; 285 | } 286 | 287 | PtpReport.ScanTime = (USHORT) PerfCounterDelta; 288 | 289 | // Allocate output memory. 290 | Status = WdfRequestRetrieveOutputMemory( 291 | Request, 292 | &RequestMemory 293 | ); 294 | 295 | if (!NT_SUCCESS(Status)) { 296 | TraceEvents( 297 | TRACE_LEVEL_ERROR, 298 | TRACE_DRIVER, 299 | "%!FUNC! WdfRequestRetrieveOutputMemory failed with %!STATUS!", 300 | Status 301 | ); 302 | goto exit; 303 | } 304 | 305 | // Type 2 touchpad surface report 306 | if (DeviceContext->IsSurfaceReportOn) { 307 | // Handles trackpad surface report here. 308 | raw_n = (NumBytesTransferred - headerSize) / fingerprintSize; 309 | if (raw_n >= PTP_MAX_CONTACT_POINTS) raw_n = PTP_MAX_CONTACT_POINTS; 310 | PtpReport.ContactCount = (UCHAR) raw_n; 311 | 312 | #ifdef INPUT_CONTENT_TRACE 313 | TraceEvents( 314 | TRACE_LEVEL_INFORMATION, 315 | TRACE_DRIVER, 316 | "%!FUNC! with %llu points.", 317 | raw_n 318 | ); 319 | #endif 320 | 321 | // Fingers 322 | for (i = 0; i < raw_n; i++) { 323 | 324 | UCHAR *f_base = Buffer + headerSize + DeviceContext->DeviceInfo->tp_delta; 325 | f = (const struct TRACKPAD_FINGER*) (f_base + i * fingerprintSize); 326 | 327 | // Translate X and Y 328 | x = (AmtRawToInteger(f->abs_x) - DeviceContext->DeviceInfo->x.min) > 0 ? 329 | ((USHORT)(AmtRawToInteger(f->abs_x) - DeviceContext->DeviceInfo->x.min)) : 0; 330 | y = (DeviceContext->DeviceInfo->y.max - AmtRawToInteger(f->abs_y)) > 0 ? 331 | ((USHORT)(DeviceContext->DeviceInfo->y.max - AmtRawToInteger(f->abs_y))) : 0; 332 | 333 | // Defuzz functions remain the same 334 | // TODO: Implement defuzz later 335 | PtpReport.Contacts[i].ContactID = (UCHAR) i; 336 | PtpReport.Contacts[i].X = x; 337 | PtpReport.Contacts[i].Y = y; 338 | PtpReport.Contacts[i].TipSwitch = (AmtRawToInteger(f->touch_major) << 1) >= 200; 339 | PtpReport.Contacts[i].Confidence = (AmtRawToInteger(f->touch_minor) << 1) > 0; 340 | 341 | #ifdef INPUT_CONTENT_TRACE 342 | TraceEvents( 343 | TRACE_LEVEL_INFORMATION, 344 | TRACE_INPUT, 345 | "%!FUNC!: Point %llu, X = %d, Y = %d, TipSwitch = %d, Confidence = %d, tMajor = %d, tMinor = %d, origin = %d, PTP Origin = %d", 346 | i, 347 | PtpReport.Contacts[i].X, 348 | PtpReport.Contacts[i].Y, 349 | PtpReport.Contacts[i].TipSwitch, 350 | PtpReport.Contacts[i].Confidence, 351 | AmtRawToInteger(f->touch_major) << 1, 352 | AmtRawToInteger(f->touch_minor) << 1, 353 | AmtRawToInteger(f->origin), 354 | (UCHAR) i 355 | ); 356 | #endif 357 | } 358 | } 359 | 360 | // Type 2 touchpad contains integrated trackpad buttons 361 | if (DeviceContext->IsButtonReportOn) { 362 | // Handles trackpad button input here. 363 | if (Buffer[DeviceContext->DeviceInfo->tp_button]) { 364 | PtpReport.IsButtonClicked = TRUE; 365 | } 366 | } 367 | 368 | // Compose final report and write it back 369 | Status = WdfMemoryCopyFromBuffer( 370 | RequestMemory, 371 | 0, 372 | (PVOID) &PtpReport, 373 | sizeof(PTP_REPORT) 374 | ); 375 | 376 | if (!NT_SUCCESS(Status)) { 377 | TraceEvents( 378 | TRACE_LEVEL_ERROR, 379 | TRACE_DRIVER, 380 | "%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!", 381 | Status 382 | ); 383 | goto exit; 384 | } 385 | 386 | // Set result 387 | WdfRequestSetInformation( 388 | Request, 389 | sizeof(PTP_REPORT) 390 | ); 391 | 392 | // Set completion flag 393 | WdfRequestComplete( 394 | Request, 395 | Status 396 | ); 397 | 398 | exit: 399 | TraceEvents( 400 | TRACE_LEVEL_INFORMATION, 401 | TRACE_DRIVER, 402 | "%!FUNC! Exit" 403 | ); 404 | return Status; 405 | 406 | } 407 | 408 | _IRQL_requires_(PASSIVE_LEVEL) 409 | NTSTATUS 410 | AmtPtpServiceTouchInputInterruptType5( 411 | _In_ PDEVICE_CONTEXT DeviceContext, 412 | _In_ UCHAR* Buffer, 413 | _In_ size_t NumBytesTransferred 414 | ) 415 | { 416 | 417 | NTSTATUS Status; 418 | WDFREQUEST Request; 419 | WDFMEMORY RequestMemory; 420 | PTP_REPORT PtpReport; 421 | 422 | const struct TRACKPAD_FINGER_TYPE5* f; 423 | const struct TRACKPAD_REPORT_TYPE5* mt_report; 424 | const struct TRACKPAD_COMBINED_REPORT_TYPE5* full_report; 425 | 426 | TraceEvents( 427 | TRACE_LEVEL_INFORMATION, 428 | TRACE_DRIVER, 429 | "%!FUNC! Entry" 430 | ); 431 | 432 | Status = STATUS_SUCCESS; 433 | PtpReport.ReportID = REPORTID_MULTITOUCH; 434 | PtpReport.IsButtonClicked = 0; 435 | 436 | UINT timestamp; 437 | INT x, y = 0; 438 | size_t raw_n, i = 0; 439 | 440 | Status = WdfIoQueueRetrieveNextRequest( 441 | DeviceContext->InputQueue, 442 | &Request 443 | ); 444 | 445 | if (!NT_SUCCESS(Status)) { 446 | TraceEvents( 447 | TRACE_LEVEL_INFORMATION, 448 | TRACE_DRIVER, 449 | "%!FUNC! No pending PTP request. Interrupt disposed" 450 | ); 451 | goto exit; 452 | } 453 | 454 | Status = WdfRequestRetrieveOutputMemory( 455 | Request, 456 | &RequestMemory 457 | ); 458 | if (!NT_SUCCESS(Status)) { 459 | TraceEvents( 460 | TRACE_LEVEL_ERROR, 461 | TRACE_DRIVER, 462 | "%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!", 463 | Status 464 | ); 465 | goto exit; 466 | } 467 | 468 | full_report = (const struct TRACKPAD_COMBINED_REPORT_TYPE5 *) Buffer; 469 | mt_report = &full_report->MTReport; 470 | 471 | timestamp = (mt_report->TimestampHigh << 5) | mt_report->TimestampLow; 472 | PtpReport.ScanTime = (USHORT) timestamp * 10; 473 | PtpReport.IsButtonClicked = (UCHAR) mt_report->Button; 474 | 475 | if (!DeviceContext->PrevPtpReportAuxAndSettingsInited) 476 | { 477 | DeviceContext->PrevPtpReportAuxAndSettingsInited = TRUE; 478 | DeviceContext->PrevPtpReportAux1.Id = (UINT32)-1; 479 | DeviceContext->PrevPtpReportAux2.Id = (UINT32)-1; 480 | DeviceContext->ButtonDisabled = ReadSettingValue(L"ButtonDisabled", 0) ? TRUE : FALSE; 481 | DeviceContext->StopPressure = ReadSettingValue(L"StopPressure", 0); 482 | DeviceContext->StopSize = ReadSettingValue(L"StopSize", 0xffffffff); 483 | DeviceContext->IgnoreButtonFinger = ReadSettingValue(L"IgnoreButtonFinger", 1) ? TRUE : FALSE; 484 | DeviceContext->IgnoreNearFingers = ReadSettingValue(L"IgnoreNearFingers", 1) ? TRUE : FALSE; 485 | DeviceContext->PalmRejection = ReadSettingValue(L"PalmRejection", 0) ? TRUE : FALSE; 486 | } 487 | 488 | if (DeviceContext->ButtonDisabled) 489 | PtpReport.IsButtonClicked = 0; 490 | 491 | // Type 5 finger report 492 | if (DeviceContext->IsSurfaceReportOn) { 493 | raw_n = (NumBytesTransferred - sizeof(struct TRACKPAD_REPORT_TYPE5)) / sizeof(struct TRACKPAD_FINGER_TYPE5); 494 | if (raw_n >= PTP_MAX_CONTACT_POINTS) raw_n = PTP_MAX_CONTACT_POINTS; 495 | PtpReport.ContactCount = (UCHAR)raw_n; 496 | 497 | #ifdef INPUT_CONTENT_TRACE 498 | TraceEvents( 499 | TRACE_LEVEL_INFORMATION, 500 | TRACE_DRIVER, 501 | "%!FUNC! with %llu points.", 502 | raw_n 503 | ); 504 | #endif 505 | 506 | // Fingers to array 507 | for (i = 0; i < raw_n; i++) { 508 | f = &mt_report->Fingers[i]; 509 | 510 | // Sign extend 511 | x = (SHORT) (f->AbsoluteX << 3) >> 3; 512 | y = -(SHORT) (f->AbsoluteY << 3) >> 3; 513 | 514 | x = (x - DeviceContext->DeviceInfo->x.min) > 0 ? (x - DeviceContext->DeviceInfo->x.min) : 0; 515 | y = (y - DeviceContext->DeviceInfo->y.min) > 0 ? (y - DeviceContext->DeviceInfo->y.min) : 0; 516 | 517 | PtpReport.Contacts[i].ContactID = f->Id; 518 | // 0x1 = Transition between states 519 | // 0x2 = Floating finger 520 | // 0x4 = Contact/Valid 521 | // I've gotten 0x6 if I press on the trackpad and then keep my finger close 522 | // Note: These values come from my MBP9,2. These also are valid on my MT2 523 | PtpReport.Contacts[i].TipSwitch = (f->State & 0x4) && (DeviceContext->IgnoreNearFingers == FALSE ? TRUE : !(f->State & 0x2)); 524 | 525 | // The Microsoft spec says reject any input larger than 25mm. This is not ideal 526 | // for Magic Trackpad 2 - so we raised the threshold a bit higher. 527 | // Or maybe I used the wrong unit? IDK 528 | // BOOL valid_size = (AmtRawToInteger(f->TouchMinor) << 1) < 345 && 529 | // (AmtRawToInteger(f->TouchMinor) << 1) < 345; 530 | 531 | // 1 = thumb, 2 = index, etc etc 532 | // 6 = palm on MT2, 7 = palm on my MBP9,2 (why are these different?) 533 | // BOOL valid_finger = f->Finger != 6; 534 | PtpReport.Contacts[i].Confidence = DeviceContext->PalmRejection == FALSE ? TRUE : f->Finger != 6; // valid_size && valid_finger; 535 | 536 | #define UINT32_SET_MSB(v) ((UINT32)v | ((UINT32)1 << 31)) 537 | 538 | PPTP_REPORT_AUX prev_contact = NULL; 539 | if ( 540 | DeviceContext->PrevPtpReportAux1.Id != UINT32_SET_MSB(f->Id) && 541 | DeviceContext->PrevPtpReportAux2.Id != UINT32_SET_MSB(f->Id) && 542 | (DeviceContext->IgnoreButtonFinger == FALSE ? TRUE : (!DeviceContext->PrevIsButtonClicked || !PtpReport.IsButtonClicked)) && 543 | (DeviceContext->StopPressure == 0xffffffff ? TRUE : f->Pressure > DeviceContext->StopPressure) && 544 | (DeviceContext->StopSize == 0xffffffff ? TRUE : f->Size > DeviceContext->StopSize) 545 | ) 546 | { 547 | PPTP_REPORT_AUX contact; 548 | 549 | if (DeviceContext->PrevPtpReportAux1.Id == f->Id) 550 | contact = &DeviceContext->PrevPtpReportAux1; 551 | else if (DeviceContext->PrevPtpReportAux2.Id == f->Id) 552 | contact = &DeviceContext->PrevPtpReportAux2; 553 | else if (!DeviceContext->PrevPtpReportAux1.TipSwitch) 554 | contact = &DeviceContext->PrevPtpReportAux1; 555 | else 556 | contact = &DeviceContext->PrevPtpReportAux2; 557 | 558 | contact->X = (USHORT)x; 559 | contact->Y = (USHORT)y; 560 | contact->Id = f->Id; 561 | contact->TipSwitch = PtpReport.Contacts[i].TipSwitch; 562 | } 563 | else // lock the pointer: 564 | { 565 | size_t j; 566 | for (j = 0; j < 2; j++) 567 | { 568 | PPTP_REPORT_AUX contact = !j ? &DeviceContext->PrevPtpReportAux1 : &DeviceContext->PrevPtpReportAux2; 569 | 570 | if (contact->Id == f->Id || contact->Id == UINT32_SET_MSB(f->Id)) 571 | { 572 | contact->TipSwitch = PtpReport.Contacts[i].TipSwitch; 573 | 574 | if (contact->TipSwitch) 575 | { 576 | prev_contact = contact; 577 | contact->Id = UINT32_SET_MSB(contact->Id); 578 | } 579 | else 580 | { 581 | contact->Id = (UINT32)-1; 582 | } 583 | } 584 | } 585 | } 586 | PtpReport.Contacts[i].X = prev_contact ? prev_contact->X : (USHORT)x; 587 | PtpReport.Contacts[i].Y = prev_contact ? prev_contact->Y : (USHORT)y; 588 | 589 | #undef UINT32_SET_MSB 590 | 591 | //#ifdef INPUT_CONTENT_TRACE 592 | TraceEvents( 593 | TRACE_LEVEL_INFORMATION, 594 | TRACE_INPUT, 595 | "%!FUNC!: Point %llu, ContactID = %lu, X = %d, Y = %d, TipSwitch = %d, Confidence = %d, tMajor = %d, tMinor = %d, finger type = %d, rotate = %d, pressure = %d, size = %d", 596 | i, 597 | PtpReport.Contacts[i].ContactID, 598 | PtpReport.Contacts[i].X, 599 | PtpReport.Contacts[i].Y, 600 | PtpReport.Contacts[i].TipSwitch, 601 | PtpReport.Contacts[i].Confidence, 602 | AmtRawToInteger(f->TouchMajor) << 1, 603 | AmtRawToInteger(f->TouchMinor) << 1, 604 | f->Finger, 605 | f->Orientation, 606 | f->Pressure, 607 | f->Size 608 | ); 609 | //#endif 610 | } 611 | } 612 | 613 | DeviceContext->PrevIsButtonClicked = PtpReport.IsButtonClicked; 614 | 615 | // Write output 616 | Status = WdfMemoryCopyFromBuffer( 617 | RequestMemory, 618 | 0, 619 | (PVOID) &PtpReport, 620 | sizeof(PTP_REPORT) 621 | ); 622 | 623 | if (!NT_SUCCESS(Status)) { 624 | TraceEvents( 625 | TRACE_LEVEL_ERROR, 626 | TRACE_DRIVER, 627 | "%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!", 628 | Status 629 | ); 630 | goto exit; 631 | } 632 | 633 | // Set result 634 | WdfRequestSetInformation( 635 | Request, 636 | sizeof(PTP_REPORT) 637 | ); 638 | 639 | // Set completion flag 640 | WdfRequestComplete( 641 | Request, 642 | Status 643 | ); 644 | 645 | exit: 646 | TraceEvents( 647 | TRACE_LEVEL_INFORMATION, 648 | TRACE_DRIVER, 649 | "%!FUNC! Exit" 650 | ); 651 | return Status; 652 | 653 | } 654 | 655 | // Helper function for numberic operation 656 | static inline INT AmtRawToInteger( 657 | _In_ USHORT x 658 | ) 659 | { 660 | return (signed short) x; 661 | } 662 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/MagicTrackpad2PtpDevice.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.33801.447 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmtPtpDeviceUsbUm", "MagicTrackpad2PtpDevice.vcxproj", "{87EFA31B-25EB-4944-A30A-300171BFFF57}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM64 = Debug|ARM64 11 | Debug|x64 = Debug|x64 12 | Release|ARM64 = Release|ARM64 13 | Release|x64 = Release|x64 14 | ReleaseSigned|ARM64 = ReleaseSigned|ARM64 15 | ReleaseSigned|x64 = ReleaseSigned|x64 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|ARM64.ActiveCfg = Debug|ARM64 19 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|ARM64.Build.0 = Debug|ARM64 20 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|ARM64.Deploy.0 = Debug|ARM64 21 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|x64.ActiveCfg = Debug|x64 22 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|x64.Build.0 = Debug|x64 23 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Debug|x64.Deploy.0 = Debug|x64 24 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|ARM64.ActiveCfg = Release|ARM64 25 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|ARM64.Build.0 = Release|ARM64 26 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|ARM64.Deploy.0 = Release|ARM64 27 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|x64.ActiveCfg = Release|x64 28 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|x64.Build.0 = Release|x64 29 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.Release|x64.Deploy.0 = Release|x64 30 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64 31 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64 32 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|ARM64.Deploy.0 = ReleaseSigned|ARM64 33 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64 34 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64 35 | {87EFA31B-25EB-4944-A30A-300171BFFF57}.ReleaseSigned|x64.Deploy.0 = ReleaseSigned|x64 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {9DB74DD3-FF04-422C-A220-CD209446BCA8} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/MagicTrackpad2PtpDevice.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | ReleaseSigned 6 | ARM64 7 | 8 | 9 | ReleaseSigned 10 | x64 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Debug 22 | ARM64 23 | 24 | 25 | Release 26 | ARM64 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | {87EFA31B-25EB-4944-A30A-300171BFFF57} 56 | {9181db3b-298d-4e39-a572-55bca4e4ac89} 57 | v4.5 58 | 12.0 59 | Debug 60 | Win32 61 | MagicTrackpad2PtpDevice 62 | AmtPtpDeviceUsbUm 63 | 64 | 65 | 66 | $(LatestTargetPlatformVersion) 67 | 68 | 69 | 10.0.19041.0 70 | 71 | 72 | 73 | Windows10 74 | true 75 | WindowsUserModeDriver10.0 76 | DynamicLibrary 77 | 2 78 | Universal 79 | 80 | 81 | Windows10 82 | false 83 | WindowsUserModeDriver10.0 84 | DynamicLibrary 85 | 2 86 | Universal 87 | 88 | 89 | Windows10 90 | false 91 | WindowsUserModeDriver10.0 92 | DynamicLibrary 93 | 2 94 | Universal 95 | 96 | 97 | Windows10 98 | true 99 | WindowsUserModeDriver10.0 100 | DynamicLibrary 101 | 2 102 | Universal 103 | 104 | 105 | Windows10 106 | false 107 | WindowsUserModeDriver10.0 108 | DynamicLibrary 109 | 2 110 | Universal 111 | 112 | 113 | Windows10 114 | false 115 | WindowsUserModeDriver10.0 116 | DynamicLibrary 117 | 2 118 | Universal 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | DbgengRemoteDebugger 130 | $(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 131 | $(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath) 132 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 133 | http://timestamp.digicert.com 134 | 135 | 136 | DbgengRemoteDebugger 137 | $(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 138 | $(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath) 139 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 140 | http://timestamp.digicert.com 141 | 142 | 143 | DbgengRemoteDebugger 144 | $(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 145 | $(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath) 146 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 147 | 148 | 149 | DbgengRemoteDebugger 150 | $(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 151 | $(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath) 152 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 153 | http://timestamp.digicert.com 154 | 155 | 156 | DbgengRemoteDebugger 157 | $(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 158 | $(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath) 159 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 160 | http://timestamp.digicert.com 161 | 162 | 163 | DbgengRemoteDebugger 164 | $(SolutionDir)build\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 165 | $(DDK_INC_PATH);$(SolutionDir)intermediate\$(Platform)\$(ConfigurationName)\;$(ProjectDir)include;$(IncludePath) 166 | $(SolutionDir)intermediate\$(ProjectName)\$(Platform)\$(ConfigurationName)\ 167 | 168 | 169 | 170 | http://timestamp.digicert.com 171 | $(ProductionCertPath) 172 | ProductionSign 173 | Off 174 | 175 | 176 | 177 | true 178 | true 179 | include\trace.h 180 | 181 | 182 | sha256 183 | 184 | 185 | 186 | 187 | true 188 | true 189 | include\trace.h 190 | 191 | 192 | sha256 193 | 194 | 195 | 196 | 197 | true 198 | true 199 | include\trace.h 200 | 201 | 202 | sha256 203 | 204 | 205 | 206 | 207 | true 208 | true 209 | include\trace.h 210 | 211 | 212 | 213 | 214 | true 215 | true 216 | include\trace.h 217 | 218 | 219 | 220 | 221 | true 222 | true 223 | include\trace.h 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/MagicTrackpad2PtpDevice.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | {d3b4239b-c0e3-4d91-a6ee-730df7a15240} 22 | 23 | 24 | 25 | 26 | Header Files 27 | 28 | 29 | Header Files 30 | 31 | 32 | Header Files 33 | 34 | 35 | Header Files 36 | 37 | 38 | Header Files 39 | 40 | 41 | Header Files 42 | 43 | 44 | Header Files 45 | 46 | 47 | Header Files 48 | 49 | 50 | Header Files 51 | 52 | 53 | Header Files 54 | 55 | 56 | Device Specific Metadata Files 57 | 58 | 59 | Device Specific Metadata Files 60 | 61 | 62 | Device Specific Metadata Files 63 | 64 | 65 | Device Specific Metadata Files 66 | 67 | 68 | Device Specific Metadata Files 69 | 70 | 71 | Device Specific Metadata Files 72 | 73 | 74 | 75 | 76 | Source Files 77 | 78 | 79 | Source Files 80 | 81 | 82 | Source Files 83 | 84 | 85 | Source Files 86 | 87 | 88 | Source Files 89 | 90 | 91 | 92 | 93 | Resource Files 94 | 95 | 96 | 97 | 98 | Resource Files 99 | 100 | 101 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/Queue.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maashrafh/MagicTrackpad2ForWindows/971609319bd85e80e667ae8445b9b1053fadef66/AmtPtpDeviceUsbUm/Queue.c -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/Resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maashrafh/MagicTrackpad2ForWindows/971609319bd85e80e667ae8445b9b1053fadef66/AmtPtpDeviceUsbUm/Resource.rc -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/AppleDefinition.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define USB_VENDOR_ID_APPLE 0x05ac 4 | 5 | /* MacbookAir, aka wellspring */ 6 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ANSI 0x0223 7 | #define USB_DEVICE_ID_APPLE_WELLSPRING_ISO 0x0224 8 | #define USB_DEVICE_ID_APPLE_WELLSPRING_JIS 0x0225 9 | /* MacbookProPenryn, aka wellspring2 */ 10 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 11 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 12 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 13 | /* Macbook5,1 (unibody), aka wellspring3 */ 14 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 15 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 16 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 17 | /* MacbookAir3,2 (unibody), aka wellspring5 */ 18 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f 19 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 20 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 21 | /* MacbookAir3,1 (unibody), aka wellspring4 */ 22 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 23 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 24 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 25 | /* Macbook8 (unibody, March 2011) */ 26 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 27 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 28 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 29 | /* MacbookAir4,1 (unibody, July 2011) */ 30 | #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 31 | #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a 32 | #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b 33 | /* MacbookAir4,2 (unibody, July 2011) */ 34 | #define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c 35 | #define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d 36 | #define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e 37 | /* Macbook8,2 (unibody) */ 38 | #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 39 | #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 40 | #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 41 | /* MacbookPro10,1 (unibody, June 2012) */ 42 | #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 43 | #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 44 | #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 45 | /* MacbookPro10,2 (unibody, October 2012) */ 46 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 47 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a 48 | #define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b 49 | /* MacbookAir6,2 (unibody, June 2013) */ 50 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290 51 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291 52 | #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292 53 | /* MacbookPro12,1 (2015) */ 54 | #define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272 55 | #define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273 56 | #define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274 57 | /* Magic Trackpad 2 (2015) */ 58 | #define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 0x0265 59 | /* Magic Trackpad 2 USB C (2024) */ 60 | #define USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC 0x0324 61 | /* Apple T2 USB trackpad */ 62 | #define USB_DEVICE_ID_APPLE_T2 0x027d 63 | 64 | /* button data structure */ 65 | struct TRACKPAD_BUTTON_DATA { 66 | UCHAR unknown1; /* constant */ 67 | UCHAR button; /* left button */ 68 | UCHAR rel_x; /* relative x coordinate */ 69 | UCHAR rel_y; /* relative y coordinate */ 70 | }; 71 | 72 | /* trackpad header types */ 73 | enum TRACKPAD_TYPE { 74 | TYPE1, /* plain trackpad */ 75 | TYPE2, /* button integrated in trackpad */ 76 | TYPE3, /* additional header fields since June 2013 */ 77 | TYPE4, /* additional header field for pressure data */ 78 | TYPE5 /* format for magic trackpad 2 */ 79 | }; 80 | 81 | /* Trackpad finger data offsets, le16-aligned */ 82 | #define HEADER_TYPE1 (13 * sizeof(USHORT)) 83 | #define HEADER_TYPE2 (15 * sizeof(USHORT)) 84 | #define HEADER_TYPE3 (19 * sizeof(USHORT)) 85 | #define HEADER_TYPE4 (23 * sizeof(USHORT)) 86 | #define HEADER_TYPE5 ( 6 * sizeof(USHORT)) 87 | 88 | /* Trackpad button data offsets */ 89 | #define BUTTON_TYPE1 0 90 | #define BUTTON_TYPE2 15 91 | #define BUTTON_TYPE3 23 92 | #define BUTTON_TYPE4 31 93 | #define BUTTON_TYPE5 1 94 | 95 | /* List of device capability bits */ 96 | #define HAS_INTEGRATED_BUTTON 1 97 | 98 | /* Trackpad finger data block size */ 99 | #define FSIZE_TYPE1 (14 * sizeof(USHORT)) 100 | #define FSIZE_TYPE2 (14 * sizeof(USHORT)) 101 | #define FSIZE_TYPE3 (14 * sizeof(USHORT)) 102 | #define FSIZE_TYPE4 (15 * sizeof(USHORT)) 103 | #define FSIZE_TYPE5 (9) 104 | 105 | /* Offset from header to finger struct */ 106 | #define DELTA_TYPE1 (0 * sizeof(USHORT)) 107 | #define DELTA_TYPE2 (0 * sizeof(USHORT)) 108 | #define DELTA_TYPE3 (0 * sizeof(USHORT)) 109 | #define DELTA_TYPE4 (1 * sizeof(USHORT)) 110 | #define DELTA_TYPE5 (0 * sizeof(USHORT)) 111 | 112 | /* USB control message mode switch data */ 113 | #define USBMSG_TYPE1 8, 0x300, 0, 0, 0x1, 0x8 114 | #define USBMSG_TYPE2 8, 0x300, 0, 0, 0x1, 0x8 115 | #define USBMSG_TYPE3 8, 0x300, 0, 0, 0x1, 0x8 116 | #define USBMSG_TYPE4 2, 0x302, 2, 1, 0x1, 0x0 117 | #define USBMSG_TYPE5 2, 0x302, 1, 1, 0x1, 0x0 118 | 119 | /* Wellspring initialization constants */ 120 | #define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1 121 | #define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9 122 | 123 | /* Trackpad finger data size, empirically at least ten fingers */ 124 | #define MAX_FINGERS 16 125 | #define MAX_FINGER_ORIENTATION 16384 126 | 127 | #define BCM5974_MOUSE_SIZE 8 128 | 129 | /* trackpad finger structure, le16-aligned */ 130 | __declspec(align(2)) struct TRACKPAD_FINGER { 131 | USHORT origin; /* zero when switching track finger */ 132 | USHORT abs_x; /* absolute x coodinate */ 133 | USHORT abs_y; /* absolute y coodinate */ 134 | USHORT rel_x; /* relative x coodinate */ 135 | USHORT rel_y; /* relative y coodinate */ 136 | USHORT tool_major; /* tool area, major axis */ 137 | USHORT tool_minor; /* tool area, minor axis */ 138 | USHORT orientation; /* 16384 when point, else 15 bit angle */ 139 | USHORT touch_major; /* touch area, major axis */ 140 | USHORT touch_minor; /* touch area, minor axis */ 141 | USHORT unused[2]; /* zeros */ 142 | USHORT pressure; /* pressure on forcetouch touchpad */ 143 | USHORT multi; /* one finger: varies, more fingers: constant */ 144 | }; 145 | 146 | #pragma pack( push, 1 ) 147 | #pragma warning( push ) 148 | #pragma warning( disable : 4200 ) 149 | 150 | /* Trackpad finger structure for type5 (magic trackpad) */ 151 | struct TRACKPAD_FINGER_TYPE5 152 | { 153 | UINT32 AbsoluteX : 13; /* absolute x coordinate */ 154 | UINT32 AbsoluteY : 13; /* absolute y coordinate */ 155 | UINT32 Finger : 3; /* finger type */ 156 | UINT32 State : 3; /* finger State */ 157 | UCHAR TouchMajor; /* touch area, major axis */ 158 | UCHAR TouchMinor; /* touch area, minor axis */ 159 | UCHAR Size; /* tool area, size */ 160 | UCHAR Pressure; /* pressure on forcetouch touchpad */ 161 | UCHAR Id : 4; /* slot id */ 162 | UCHAR _ : 1; 163 | UCHAR Orientation : 3; /* contact angle */ 164 | }; 165 | 166 | /* Appended Mouse report on front of MT2 USB reports */ 167 | struct MOUSE_REPORT 168 | { 169 | UCHAR ReportId; 170 | UCHAR Button; 171 | UCHAR X; 172 | UCHAR Y; 173 | UCHAR _[4]; 174 | }; 175 | 176 | /* Multitouch report from MT2 */ 177 | struct TRACKPAD_REPORT_TYPE5 178 | { 179 | UCHAR ReportId; 180 | UINT8 Button : 1; 181 | UINT8 _ : 2; 182 | UINT8 TimestampLow : 5; 183 | UINT16 TimestampHigh; 184 | struct TRACKPAD_FINGER_TYPE5 Fingers[]; 185 | }; 186 | 187 | /* Full trackpad report for mt2 over USB */ 188 | struct TRACKPAD_COMBINED_REPORT_TYPE5 189 | { 190 | struct MOUSE_REPORT Mouse; 191 | struct TRACKPAD_REPORT_TYPE5 MTReport; 192 | }; 193 | 194 | #pragma warning( pop ) 195 | #pragma pack( pop ) 196 | 197 | /* device-specific parameters */ 198 | struct BCM5974_PARAM { 199 | int snratio; /* signal-to-noise ratio */ 200 | int min; /* device minimum reading */ 201 | int max; /* device maximum reading */ 202 | }; 203 | 204 | /* device-specific configuration */ 205 | struct BCM5974_CONFIG { 206 | int ansi, iso, jis; /* the product id of this device */ 207 | int caps; /* device capability bitmask */ 208 | int bt_ep; /* the endpoint of the button interface */ 209 | int bt_datalen; /* data length of the button interface */ 210 | int tp_ep; /* the endpoint of the trackpad interface */ 211 | enum TRACKPAD_TYPE tp_type; /* type of trackpad interface */ 212 | int tp_header; /* bytes in header block */ 213 | int tp_datalen; /* data length of the trackpad interface */ 214 | int tp_button; /* offset to button data */ 215 | int tp_fsize; /* bytes in single finger block */ 216 | int tp_delta; /* offset from header to finger struct */ 217 | int um_size; /* usb control message length */ 218 | int um_req_val; /* usb control message value */ 219 | int um_req_idx; /* usb control message index */ 220 | int um_switch_idx; /* usb control message mode switch index */ 221 | int um_switch_on; /* usb control message mode switch on */ 222 | int um_switch_off; /* usb control message mode switch off */ 223 | struct BCM5974_PARAM p; /* finger pressure limits */ 224 | struct BCM5974_PARAM w; /* finger width limits */ 225 | struct BCM5974_PARAM x; /* horizontal limits */ 226 | struct BCM5974_PARAM y; /* vertical limits */ 227 | struct BCM5974_PARAM o; /* orientation limits */ 228 | }; 229 | 230 | #define DATAFORMAT(type) \ 231 | type, \ 232 | HEADER_##type, \ 233 | HEADER_##type + (MAX_FINGERS) * (FSIZE_##type), \ 234 | BUTTON_##type, \ 235 | FSIZE_##type, \ 236 | DELTA_##type, \ 237 | USBMSG_##type 238 | 239 | /* logical signal quality */ 240 | #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */ 241 | #define SN_WIDTH 25 /* width signal-to-noise ratio */ 242 | #define SN_COORD 250 /* coordinate signal-to-noise ratio */ 243 | #define SN_ORIENT 10 /* orientation signal-to-noise ratio */ 244 | 245 | #define PRESSURE_QUALIFICATION_THRESHOLD 2 246 | #define SIZE_QUALIFICATION_THRESHOLD 9 247 | #define SIZE_MU_LOWER_THRESHOLD 5 248 | 249 | #define PRESSURE_MU_QUALIFICATION_THRESHOLD_TOTAL 15 250 | #define SIZE_MU_QUALIFICATION_THRESHOLD_TOTAL 25 251 | 252 | /* device constants */ 253 | static const struct BCM5974_CONFIG Bcm5974ConfigTable[] = { 254 | { 255 | USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, 256 | USB_DEVICE_ID_APPLE_WELLSPRING_ISO, 257 | USB_DEVICE_ID_APPLE_WELLSPRING_JIS, 258 | 0, 259 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 260 | 0x81, DATAFORMAT(TYPE1), 261 | { SN_PRESSURE, 0, 256 }, 262 | { SN_WIDTH, 0, 2048 }, 263 | { SN_COORD, -4824, 5342 }, 264 | { SN_COORD, -172, 5820 }, 265 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 266 | }, 267 | { 268 | USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, 269 | USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, 270 | USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, 271 | 0, 272 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 273 | 0x81, DATAFORMAT(TYPE1), 274 | { SN_PRESSURE, 0, 256 }, 275 | { SN_WIDTH, 0, 2048 }, 276 | { SN_COORD, -4824, 4824 }, 277 | { SN_COORD, -172, 4290 }, 278 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 279 | }, 280 | { 281 | USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI, 282 | USB_DEVICE_ID_APPLE_WELLSPRING3_ISO, 283 | USB_DEVICE_ID_APPLE_WELLSPRING3_JIS, 284 | HAS_INTEGRATED_BUTTON, 285 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 286 | 0x81, DATAFORMAT(TYPE2), 287 | { SN_PRESSURE, 0, 300 }, 288 | { SN_WIDTH, 0, 2048 }, 289 | { SN_COORD, -4460, 5166 }, 290 | { SN_COORD, -75, 6700 }, 291 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 292 | }, 293 | { 294 | USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI, 295 | USB_DEVICE_ID_APPLE_WELLSPRING4_ISO, 296 | USB_DEVICE_ID_APPLE_WELLSPRING4_JIS, 297 | HAS_INTEGRATED_BUTTON, 298 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 299 | 0x81, DATAFORMAT(TYPE2), 300 | { SN_PRESSURE, 0, 300 }, 301 | { SN_WIDTH, 0, 2048 }, 302 | { SN_COORD, -4620, 5140 }, 303 | { SN_COORD, -150, 6600 }, 304 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 305 | }, 306 | { 307 | USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI, 308 | USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO, 309 | USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS, 310 | HAS_INTEGRATED_BUTTON, 311 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 312 | 0x81, DATAFORMAT(TYPE2), 313 | { SN_PRESSURE, 0, 300 }, 314 | { SN_WIDTH, 0, 2048 }, 315 | { SN_COORD, -4616, 5112 }, 316 | { SN_COORD, -142, 5234 }, 317 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 318 | }, 319 | { 320 | USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI, 321 | USB_DEVICE_ID_APPLE_WELLSPRING5_ISO, 322 | USB_DEVICE_ID_APPLE_WELLSPRING5_JIS, 323 | HAS_INTEGRATED_BUTTON, 324 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 325 | 0x81, DATAFORMAT(TYPE2), 326 | { SN_PRESSURE, 0, 300 }, 327 | { SN_WIDTH, 0, 2048 }, 328 | { SN_COORD, -4415, 5050 }, 329 | { SN_COORD, -55, 6680 }, 330 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 331 | }, 332 | { 333 | USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI, 334 | USB_DEVICE_ID_APPLE_WELLSPRING6_ISO, 335 | USB_DEVICE_ID_APPLE_WELLSPRING6_JIS, 336 | HAS_INTEGRATED_BUTTON, 337 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 338 | 0x81, DATAFORMAT(TYPE2), 339 | { SN_PRESSURE, 0, 300 }, 340 | { SN_WIDTH, 0, 2048 }, 341 | { SN_COORD, -4620, 5140 }, 342 | { SN_COORD, -150, 6600 }, 343 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 344 | }, 345 | { 346 | USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI, 347 | USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO, 348 | USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS, 349 | HAS_INTEGRATED_BUTTON, 350 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 351 | 0x81, DATAFORMAT(TYPE2), 352 | { SN_PRESSURE, 0, 300 }, 353 | { SN_WIDTH, 0, 2048 }, 354 | { SN_COORD, -4750, 5280 }, 355 | { SN_COORD, -150, 6730 }, 356 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 357 | }, 358 | { 359 | USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI, 360 | USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO, 361 | USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS, 362 | HAS_INTEGRATED_BUTTON, 363 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 364 | 0x81, DATAFORMAT(TYPE2), 365 | { SN_PRESSURE, 0, 300 }, 366 | { SN_WIDTH, 0, 2048 }, 367 | { SN_COORD, -4620, 5140 }, 368 | { SN_COORD, -150, 6600 }, 369 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 370 | }, 371 | { 372 | USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI, 373 | USB_DEVICE_ID_APPLE_WELLSPRING7_ISO, 374 | USB_DEVICE_ID_APPLE_WELLSPRING7_JIS, 375 | HAS_INTEGRATED_BUTTON, 376 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 377 | 0x81, DATAFORMAT(TYPE2), 378 | { SN_PRESSURE, 0, 300 }, 379 | { SN_WIDTH, 0, 2048 }, 380 | { SN_COORD, -4750, 5280 }, 381 | { SN_COORD, -150, 6730 }, 382 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 383 | }, 384 | { 385 | USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI, 386 | USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO, 387 | USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS, 388 | HAS_INTEGRATED_BUTTON, 389 | 0x84, sizeof(struct TRACKPAD_BUTTON_DATA), 390 | 0x81, DATAFORMAT(TYPE2), 391 | { SN_PRESSURE, 0, 300 }, 392 | { SN_WIDTH, 0, 2048 }, 393 | { SN_COORD, -4750, 5280 }, 394 | { SN_COORD, -150, 6730 }, 395 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 396 | }, 397 | { 398 | USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI, 399 | USB_DEVICE_ID_APPLE_WELLSPRING8_ISO, 400 | USB_DEVICE_ID_APPLE_WELLSPRING8_JIS, 401 | HAS_INTEGRATED_BUTTON, 402 | 0, sizeof(struct TRACKPAD_BUTTON_DATA), 403 | 0x83, DATAFORMAT(TYPE3), 404 | { SN_PRESSURE, 0, 300 }, 405 | { SN_WIDTH, 0, 2048 }, 406 | { SN_COORD, -4620, 5140 }, 407 | { SN_COORD, -150, 6600 }, 408 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 409 | }, 410 | { 411 | USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI, 412 | USB_DEVICE_ID_APPLE_WELLSPRING9_ISO, 413 | USB_DEVICE_ID_APPLE_WELLSPRING9_JIS, 414 | HAS_INTEGRATED_BUTTON, 415 | 0, sizeof(struct TRACKPAD_BUTTON_DATA), 416 | 0x83, DATAFORMAT(TYPE4), 417 | { SN_PRESSURE, 0, 300 }, 418 | { SN_WIDTH, 0, 2048 }, 419 | { SN_COORD, -4828, 5345 }, 420 | { SN_COORD, -203, 6803 }, 421 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 422 | }, 423 | { 424 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD2, 425 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD2, 426 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD2, 427 | HAS_INTEGRATED_BUTTON, 428 | 0, sizeof(struct TRACKPAD_BUTTON_DATA), 429 | 0x83, DATAFORMAT(TYPE5), 430 | { SN_PRESSURE, 0, 300 }, 431 | { SN_WIDTH, 0, 2048 }, 432 | { SN_COORD, -3678, 3934 }, 433 | { SN_COORD, -2479, 2586 }, 434 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 435 | }, 436 | { 437 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC, 438 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC, 439 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC, 440 | HAS_INTEGRATED_BUTTON, 441 | 0, sizeof(struct TRACKPAD_BUTTON_DATA), 442 | 0x83, DATAFORMAT(TYPE5), 443 | { SN_PRESSURE, 0, 300 }, 444 | { SN_WIDTH, 0, 2048 }, 445 | { SN_COORD, -3678, 3934 }, 446 | { SN_COORD, -2479, 2586 }, 447 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 448 | }, 449 | { 450 | USB_DEVICE_ID_APPLE_T2, 451 | USB_DEVICE_ID_APPLE_T2, 452 | USB_DEVICE_ID_APPLE_T2, 453 | HAS_INTEGRATED_BUTTON, 454 | 0, sizeof(struct TRACKPAD_BUTTON_DATA), 455 | 0x83, DATAFORMAT(TYPE4), 456 | { SN_PRESSURE, 0, 300 }, 457 | /* This is incorrect; check actual data later */ 458 | { SN_WIDTH, 0, 2048 }, 459 | { SN_COORD, -4828, 5345 }, 460 | { SN_COORD, -203, 6803 }, 461 | { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } 462 | }, 463 | }; -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/Device.h: -------------------------------------------------------------------------------- 1 | // Device.h: Device definitions 2 | 3 | EXTERN_C_START 4 | 5 | typedef struct _PTP_REPORT_AUX { 6 | USHORT X, Y; 7 | UINT32 Id; 8 | UCHAR TipSwitch; 9 | } PTP_REPORT_AUX, * PPTP_REPORT_AUX; 10 | 11 | // Device context struct 12 | typedef struct _DEVICE_CONTEXT 13 | { 14 | WDFUSBDEVICE UsbDevice; 15 | WDFUSBPIPE InterruptPipe; 16 | WDFUSBINTERFACE UsbInterface; 17 | WDFQUEUE InputQueue; 18 | 19 | USB_DEVICE_DESCRIPTOR DeviceDescriptor; 20 | 21 | const struct BCM5974_CONFIG *DeviceInfo; 22 | 23 | ULONG UsbDeviceTraits; 24 | 25 | UCHAR PressureQualLevel; 26 | UCHAR SgContactSizeQualLevel; 27 | UCHAR MuContactSizeQualLevel; 28 | 29 | BOOL IsWellspringModeOn; 30 | BOOL IsSurfaceReportOn; 31 | BOOL IsButtonReportOn; 32 | 33 | LARGE_INTEGER PerfCounter; 34 | 35 | PTP_REPORT_AUX PrevPtpReportAux1, PrevPtpReportAux2; 36 | BOOL PrevPtpReportAuxAndSettingsInited; 37 | UCHAR PrevIsButtonClicked; 38 | BOOL ButtonDisabled; 39 | ULONG StopPressure; 40 | ULONG StopSize; 41 | BOOL IgnoreButtonFinger; 42 | BOOL IgnoreNearFingers; 43 | BOOL PalmRejection; 44 | 45 | } DEVICE_CONTEXT, *PDEVICE_CONTEXT; 46 | 47 | // 48 | // This macro will generate an inline function called DeviceGetContext 49 | // which will be used to get a pointer to the device context memory 50 | // in a type safe manner. 51 | // 52 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, DeviceGetContext) 53 | 54 | // 55 | // Pool tags 56 | // 57 | #define POOL_TAG_PTP_CONTROL 'PTPC' 58 | 59 | // 60 | // Function to initialize the device's queues and callbacks 61 | // 62 | NTSTATUS 63 | AmtPtpCreateDevice( 64 | _In_ WDFDRIVER Driver, 65 | _Inout_ PWDFDEVICE_INIT DeviceInit 66 | ); 67 | 68 | // 69 | // Function to select the device's USB configuration and get a WDFUSBDEVICE 70 | // handle 71 | // 72 | EVT_WDF_DEVICE_PREPARE_HARDWARE AmtPtpEvtDevicePrepareHardware; 73 | EVT_WDF_DEVICE_D0_ENTRY AmtPtpEvtDeviceD0Entry; 74 | EVT_WDF_DEVICE_D0_EXIT AmtPtpEvtDeviceD0Exit; 75 | 76 | _IRQL_requires_(PASSIVE_LEVEL) 77 | NTSTATUS 78 | AmtPtpConfigContReaderForInterruptEndPoint( 79 | _In_ PDEVICE_CONTEXT DeviceContext 80 | ); 81 | 82 | _IRQL_requires_(PASSIVE_LEVEL) 83 | NTSTATUS 84 | AmtPtpGetWellspringMode( 85 | _In_ PDEVICE_CONTEXT DeviceContext, 86 | _Out_ BOOL* IsWellspringModeOn 87 | ); 88 | 89 | _IRQL_requires_(PASSIVE_LEVEL) 90 | NTSTATUS 91 | SelectInterruptInterface( 92 | _In_ WDFDEVICE Device 93 | ); 94 | 95 | _IRQL_requires_(PASSIVE_LEVEL) 96 | NTSTATUS 97 | AmtPtpSetWellspringMode( 98 | _In_ PDEVICE_CONTEXT DeviceContext, 99 | _In_ BOOL IsWellspringModeOn 100 | ); 101 | 102 | _IRQL_requires_(PASSIVE_LEVEL) 103 | NTSTATUS 104 | AmtPtpSetHapticFeedback( 105 | _In_ PDEVICE_CONTEXT DeviceContext, 106 | _In_ ULONG FeedbackClick, 107 | _In_ ULONG FeedbackRelease 108 | ); 109 | 110 | _IRQL_requires_(PASSIVE_LEVEL) 111 | ULONG ReadSettingValue( 112 | _In_ PWCHAR SettingName, 113 | _In_ ULONG DefaultValue 114 | ); 115 | 116 | _IRQL_requires_(PASSIVE_LEVEL) 117 | PCHAR 118 | DbgDevicePowerString( 119 | _In_ WDF_POWER_DEVICE_STATE Type 120 | ); 121 | 122 | _IRQL_requires_(PASSIVE_LEVEL) 123 | VOID 124 | AmtPtpEvtUsbInterruptPipeReadComplete( 125 | _In_ WDFUSBPIPE Pipe, 126 | _In_ WDFMEMORY Buffer, 127 | _In_ size_t NumBytesTransferred, 128 | _In_ WDFCONTEXT Context 129 | ); 130 | 131 | _IRQL_requires_(PASSIVE_LEVEL) 132 | BOOLEAN 133 | AmtPtpEvtUsbInterruptReadersFailed( 134 | _In_ WDFUSBPIPE Pipe, 135 | _In_ NTSTATUS Status, 136 | _In_ USBD_STATUS UsbdStatus 137 | ); 138 | 139 | _IRQL_requires_(PASSIVE_LEVEL) 140 | NTSTATUS 141 | AmtPtpServiceTouchInputInterrupt( 142 | _In_ PDEVICE_CONTEXT DeviceContext, 143 | _In_ UCHAR* Buffer, 144 | _In_ size_t NumBytesTransferred 145 | ); 146 | 147 | _IRQL_requires_(PASSIVE_LEVEL) 148 | NTSTATUS 149 | AmtPtpServiceTouchInputInterruptType5( 150 | _In_ PDEVICE_CONTEXT DeviceContext, 151 | _In_ UCHAR* Buffer, 152 | _In_ size_t NumBytesTransferred 153 | ); 154 | 155 | _IRQL_requires_(PASSIVE_LEVEL) 156 | NTSTATUS 157 | AmtPtpEmergResetDevice( 158 | _In_ PDEVICE_CONTEXT DeviceContext 159 | ); 160 | 161 | /// 162 | /// HID sections 163 | /// 164 | 165 | _IRQL_requires_(PASSIVE_LEVEL) 166 | NTSTATUS 167 | AmtPtpGetHidDescriptor( 168 | _In_ WDFDEVICE Device, 169 | _In_ WDFREQUEST Request 170 | ); 171 | 172 | _IRQL_requires_(PASSIVE_LEVEL) 173 | NTSTATUS 174 | AmtPtpGetDeviceAttribs( 175 | _In_ WDFDEVICE Device, 176 | _In_ WDFREQUEST Request 177 | ); 178 | 179 | _IRQL_requires_(PASSIVE_LEVEL) 180 | NTSTATUS 181 | AmtPtpGetReportDescriptor( 182 | _In_ WDFDEVICE Device, 183 | _In_ WDFREQUEST Request 184 | ); 185 | 186 | _IRQL_requires_(PASSIVE_LEVEL) 187 | NTSTATUS 188 | AmtPtpGetStrings( 189 | _In_ WDFDEVICE Device, 190 | _In_ WDFREQUEST Request 191 | ); 192 | 193 | _IRQL_requires_(PASSIVE_LEVEL) 194 | NTSTATUS 195 | AmtPtpReportFeatures( 196 | _In_ WDFDEVICE Device, 197 | _In_ WDFREQUEST Request 198 | ); 199 | 200 | _IRQL_requires_(PASSIVE_LEVEL) 201 | NTSTATUS 202 | AmtPtpSetFeatures( 203 | _In_ WDFDEVICE Device, 204 | _In_ WDFREQUEST Request 205 | ); 206 | 207 | // 208 | // Utils 209 | // 210 | 211 | _IRQL_requires_(PASSIVE_LEVEL) 212 | NTSTATUS 213 | RequestGetHidXferPacketToReadFromDevice( 214 | _In_ WDFREQUEST Request, 215 | _Out_ HID_XFER_PACKET *Packet 216 | ); 217 | 218 | _IRQL_requires_(PASSIVE_LEVEL) 219 | NTSTATUS 220 | RequestGetHidXferPacketToWriteToDevice( 221 | _In_ WDFREQUEST Request, 222 | _Out_ HID_XFER_PACKET *Packet 223 | ); 224 | 225 | // Helper function for numberic operation 226 | static inline INT AmtRawToInteger( 227 | _In_ USHORT x 228 | ); 229 | 230 | EXTERN_C_END 231 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_1 \ 6 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 7 | /* Begin a byte */ \ 8 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 9 | USAGE, 0x47, /* Usage: Confidence */ \ 10 | USAGE, 0x42, /* Usage: Tip switch */ \ 11 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 12 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 13 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 14 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 15 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 16 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 17 | /* End of a byte */ \ 18 | /* Begin of 4 bytes */ \ 19 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 20 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 21 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 22 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 23 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 24 | /* End of 4 bytes */ \ 25 | /* Begin of 4 bytes */ \ 26 | /* Size is hard-coded at this moment */ \ 27 | /* This hard-coded size is designed for MacBookAir 7,2 */ \ 28 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 29 | LOGICAL_MAXIMUM_2, 0x9a, 0x25, /* Logical Maximum: 9626 (See defintion) */ \ 30 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 31 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 32 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 33 | USAGE, 0x30, /* Usage: X */ \ 34 | PHYSICAL_MAXIMUM_2, 0x1a, 0x04, /* Physical Maximum: 1050 (See Apple Spec) */ \ 35 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 36 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 37 | PHYSICAL_MAXIMUM_2, 0xf8, 0x02, /* Physical Maximum: 760 (See Apple Spec) */ \ 38 | LOGICAL_MAXIMUM_2, 0x77, 0x1a, /* Logical Maximum: 6775 (See definition) */ \ 39 | USAGE, 0x31, /* Usage: Y */ \ 40 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 41 | PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \ 42 | UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \ 43 | UNIT, 0x00, /* Unit: None */ \ 44 | /* End of 4 bytes */ \ 45 | END_COLLECTION /* End Collection */ \ 46 | 47 | #define AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_2 \ 48 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 49 | /* Begin a byte */ \ 50 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 51 | USAGE, 0x47, /* Usage: Confidence */ \ 52 | USAGE, 0x42, /* Usage: Tip switch */ \ 53 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 54 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 55 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 56 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 57 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 58 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 59 | /* End of a byte */ \ 60 | /* Begin of 4 bytes */ \ 61 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 62 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 63 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 64 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 65 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 66 | /* End of 4 bytes */ \ 67 | /* Begin of 4 bytes */ \ 68 | /* Size is hard-coded at this moment */ \ 69 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 70 | LOGICAL_MAXIMUM_2, 0x9a, 0x25, /* Logical Maximum: 9626 (See defintion) */ \ 71 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 72 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 73 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 74 | USAGE, 0x30, /* Usage: X */ \ 75 | PHYSICAL_MAXIMUM_2, 0x1a, 0x04, /* Physical Maximum: 1050 (See Apple Spec) */ \ 76 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 77 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 78 | PHYSICAL_MAXIMUM_2, 0xf8, 0x02, /* Physical Maximum: 760 (See Apple Spec) */ \ 79 | LOGICAL_MAXIMUM_2, 0x77, 0x1a, /* Logical Maximum: 6775 (See definition) */ \ 80 | USAGE, 0x31, /* Usage: Y */ \ 81 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 82 | /* End of 4 bytes */ \ 83 | END_COLLECTION /* End Collection */ \ 84 | 85 | #define AAPL_WELLSPRING_3_PTP_TLC \ 86 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 87 | USAGE, 0x05, /* Usage: Touch Pad */ \ 88 | BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \ 89 | REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \ 90 | USAGE, 0x22, /* Usage: Finger */ \ 91 | AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_1, /* 1 */ \ 92 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 93 | USAGE, 0x22, /* Usage: Finger */ \ 94 | AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_1, /* 2 */ \ 95 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 96 | USAGE, 0x22, /* Usage: Finger */ \ 97 | AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_2, /* 3 */ \ 98 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 99 | USAGE, 0x22, /* Usage: Finger */ \ 100 | AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_1, /* 4 */ \ 101 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 102 | USAGE, 0x22, /* Usage: Finger */ \ 103 | AAPL_WELLSPRING_3_PTP_FINGER_COLLECTION_2, /* 5 */ \ 104 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 105 | UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \ 106 | UNIT_2, 0x01, 0x10, /* Time: Second */ \ 107 | PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 108 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 109 | USAGE, 0x56, /* Usage: Scan Time */ \ 110 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 111 | USAGE, 0x54, /* Usage: Contact Count */ \ 112 | LOGICAL_MAXIMUM, 0x7f, \ 113 | REPORT_SIZE, 0x08, \ 114 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 115 | USAGE_PAGE, 0x09, /* Usage Page: Button */ \ 116 | USAGE, 0x01, /* Button 1 */ \ 117 | LOGICAL_MAXIMUM, 0x01, \ 118 | REPORT_SIZE, 0x01, \ 119 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 120 | REPORT_COUNT, 0x07, \ 121 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 122 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 123 | REPORT_ID, REPORTID_DEVICE_CAPS, \ 124 | USAGE, 0x55, /* Usage: Maximum Contacts */ \ 125 | USAGE, 0x59, /* Usage: Touchpad Button Type*/ \ 126 | LOGICAL_MINIMUM, 0x00, \ 127 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 128 | REPORT_SIZE, 0x08, \ 129 | REPORT_COUNT, 0x02, \ 130 | FEATURE, 0x02, \ 131 | USAGE_PAGE_1, 0x00, 0xff, \ 132 | REPORT_ID, REPORTID_PTPHQA, \ 133 | USAGE, 0xc5, \ 134 | LOGICAL_MINIMUM, 0x00, \ 135 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 136 | REPORT_SIZE, 0x08, \ 137 | REPORT_COUNT_2, 0x00, 0x01, \ 138 | FEATURE, 0x02, \ 139 | END_COLLECTION /* End Collection */ 140 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring5.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_1 \ 6 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 7 | /* Begin a byte */ \ 8 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 9 | USAGE, 0x47, /* Usage: Confidence */ \ 10 | USAGE, 0x42, /* Usage: Tip switch */ \ 11 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 12 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 13 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 14 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 15 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 16 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 17 | /* End of a byte */ \ 18 | /* Begin of 4 bytes */ \ 19 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 20 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 21 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 22 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 23 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 24 | /* End of 4 bytes */ \ 25 | /* Begin of 4 bytes */ \ 26 | /* Size is hard-coded at this moment */ \ 27 | /* This hard-coded size is designed for MacBookAir 7,2 */ \ 28 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 29 | LOGICAL_MAXIMUM_2, 0xf9, 0x24, /* Logical Maximum: 9465 (See defintion) */ \ 30 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 31 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 32 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 33 | USAGE, 0x30, /* Usage: X */ \ 34 | PHYSICAL_MAXIMUM_2, 0x1a, 0x04, /* Physical Maximum: 1050 (See Apple Spec) */ \ 35 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 36 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 37 | PHYSICAL_MAXIMUM_2, 0x2a, 0x03, /* Physical Maximum: 810 (See Apple Spec) */ \ 38 | LOGICAL_MAXIMUM_2, 0x4f, 0x1a, /* Logical Maximum: 6735 (See definition) */ \ 39 | USAGE, 0x31, /* Usage: Y */ \ 40 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 41 | PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \ 42 | UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \ 43 | UNIT, 0x00, /* Unit: None */ \ 44 | /* End of 4 bytes */ \ 45 | END_COLLECTION /* End Collection */ \ 46 | 47 | #define AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_2 \ 48 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 49 | /* Begin a byte */ \ 50 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 51 | USAGE, 0x47, /* Usage: Confidence */ \ 52 | USAGE, 0x42, /* Usage: Tip switch */ \ 53 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 54 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 55 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 56 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 57 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 58 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 59 | /* End of a byte */ \ 60 | /* Begin of 4 bytes */ \ 61 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 62 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 63 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 64 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 65 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 66 | /* End of 4 bytes */ \ 67 | /* Begin of 4 bytes */ \ 68 | /* Size is hard-coded at this moment */ \ 69 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 70 | LOGICAL_MAXIMUM_2, 0xf9, 0x24, /* Logical Maximum: 9465 (See defintion) */ \ 71 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 72 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 73 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 74 | USAGE, 0x30, /* Usage: X */ \ 75 | PHYSICAL_MAXIMUM_2, 0x1a, 0x04, /* Physical Maximum: 1050 (See Apple Spec) */ \ 76 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 77 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 78 | PHYSICAL_MAXIMUM_2, 0x2a, 0x03, /* Physical Maximum: 810 (See Apple Spec) */ \ 79 | LOGICAL_MAXIMUM_2, 0x4f, 0x1a, /* Logical Maximum: 6735 (See definition) */ \ 80 | USAGE, 0x31, /* Usage: Y */ \ 81 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 82 | /* End of 4 bytes */ \ 83 | END_COLLECTION /* End Collection */ \ 84 | 85 | #define AAPL_WELLSPRING_5_PTP_TLC \ 86 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 87 | USAGE, 0x05, /* Usage: Touch Pad */ \ 88 | BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \ 89 | REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \ 90 | USAGE, 0x22, /* Usage: Finger */ \ 91 | AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_1, /* 1 */ \ 92 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 93 | USAGE, 0x22, /* Usage: Finger */ \ 94 | AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_1, /* 2 */ \ 95 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 96 | USAGE, 0x22, /* Usage: Finger */ \ 97 | AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_2, /* 3 */ \ 98 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 99 | USAGE, 0x22, /* Usage: Finger */ \ 100 | AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_1, /* 4 */ \ 101 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 102 | USAGE, 0x22, /* Usage: Finger */ \ 103 | AAPL_WELLSPRING_5_PTP_FINGER_COLLECTION_2, /* 5 */ \ 104 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 105 | UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \ 106 | UNIT_2, 0x01, 0x10, /* Time: Second */ \ 107 | PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 108 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 109 | USAGE, 0x56, /* Usage: Scan Time */ \ 110 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 111 | USAGE, 0x54, /* Usage: Contact Count */ \ 112 | LOGICAL_MAXIMUM, 0x7f, \ 113 | REPORT_SIZE, 0x08, \ 114 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 115 | USAGE_PAGE, 0x09, /* Usage Page: Button */ \ 116 | USAGE, 0x01, /* Button 1 */ \ 117 | LOGICAL_MAXIMUM, 0x01, \ 118 | REPORT_SIZE, 0x01, \ 119 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 120 | REPORT_COUNT, 0x07, \ 121 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 122 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 123 | REPORT_ID, REPORTID_DEVICE_CAPS, \ 124 | USAGE, 0x55, /* Usage: Maximum Contacts */ \ 125 | USAGE, 0x59, /* Usage: Touchpad Button Type*/ \ 126 | LOGICAL_MINIMUM, 0x00, \ 127 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 128 | REPORT_SIZE, 0x08, \ 129 | REPORT_COUNT, 0x02, \ 130 | FEATURE, 0x02, \ 131 | USAGE_PAGE_1, 0x00, 0xff, \ 132 | REPORT_ID, REPORTID_PTPHQA, \ 133 | USAGE, 0xc5, \ 134 | LOGICAL_MINIMUM, 0x00, \ 135 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 136 | REPORT_SIZE, 0x08, \ 137 | REPORT_COUNT_2, 0x00, 0x01, \ 138 | FEATURE, 0x02, \ 139 | END_COLLECTION /* End Collection */ 140 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring6.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_1 \ 6 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 7 | /* Begin a byte */ \ 8 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 9 | USAGE, 0x47, /* Usage: Confidence */ \ 10 | USAGE, 0x42, /* Usage: Tip switch */ \ 11 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 12 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 13 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 14 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 15 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 16 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 17 | /* End of a byte */ \ 18 | /* Begin of 4 bytes */ \ 19 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 20 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 21 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 22 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 23 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 24 | /* End of 4 bytes */ \ 25 | /* Begin of 4 bytes */ \ 26 | /* Size is hard-coded at this moment */ \ 27 | /* This hard-coded size is designed for MacBookAir 7,2 */ \ 28 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 29 | LOGICAL_MAXIMUM_2, 0x20, 0x26, /* Logical Maximum: 9760 (See defintion) */ \ 30 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 31 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 32 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 33 | USAGE, 0x30, /* Usage: X */ \ 34 | PHYSICAL_MAXIMUM_2, 0x2b, 0x04, /* Physical Maximum: 1067 (See Apple Spec) */ \ 35 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 36 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 37 | PHYSICAL_MAXIMUM_2, 0xfa, 0x02, /* Physical Maximum: 762 (See Apple Spec) */ \ 38 | LOGICAL_MAXIMUM_2, 0x5e, 0x1a, /* Logical Maximum: 6750 (See definition) */ \ 39 | USAGE, 0x31, /* Usage: Y */ \ 40 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 41 | PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \ 42 | UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \ 43 | UNIT, 0x00, /* Unit: None */ \ 44 | /* End of 4 bytes */ \ 45 | END_COLLECTION /* End Collection */ \ 46 | 47 | #define AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_2 \ 48 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 49 | /* Begin a byte */ \ 50 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 51 | USAGE, 0x47, /* Usage: Confidence */ \ 52 | USAGE, 0x42, /* Usage: Tip switch */ \ 53 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 54 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 55 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 56 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 57 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 58 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 59 | /* End of a byte */ \ 60 | /* Begin of 4 bytes */ \ 61 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 62 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 63 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 64 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 65 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 66 | /* End of 4 bytes */ \ 67 | /* Begin of 4 bytes */ \ 68 | /* Size is hard-coded at this moment */ \ 69 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 70 | LOGICAL_MAXIMUM_2, 0x20, 0x26, /* Logical Maximum: 9760 (See defintion) */ \ 71 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 72 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 73 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 74 | USAGE, 0x30, /* Usage: X */ \ 75 | PHYSICAL_MAXIMUM_2, 0x2b, 0x04, /* Physical Maximum: 1067 (See Apple Spec) */ \ 76 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 77 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 78 | PHYSICAL_MAXIMUM_2, 0xfa, 0x02, /* Physical Maximum: 762 (See Apple Spec) */ \ 79 | LOGICAL_MAXIMUM_2, 0x5e, 0x1a, /* Logical Maximum: 6750 (See definition) */ \ 80 | USAGE, 0x31, /* Usage: Y */ \ 81 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 82 | /* End of 4 bytes */ \ 83 | END_COLLECTION /* End Collection */ \ 84 | 85 | #define AAPL_WELLSPRING_6_PTP_TLC \ 86 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 87 | USAGE, 0x05, /* Usage: Touch Pad */ \ 88 | BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \ 89 | REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \ 90 | USAGE, 0x22, /* Usage: Finger */ \ 91 | AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_1, /* 1 */ \ 92 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 93 | USAGE, 0x22, /* Usage: Finger */ \ 94 | AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_1, /* 2 */ \ 95 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 96 | USAGE, 0x22, /* Usage: Finger */ \ 97 | AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_2, /* 3 */ \ 98 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 99 | USAGE, 0x22, /* Usage: Finger */ \ 100 | AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_1, /* 4 */ \ 101 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 102 | USAGE, 0x22, /* Usage: Finger */ \ 103 | AAPL_WELLSPRING_6_PTP_FINGER_COLLECTION_2, /* 5 */ \ 104 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 105 | UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \ 106 | UNIT_2, 0x01, 0x10, /* Time: Second */ \ 107 | PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 108 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 109 | USAGE, 0x56, /* Usage: Scan Time */ \ 110 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 111 | USAGE, 0x54, /* Usage: Contact Count */ \ 112 | LOGICAL_MAXIMUM, 0x7f, \ 113 | REPORT_SIZE, 0x08, \ 114 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 115 | USAGE_PAGE, 0x09, /* Usage Page: Button */ \ 116 | USAGE, 0x01, /* Button 1 */ \ 117 | LOGICAL_MAXIMUM, 0x01, \ 118 | REPORT_SIZE, 0x01, \ 119 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 120 | REPORT_COUNT, 0x07, \ 121 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 122 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 123 | REPORT_ID, REPORTID_DEVICE_CAPS, \ 124 | USAGE, 0x55, /* Usage: Maximum Contacts */ \ 125 | USAGE, 0x59, /* Usage: Touchpad Button Type*/ \ 126 | LOGICAL_MINIMUM, 0x00, \ 127 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 128 | REPORT_SIZE, 0x08, \ 129 | REPORT_COUNT, 0x02, \ 130 | FEATURE, 0x02, \ 131 | USAGE_PAGE_1, 0x00, 0xff, \ 132 | REPORT_ID, REPORTID_PTPHQA, \ 133 | USAGE, 0xc5, \ 134 | LOGICAL_MINIMUM, 0x00, \ 135 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 136 | REPORT_SIZE, 0x08, \ 137 | REPORT_COUNT_2, 0x00, 0x01, \ 138 | FEATURE, 0x02, \ 139 | END_COLLECTION /* End Collection */ -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring7A.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_1 \ 6 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 7 | /* Begin a byte */ \ 8 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 9 | USAGE, 0x47, /* Usage: Confidence */ \ 10 | USAGE, 0x42, /* Usage: Tip switch */ \ 11 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 12 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 13 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 14 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 15 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 16 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 17 | /* End of a byte */ \ 18 | /* Begin of 4 bytes */ \ 19 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 20 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 21 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 22 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 23 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 24 | /* End of 4 bytes */ \ 25 | /* Begin of 4 bytes */ \ 26 | /* Size is hard-coded at this moment */ \ 27 | /* This hard-coded size is designed for MacBookPro 11,1 */ \ 28 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 29 | LOGICAL_MAXIMUM_2, 0x2e, 0x27, /* Logical Maximum: 10030 (See defintion) */ \ 30 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 31 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 32 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 33 | USAGE, 0x30, /* Usage: X */ \ 34 | PHYSICAL_MAXIMUM_2, 0x28, 0x04, /* Physical Maximum: 1064 (See Apple Spec) */ \ 35 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 36 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 37 | PHYSICAL_MAXIMUM_2, 0x05, 0x03, /* Physical Maximum: 773 (See Apple Spec) */ \ 38 | LOGICAL_MAXIMUM_2, 0xe0, 0x1a, /* Logical Maximum: 6880 (See definition) */ \ 39 | USAGE, 0x31, /* Usage: Y */ \ 40 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 41 | PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \ 42 | UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \ 43 | UNIT, 0x00, /* Unit: None */ \ 44 | /* End of 4 bytes */ \ 45 | END_COLLECTION /* End Collection */ \ 46 | 47 | #define AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_2 \ 48 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 49 | /* Begin a byte */ \ 50 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 51 | USAGE, 0x47, /* Usage: Confidence */ \ 52 | USAGE, 0x42, /* Usage: Tip switch */ \ 53 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 54 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 55 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 56 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 57 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 58 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 59 | /* End of a byte */ \ 60 | /* Begin of 4 bytes */ \ 61 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 62 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 63 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 64 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 65 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 66 | /* End of 4 bytes */ \ 67 | /* Begin of 4 bytes */ \ 68 | /* Size is hard-coded at this moment */ \ 69 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 70 | LOGICAL_MAXIMUM_2, 0x2e, 0x27, /* Logical Maximum: 10030 (See defintion) */ \ 71 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 72 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 73 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 74 | USAGE, 0x30, /* Usage: X */ \ 75 | PHYSICAL_MAXIMUM_2, 0x28, 0x04, /* Physical Maximum: 1064 (See Apple Spec) */ \ 76 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 77 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 78 | PHYSICAL_MAXIMUM_2, 0x05, 0x03, /* Physical Maximum: 773 (See Apple Spec) */ \ 79 | LOGICAL_MAXIMUM_2, 0xe0, 0x1a, /* Logical Maximum: 6880 (See definition) */ \ 80 | USAGE, 0x31, /* Usage: Y */ \ 81 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 82 | /* End of 4 bytes */ \ 83 | END_COLLECTION /* End Collection */ \ 84 | 85 | #define AAPL_WELLSPRING_7A_PTP_TLC \ 86 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 87 | USAGE, 0x05, /* Usage: Touch Pad */ \ 88 | BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \ 89 | REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \ 90 | USAGE, 0x22, /* Usage: Finger */ \ 91 | AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_1, /* 1 */ \ 92 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 93 | USAGE, 0x22, /* Usage: Finger */ \ 94 | AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_1, /* 2 */ \ 95 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 96 | USAGE, 0x22, /* Usage: Finger */ \ 97 | AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_2, /* 3 */ \ 98 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 99 | USAGE, 0x22, /* Usage: Finger */ \ 100 | AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_1, /* 4 */ \ 101 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 102 | USAGE, 0x22, /* Usage: Finger */ \ 103 | AAPL_WELLSPRING_7A_PTP_FINGER_COLLECTION_2, /* 5 */ \ 104 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 105 | UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \ 106 | UNIT_2, 0x01, 0x10, /* Time: Second */ \ 107 | PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 108 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 109 | USAGE, 0x56, /* Usage: Scan Time */ \ 110 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 111 | USAGE, 0x54, /* Usage: Contact Count */ \ 112 | LOGICAL_MAXIMUM, 0x7f, \ 113 | REPORT_SIZE, 0x08, \ 114 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 115 | USAGE_PAGE, 0x09, /* Usage Page: Button */ \ 116 | USAGE, 0x01, /* Button 1 */ \ 117 | LOGICAL_MAXIMUM, 0x01, \ 118 | REPORT_SIZE, 0x01, \ 119 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 120 | REPORT_COUNT, 0x07, \ 121 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 122 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 123 | REPORT_ID, REPORTID_DEVICE_CAPS, \ 124 | USAGE, 0x55, /* Usage: Maximum Contacts */ \ 125 | USAGE, 0x59, /* Usage: Touchpad Button Type*/ \ 126 | LOGICAL_MINIMUM, 0x00, \ 127 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 128 | REPORT_SIZE, 0x08, \ 129 | REPORT_COUNT, 0x02, \ 130 | FEATURE, 0x02, \ 131 | USAGE_PAGE_1, 0x00, 0xff, \ 132 | REPORT_ID, REPORTID_PTPHQA, \ 133 | USAGE, 0xc5, \ 134 | LOGICAL_MINIMUM, 0x00, \ 135 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 136 | REPORT_SIZE, 0x08, \ 137 | REPORT_COUNT_2, 0x00, 0x01, \ 138 | FEATURE, 0x02, \ 139 | END_COLLECTION /* End Collection */ 140 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/DeviceFamily/Wellspring8.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_1 \ 6 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 7 | /* Begin a byte */ \ 8 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 9 | USAGE, 0x47, /* Usage: Confidence */ \ 10 | USAGE, 0x42, /* Usage: Tip switch */ \ 11 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 12 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 13 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 14 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 15 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 16 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 17 | /* End of a byte */ \ 18 | /* Begin of 4 bytes */ \ 19 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 20 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 21 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 22 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 23 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 24 | /* End of 4 bytes */ \ 25 | /* Begin of 4 bytes */ \ 26 | /* Size is hard-coded at this moment */ \ 27 | /* This hard-coded size is designed for MacBookAir 7,2 */ \ 28 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 29 | LOGICAL_MAXIMUM_2, 0x20, 0x26, /* Logical Maximum: 9760 (See defintion) */ \ 30 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 31 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 32 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 33 | USAGE, 0x30, /* Usage: X */ \ 34 | PHYSICAL_MAXIMUM_2, 0x15, 0x04, /* Physical Maximum: 1045 (See Apple Spec) */ \ 35 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 36 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 37 | PHYSICAL_MAXIMUM_2, 0xee, 0x02, /* Physical Maximum: 750 (See Apple Spec) */ \ 38 | LOGICAL_MAXIMUM_2, 0x5e, 0x1a, /* Logical Maximum: 6750 (See definition) */ \ 39 | USAGE, 0x31, /* Usage: Y */ \ 40 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 41 | PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \ 42 | UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \ 43 | UNIT, 0x00, /* Unit: None */ \ 44 | /* End of 4 bytes */ \ 45 | END_COLLECTION /* End Collection */ \ 46 | 47 | #define AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_2 \ 48 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 49 | /* Begin a byte */ \ 50 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 51 | USAGE, 0x47, /* Usage: Confidence */ \ 52 | USAGE, 0x42, /* Usage: Tip switch */ \ 53 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 54 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 55 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 56 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 57 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 58 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 59 | /* End of a byte */ \ 60 | /* Begin of 4 bytes */ \ 61 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 62 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 63 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 64 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 65 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 66 | /* End of 4 bytes */ \ 67 | /* Begin of 4 bytes */ \ 68 | /* Size is hard-coded at this moment */ \ 69 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 70 | LOGICAL_MAXIMUM_2, 0x20, 0x26, /* Logical Maximum: 9760 (See defintion) */ \ 71 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 72 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 73 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 74 | USAGE, 0x30, /* Usage: X */ \ 75 | PHYSICAL_MAXIMUM_2, 0x15, 0x04, /* Physical Maximum: 1045 (See Apple Spec) */ \ 76 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 77 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 78 | PHYSICAL_MAXIMUM_2, 0xee, 0x02, /* Physical Maximum: 750 (See Apple Spec) */ \ 79 | LOGICAL_MAXIMUM_2, 0x5e, 0x1a, /* Logical Maximum: 6750 (See definition) */ \ 80 | USAGE, 0x31, /* Usage: Y */ \ 81 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 82 | /* End of 4 bytes */ \ 83 | END_COLLECTION /* End Collection */ \ 84 | 85 | #define AAPL_WELLSPRING_8_PTP_TLC \ 86 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 87 | USAGE, 0x05, /* Usage: Touch Pad */ \ 88 | BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \ 89 | REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \ 90 | USAGE, 0x22, /* Usage: Finger */ \ 91 | AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_1, /* 1 */ \ 92 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 93 | USAGE, 0x22, /* Usage: Finger */ \ 94 | AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_1, /* 2 */ \ 95 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 96 | USAGE, 0x22, /* Usage: Finger */ \ 97 | AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_2, /* 3 */ \ 98 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 99 | USAGE, 0x22, /* Usage: Finger */ \ 100 | AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_1, /* 4 */ \ 101 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 102 | USAGE, 0x22, /* Usage: Finger */ \ 103 | AAPL_WELLSPRING_8_PTP_FINGER_COLLECTION_2, /* 5 */ \ 104 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 105 | UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \ 106 | UNIT_2, 0x01, 0x10, /* Time: Second */ \ 107 | PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 108 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 109 | USAGE, 0x56, /* Usage: Scan Time */ \ 110 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 111 | USAGE, 0x54, /* Usage: Contact Count */ \ 112 | LOGICAL_MAXIMUM, 0x7f, \ 113 | REPORT_SIZE, 0x08, \ 114 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 115 | USAGE_PAGE, 0x09, /* Usage Page: Button */ \ 116 | USAGE, 0x01, /* Button 1 */ \ 117 | LOGICAL_MAXIMUM, 0x01, \ 118 | REPORT_SIZE, 0x01, \ 119 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 120 | REPORT_COUNT, 0x07, \ 121 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 122 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 123 | REPORT_ID, REPORTID_DEVICE_CAPS, \ 124 | USAGE, 0x55, /* Usage: Maximum Contacts */ \ 125 | USAGE, 0x59, /* Usage: Touchpad Button Type*/ \ 126 | LOGICAL_MINIMUM, 0x00, \ 127 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 128 | REPORT_SIZE, 0x08, \ 129 | REPORT_COUNT, 0x02, \ 130 | FEATURE, 0x02, \ 131 | USAGE_PAGE_1, 0x00, 0xff, \ 132 | REPORT_ID, REPORTID_PTPHQA, \ 133 | USAGE, 0xc5, \ 134 | LOGICAL_MINIMUM, 0x00, \ 135 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 136 | REPORT_SIZE, 0x08, \ 137 | REPORT_COUNT_2, 0x00, 0x01, \ 138 | FEATURE, 0x02, \ 139 | END_COLLECTION /* End Collection */ 140 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/DeviceFamily/WellspringMt2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1 \ 6 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 7 | /* Begin a byte */ \ 8 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 9 | USAGE, 0x47, /* Usage: Confidence */ \ 10 | USAGE, 0x42, /* Usage: Tip switch */ \ 11 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 12 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 13 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 14 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 15 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 16 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 17 | /* End of a byte */ \ 18 | /* Begin of 4 bytes */ \ 19 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 20 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 21 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 22 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 23 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 24 | /* End of 4 bytes */ \ 25 | /* Begin of 4 bytes */ \ 26 | /* Size is hard-coded at this moment */ \ 27 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 28 | LOGICAL_MAXIMUM_2, 0xbc, 0x1d, /* Logical Maximum: 7612 (See defintion) */ \ 29 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 30 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 31 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 32 | USAGE, 0x30, /* Usage: X */ \ 33 | PHYSICAL_MAXIMUM_2, 0x40, 0x06, /* Physical Maximum: 1600 (See Apple Spec) */ \ 34 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 35 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 36 | PHYSICAL_MAXIMUM_2, 0x7d, 0x04, /* Physical Maximum: 1149 (See Apple Spec) */ \ 37 | LOGICAL_MAXIMUM_2, 0xc9, 0x13, /* Logical Maximum: 5065 (See definition) */ \ 38 | USAGE, 0x31, /* Usage: Y */ \ 39 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 40 | PHYSICAL_MAXIMUM, 0x00, /* Physical Maximum: 0 */ \ 41 | UNIT_EXPONENT, 0x00, /* Unit exponent: 0 */ \ 42 | UNIT, 0x00, /* Unit: None */ \ 43 | /* End of 4 bytes */ \ 44 | END_COLLECTION /* End Collection */ \ 45 | 46 | #define AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_2 \ 47 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 48 | /* Begin a byte */ \ 49 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 1 */ \ 50 | USAGE, 0x47, /* Usage: Confidence */ \ 51 | USAGE, 0x42, /* Usage: Tip switch */ \ 52 | REPORT_COUNT, 0x02, /* Report Count: 2 */ \ 53 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 54 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 55 | REPORT_SIZE, 0x01, /* Report Size: 1 */ \ 56 | REPORT_COUNT, 0x06, /* Report Count: 6 */ \ 57 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 58 | /* End of a byte */ \ 59 | /* Begin of 4 bytes */ \ 60 | REPORT_COUNT, 0x01, /* Report Count: 1 */ \ 61 | REPORT_SIZE, 0x20, /* Report Size: 0x20 (4 bytes) */ \ 62 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0xff, 0xff, /* Logical Maximum: 0xffffffff */ \ 63 | USAGE, 0x51, /* Usage: Contract Identifier */ \ 64 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 65 | /* End of 4 bytes */ \ 66 | /* Begin of 4 bytes */ \ 67 | /* Size is hard-coded at this moment */ \ 68 | USAGE_PAGE, 0x01, /* Usage Page: Generic Desktop */ \ 69 | LOGICAL_MAXIMUM_2, 0xbc, 0x1d, /* Logical Maximum: 7612 (See defintion) */ \ 70 | REPORT_SIZE, 0x10, /* Report Size: 0x10 (2 bytes) */ \ 71 | UNIT_EXPONENT, 0x0e, /* Unit exponent: -2 */ \ 72 | UNIT, 0x11, /* Unit: SI Length (cm) */ \ 73 | USAGE, 0x30, /* Usage: X */ \ 74 | PHYSICAL_MAXIMUM_2, 0x40, 0x06, /* Physical Maximum: 1600 (See Apple Spec) */ \ 75 | REPORT_COUNT, 0x01, /* Report count: 1 */ \ 76 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 77 | PHYSICAL_MAXIMUM_2, 0x7d, 0x04, /* Physical Maximum: 1149 (See Apple Spec) */ \ 78 | LOGICAL_MAXIMUM_2, 0xc9, 0x13, /* Logical Maximum: 5065 (See definition) */ \ 79 | USAGE, 0x31, /* Usage: Y */ \ 80 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 81 | /* End of 4 bytes */ \ 82 | END_COLLECTION /* End Collection */ \ 83 | 84 | #define AAPL_MAGIC_TRACKPAD2_PTP_TLC \ 85 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 86 | USAGE, 0x05, /* Usage: Touch Pad */ \ 87 | BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \ 88 | REPORT_ID, REPORTID_MULTITOUCH, /* Report ID: Multi-touch */ \ 89 | USAGE, 0x22, /* Usage: Finger */ \ 90 | AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 1 */ \ 91 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 92 | USAGE, 0x22, /* Usage: Finger */ \ 93 | AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 2 */ \ 94 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 95 | USAGE, 0x22, /* Usage: Finger */ \ 96 | AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_2, /* 3 */ \ 97 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 98 | USAGE, 0x22, /* Usage: Finger */ \ 99 | AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_1, /* 4 */ \ 100 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 101 | USAGE, 0x22, /* Usage: Finger */ \ 102 | AAPL_MAGIC_TRACKPAD2_PTP_FINGER_COLLECTION_2, /* 5 */ \ 103 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 104 | UNIT_EXPONENT, 0x0c, /* Unit exponent: -4 */ \ 105 | UNIT_2, 0x01, 0x10, /* Time: Second */ \ 106 | PHYSICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 107 | LOGICAL_MAXIMUM_3, 0xff, 0xff, 0x00, 0x00, \ 108 | USAGE, 0x56, /* Usage: Scan Time */ \ 109 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 110 | USAGE, 0x54, /* Usage: Contact Count */ \ 111 | LOGICAL_MAXIMUM, 0x7f, \ 112 | REPORT_SIZE, 0x08, \ 113 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 114 | USAGE_PAGE, 0x09, /* Usage Page: Button */ \ 115 | USAGE, 0x01, /* Button 1 */ \ 116 | LOGICAL_MAXIMUM, 0x01, \ 117 | REPORT_SIZE, 0x01, \ 118 | INPUT, 0x02, /* Input: (Data, Var, Abs) */ \ 119 | REPORT_COUNT, 0x07, \ 120 | INPUT, 0x03, /* Input: (Const, Var, Abs) */ \ 121 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 122 | REPORT_ID, REPORTID_DEVICE_CAPS, \ 123 | USAGE, 0x55, /* Usage: Maximum Contacts */ \ 124 | USAGE, 0x59, /* Usage: Touchpad Button Type*/ \ 125 | LOGICAL_MINIMUM, 0x00, \ 126 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 127 | REPORT_SIZE, 0x08, \ 128 | REPORT_COUNT, 0x02, \ 129 | FEATURE, 0x02, \ 130 | USAGE_PAGE_1, 0x00, 0xff, \ 131 | REPORT_ID, REPORTID_PTPHQA, \ 132 | USAGE, 0xc5, \ 133 | LOGICAL_MINIMUM, 0x00, \ 134 | LOGICAL_MAXIMUM_2, 0xff, 0x00, \ 135 | REPORT_SIZE, 0x08, \ 136 | REPORT_COUNT_2, 0x00, 0x01, \ 137 | FEATURE, 0x02, \ 138 | END_COLLECTION /* End Collection */ 139 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/Driver.h: -------------------------------------------------------------------------------- 1 | // Driver.h: Driver definitions 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // ModernTrace is for runtime debugging 11 | // Trace is WPP-based, development debugging 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | EXTERN_C_START 21 | 22 | // 23 | // WDFDRIVER Events 24 | // 25 | 26 | DRIVER_INITIALIZE DriverEntry; 27 | EVT_WDF_DRIVER_DEVICE_ADD AmtPtpDeviceEvtDeviceAdd; 28 | EVT_WDF_OBJECT_CONTEXT_CLEANUP AmtPtpDeviceEvtDriverContextCleanup; 29 | 30 | 31 | // 32 | // Driver initialization routines 33 | // 34 | 35 | VOID 36 | DriverTraceInit( 37 | _In_ PDRIVER_OBJECT DriverObject, 38 | _In_ PUNICODE_STRING RegistryPath 39 | ); 40 | 41 | VOID 42 | DriverTraceCleanup( 43 | _In_ WDFOBJECT DriverObject 44 | ); 45 | 46 | EXTERN_C_END 47 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/Hid.h: -------------------------------------------------------------------------------- 1 | // Hid.h: Device-related HID definitions 2 | #pragma once 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | // Device family metadata 10 | #include "DeviceFamily/Wellspring3.h" 11 | #include "DeviceFamily/Wellspring5.h" 12 | #include "DeviceFamily/Wellspring6.h" 13 | #include "DeviceFamily/Wellspring7A.h" 14 | #include "DeviceFamily/Wellspring8.h" 15 | #include "DeviceFamily/WellspringMt2.h" 16 | 17 | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR; 18 | 19 | #define DEVICE_VERSION 0x01 20 | #define DEVICE_VID 0x8910 21 | 22 | #define AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC \ 23 | USAGE_PAGE_1, 0x00, 0xff, /* Usage Page: Vendor defined */ \ 24 | USAGE, 0x01, /* Usage: Vendor Usage 0x01 */ \ 25 | BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \ 26 | REPORT_ID, REPORTID_UMAPP_CONF, /* Report ID: User-mode Application configuration */ \ 27 | USAGE, 0x01, /* Usage: Vendor Usage 0x01 */ \ 28 | LOGICAL_MINIMUM, 0x00, /* Logical Minimum 0 */ \ 29 | LOGICAL_MAXIMUM_2, 0xff, 0x00, /* Logical Maximum 255 */ \ 30 | REPORT_SIZE, 0x08, /* Report Size: 8 */ \ 31 | REPORT_COUNT, 0x03, /* Report Count: 3 */ \ 32 | FEATURE, 0x02, /* Feature: (Data, Var, Abs) */ \ 33 | END_COLLECTION 34 | 35 | #define AAPL_PTP_WINDOWS_CONFIGURATION_TLC \ 36 | USAGE_PAGE, 0x0d, /* Usage Page: Digitizer */ \ 37 | USAGE, 0x0e, /* Usage: Configuration */ \ 38 | BEGIN_COLLECTION, 0x01, /* Begin Collection: Application */ \ 39 | REPORT_ID, REPORTID_REPORTMODE, /* Report ID: Mode Selection */ \ 40 | USAGE, 0x22, /* Usage: Finger */ \ 41 | BEGIN_COLLECTION, 0x02, /* Begin Collection: Logical */ \ 42 | USAGE, 0x52, /* Usage: Input Mode */ \ 43 | LOGICAL_MINIMUM, 0x00, /* Logical Minumum: 0 finger */ \ 44 | LOGICAL_MAXIMUM, MAX_FINGERS, /* Logical Maximum: MAX_TOUCH_COUNT fingers */ \ 45 | REPORT_SIZE, 0x08, /* Report Size: 0x08 */ \ 46 | REPORT_COUNT, 0x01, /* Report Count: 0x01 */ \ 47 | FEATURE, 0x02, /* Feature: (Data, Var, Abs) */ \ 48 | END_COLLECTION, /* End Collection */ \ 49 | BEGIN_COLLECTION, 0x00, /* Begin Collection: Physical */ \ 50 | REPORT_ID, REPORTID_FUNCSWITCH, /* Report ID: Function Switch */ \ 51 | USAGE, BUTTON_SWITCH, /* Usage: Button Switch */ \ 52 | USAGE, SURFACE_SWITCH, /* Usage: Surface Switch */ \ 53 | REPORT_SIZE, 0x01, /* Report Size: 0x01 */ \ 54 | REPORT_COUNT, 0x02, /* Report Count: 0x02 */ \ 55 | LOGICAL_MAXIMUM, 0x01, /* Logical Maximum: 0x01 */ \ 56 | FEATURE, 0x02, /* Feature: (Data, Var, Abs) */ \ 57 | REPORT_COUNT, 0x06, /* Report Count: 0x06 */ \ 58 | FEATURE, 0x03, /* Feature: (Const, Var, Abs) */ \ 59 | END_COLLECTION, /* End Collection */ \ 60 | END_COLLECTION /* End Collection */ 61 | 62 | #define DEFAULT_PTP_HQA_BLOB \ 63 | 0xfc, 0x28, 0xfe, 0x84, 0x40, 0xcb, 0x9a, 0x87, \ 64 | 0x0d, 0xbe, 0x57, 0x3c, 0xb6, 0x70, 0x09, 0x88, \ 65 | 0x07, 0x97, 0x2d, 0x2b, 0xe3, 0x38, 0x34, 0xb6, \ 66 | 0x6c, 0xed, 0xb0, 0xf7, 0xe5, 0x9c, 0xf6, 0xc2, \ 67 | 0x2e, 0x84, 0x1b, 0xe8, 0xb4, 0x51, 0x78, 0x43, \ 68 | 0x1f, 0x28, 0x4b, 0x7c, 0x2d, 0x53, 0xaf, 0xfc, \ 69 | 0x47, 0x70, 0x1b, 0x59, 0x6f, 0x74, 0x43, 0xc4, \ 70 | 0xf3, 0x47, 0x18, 0x53, 0x1a, 0xa2, 0xa1, 0x71, \ 71 | 0xc7, 0x95, 0x0e, 0x31, 0x55, 0x21, 0xd3, 0xb5, \ 72 | 0x1e, 0xe9, 0x0c, 0xba, 0xec, 0xb8, 0x89, 0x19, \ 73 | 0x3e, 0xb3, 0xaf, 0x75, 0x81, 0x9d, 0x53, 0xb9, \ 74 | 0x41, 0x57, 0xf4, 0x6d, 0x39, 0x25, 0x29, 0x7c, \ 75 | 0x87, 0xd9, 0xb4, 0x98, 0x45, 0x7d, 0xa7, 0x26, \ 76 | 0x9c, 0x65, 0x3b, 0x85, 0x68, 0x89, 0xd7, 0x3b, \ 77 | 0xbd, 0xff, 0x14, 0x67, 0xf2, 0x2b, 0xf0, 0x2a, \ 78 | 0x41, 0x54, 0xf0, 0xfd, 0x2c, 0x66, 0x7c, 0xf8, \ 79 | 0xc0, 0x8f, 0x33, 0x13, 0x03, 0xf1, 0xd3, 0xc1, \ 80 | 0x0b, 0x89, 0xd9, 0x1b, 0x62, 0xcd, 0x51, 0xb7, \ 81 | 0x80, 0xb8, 0xaf, 0x3a, 0x10, 0xc1, 0x8a, 0x5b, \ 82 | 0xe8, 0x8a, 0x56, 0xf0, 0x8c, 0xaa, 0xfa, 0x35, \ 83 | 0xe9, 0x42, 0xc4, 0xd8, 0x55, 0xc3, 0x38, 0xcc, \ 84 | 0x2b, 0x53, 0x5c, 0x69, 0x52, 0xd5, 0xc8, 0x73, \ 85 | 0x02, 0x38, 0x7c, 0x73, 0xb6, 0x41, 0xe7, 0xff, \ 86 | 0x05, 0xd8, 0x2b, 0x79, 0x9a, 0xe2, 0x34, 0x60, \ 87 | 0x8f, 0xa3, 0x32, 0x1f, 0x09, 0x78, 0x62, 0xbc, \ 88 | 0x80, 0xe3, 0x0f, 0xbd, 0x65, 0x20, 0x08, 0x13, \ 89 | 0xc1, 0xe2, 0xee, 0x53, 0x2d, 0x86, 0x7e, 0xa7, \ 90 | 0x5a, 0xc5, 0xd3, 0x7d, 0x98, 0xbe, 0x31, 0x48, \ 91 | 0x1f, 0xfb, 0xda, 0xaf, 0xa2, 0xa8, 0x6a, 0x89, \ 92 | 0xd6, 0xbf, 0xf2, 0xd3, 0x32, 0x2a, 0x9a, 0xe4, \ 93 | 0xcf, 0x17, 0xb7, 0xb8, 0xf4, 0xe1, 0x33, 0x08, \ 94 | 0x24, 0x8b, 0xc4, 0x43, 0xa5, 0xe5, 0x24, 0xc2 95 | 96 | #define PTP_MAX_CONTACT_POINTS 5 97 | #define PTP_BUTTON_TYPE_CLICK_PAD 0 98 | #define PTP_BUTTON_TYPE_PRESSURE_PAD 1 99 | 100 | #define PTP_COLLECTION_MOUSE 0 101 | #define PTP_COLLECTION_WINDOWS 3 102 | 103 | #define PTP_CONTACT_CONFIDENCE_BIT 1 104 | #define PTP_CONTACT_TIPSWITCH_BIT 2 105 | 106 | typedef struct _HID_AAPL_MOUSE_REPORT { 107 | struct { 108 | UCHAR bButtons; 109 | UCHAR wXData; 110 | UCHAR wYData; 111 | UINT Padding; 112 | } InputReport; 113 | } HID_AAPL_MOUSE_REPORT, *PHID_AAPL_MOUSE_REPORT; 114 | 115 | typedef struct _HID_INPUT_REPORT { 116 | UCHAR ReportID; 117 | HID_AAPL_MOUSE_REPORT MouseReport; 118 | } HID_INPUT_REPORT, *PHID_INPUT_REPORT; 119 | 120 | typedef struct _PTP_DEVICE_CAPS_FEATURE_REPORT { 121 | UCHAR ReportID; 122 | UCHAR MaximumContactPoints; 123 | UCHAR ButtonType; 124 | } PTP_DEVICE_CAPS_FEATURE_REPORT, *PPTP_DEVICE_CAPS_FEATURE_REPORT; 125 | 126 | typedef struct _PTP_DEVICE_HQA_CERTIFICATION_REPORT { 127 | UCHAR ReportID; 128 | UCHAR CertificationBlob[256]; 129 | } PTP_DEVICE_HQA_CERTIFICATION_REPORT, *PPTP_DEVICE_HQA_CERTIFICATION_REPORT; 130 | 131 | typedef struct _PTP_DEVICE_INPUT_MODE_REPORT { 132 | UCHAR ReportID; 133 | UCHAR Mode; 134 | } PTP_DEVICE_INPUT_MODE_REPORT, *PPTP_DEVICE_INPUT_MODE_REPORT; 135 | 136 | #pragma pack(1) 137 | typedef struct _PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT { 138 | UCHAR ReportID; 139 | UCHAR ButtonReport : 1; 140 | UCHAR SurfaceReport : 1; 141 | UCHAR Padding : 6; 142 | } PTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT, *PPTP_DEVICE_SELECTIVE_REPORT_MODE_REPORT; 143 | #pragma pack() 144 | 145 | #pragma pack(1) 146 | typedef struct _PTP_CONTACT { 147 | UCHAR Confidence : 1; 148 | UCHAR TipSwitch : 1; 149 | UCHAR Padding : 6; 150 | ULONG ContactID; 151 | USHORT X; 152 | USHORT Y; 153 | } PTP_CONTACT, *PPTP_CONTACT; 154 | #pragma pack() 155 | 156 | typedef struct _PTP_REPORT { 157 | UCHAR ReportID; 158 | PTP_CONTACT Contacts[5]; 159 | USHORT ScanTime; 160 | UCHAR ContactCount; 161 | UCHAR IsButtonClicked; 162 | } PTP_REPORT, *PPTP_REPORT; 163 | 164 | typedef struct _PTP_USERMODEAPP_CONF_REPORT { 165 | UCHAR ReportID; 166 | UCHAR PressureQualificationLevel; 167 | UCHAR SingleContactSizeQualificationLevel; 168 | UCHAR MultipleContactSizeQualificationLevel; 169 | } PTP_USERMODEAPP_CONF_REPORT, *PPTP_USERMODEAPP_CONF_REPORT; 170 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/HidCommon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define REPORTID_STANDARDMOUSE 0x02 4 | #define REPORTID_MULTITOUCH 0x05 5 | #define REPORTID_REPORTMODE 0x04 6 | #define REPORTID_PTPHQA 0x08 7 | #define REPORTID_FUNCSWITCH 0x06 8 | #define REPORTID_DEVICE_CAPS 0x07 9 | #define REPORTID_UMAPP_CONF 0x09 10 | 11 | #define BUTTON_SWITCH 0x57 12 | #define SURFACE_SWITCH 0x58 13 | 14 | #define USAGE_PAGE 0x05 15 | #define USAGE_PAGE_1 0x06 16 | #define USAGE 0x09 17 | #define USAGE_MINIMUM 0x19 18 | #define USAGE_MAXIMUM 0x29 19 | #define LOGICAL_MINIMUM 0x15 20 | #define LOGICAL_MAXIMUM 0x25 21 | #define LOGICAL_MAXIMUM_2 0x26 22 | #define LOGICAL_MAXIMUM_3 0x27 23 | #define PHYSICAL_MINIMUM 0x35 24 | #define PHYSICAL_MAXIMUM 0x45 25 | #define PHYSICAL_MAXIMUM_2 0x46 26 | #define PHYSICAL_MAXIMUM_3 0x47 27 | #define UNIT_EXPONENT 0x55 28 | #define UNIT 0x65 29 | #define UNIT_2 0x66 30 | 31 | #define REPORT_ID 0x85 32 | #define REPORT_COUNT 0x95 33 | #define REPORT_COUNT_2 0x96 34 | #define REPORT_SIZE 0x75 35 | #define INPUT 0x81 36 | #define FEATURE 0xb1 37 | 38 | #define BEGIN_COLLECTION 0xa1 39 | #define END_COLLECTION 0xc0 40 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/ModernTrace.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // This is the new Windows 10 trace logger provider 3 | #include 4 | 5 | EXTERN_C_START 6 | 7 | // 8 | // Declare TraceLogger Handler 9 | // TraceLogger GUID {871B1E2D-CC5A-4ADE-B74E-6CF1004EF149} 10 | // Do not confuse with WPP tracing 11 | // 12 | TRACELOGGING_DECLARE_PROVIDER(g_hAmtPtpDeviceTraceProvider); 13 | 14 | EXTERN_C_END 15 | 16 | // 17 | // Defines a set of events to use 18 | // 19 | 20 | #define EVENT_DRIVER_FUNCTIONAL "DriverFunctionalEvent" 21 | #define EVENT_DEVICE_IDENTIFICATION "DeviceIdentificationEvent" 22 | #define EVENT_DEVICE_USBOPERATION "DeviceUsbOperationEvent" 23 | #define EVENT_INPUT_DIAGNOSTICS "InputDiagnosticsEvent" 24 | 25 | #define EVENT_DRIVER_FUNC_SUBTYPE "Subtype" 26 | #define EVENT_DRIVER_FUNC_SUBTYPE_CRITFAIL "CriticalFailure" 27 | #define EVENT_DEVICE_ID_SUBTYPE_NOTFOUND "DeviceNotFoundInRegistry" 28 | #define EVENT_DEVICE_ID_SUBTYPE_HIDREG_NOTFOUND "DeviceDescriptorNotFoundInRegistry" 29 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/Queue.h: -------------------------------------------------------------------------------- 1 | // Queue.h: This file contains the queue definitions. 2 | 3 | EXTERN_C_START 4 | 5 | // 6 | // This is the context that can be placed per queue 7 | // and would contain per queue information. 8 | // 9 | typedef struct _QUEUE_CONTEXT { 10 | 11 | ULONG placeholder; 12 | 13 | } QUEUE_CONTEXT, *PQUEUE_CONTEXT; 14 | 15 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext) 16 | 17 | _IRQL_requires_(PASSIVE_LEVEL) 18 | PCHAR 19 | DbgIoControlGetString( 20 | _In_ ULONG IoControlCode 21 | ); 22 | 23 | NTSTATUS 24 | AmtPtpDeviceQueueInitialize( 25 | _In_ WDFDEVICE Device 26 | ); 27 | 28 | NTSTATUS 29 | AmtPtpDispatchReadReportRequests( 30 | _In_ WDFDEVICE Device, 31 | _In_ WDFREQUEST Request, 32 | _Out_ BOOLEAN *Pending 33 | ); 34 | 35 | // 36 | // Events from the IoQueue object 37 | // 38 | EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL AmtPtpDeviceEvtIoDeviceControl; 39 | EVT_WDF_IO_QUEUE_IO_STOP AmtPtpDeviceEvtIoStop; 40 | 41 | EXTERN_C_END 42 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/StaticHidRegistry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _AAPL_HID_DESCRIPTOR_H_ 4 | #define _AAPL_HID_DESCRIPTOR_H_ 5 | 6 | HID_REPORT_DESCRIPTOR AmtPtp3ReportDescriptor[] = { 7 | AAPL_WELLSPRING_3_PTP_TLC, 8 | AAPL_PTP_WINDOWS_CONFIGURATION_TLC, 9 | AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC 10 | }; 11 | 12 | HID_REPORT_DESCRIPTOR AmtPtp5ReportDescriptor[] = { 13 | AAPL_WELLSPRING_5_PTP_TLC, 14 | AAPL_PTP_WINDOWS_CONFIGURATION_TLC, 15 | AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC 16 | }; 17 | 18 | HID_REPORT_DESCRIPTOR AmtPtp6ReportDescriptor[] = { 19 | AAPL_WELLSPRING_6_PTP_TLC, 20 | AAPL_PTP_WINDOWS_CONFIGURATION_TLC, 21 | AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC 22 | }; 23 | 24 | HID_REPORT_DESCRIPTOR AmtPtp7aReportDescriptor[] = { 25 | AAPL_WELLSPRING_7A_PTP_TLC, 26 | AAPL_PTP_WINDOWS_CONFIGURATION_TLC, 27 | AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC 28 | }; 29 | 30 | HID_REPORT_DESCRIPTOR AmtPtp8ReportDescriptor[] = { 31 | AAPL_WELLSPRING_8_PTP_TLC, 32 | AAPL_PTP_WINDOWS_CONFIGURATION_TLC, 33 | AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC 34 | }; 35 | 36 | HID_REPORT_DESCRIPTOR AmtPtpMt2ReportDescriptor[] = { 37 | AAPL_MAGIC_TRACKPAD2_PTP_TLC, 38 | AAPL_PTP_WINDOWS_CONFIGURATION_TLC, 39 | AAPL_PTP_USERMODE_CONFIGURATION_APP_TLC 40 | }; 41 | 42 | HID_DESCRIPTOR AmtPtp3DefaultHidDescriptor = { 43 | 0x09, // bLength 44 | 0x21, // bDescriptorType 45 | 0x0100, // bcdHID 46 | 0x00, // bCountryCode 47 | 0x01, // bNumDescriptors 48 | { 49 | 0x22, // bDescriptorType 50 | sizeof(AmtPtp3ReportDescriptor) // bDescriptorLength 51 | }, 52 | }; 53 | 54 | HID_DESCRIPTOR AmtPtp5DefaultHidDescriptor = { 55 | 0x09, // bLength 56 | 0x21, // bDescriptorType 57 | 0x0100, // bcdHID 58 | 0x00, // bCountryCode 59 | 0x01, // bNumDescriptors 60 | { 61 | 0x22, // bDescriptorType 62 | sizeof(AmtPtp5ReportDescriptor) // bDescriptorLength 63 | }, 64 | }; 65 | 66 | HID_DESCRIPTOR AmtPtp6DefaultHidDescriptor = { 67 | 0x09, // bLength 68 | 0x21, // bDescriptorType 69 | 0x0100, // bcdHID 70 | 0x00, // bCountryCode 71 | 0x01, // bNumDescriptors 72 | { 73 | 0x22, // bDescriptorType 74 | sizeof(AmtPtp6ReportDescriptor) // bDescriptorLength 75 | }, 76 | }; 77 | 78 | HID_DESCRIPTOR AmtPtp7aDefaultHidDescriptor = { 79 | 0x09, // bLength 80 | 0x21, // bDescriptorType 81 | 0x0100, // bcdHID 82 | 0x00, // bCountryCode 83 | 0x01, // bNumDescriptors 84 | { 85 | 0x22, // bDescriptorType 86 | sizeof(AmtPtp7aReportDescriptor) // bDescriptorLength 87 | }, 88 | }; 89 | 90 | HID_DESCRIPTOR AmtPtp8DefaultHidDescriptor = { 91 | 0x09, // bLength 92 | 0x21, // bDescriptorType 93 | 0x0100, // bcdHID 94 | 0x00, // bCountryCode 95 | 0x01, // bNumDescriptors 96 | { 97 | 0x22, // bDescriptorType 98 | sizeof(AmtPtp8ReportDescriptor) // bDescriptorLength 99 | }, 100 | }; 101 | 102 | HID_DESCRIPTOR AmtPtpMt2DefaultHidDescriptor = { 103 | 0x09, // bLength 104 | 0x21, // bDescriptorType 105 | 0x0100, // bcdHID 106 | 0x00, // bCountryCode 107 | 0x01, // bNumDescriptors 108 | { 109 | 0x22, // bDescriptorType 110 | sizeof(AmtPtpMt2ReportDescriptor) // bDescriptorLength 111 | }, 112 | }; 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/Trace.h: -------------------------------------------------------------------------------- 1 | // Trace.h: Local type definitions for tracing 2 | 3 | // 4 | // Device Interface GUID 5 | // 4a5064e5-7d39-41d1-a0e4-81097edce967 6 | // 7 | DEFINE_GUID(GUID_DEVINTERFACE_AmtPtpDevice, 8 | 0x4a5064e5, 0x7d39, 0x41d1, 0xa0, 0xe4, 0x81, 0x09, 0x7e, 0xdc, 0xe9, 0x67); 9 | 10 | // 11 | // Define the tracing flags. 12 | // 13 | // Tracing GUID - efc3ce99-43ff-4b59-afe4-c856e1afd8b0 14 | // 15 | 16 | #define WPP_CONTROL_GUIDS \ 17 | WPP_DEFINE_CONTROL_GUID( \ 18 | AmtPtpDriverTraceGuid, (efc3ce99,43ff,4b59,afe4,c856e1afd8b0), \ 19 | \ 20 | WPP_DEFINE_BIT(AMTPTPDRIVER_ALL_INFO) \ 21 | WPP_DEFINE_BIT(TRACE_DRIVER) \ 22 | WPP_DEFINE_BIT(TRACE_DEVICE) \ 23 | WPP_DEFINE_BIT(TRACE_QUEUE) \ 24 | WPP_DEFINE_BIT(TRACE_INPUT) \ 25 | ) 26 | 27 | #define WPP_FLAG_LEVEL_LOGGER(flag, level) \ 28 | WPP_LEVEL_LOGGER(flag) 29 | 30 | #define WPP_FLAG_LEVEL_ENABLED(flag, level) \ 31 | (WPP_LEVEL_ENABLED(flag) && \ 32 | WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) 33 | 34 | #define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \ 35 | WPP_LEVEL_LOGGER(flags) 36 | 37 | #define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \ 38 | (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) 39 | 40 | // 41 | // This comment block is scanned by the trace preprocessor to define our 42 | // Trace function. 43 | // 44 | // begin_wpp config 45 | // FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); 46 | // FUNC TraceEvents(LEVEL, FLAGS, MSG, ...); 47 | // end_wpp 48 | // -------------------------------------------------------------------------------- /AmtPtpDeviceUsbUm/include/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Resource.rc 4 | 5 | #define IDS_APP_TITLE 103 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 101 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is the Precision Touchpad driver for the Magic Trackpad 2 that I personally use on my PCs. It is based entirely on the excellent [imbushuo driver](https://github.com/imbushuo/mac-precision-touchpad) and solves a number of problems explained in the "Context" section below. This is an image of the Control Panel: (each option is an additional feature built on top of the "vanilla" imbushuo driver) 2 | 3 | ![Control Panel](https://raw.githubusercontent.com/vitoplantamura/MagicTrackpad2ForWindows/master/assets/ControlPanel.png) 4 | 5 | # Context 6 | 7 | In terms of hardware, the Magic Trackpad 2 is the best external touchpad you can buy (not just for macOS), by far. In terms of software, specifically for Windows, AFAIK there are 4 options to use it: Trackpad++, Magic Utilities, the excellent [open source driver by imbushuo](https://github.com/imbushuo/mac-precision-touchpad) and the [official 2021 Apple driver](https://github.com/lc700x/MagicTrackPad2_Windows_Precision_Drivers). In my opinion the two options that offer the best feeling, experience and stability (using the MT2 via USB at least) are the last two (imbushuo and Apple drivers) which coincidentally are extremely similar according to my tests (in terms of "feeling", and they are the only 2 that present the MT2 as a Precision Touchpad to Windows). Unfortunately these two solutions present different pointer precision problems. One problem is that of "near field fingers", i.e. the trackpad registers movements and clicks even without physically touching the trackpad surface, at a distance of even one millimeter from the surface. Another issue (determined by the first) is the accuracy of the pointer when you lift your finger from the trackpad. Furthermore, AFAIK, with both the imbushuo driver and the Apple one, it is not possible to adjust the behavior of the haptic feedback. 8 | 9 | A few months ago, I discovered [this excellent PR](https://github.com/imbushuo/mac-precision-touchpad/pull/533) of [1Revenger1](https://github.com/1Revenger1) to the imbushuo repo (which unfortunately hasn't been updated for 3 years). This PR solves the "near field fingers" problem. It also removes the QueryPerformanceCounter call in the interrupt function, instead setting the timestamp of the reports to the value returned by the Magic Trackpad itself (this may seem secondary but it is important, since using the MT2 in conditions of heavy PC load can determine returning inaccurate timestamps due to delayed thread scheduling). This PR convinced me that it might be worth investing some time in trying to solve all the other problems that made using MT2 more uncomfortable on PC than on macOS: I added the Control Panel, the ability to control the MT2's haptic feedback and other pointer precision options which I personally found useful. 10 | 11 | I'm really happy with the result: the feeling of the MT2 is identical to that of the touchpad of my laptop and very similar to that of the MT2 when used in macOS (pointer acceleration is different, but this is not determined by the driver). 12 | 13 | **Additional Credits**: The haptic feedback control messages sent by the driver to the MT2 in this project are based on the excellent reverse engineering work of [dos1](https://github.com/dos1) ([here](https://github.com/mwyborski/Linux-Magic-Trackpad-2-Driver/issues/28#issuecomment-451625504)). 14 | 15 | **License**: This project has the same license as the imbushuo project, on which it is entirely based. 16 | 17 | # Installation 18 | 19 | **NOTE**: Only for the MT2 when connected via USB, ie bluetooth not supported. 20 | 21 | 1) Connect the MT2 to the PC via USB and first install the imbushuo driver: download [this file (for x86)](https://github.com/imbushuo/mac-precision-touchpad/releases/download/2105-3979/Drivers-amd64-ReleaseMSSigned.zip) or [this file (for ARM)](https://github.com/imbushuo/mac-precision-touchpad/releases/download/2105-3979/Drivers-arm64-ReleaseMSSigned.zip), unzip it, right-click on the INF file and click "Install". 22 | 23 | 2) Download the zip file of this project from the [Releases](https://github.com/vitoplantamura/MagicTrackpad2ForWindows/releases) of this repo, unzip it, start the Control Panel and click on "Install Driver". 24 | 25 | # How the Installation Works 26 | 27 | The imbushuo MT2 USB driver is a UMDF driver. Windows Driver Signature Enforcement does not block the loading of self-signed UMDF drivers. This unfortunately does not apply to KMDF drivers such as the imbushuo bluetooth driver for the MT2 and this is the reason why this project only supports the USB version of the driver. On a personal note I prefer to use the MT2 via USB: the MT2 can be switched between different computers without problems, no worries about the battery, the driver cannot bluescreen the PC and the USB version of the imbushuo driver in particular has proven to be very stable over the years. 28 | 29 | When you click on "Install Driver" in the Control Panel, all MT2s connected to the system are disabled and then the AmtPtpDeviceUsbUm.dll file is updated directly in the Windows Driver Store. The owner and ACL of the file are modified to allow copying, and are restored to their original state at the end of the procedure. At the end of the copy, the MT2 is re-enabled. This procedure is not supported by Microsoft, but is commonly used during driver development and does not put system security at risk (as long as the file you are copying is trusted). 30 | 31 | **If your Magic Trackpad 2 is with Lightning Port (before Oct 2024), the installation is finished. If it is with USB-C (after Oct 2024) then this further step is necessary:** 32 | 33 | Manually choose the drivers in Device Manager for the Human Interface Devices with the Instance Path that matches this: ```USB\VID_05AC&PID_0324&MI_00\***``` & ```USB\VID_05AC&PID_0324&MI_01\***``` to be the Apple USB Precision Touchpad Device (User-mode) by Bingxing Wang (imbushuo). This can be done by double-clicking the device item in Device Manager -> (Details Tab) Update Driver -> Browse my computer for drivers -> Pick from list of drivers -> Uncheck Show compatible hardware. 34 | -------------------------------------------------------------------------------- /assets/ControlPanel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maashrafh/MagicTrackpad2ForWindows/971609319bd85e80e667ae8445b9b1053fadef66/assets/ControlPanel.png --------------------------------------------------------------------------------