diff --git a/src/AmtPtpDeviceUsbUm/InputInterrupt.c b/src/AmtPtpDeviceUsbUm/InputInterrupt.c index 3ece692..f8861d3 100644 --- a/src/AmtPtpDeviceUsbUm/InputInterrupt.c +++ b/src/AmtPtpDeviceUsbUm/InputInterrupt.c @@ -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, diff --git a/src/AmtPtpDeviceUsbUm/include/AppleDefinition.h b/src/AmtPtpDeviceUsbUm/include/AppleDefinition.h index 1a0aee5..bd4bd75 100644 --- a/src/AmtPtpDeviceUsbUm/include/AppleDefinition.h +++ b/src/AmtPtpDeviceUsbUm/include/AppleDefinition.h @@ -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 */ diff --git a/src/AmtPtpHidFilter/Device.c b/src/AmtPtpHidFilter/Device.c index e86b898..306d96a 100644 --- a/src/AmtPtpHidFilter/Device.c +++ b/src/AmtPtpHidFilter/Device.c @@ -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; diff --git a/src/AmtPtpHidFilter/Input.c b/src/AmtPtpHidFilter/Input.c index 1d5265e..6fdd0a8 100644 --- a/src/AmtPtpHidFilter/Input.c +++ b/src/AmtPtpHidFilter/Input.c @@ -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(¤tTSC); - 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, , ) + 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 diff --git a/src/AmtPtpHidFilter/include/Device.h b/src/AmtPtpHidFilter/include/Device.h index 97410bc..565ee48 100644 --- a/src/AmtPtpHidFilter/include/Device.h +++ b/src/AmtPtpHidFilter/include/Device.h @@ -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; diff --git a/src/AmtPtpHidFilter/include/HidDevice.h b/src/AmtPtpHidFilter/include/HidDevice.h index e628376..bc5e1e7 100644 --- a/src/AmtPtpHidFilter/include/HidDevice.h +++ b/src/AmtPtpHidFilter/include/HidDevice.h @@ -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 + +#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 + 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 )