Skip to content

Updated INF configurations on top of PR #533 (stability updates from @1revenge1) #550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.idea

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

4 changes: 2 additions & 2 deletions src/AmtPtpDevice.Settings/AmtPtpDevice.Settings.csproj
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@
<AssemblyName>AmtPtpDevice.Settings</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.15063.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.15063.0</TargetPlatformMinVersion>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.17763.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
50 changes: 36 additions & 14 deletions src/AmtPtpDeviceUniversalPkg/AmtPtpDevice.inf
Original file line number Diff line number Diff line change
@@ -25,9 +25,9 @@ AmtPtpDeviceSpiKm.sys = 1,,
AmtPtpHidFilter.sys = 1,,

[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$
%ManufacturerName%=Standard,NT$ARCH$.10.0...18362

[Standard.NT$ARCH$]
[Standard.NT$ARCH$.10.0...18362]
; Apple T2
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0273&MI_02
%AmtPtpDeviceUsbKm.DeviceDesc%=AmtPtpDeviceUsbKm_Device, USB\Vid_05ac&Pid_0274&MI_02
@@ -110,22 +110,21 @@ AmtPtpDeviceUsbUm.dll
[SpiKmDrivers_Dir]
AmtPtpDeviceSpiKm.sys

; Microsoft HID KMDF driver install sections
[mshidkmdf_Service_Inst]
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\mshidkmdf.sys

; PTP filter
[AmtPtpHidFilter_MiniPortDevice.NT]
CopyFiles=FilterDriver_Payload
Include=MsHidKmdf.inf
Needs=MsHidKmdf_LowerFilter.NT

[AmtPtpHidFilter_MiniPortDevice.NT.Services]
Include=MsHidKmdf.inf
Needs=MsHidKmdf_LowerFilter.NT.Services
AddService = AmtPtpHidFilter,, AmtPtpHidFilter_Service_Inst
AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst
;AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst

[AmtPtpHidFilter_MiniPortDevice.NT.HW]
Include=MsHidKmdf.inf
Needs=MsHidKmdf_LowerFilter.NT.HW
AddReg=AmtPtpHidFilter_AddReg

[AmtPtpHidFilter_AddReg]
@@ -148,14 +147,25 @@ KmdfLibraryVersion = $KMDFVERSION$
; USB KM
[AmtPtpDeviceUsbKm_Device.NT]
CopyFiles=PtpKmDrivers_Dir
Include=WUDFRD.inf
Needs=WUDFRD_LowerFilter.NT


[AmtPtpDeviceUsbKm_Device.NT.Services]
Include=WUDFRD.inf
Needs=WUDFRD_LowerFilter.NT.Services
AddService = AmtPtpDeviceUsbKm,, AmtPtpDeviceUsbKm_Service_Inst
AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst
; AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst

[AmtPtpDeviceUsbKm_Device.NT.HW]
Include=WUDFRD.inf
Needs=WUDFRD_LowerFilter.NT.HW
AddReg=AmtPtpDeviceUsbKm_AddReg

[AmtPtpDeviceUsbKm_Device.NT.Filters]
Include=WUDFRD.inf
Needs=WUDFRD_LowerFilter.NT.Filters

[AmtPtpDeviceUsbKm_AddReg]
HKR,,FriendlyName,,%AmtPtpDeviceUsbKm.DeviceDesc%
HKR,,"LowerFilters",0x00010008,"AmtPtpDeviceUsbKm"
@@ -176,14 +186,20 @@ KmdfLibraryVersion = $KMDFVERSION$

; USB UM
[AmtPtpDeviceUsbUm_Install.NT]
Include=WUDFRD.inf
Needs=WUDFRD_LowerFilter.NT
CopyFiles=PtpUmDrivers_Dir

[AmtPtpDeviceUsbUm_Install.NT.hw]
Include=WUDFRD.inf
Needs=WUDFRD_LowerFilter.NT.HW
AddReg=AmtPtpDeviceUsbUm_AddReg

[AmtPtpDeviceUsbUm_Install.NT.Services]
AddService=mshidumdf, 0x000001fa, MSHIDUMDF_ServiceInstall ; flag 0x2 sets this as the service for the device
AddService=WUDFRd,0x000001f8,WUDFRD_ServiceInstall ; this service is installed because its a filter.
Include=WUDFRD.inf
Needs=WUDFRD_LowerFilter.NT.Services
;AddService=mshidumdf, 0x000001fa, MSHIDUMDF_ServiceInstall ; flag 0x2 sets this as the service for the device
;AddService=WUDFRd,0x000001f8,WUDFRD_ServiceInstall ; this service is installed because its a filter.

[AmtPtpDeviceUsbUm_Install.NT.Wdf]
UmdfDispatcher=NativeUSB
@@ -219,12 +235,18 @@ ServiceBinary = %12%\WUDFRd.sys
; SPI KM
[AmtPtpDeviceSpiKm_Device.NT]
CopyFiles=SpiKmDrivers_Dir
Include=MsHidKmdf.inf
Needs=MsHidKmdf_LowerFilter.NT

[AmtPtpDeviceSpiKm_Device.NT.Services]
Include=MsHidKmdf.inf
Needs=MsHidKmdf_LowerFilter.NT.Services
AddService = AmtPtpDeviceSpiKm,, AmtPtpDeviceSpiKm_Service_Inst
AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst ;flag 0x2 sets this as the service for the device
;AddService = mshidkmdf, %SPSVCINST_ASSOCSERVICE%, mshidkmdf_Service_Inst ;flag 0x2 sets this as the service for the device

[AmtPtpDeviceSpiKm_Device.NT.HW]
Include=MsHidKmdf.inf
Needs=MsHidKmdf_LowerFilter.NT.HW
AddReg = AmtPtpDeviceSpiKm_Device.NT.AddReg

[AmtPtpDeviceSpiKm_Device.NT.AddReg]
76 changes: 33 additions & 43 deletions src/AmtPtpDeviceUsbUm/InputInterrupt.c
Original file line number Diff line number Diff line change
@@ -418,11 +418,10 @@ AmtPtpServiceTouchInputInterruptType5(
WDFREQUEST Request;
WDFMEMORY RequestMemory;
PTP_REPORT PtpReport;
LARGE_INTEGER CurrentPerfCounter;
LONGLONG PerfCounterDelta;

const struct TRACKPAD_FINGER *f;
const struct TRACKPAD_FINGER_TYPE5 *f_type5;
const struct TRACKPAD_FINGER_TYPE5* f;
const struct TRACKPAD_REPORT_TYPE5* mt_report;
const struct TRACKPAD_COMBINED_REPORT_TYPE5* full_report;

TraceEvents(
TRACE_LEVEL_INFORMATION,
@@ -434,10 +433,9 @@ AmtPtpServiceTouchInputInterruptType5(
PtpReport.ReportID = REPORTID_MULTITOUCH;
PtpReport.IsButtonClicked = 0;

UINT timestamp;
INT x, y = 0;
size_t raw_n, i = 0;
size_t headerSize = (unsigned int) DeviceContext->DeviceInfo->tp_header;
size_t fingerprintSize = (unsigned int) DeviceContext->DeviceInfo->tp_fsize;

Status = WdfIoQueueRetrieveNextRequest(
DeviceContext->InputQueue,
@@ -467,23 +465,16 @@ AmtPtpServiceTouchInputInterruptType5(
goto exit;
}

QueryPerformanceCounter(
&CurrentPerfCounter
);
full_report = (const struct TRACKPAD_COMBINED_REPORT_TYPE5 *) Buffer;
mt_report = &full_report->MTReport;

// Scan time is in 100us
PerfCounterDelta = (CurrentPerfCounter.QuadPart - DeviceContext->PerfCounter.QuadPart) / 100;
// Only two bytes allocated
if (PerfCounterDelta > 0xFF)
{
PerfCounterDelta = 0xFF;
}

PtpReport.ScanTime = (USHORT) PerfCounterDelta;
timestamp = (mt_report->TimestampHigh << 5) | mt_report->TimestampLow;
PtpReport.ScanTime = (USHORT) timestamp * 10;
PtpReport.IsButtonClicked = (UCHAR) mt_report->Button;

// Type 5 finger report
if (DeviceContext->IsSurfaceReportOn) {
raw_n = (NumBytesTransferred - headerSize) / fingerprintSize;
raw_n = (NumBytesTransferred - sizeof(struct TRACKPAD_REPORT_TYPE5)) / sizeof(struct TRACKPAD_FINGER_TYPE5);
if (raw_n >= PTP_MAX_CONTACT_POINTS) raw_n = PTP_MAX_CONTACT_POINTS;
PtpReport.ContactCount = (UCHAR)raw_n;

@@ -498,56 +489,55 @@ AmtPtpServiceTouchInputInterruptType5(

// Fingers to array
for (i = 0; i < raw_n; i++) {
f = &mt_report->Fingers[i];

UCHAR *f_base = Buffer + headerSize + DeviceContext->DeviceInfo->tp_delta;
f = (const struct TRACKPAD_FINGER*) (f_base + i * fingerprintSize);
f_type5 = (const struct TRACKPAD_FINGER_TYPE5*) f;

USHORT tmp_x = (*((USHORT*)f_type5)) & 0x1fff;
UINT tmp_y = (INT)(*((UINT*)f_type5));

x = (SHORT) (tmp_x << 3) >> 3;
y = -(INT) (tmp_y << 6) >> 19;
// Sign extend
x = (SHORT) (f->AbsoluteX << 3) >> 3;
y = -(SHORT) (f->AbsoluteY << 3) >> 3;

x = (x - DeviceContext->DeviceInfo->x.min) > 0 ? (x - DeviceContext->DeviceInfo->x.min) : 0;
y = (y - DeviceContext->DeviceInfo->y.min) > 0 ? (y - DeviceContext->DeviceInfo->y.min) : 0;

PtpReport.Contacts[i].ContactID = f_type5->ContactIdentifier.Id;
PtpReport.Contacts[i].ContactID = f->Id;
PtpReport.Contacts[i].X = (USHORT) x;
PtpReport.Contacts[i].Y = (USHORT) y;
PtpReport.Contacts[i].TipSwitch = (AmtRawToInteger(f_type5->TouchMajor) << 1) > 0;
// 0x1 = Transition between states
// 0x2 = Floating finger
// 0x4 = Contact/Valid
// I've gotten 0x6 if I press on the trackpad and then keep my finger close
// Note: These values come from my MBP9,2. These also are valid on my MT2
PtpReport.Contacts[i].TipSwitch = (f->State & 0x4) && !(f->State & 0x2);

// The Microsoft spec says reject any input larger than 25mm. This is not ideal
// for Magic Trackpad 2 - so we raised the threshold a bit higher.
// Or maybe I used the wrong unit? IDK
PtpReport.Contacts[i].Confidence = (AmtRawToInteger(f_type5->TouchMinor) << 1) < 345 &&
(AmtRawToInteger(f_type5->TouchMinor) << 1) < 345;
BOOL valid_size = (AmtRawToInteger(f->TouchMinor) << 1) < 345 &&
(AmtRawToInteger(f->TouchMinor) << 1) < 345;

// 1 = thumb, 2 = index, etc etc
// 6 = palm on MT2, 7 = palm on my MBP9,2 (why are these different?)
BOOL valid_finger = f->Finger != 6;
PtpReport.Contacts[i].Confidence = valid_size && valid_finger;

#ifdef INPUT_CONTENT_TRACE
TraceEvents(
TRACE_LEVEL_INFORMATION,
TRACE_INPUT,
"%!FUNC!: Point %llu, X = %d, Y = %d, TipSwitch = %d, Confidence = %d, tMajor = %d, tMinor = %d, origin = %d",
"%!FUNC!: Point %llu, X = %d, Y = %d, TipSwitch = %d, Confidence = %d, tMajor = %d, tMinor = %d, finger type = %d, rotate = %d",
i,
PtpReport.Contacts[i].X,
PtpReport.Contacts[i].Y,
PtpReport.Contacts[i].TipSwitch,
PtpReport.Contacts[i].Confidence,
AmtRawToInteger(f_type5->TouchMajor) << 1,
AmtRawToInteger(f_type5->TouchMinor) << 1,
f_type5->ContactIdentifier.Id
AmtRawToInteger(f->TouchMajor) << 1,
AmtRawToInteger(f->TouchMinor) << 1,
f->Finger,
f->Orientation
);
#endif
}
}

// Button
if (DeviceContext->IsButtonReportOn) {
if (Buffer[DeviceContext->DeviceInfo->tp_button]) {
PtpReport.IsButtonClicked = TRUE;
}
}

// Write output
Status = WdfMemoryCopyFromBuffer(
RequestMemory,
58 changes: 44 additions & 14 deletions src/AmtPtpDeviceUsbUm/include/AppleDefinition.h
Original file line number Diff line number Diff line change
@@ -141,27 +141,57 @@ __declspec(align(2)) struct TRACKPAD_FINGER {
USHORT multi; /* one finger: varies, more fingers: constant */
};

/* Trackpad finger structure for type5 (magic trackpad), le16-aligned */
__declspec(align(2)) struct TRACKPAD_FINGER_TYPE5
#pragma pack( push, 1 )
#pragma warning( push )
#pragma warning( disable : 4200 )

/* Trackpad finger structure for type5 (magic trackpad) */
struct TRACKPAD_FINGER_TYPE5
{
UCHAR AbsoluteX; /* absolute x coodinate */
UCHAR AbsoluteXY; /* absolute x,y coodinate */
UCHAR AbsoluteY[2]; /* absolute y coodinate */
UINT32 AbsoluteX : 13; /* absolute x coordinate */
UINT32 AbsoluteY : 13; /* absolute y coordinate */
UINT32 Finger : 3; /* finger type */
UINT32 State : 3; /* finger State */
UCHAR TouchMajor; /* touch area, major axis */
UCHAR TouchMinor; /* touch area, minor axis */
UCHAR Size; /* tool area, size */
UCHAR Pressure; /* pressure on forcetouch touchpad */
union
{
struct
{
UCHAR Id : 4;
UCHAR Orientation : 4;
} ContactIdentifier;
UCHAR RawOrientationAndOrigin;
};
UCHAR Id : 4; /* slot id */
UCHAR _ : 1;
UCHAR Orientation : 3; /* contact angle */
};

/* Appended Mouse report on front of MT2 USB reports */
struct MOUSE_REPORT
{
UCHAR ReportId;
UCHAR Button;
UCHAR X;
UCHAR Y;
UCHAR _[4];
};

/* Multitouch report from MT2 */
struct TRACKPAD_REPORT_TYPE5
{
UCHAR ReportId;
UINT8 Button : 1;
UINT8 _ : 2;
UINT8 TimestampLow : 5;
UINT16 TimestampHigh;
struct TRACKPAD_FINGER_TYPE5 Fingers[];
};

/* Full trackpad report for mt2 over USB */
struct TRACKPAD_COMBINED_REPORT_TYPE5
{
struct MOUSE_REPORT Mouse;
struct TRACKPAD_REPORT_TYPE5 MTReport;
};

#pragma warning( pop )
#pragma pack( pop )

/* device-specific parameters */
struct BCM5974_PARAM {
int snratio; /* signal-to-noise ratio */
4 changes: 2 additions & 2 deletions src/AmtPtpHidFilter/AmtPtpHidFilter.inf
Original file line number Diff line number Diff line change
@@ -29,9 +29,9 @@ AmtPtpHidFilter.sys = 1,,
;*****************************************

[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$.10.0
%ManufacturerName%=Standard,NT$ARCH$.10.0...17134

[Standard.NT$ARCH$.10.0]
[Standard.NT$ARCH$.10.0...17134]
; Driver migration: if this user installed the old Precision Touch Driver, install the generic HID USB driver for them
%AmtPtpHidRootDevice.DeviceDesc%=StandardUsbHid_Device, USB\Vid_05ac&Pid_0265&MI_01

10 changes: 0 additions & 10 deletions src/AmtPtpHidFilter/Device.c
Original file line number Diff line number Diff line change
@@ -320,11 +320,6 @@ PtpFilterConfigureMultiTouch(
pHidPacket = (PHID_XFER_PACKET) &hidPacketBuffer;

if (deviceContext->VendorID == HID_VID_APPLE_USB) {
deviceContext->InputFingerSize = FSIZE_TYPE5;
deviceContext->InputHeaderSize = HOFFSET_TYPE_USB_5;
deviceContext->InputFingerDelta = FDELTA_TYPE5;
deviceContext->InputButtonDelta = BOFFSET_TYPE5;

deviceContext->X.snratio = 250;
deviceContext->X.min = -3678;
deviceContext->X.max = 3934;
@@ -341,11 +336,6 @@ PtpFilterConfigureMultiTouch(
pHidPacket->reportBuffer[3] = 0x00;
}
else if (deviceContext->VendorID == HID_VID_APPLE_BT) {
deviceContext->InputFingerSize = FSIZE_TYPE5;
deviceContext->InputHeaderSize = HOFFSET_TYPE_BTH_5;
deviceContext->InputFingerDelta = FDELTA_TYPE5;
deviceContext->InputButtonDelta = BOFFSET_TYPE5;

deviceContext->X.snratio = 250;
deviceContext->X.min = -3678;
deviceContext->X.max = 3934;
213 changes: 134 additions & 79 deletions src/AmtPtpHidFilter/Input.c
Original file line number Diff line number Diff line change
@@ -116,130 +116,185 @@ PtpFilterInputIssueTransportRequest(
}
}

static
VOID
PtpFilterInputRequestCompletionCallback(
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS Params,
_In_ WDFCONTEXT Context
PtpFilterInputParseMT2Report(
_In_ PUCHAR Buffer,
_In_ SIZE_T BufferLength,
_In_ PDEVICE_CONTEXT DeviceContext
)
{
PWORKER_REQUEST_CONTEXT requestContext;
PDEVICE_CONTEXT deviceContext;
NTSTATUS status;

WDFREQUEST ptpRequest;
PTP_REPORT ptpOutputReport;
WDFMEMORY ptpRequestMemory;
PTP_REPORT ptpOutputReport;

size_t responseLength;
PUCHAR responseBuffer;

LARGE_INTEGER currentTSC;
LONGLONG tSCDelta;

const TRACKPAD_FINGER* f;
const TRACKPAD_FINGER_TYPE5* f_type5;
size_t raw_n, headerSize, fingerprintSize = 0;
const TRACKPAD_REPORT_TYPE5* mt_report;
const TRACKPAD_FINGER_TYPE5* f;
SIZE_T raw_n;
INT x, y = 0;
UINT32 timestamp;

UNREFERENCED_PARAMETER(Target);

requestContext = (PWORKER_REQUEST_CONTEXT)Context;
deviceContext = requestContext->DeviceContext;
responseLength = (size_t)(LONG)WdfRequestGetInformation(Request);
responseBuffer = WdfMemoryGetBuffer(Params->Parameters.Ioctl.Output.Buffer, NULL);
headerSize = deviceContext->InputHeaderSize;
fingerprintSize = deviceContext->InputFingerSize;
mt_report = (const TRACKPAD_REPORT_TYPE5*)Buffer;

// Pre-flight check 0: Right now we only have Magic Trackpad 2 (BT and USB)
if (deviceContext->VendorID != HID_VID_APPLE_USB && deviceContext->VendorID != HID_VID_APPLE_BT) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! Unsupported device entered this routine");
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedNoRestart);
goto cleanup;
}

// Pre-flight check 1: if size is 0, this is not something we need. Ignore the read, and issue next request.
if (responseLength <= 0) {
WdfWorkItemEnqueue(requestContext->DeviceContext->HidTransportRecoveryWorkItem);
goto cleanup;
}

// Pre-flight check 2: the response size should be sane
if (responseLength < deviceContext->InputHeaderSize || (responseLength - deviceContext->InputHeaderSize) % deviceContext->InputFingerSize != 0) {
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_INPUT, "%!FUNC! Malformed input received. Length = %llu. Attempt to reconfigure the device.", responseLength);
WdfTimerStart(deviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(3));
goto cleanup;
// Pre-flight check 1: the response size should be sane
if (BufferLength < sizeof(TRACKPAD_REPORT_TYPE5) ||
(BufferLength - sizeof(TRACKPAD_REPORT_TYPE5)) % sizeof(TRACKPAD_FINGER_TYPE5) != 0)
{
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_INPUT, "%!FUNC! Malformed input received. Length = %llu. Attempt to reconfigure the device.", BufferLength);
WdfTimerStart(DeviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(3));
return;
}

// Read report and fulfill PTP request. If no report is found, just exit.
status = WdfIoQueueRetrieveNextRequest(deviceContext->HidReadQueue, &ptpRequest);
if (!NT_SUCCESS(status)) {
// Retrieve PTP output
status = WdfIoQueueRetrieveNextRequest(DeviceContext->HidReadQueue, &ptpRequest);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! WdfIoQueueRetrieveNextRequest failed with %!STATUS!", status);
goto cleanup;
return;
}

timestamp = (mt_report->TimestampHigh << 5) | mt_report->TimestampLow;

// Report header
ptpOutputReport.ReportID = REPORTID_MULTITOUCH;
ptpOutputReport.IsButtonClicked = 0;

// Capture current timestamp and get input delta in 100us unit
KeQueryPerformanceCounter(&currentTSC);
tSCDelta = (currentTSC.QuadPart - deviceContext->LastReportTime.QuadPart) / 100;
ptpOutputReport.ScanTime = (tSCDelta >= 0xFF) ? 0xFF : (USHORT)tSCDelta;
deviceContext->LastReportTime.QuadPart = currentTSC.QuadPart;
ptpOutputReport.IsButtonClicked = (UCHAR) mt_report->Button;
ptpOutputReport.ScanTime = (USHORT) timestamp * 10;

// Report required content
// Touch
raw_n = (responseLength - headerSize) / fingerprintSize;
raw_n = (BufferLength - sizeof(TRACKPAD_REPORT_TYPE5)) / sizeof(TRACKPAD_FINGER_TYPE5);
if (raw_n >= PTP_MAX_CONTACT_POINTS) raw_n = PTP_MAX_CONTACT_POINTS;
ptpOutputReport.ContactCount = (UCHAR) raw_n;
for (size_t i = 0; i < raw_n; i++) {
PUCHAR f_base = responseBuffer + headerSize + deviceContext->InputFingerDelta;
f = (const TRACKPAD_FINGER*)(f_base + i * fingerprintSize);
f_type5 = (const TRACKPAD_FINGER_TYPE5*)f;

USHORT tmp_x = (*((USHORT*)f_type5)) & 0x1fff;
unsigned int tmp_y = (INT)(*((unsigned int*) f_type5));

x = (SHORT)(tmp_x << 3) >> 3;
y = -(INT)(tmp_y << 6) >> 19;
x = (x - deviceContext->X.min) > 0 ? (x - deviceContext->X.min) : 0;
y = (y - deviceContext->Y.min) > 0 ? (y - deviceContext->Y.min) : 0;

ptpOutputReport.Contacts[i].ContactID = f_type5->OrientationAndOrigin.ContactIdentifier.Id;
f = &mt_report->Fingers[i];

// Sign extend
x = (SHORT)(f->AbsoluteX << 3) >> 3;
y = -(SHORT)(f->AbsoluteY << 3) >> 3;
x = (x - DeviceContext->X.min) > 0 ? (x - DeviceContext->X.min) : 0;
y = (y - DeviceContext->Y.min) > 0 ? (y - DeviceContext->Y.min) : 0;

ptpOutputReport.Contacts[i].ContactID = f->Id;
ptpOutputReport.Contacts[i].X = (USHORT)x;
ptpOutputReport.Contacts[i].Y = (USHORT)y;
ptpOutputReport.Contacts[i].TipSwitch = ((signed short) (f_type5->TouchMajor) << 1) > 0;

// 0x1 = Transition between states
// 0x2 = Floating finger
// 0x4 = Contact/Valid
// I've gotten 0x6 if I press on the trackpad and then keep my finger close
// Note: These values come from my MBP9,2. These also are valid on my MT2
ptpOutputReport.Contacts[i].TipSwitch = (f->State & 0x4) && !(f->State & 0x2);

// The Microsoft spec says reject any input larger than 25mm. This is not ideal
// for Magic Trackpad 2 - so we raised the threshold a bit higher.
// Or maybe I used the wrong unit? IDK
ptpOutputReport.Contacts[i].Confidence = ((signed short) (f_type5->TouchMinor) << 1) < 345 && ((signed short) (f_type5->TouchMinor) << 1) < 345;
}
CHAR valid_size = ((SHORT)(f->TouchMinor) << 1) < 345 && ((SHORT)(f->TouchMinor) << 1) < 345;

// Button
if ((responseBuffer[deviceContext->InputButtonDelta] & 1) != 0) {
ptpOutputReport.IsButtonClicked = TRUE;
// 1 = thumb, 2 = index, etc etc
// 6 = palm on MT2, 7 = palm on my MBP9,2 (why are these different?)
CHAR valid_finger = f->Finger != 6;
ptpOutputReport.Contacts[i].Confidence = valid_size && valid_finger;
}

status = WdfRequestRetrieveOutputMemory(ptpRequest, &ptpRequestMemory);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! WdfRequestRetrieveOutputBuffer failed with %!STATUS!", status);
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedAttemptRestart);
goto cleanup;
return;
}

status = WdfMemoryCopyFromBuffer(ptpRequestMemory, 0, (PVOID) &ptpOutputReport, sizeof(PTP_REPORT));
status = WdfMemoryCopyFromBuffer(ptpRequestMemory, 0, (PVOID)&ptpOutputReport, sizeof(PTP_REPORT));
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! WdfMemoryCopyFromBuffer failed with %!STATUS!", status);
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedAttemptRestart);
goto cleanup;
WdfDeviceSetFailed(DeviceContext->Device, WdfDeviceFailedAttemptRestart);
return;
}

WdfRequestSetInformation(ptpRequest, sizeof(PTP_REPORT));
WdfRequestComplete(ptpRequest, status);
}

static
VOID
PtpFilterInputParseReport(
_In_ PUCHAR Buffer,
_In_ SIZE_T BufferLength,
_In_ PDEVICE_CONTEXT DeviceContext
)
{
UCHAR reportId = Buffer[0];

switch (reportId) {
case 0x2: // Mouse report
// USB devices have mouse reports prepended, so skip over it to get to next input report
if (BufferLength > sizeof(MOUSE_REPORT))
{
Buffer += sizeof(MOUSE_REPORT);
BufferLength -= sizeof(MOUSE_REPORT);
PtpFilterInputParseReport(Buffer, BufferLength, DeviceContext);
}
else
{
TraceEvents(TRACE_LEVEL_WARNING, TRACE_INPUT,
"%!FUNC! Mouse Packet - Setting Wellspring mode");
WdfTimerStart(DeviceContext->HidTransportRecoveryTimer, WDF_REL_TIMEOUT_IN_SEC(3));
}
break;

case 0x31: // MT2 report
PtpFilterInputParseMT2Report(Buffer, BufferLength, DeviceContext);
break;

case 0xF7: // Two packets in one (0xF7, pkt 1 len, <pkt 1>, <pkt 2>)
case 0xFC: // Part one of large packet
case 0xFE: // Part two of large packet
case 0x90: // Battery status
default:
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_INPUT,
"%!FUNC! Unhandled packet (Report ID: 0x%x)", reportId);
WdfWorkItemEnqueue(DeviceContext->HidTransportRecoveryWorkItem);
break;
}
}

VOID
PtpFilterInputRequestCompletionCallback(
_In_ WDFREQUEST Request,
_In_ WDFIOTARGET Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS Params,
_In_ WDFCONTEXT Context
)
{
PWORKER_REQUEST_CONTEXT requestContext;
PDEVICE_CONTEXT deviceContext;

size_t responseLength;
PUCHAR responseBuffer;

UNREFERENCED_PARAMETER(Target);

requestContext = (PWORKER_REQUEST_CONTEXT)Context;
deviceContext = requestContext->DeviceContext;
responseLength = (size_t)(LONG)WdfRequestGetInformation(Request);
responseBuffer = WdfMemoryGetBuffer(Params->Parameters.Ioctl.Output.Buffer, NULL);

// Pre-flight check 0: Right now we only have Magic Trackpad 2 (BT and USB)
if (deviceContext->VendorID != HID_VID_APPLE_USB && deviceContext->VendorID != HID_VID_APPLE_BT) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_INPUT, "%!FUNC! Unsupported device entered this routine");
WdfDeviceSetFailed(deviceContext->Device, WdfDeviceFailedNoRestart);
goto cleanup;
}

// Pre-flight check 1: if size is 0, this is not something we need. Ignore the read, and issue next request.
if (responseLength <= 0) {
WdfWorkItemEnqueue(requestContext->DeviceContext->HidTransportRecoveryWorkItem);
goto cleanup;
}

PtpFilterInputParseReport(responseBuffer, responseLength, deviceContext);

cleanup:
// Cleanup
4 changes: 0 additions & 4 deletions src/AmtPtpHidFilter/include/Device.h
Original file line number Diff line number Diff line change
@@ -33,10 +33,6 @@ typedef struct _DEVICE_CONTEXT
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
size_t InputHeaderSize;
size_t InputFingerSize;
size_t InputFingerDelta;
size_t InputButtonDelta;
BCM5974_PARAM X;
BCM5974_PARAM Y;

92 changes: 42 additions & 50 deletions src/AmtPtpHidFilter/include/HidDevice.h
Original file line number Diff line number Diff line change
@@ -1,41 +1,6 @@
// HidDevice.h: devicei-specific HID structures
#pragma once

/* Trackpad finger data offsets, le16-aligned */
#define HOFFSET_TYPE_USB_1 (13 * sizeof(USHORT))
#define HOFFSET_TYPE_USB_2 (15 * sizeof(USHORT))
#define HOFFSET_TYPE_USB_3 (19 * sizeof(USHORT))
#define HOFFSET_TYPE_USB_4 (23 * sizeof(USHORT))
#define HOFFSET_TYPE_USB_5 ( 6 * sizeof(USHORT))
#define HOFFSET_TYPE_BTH_5 ( 2 * sizeof(USHORT))

/* Trackpad button data offsets */
#define BOFFSET_TYPE1 0
#define BOFFSET_TYPE2 15
#define BOFFSET_TYPE3 23
#define BOFFSET_TYPE4 31
#define BOFFSET_TYPE5 1

/* Trackpad finger data block size */
#define FSIZE_TYPE1 (14 * sizeof(USHORT))
#define FSIZE_TYPE2 (14 * sizeof(USHORT))
#define FSIZE_TYPE3 (14 * sizeof(USHORT))
#define FSIZE_TYPE4 (15 * sizeof(USHORT))
#define FSIZE_TYPE5 (9)

/* List of device capability bits */
#define HAS_INTEGRATED_BUTTON 1

/* Offset from header to finger struct */
#define FDELTA_TYPE1 (0 * sizeof(USHORT))
#define FDELTA_TYPE2 (0 * sizeof(USHORT))
#define FDELTA_TYPE3 (0 * sizeof(USHORT))
#define FDELTA_TYPE4 (1 * sizeof(USHORT))
#define FDELTA_TYPE5 (0 * sizeof(USHORT))

/* Trackpad finger data size, empirically at least ten fingers */
#define MAX_FINGERS 16
#define MAX_FINGER_ORIENTATION 16384

/* button data structure */
typedef struct _TRACKPAD_BUTTON_DATA {
@@ -63,24 +28,51 @@ typedef struct _TRACKPAD_FINGER {
USHORT multi; /* one finger: varies, more fingers: constant */
} TRACKPAD_FINGER, *PTRACKPAD_FINGER;

/* Trackpad finger structure for type5 (magic trackpad), le16-aligned */
#include <poppack.h>

#pragma pack( push, 1 )
#pragma warning( push )
#pragma warning( disable : 4200 )

/* Trackpad finger structure for type5 (magic trackpad) */
typedef struct _TRACKPAD_FINGER_TYPE5
{
UCHAR AbsoluteX; /* absolute x coodinate */
UCHAR AbsoluteXY; /* absolute x,y coodinate */
UCHAR AbsoluteY[2]; /* absolute y coodinate */
UINT32 AbsoluteX : 13; /* absolute x coordinate */
UINT32 AbsoluteY : 13; /* absolute y coordinate */
UINT32 Finger : 3; /* finger type */
UINT32 State : 3; /* finger State */
UCHAR TouchMajor; /* touch area, major axis */
UCHAR TouchMinor; /* touch area, minor axis */
UCHAR Size; /* tool area, size */
UCHAR Pressure; /* pressure on forcetouch touchpad */
union _ORIDENTATION_AND_ORIGIN
{
struct _CONTACT_IDENTIFIER
{
UCHAR Id : 4;
UCHAR Orientation : 4;
} ContactIdentifier;
UCHAR RawValue;
} OrientationAndOrigin;
} TRACKPAD_FINGER_TYPE5, *PTRACKPAD_FINGER_TYPE5;
#include <poppack.h>
UCHAR Id : 4; /* slot id */
UCHAR _ : 1;
UCHAR Orientation : 3; /* contact angle */
} TRACKPAD_FINGER_TYPE5;

/* Appended Mouse report on front of MT2 USB reports */
typedef struct _MOUSE_REPORT
{
UCHAR ReportId;
UCHAR Button;
UCHAR X;
UCHAR Y;
UCHAR _[4];
} MOUSE_REPORT;

/* Multitouch report from MT2 */
typedef struct _TRACKPAD_REPORT_TYPE5
{
UCHAR ReportId;
UINT8 Button : 1;
UINT8 _ : 2;
UINT8 TimestampLow : 5;
UINT16 TimestampHigh;
TRACKPAD_FINGER_TYPE5 Fingers[];
} TRACKPAD_REPORT_TYPE5;

static_assert(sizeof(TRACKPAD_FINGER_TYPE5) == 9, "Unexpected MAGIC_TRACKPAD_INPUT_REPORT_FINGER size");
static_assert(sizeof(TRACKPAD_REPORT_TYPE5) == 4, "Unexpected MAGIC_TRACKPAD_INPUT_REPORT_FINGER size");

#pragma warning( pop )
#pragma pack( pop )