From 6ef9bb2c0142082e97e8a19ab4fab56c8258fcb8 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 31 Dec 2022 23:23:35 -0800 Subject: [PATCH 01/32] User Client and simulator --- VoodooInput.xcodeproj/project.pbxproj | 24 ++++ .../VoodooInputMT1Simulator.cpp | 132 ++++++++++++++++++ .../VoodooInputMT1Simulator.hpp | 108 ++++++++++++++ .../VoodooInputMT1UserClient.cpp | 131 +++++++++++++++++ .../VoodooInputMT1UserClient.hpp | 64 +++++++++ 5 files changed, 459 insertions(+) create mode 100644 VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp create mode 100644 VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp create mode 100644 VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp create mode 100644 VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index 0de7386..23b86f9 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -17,6 +17,10 @@ 7BBAB21B22E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 7BBAB21522E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp */; }; CE8DA19D2518354A008C44E8 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE8DA19C2518354A008C44E8 /* libkmod.a */; }; EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EEC13CEA2C1DFD270080F2D1 /* VoodooInputIDs.hpp */; }; + EE7EE27F296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE27D296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp */; }; + EE7EE280296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE27E296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp */; }; + EE7EE283296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE281296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp */; }; + EE7EE284296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE282296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -39,6 +43,10 @@ CEFB081D2397003600215B0B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; CEFB081E2397003600215B0B /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE.txt; sourceTree = SOURCE_ROOT; }; EEC13CEA2C1DFD270080F2D1 /* VoodooInputIDs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputIDs.hpp; sourceTree = ""; }; + EE7EE27D296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputMT1Simulator.cpp; sourceTree = ""; }; + EE7EE27E296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputMT1Simulator.hpp; sourceTree = ""; }; + EE7EE281296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputMT1UserClient.cpp; sourceTree = ""; }; + EE7EE282296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputMT1UserClient.hpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -84,6 +92,7 @@ 7BBAB1FB22E3A2F800B2941A /* VoodooInput */ = { isa = PBXGroup; children = ( + EE7EE27C296116B1005EFCC4 /* VoodooInputMT1Simulator */, 358914F125798FA5007A0B58 /* Trackpoint */, CEC086442439FD3E00F5B701 /* VoodooInputMultitouch */, 7BBAB20F22E3AC7E00B2941A /* VoodooInputSimulator */, @@ -136,6 +145,17 @@ path = VoodooInput; sourceTree = ""; }; + EE7EE27C296116B1005EFCC4 /* VoodooInputMT1Simulator */ = { + isa = PBXGroup; + children = ( + EE7EE27D296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp */, + EE7EE27E296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp */, + EE7EE281296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp */, + EE7EE282296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp */, + ); + path = VoodooInputMT1Simulator; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -146,6 +166,8 @@ 7BBAB21722E3AD0E00B2941A /* VoodooInputSimulatorDevice.hpp in Headers */, 358914F425798FA5007A0B58 /* TrackpointDevice.hpp in Headers */, 7BBAB21B22E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp in Headers */, + EE7EE280296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp in Headers */, + EE7EE284296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp in Headers */, 7BBAB1FD22E3A2F800B2941A /* VoodooInput.hpp in Headers */, EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */, ); @@ -252,6 +274,8 @@ 358914F525798FA5007A0B58 /* TrackpointDevice.cpp in Sources */, 7BBAB1FF22E3A2F800B2941A /* VoodooInput.cpp in Sources */, 7BBAB21922E3AD0E00B2941A /* VoodooInputActuatorDevice.cpp in Sources */, + EE7EE283296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp in Sources */, + EE7EE27F296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp in Sources */, 7BBAB21822E3AD0E00B2941A /* VoodooInputSimulatorDevice.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp new file mode 100644 index 0000000..e78b8c0 --- /dev/null +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp @@ -0,0 +1,132 @@ +// +// AppleUSBMultitouchDriver.cpp +// VoodooInput +// +// Created by Avery Black on 12/31/22. +// Copyright © 2022 Kishor Prins. All rights reserved. +// + +#include "VoodooInputMT1Simulator.hpp" + +#define super IOService +OSDefineMetaClassAndStructors(VoodooInputMT1Simulator, IOService); + +bool VoodooInputMT1Simulator::start(IOService *provider) { + if (!super::start(provider)) return false; + + engine = OSDynamicCast(VoodooInput, provider); + if (!engine) { + return false; + } + + workloop = getWorkLoop(); + if (workloop == nullptr) { + IOLog("MT1Sim: Failed to create work loop!\n"); + return false; + } + + workloop->retain(); + + cmdGate = OSTypeAlloc(IOCommandGate); + if (cmdGate == nullptr) { + IOLog("MT1Sim: Failed to create cmd gate\n"); + return false; + } + + workloop->addEventSource(cmdGate); + + userClients = OSSet::withCapacity(1); + if (userClients == nullptr) { + IOLog("MT1Sim: Failed to create user clients array\n"); + return false; + } + + // Set name so that WindowServer attaches to us + setName("AppleUSBMultitouchDriver"); + setProperty(kIOUserClientClassKey, "VoodooInputMT1UserClient"); + registerService(); + + return true; +} + +void VoodooInputMT1Simulator::stop(IOService *provider) { + OSSafeReleaseNULL(workloop); + OSSafeReleaseNULL(cmdGate); + if (userClients != nullptr) { + userClients->flushCollection(); + OSSafeReleaseNULL(userClients); + } + + super::stop(provider); +} + +bool VoodooInputMT1Simulator::registerUserClient(IOService *client) { + IOLog("MT1Sim: Adding user client\n"); + return userClients->setObject(client); +} + +void VoodooInputMT1Simulator::unregisterUserClient(IOService *client) { + IOLog("MT1Sim: Removing user client\n"); + userClients->removeObject(client); +} + +// Reports come from a MacbookPro9,2 +#define SensorParamsLength 6 +static const UInt8 MT1SensorParams[SensorParamsLength] = {0x00, 0x00, 0x03, 0x00, 0xD6, 0x01}; + +#define SensorDescLength 8 +static const UInt8 MT1SensorDesc[SensorDescLength] = {0x01, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x14, 0x00}; + +#define SensorRowsLength 5 +static const UInt8 MT1SensorRows[SensorRowsLength] = { + 0x01, // Endianness (no clue what 1 means) + 0x0C, // Rows + 0x14, // Columns + 0x01, 0x09 // BCD Version +}; + +#define FamilyID 0x62 +#define FamilyIDLength 1 + +IOReturn VoodooInputMT1Simulator::getReport(MT1DeviceReportStruct *toFill) { + UInt32 width, height; + + switch (toFill->reportId) { + case MT1ReportSensorParam: + memcpy(toFill->data, MT1SensorParams, SensorParamsLength); + toFill->dataSize = SensorParamsLength; + break; + case MT1ReportSensorDescriptor: + memcpy(toFill->data, MT1SensorDesc, SensorDescLength); + toFill->dataSize = SensorDescLength; + break; + case MT1ReportSensorSize: + width = engine->getPhysicalMaxX(); + height = engine->getPhysicalMaxY(); + + for (int i = 0; i < sizeof(UInt32); i++) { + toFill->data[i] = width & 0xFF; + width >>= 8; + } + + for (int i = 4; i < sizeof(UInt32) + 4; i++) { + toFill->data[i] = height & 0xFF; + height >>= 8; + } + + toFill->dataSize = sizeof(UInt32) * 2; + break; + case MT1ReportSensorRows: + memcpy(toFill->data, MT1SensorRows, SensorRowsLength); + toFill->dataSize = SensorRowsLength; + break; + case MT1ReportFamilyId: + toFill->data[0] = FamilyID; + toFill->dataSize = FamilyIDLength; + break; + + default: return kIOReturnError; + } + + return kIOReturnSuccess; +} diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp new file mode 100644 index 0000000..36b9e2d --- /dev/null +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp @@ -0,0 +1,108 @@ +// +// AppleUSBMultitouchDriver.hpp +// VoodooInput +// +// Created by Avery Black on 12/31/22. +// Copyright © 2022 Kishor Prins. All rights reserved. +// + +#ifndef AppleUSBMultitouchDriver_hpp +#define AppleUSBMultitouchDriver_hpp + +#include +#include +#include +#include +#include + +#include "../VoodooInput.hpp" +#include "../VoodooInputMultitouch/VoodooInputTransducer.h" +#include "../VoodooInputMultitouch/VoodooInputEvent.h" +#include "../VoodooInputMultitouch/MultitouchHelpers.h" + +/* Finger Packet ++---+---+---+---+---+---+---+---+---+ +| | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ++---+---+---+---+---+---+---+---+---+ +| 0 | x: SInt13 | ++---+-----------+ + +| 1 | | | ++---+ +-------------------+ +| 2 | y: SInt13 | ++---+-----------+-----------+ + +| 3 | | | +| | | | ++---+-----------+-----------+-------+ +| 4 | touchMajor: UInt8 | ++---+-------------------------------+ +| 5 | touchMinor: UInt8 | ++---+-------+-----------------------+ +| 6 | id | size: UInt6 | ++---+-------+---------------+-------+ +| 7 | orientation: UInt6 | id: 4 | ++---+---------------+-------+-------+ +| 8 | state | | +| | UInt4 | | ++---+---------------+---------------+ +*/ +struct __attribute__((__packed__)) MT_1_INPUT_REPORT_FINGER { + SInt16 X: 13; + SInt16 Y: 13; + UInt8 : 6; + UInt8 Touch_Major; + UInt8 Touch_Minor; + UInt8 Size: 6; + UInt8 Identifier: 4; + UInt8 Orientation: 6; + UInt8 State: 4; + UInt8 : 4; +}; + +// Missing angle and finger (Maybe they are in Byte 3?) + +struct __attribute__((__packed__)) MT1_INPUT_REPORT { + UInt8 ReportID; + UInt8 Button: 6; + UInt32 Timestamp: 18; + + MT_1_INPUT_REPORT_FINGER FINGERS[]; // May support more fingers + + // UInt16 Checksum; +}; + +static_assert(sizeof(MT1_INPUT_REPORT) == 4, "Unexpected MT1_INPUT_REPORT size"); +static_assert(sizeof(MT_1_INPUT_REPORT_FINGER) == 9, "Unexpected MT1_INPUT_REPORT_FINGER size"); + +// Missing finger type + +struct MT1DeviceReportStruct { + uint8_t reportId; + uint8_t data[512]; + uint32_t dataSize; +}; + +#define MT1ReportSensorParam 0xA1 +#define MT1ReportSensorDescriptor 0xD0 +#define MT1ReportFamilyId 0xD1 +#define MT1ReportSensorRows 0xD3 +#define MT1ReportSensorSize 0xD9 + +class EXPORT VoodooInputMT1Simulator : public IOService { + OSDeclareDefaultStructors(VoodooInputMT1Simulator); +public: + + virtual bool start(IOService *provider) override; + virtual void stop(IOService *provider) override; + + bool registerUserClient(IOService *client); + void unregisterUserClient(IOService *client); + + IOReturn getReport(MT1DeviceReportStruct *toFill); +private: + OSSet *userClients {nullptr}; + IOWorkLoop *workloop {nullptr}; + IOCommandGate *cmdGate {nullptr}; + VoodooInput *engine {nullptr}; +}; + +#endif /* AppleUSBMultitouchDriver_hpp */ diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp new file mode 100644 index 0000000..a2ca5a7 --- /dev/null +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp @@ -0,0 +1,131 @@ +// +// VoodooInputMT1UserClient.cpp +// VoodooInput +// +// Created by Avery Black on 12/31/22. +// Copyright © 2022 Kishor Prins. All rights reserved. +// + +#include "VoodooInputMT1UserClient.hpp" + +#define super IOUserClient +OSDefineMetaClassAndStructors(VoodooInputMT1UserClient, IOUserClient); + +#if defined(__x86_64__) +// { Object, Func pointer, Padding, Flags, Count 0, Count 1 } +IOExternalMethodACID VoodooInputMT1UserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { + // VoodooInputMT1UserClientMethodsSetSendsFrames + {0, static_cast(&VoodooInputMT1UserClient::sSetSendFrames), kIOExternalMethodACIDPadding, 0, 0, 1}, + // VoodooInputMT1UserClientMethodsGetReport + {0, static_cast(&VoodooInputMT1UserClient::sGetReport), kIOExternalMethodACIDPadding, 0, 3, 0x208}, + // VoodooInputMT1UserClientMethodsSetReport + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOExternalMethodACIDPadding, 0, 3, 0x208}, + // VoodooInputMT1UserClientMethodsSetSendLogs + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOExternalMethodACIDPadding, 0, 0, 1}, + // VoodooInputMT1UserClientMethodsIssueDriverRequest + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOExternalMethodACIDPadding, 0, 3, 204}, + {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 3}, // Relative Mouse Movement + {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 3}, // Scroll Wheel + {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 2}, // Keyboard + {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 1}, // Map Clicks + // VoodooInputMT1UserClientMethodsRecacheProperties + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOExternalMethodACIDPadding, 0, 0, 0}, + {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 3}, // Momentum Scroll +}; +#else // __defined(__x86_64__) +// TODO: Switch where padding is in struct +#error "Invalid architecture" +#endif // __defined(__x86_64__) + +bool VoodooInputMT1UserClient::start(IOService *provider) { + if (!super::start(provider)) return false; + simulator = OSDynamicCast(VoodooInputMT1Simulator, provider); + + if (simulator == nullptr) { + IOLog("%s Invalid provider!\n", getName()); + return false; + } + + dataQueue = IOSharedDataQueue::withCapacity(0x10004); + // Don't think we need to use this? Setting a small size for now + logQueue = IOSharedDataQueue::withCapacity(0x1); + + if (dataQueue == nullptr || logQueue == nullptr) { + return false; + } + + dataQueueDesc = dataQueue->getMemoryDescriptor(); + logQueueDesc = logQueue->getMemoryDescriptor(); + if (dataQueueDesc == nullptr || logQueueDesc == nullptr) { + return false; + } + + return true; +} + +void VoodooInputMT1UserClient::stop(IOService *provider) { + OSSafeReleaseNULL(dataQueue); + OSSafeReleaseNULL(logQueue); +} + +IOReturn VoodooInputMT1UserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { + dataQueue->setNotificationPort(port); + logQueue->setNotificationPort(port); + return kIOReturnSuccess; +} + +IOReturn VoodooInputMT1UserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { + if (type == 0x10) { + dataQueueDesc->retain(); + *memory = dataQueueDesc; + } else { + logQueueDesc->retain(); + *memory = logQueue->getMemoryDescriptor(); + } + + *options = 0; + return kIOReturnSuccess; +} + +IOExternalMethod *VoodooInputMT1UserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { + if (index >= VoodooInputMT1UserClientMethodsNumMethods) { + return nullptr; + } + + *targetP = this; + sMethods[index].object = this; + return reinterpret_cast(&sMethods[index]); +} + +IOReturn VoodooInputMT1UserClient::sSetSendFrames(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { + bool success = true; + + if (static_cast(p1)) { + success = simulator->registerUserClient(this); + } else { + simulator->unregisterUserClient(this); + } + + return success ? kIOReturnSuccess : kIOReturnError; +} + +// I'm not really sure why they use two different structs here??? +IOReturn VoodooInputMT1UserClient::sGetReport(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { + MT1DeviceReportStruct *input = static_cast(p1); + MT1DeviceReportStruct *output = static_cast(p2); + if (input == nullptr || output == nullptr) { + return kIOReturnBadArgument; + } + + IOReturn ret = simulator->getReport(input); + if (ret == kIOReturnSuccess) { + memmove(output->data, input->data, input->dataSize); + output->dataSize = input->dataSize; + } + + return ret; +} + +IOReturn VoodooInputMT1UserClient::sNoop(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { + return kIOReturnSuccess; // noop +} diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp new file mode 100644 index 0000000..88e1ca9 --- /dev/null +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp @@ -0,0 +1,64 @@ +// +// VoodooInputMT1UserClient.hpp +// VoodooInput +// +// Created by Avery Black on 12/31/22. +// Copyright © 2022 Kishor Prins. All rights reserved. +// + +#ifndef VoodooInputMT1UserClient_hpp +#define VoodooInputMT1UserClient_hpp + +#include +#include +#include +#include "./VoodooInputMT1Simulator.hpp" + +#include "../VoodooInput.hpp" +#include "../VoodooInputMultitouch/VoodooInputTransducer.h" +#include "../VoodooInputMultitouch/VoodooInputEvent.h" +#include "../VoodooInputMultitouch/MultitouchHelpers.h" + +enum VoodooInputMT1UserClientMethods { + VoodooInputMT1UserClientMethodsSetSendsFrames, + VoodooInputMT1UserClientMethodsGetReport, + VoodooInputMT1UserClientMethodsSetReport, + VoodooInputMT1UserClientMethodsSetSendsLogs, + VoodooInputMT1UserClientMethodsIssueDriverRequest, + VoodooInputMT1UserClientMethodsPostRelativeMouseMovement, + VoodooInputMT1UserClientMethodsPostScrollWheelEvent, + VoodooInputMT1UserClientMethodsPostKeyboardEvent, + VoodooInputMT1UserClientMethodsSetMapClicks, + VoodooInputMT1UserClientMethodsRecacheProperties, + VoodooInputMT1UserClientMethodsMomentumScroll, + VoodooInputMT1UserClientMethodsNumMethods +}; + +static_assert(VoodooInputMT1UserClientMethodsNumMethods == 11, "Invalid number of Userclient methods"); + +class EXPORT VoodooInputMT1UserClient : public IOUserClient { + OSDeclareDefaultStructors(VoodooInputMT1UserClient); + +public: + virtual bool start(IOService *provider) override; + virtual void stop(IOService *provider) override; + + virtual IOReturn registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) override; + virtual IOReturn clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) override; + + virtual IOExternalMethod *getTargetAndMethodForIndex(IOService **targetP, UInt32 index) override; + IOReturn sSetSendFrames(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + IOReturn sGetReport(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + IOReturn sNoop(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); +private: + VoodooInputMT1Simulator *simulator {nullptr}; + + IOSharedDataQueue *dataQueue {nullptr}; + IOSharedDataQueue *logQueue {nullptr}; + IOMemoryDescriptor *dataQueueDesc {nullptr}; + IOMemoryDescriptor *logQueueDesc {nullptr}; + + static IOExternalMethodACID sMethods[VoodooInputMT1UserClientMethodsNumMethods]; +}; + +#endif /* VoodooInputMT1UserClient_hpp */ From 19cec135531202b38e4327b79f7a8bc687ea352d Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 31 Dec 2022 23:59:39 -0800 Subject: [PATCH 02/32] Test MT1 --- VoodooInput/VoodooInput.cpp | 42 ++++++++++--------- VoodooInput/VoodooInput.hpp | 6 ++- .../VoodooInputMT1Simulator.cpp | 4 ++ 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index 01dc650..abd2d11 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -11,6 +11,7 @@ #include "VoodooInputMultitouch/VoodooInputMessages.h" #include "VoodooInputSimulator/VoodooInputActuatorDevice.hpp" #include "VoodooInputSimulator/VoodooInputSimulatorDevice.hpp" +#include "VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp" #include "Trackpoint/TrackpointDevice.hpp" #include "libkern/version.h" @@ -32,14 +33,15 @@ bool VoodooInput::start(IOService *provider) { } // Allocate the simulator and actuator devices - simulator = OSTypeAlloc(VoodooInputSimulatorDevice); - actuator = OSTypeAlloc(VoodooInputActuatorDevice); +// simulator = OSTypeAlloc(VoodooInputSimulatorDevice); +// actuator = OSTypeAlloc(VoodooInputActuatorDevice); + simulator = OSTypeAlloc(VoodooInputMT1Simulator); trackpoint = OSTypeAlloc(TrackpointDevice); - if (!simulator || !actuator || !trackpoint) { + if (!simulator /*|| !actuator*/ || !trackpoint) { IOLog("VoodooInput could not alloc simulator, actuator or trackpoint!\n"); OSSafeReleaseNULL(simulator); - OSSafeReleaseNULL(actuator); +// OSSafeReleaseNULL(actuator); OSSafeReleaseNULL(trackpoint); return false; } @@ -56,15 +58,15 @@ bool VoodooInput::start(IOService *provider) { } // Initialize actuator device - if (!actuator->init(NULL) || !actuator->attach(this)) { - IOLog("VoodooInput could not init or attach actuator!\n"); - goto exit; - } - else if (!actuator->start(this)) { - IOLog("VoodooInput could not start actuator!\n"); - actuator->detach(this); - goto exit; - } +// if (!actuator->init(NULL) || !actuator->attach(this)) { +// IOLog("VoodooInput could not init or attach actuator!\n"); +// goto exit; +// } +// else if (!actuator->start(this)) { +// IOLog("VoodooInput could not start actuator!\n"); +// actuator->detach(this); +// goto exit; +// } // Initialize trackpoint device if (!trackpoint->init(NULL) || !trackpoint->attach(this)) { @@ -105,11 +107,11 @@ void VoodooInput::stop(IOService *provider) { OSSafeReleaseNULL(simulator); } - if (actuator) { - actuator->stop(this); - actuator->detach(this); - OSSafeReleaseNULL(actuator); - } +// if (actuator) { +// actuator->stop(this); +// actuator->detach(this); +// OSSafeReleaseNULL(actuator); +// } if (trackpoint) { trackpoint->stop(this); @@ -164,8 +166,8 @@ UInt32 VoodooInput::getLogicalMaxY() { IOReturn VoodooInput::message(UInt32 type, IOService *provider, void *argument) { switch (type) { case kIOMessageVoodooInputMessage: - if (provider == parentProvider && argument && simulator) - simulator->constructReport(*(VoodooInputEvent*)argument); +// if (provider == parentProvider && argument && simulator) +// simulator->constructReport(*(VoodooInputEvent*)argument); break; case kIOMessageVoodooInputUpdateDimensionsMessage: diff --git a/VoodooInput/VoodooInput.hpp b/VoodooInput/VoodooInput.hpp index 97d0063..446ba17 100644 --- a/VoodooInput/VoodooInput.hpp +++ b/VoodooInput/VoodooInput.hpp @@ -12,6 +12,7 @@ class VoodooInputSimulatorDevice; class VoodooInputActuatorDevice; +class VoodooInputMT1Simulator; class TrackpointDevice; #ifndef EXPORT @@ -23,8 +24,9 @@ class EXPORT VoodooInput : public IOService { IOService* parentProvider; - VoodooInputSimulatorDevice* simulator; - VoodooInputActuatorDevice* actuator; +// VoodooInputSimulatorDevice* simulator; +// VoodooInputActuatorDevice* actuator; + VoodooInputMT1Simulator* simulator; TrackpointDevice* trackpoint; UInt8 transformKey; diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp index e78b8c0..bcb834d 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp @@ -50,6 +50,10 @@ bool VoodooInputMT1Simulator::start(IOService *provider) { } void VoodooInputMT1Simulator::stop(IOService *provider) { + if (workloop) { + workloop->removeEventSource(cmdGate); + } + OSSafeReleaseNULL(workloop); OSSafeReleaseNULL(cmdGate); if (userClients != nullptr) { From 086b5d49fe20a243fa28552e27a6ec44155737b9 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Mon, 2 Jan 2023 23:08:13 -0800 Subject: [PATCH 03/32] It almost works --- VoodooInput/VoodooInput.cpp | 4 +- VoodooInput/VoodooInput.hpp | 12 + .../VoodooInputMT1Simulator.cpp | 319 +++++++++++++++++- .../VoodooInputMT1Simulator.hpp | 72 ++-- .../VoodooInputMT1UserClient.cpp | 51 +-- .../VoodooInputMT1UserClient.hpp | 10 +- .../VoodooInputSimulatorDevice.hpp | 12 - 7 files changed, 416 insertions(+), 64 deletions(-) diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index abd2d11..4152892 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -166,8 +166,8 @@ UInt32 VoodooInput::getLogicalMaxY() { IOReturn VoodooInput::message(UInt32 type, IOService *provider, void *argument) { switch (type) { case kIOMessageVoodooInputMessage: -// if (provider == parentProvider && argument && simulator) -// simulator->constructReport(*(VoodooInputEvent*)argument); + if (provider == parentProvider && argument && simulator) + simulator->constructReport(*(VoodooInputEvent*)argument); break; case kIOMessageVoodooInputUpdateDimensionsMessage: diff --git a/VoodooInput/VoodooInput.hpp b/VoodooInput/VoodooInput.hpp index 446ba17..8e594c5 100644 --- a/VoodooInput/VoodooInput.hpp +++ b/VoodooInput/VoodooInput.hpp @@ -19,6 +19,18 @@ class TrackpointDevice; #define EXPORT __attribute__((visibility("default"))) #endif +/* State bits reference: linux/drivers/hid/hid-magicmouse.c#L58-L63 */ +#define MT2_TOUCH_STATE_BIT_TRANSITION (0x1) +#define MT2_TOUCH_STATE_BIT_NEAR (0x1 << 1) +#define MT2_TOUCH_STATE_BIT_CONTACT (0x1 << 2) + +enum TouchStates { + kTouchStateInactive = 0x0, + kTouchStateStart = MT2_TOUCH_STATE_BIT_NEAR | MT2_TOUCH_STATE_BIT_TRANSITION, + kTouchStateActive = MT2_TOUCH_STATE_BIT_CONTACT, + kTouchStateStop = MT2_TOUCH_STATE_BIT_CONTACT | MT2_TOUCH_STATE_BIT_NEAR | MT2_TOUCH_STATE_BIT_TRANSITION +}; + class EXPORT VoodooInput : public IOService { OSDeclareDefaultStructors(VoodooInput); diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp index bcb834d..86c1cb8 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp @@ -7,9 +7,106 @@ // #include "VoodooInputMT1Simulator.hpp" +#include -#define super IOService -OSDefineMetaClassAndStructors(VoodooInputMT1Simulator, IOService); +#define super IOHIDDevice +OSDefineMetaClassAndStructors(VoodooInputMT1Simulator, IOHIDDevice); + +bool VoodooInputMT1Simulator::setProperty(const char *aKey, OSObject *anObject) { + IOLog("MT1Sim: Attempting to set Property! %s\n", aKey); + OSString *str = OSString::withCString(aKey); + bool ret = false; + if (!str->isEqualTo("IOUserClientClass")) { + ret = super::setProperty(aKey, anObject); + } + OSSafeReleaseNULL(str); + return ret; +} + +bool VoodooInputMT1Simulator::setProperty(const char *aKey, unsigned long long aValue, unsigned int aNumberOfBits) { + return super::setProperty(aKey, aValue, aNumberOfBits); +} + +bool VoodooInputMT1Simulator::setProperty(const char *aKey, const char *aString) { + IOLog("MT1Sim: Attempting to set String Property! %s\n", aKey); + OSString *str = OSString::withCString(aKey); + bool ret = false; + if (!str->isEqualTo("IOUserClientClass")) { + ret = super::setProperty(aKey, aString); + } + OSSafeReleaseNULL(str); + return ret; +} + +bool VoodooInputMT1Simulator::setProperty(const OSSymbol *aKey, OSObject *anObject) { + IOLog("MT1Sim: Attempting to set OSSymbol Object Property! %s\n", aKey->getCStringNoCopy()); + bool ret = false; + if (!aKey->isEqualTo("IOUserClientClass")) { + ret = super::setProperty(aKey, anObject); + } + return ret; +} + +bool VoodooInputMT1Simulator::setProperty(const OSString *aKey, OSObject *anObject) { + IOLog("MT1Sim: Attempting to set OSString Object Property! %s\n", aKey->getCStringNoCopy()); + bool ret = false; + if (!aKey->isEqualTo("IOUserClientClass")) { + ret = super::setProperty(aKey, anObject); + } + return ret; +} + +bool VoodooInputMT1Simulator::init(OSDictionary *props) { + // Hidd tries to set a new user client, so we block setProperty writes to the user client key. + // This means that we need to set the user here in the props dictionary + props = OSDictionary::withCapacity(1); + OSString* userClient = OSString::withCString("VoodooInputMT1UserClient"); + props->setObject(kIOUserClientClassKey, userClient); + props->setObject("Clicking", kOSBooleanTrue); + props->setObject("TrackpadScroll", kOSBooleanTrue); + props->setObject("TrackpadHorizScroll", kOSBooleanTrue); + bool success = super::init(props); + OSSafeReleaseNULL(userClient); + OSSafeReleaseNULL(props); + + if (!success) { + return false; + } + + setProperty("MTHIDDevice", kOSBooleanTrue); + setProperty("Multitouch ID", 0x30000001d183000, 64); + setProperty("Family ID", 0x62, 8); + setProperty("bcdVersion", 0x109, 16); + setProperty("parser-type", 0x3e8, 32); + setProperty("parser-options", 39, 32); + setProperty("HIDDefaultBehavior", "Mouse"); + setProperty("HIDServiceSupport", kOSBooleanTrue); + setProperty("Max Packet Size", 0x200, 32); + + if (version_major >= 16) { + setProperty("SupportsGestureScrolling", kOSBooleanTrue); + setProperty("TrackpadFourFingerGestures", kOSBooleanTrue); + setProperty("ApplePreferenceIdentifier", "com.apple.AppleMultitouchTrackpad"); + setProperty("MT Built-in", kOSBooleanTrue); + setProperty("ApplePreferenceCapability", kOSBooleanTrue); + setProperty("TrackpadEmbedded", kOSBooleanTrue); + setProperty("TrackpadThreeFingerDrag", kOSBooleanTrue); + } + + setProperty("TrackpadCornerSecondaryClick", kOSBooleanTrue); + OSDictionary* dict = OSDictionary::withCapacity(1); + OSString* str = OSString::withCString("AppleMultitouchDriver.kext/Contents/PlugIns/MultitouchHID.plugin"); + dict->setObject("0516B563-B15B-11DA-96EB-0014519758EF", str); + + setProperty(kIOCFPlugInTypesKey, dict); + OSSafeReleaseNULL(str); + OSSafeReleaseNULL(dict); + + OSDictionary* trackpadPrefs = OSDictionary::withCapacity(1); + setProperty("TrackpadUserPreferences", trackpadPrefs); + OSSafeReleaseNULL(trackpadPrefs); + return true; +} bool VoodooInputMT1Simulator::start(IOService *provider) { if (!super::start(provider)) return false; @@ -19,6 +116,9 @@ bool VoodooInputMT1Simulator::start(IOService *provider) { return false; } + setProperty("Sensor Surface Width", engine->getPhysicalMaxX(), 32); + setProperty("Sensor Surface Height", engine->getPhysicalMaxY(), 32); + workloop = getWorkLoop(); if (workloop == nullptr) { IOLog("MT1Sim: Failed to create work loop!\n"); @@ -27,7 +127,7 @@ bool VoodooInputMT1Simulator::start(IOService *provider) { workloop->retain(); - cmdGate = OSTypeAlloc(IOCommandGate); + cmdGate = IOCommandGate::commandGate(this); if (cmdGate == nullptr) { IOLog("MT1Sim: Failed to create cmd gate\n"); return false; @@ -41,9 +141,8 @@ bool VoodooInputMT1Simulator::start(IOService *provider) { return false; } - // Set name so that WindowServer attaches to us - setName("AppleUSBMultitouchDriver"); - setProperty(kIOUserClientClassKey, "VoodooInputMT1UserClient"); + clock_get_uptime(&startTimestamp); + registerService(); return true; @@ -64,6 +163,63 @@ void VoodooInputMT1Simulator::stop(IOService *provider) { super::stop(provider); } +const unsigned char report_descriptor[] = { + 0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x03, 0x06, + 0x00, 0xFF, 0x09, 0x01, 0x15, 0x00, 0x26, 0xFF, + 0x00, 0x85, 0x44, 0x75, 0x08, 0x96, 0xFF, 0x01, + 0x81, 0x00, 0xC0 +}; + +IOReturn VoodooInputMT1Simulator::newReportDescriptor(IOMemoryDescriptor** descriptor) const { + IOBufferMemoryDescriptor* report_descriptor_buffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, sizeof(report_descriptor)); + + if (!report_descriptor_buffer) { + IOLog("%s Could not allocate buffer for report descriptor\n", getName()); + return kIOReturnNoResources; + } + + report_descriptor_buffer->writeBytes(0, report_descriptor, sizeof(report_descriptor)); + *descriptor = report_descriptor_buffer; + + return kIOReturnSuccess; +} + +OSNumber* VoodooInputMT1Simulator::newPrimaryUsageNumber() const { + return OSNumber::withNumber(kHIDUsage_GD_Mouse, 32); +} + +OSNumber* VoodooInputMT1Simulator::newPrimaryUsagePageNumber() const { + return OSNumber::withNumber(kHIDPage_GenericDesktop, 32); +} + +OSNumber* VoodooInputMT1Simulator::newProductIDNumber() const { + return OSNumber::withNumber(0x252, 32); +} + +OSString* VoodooInputMT1Simulator::newProductString() const { + return OSString::withCString("Apple Internal Trackpad"); +} + +OSString* VoodooInputMT1Simulator::newSerialNumberString() const { + return OSString::withCString("None"); +} + +OSString* VoodooInputMT1Simulator::newTransportString() const { + return OSString::withCString("USB"); +} + +OSNumber* VoodooInputMT1Simulator::newVendorIDNumber() const { + return OSNumber::withNumber(0x5ac, 16); +} + +OSNumber* VoodooInputMT1Simulator::newLocationIDNumber() const { + return OSNumber::withNumber(0x1d183000, 32); +} + +OSNumber* VoodooInputMT1Simulator::newVersionNumber() const { + return OSNumber::withNumber(0x219, 32); +} + bool VoodooInputMT1Simulator::registerUserClient(IOService *client) { IOLog("MT1Sim: Adding user client\n"); return userClients->setObject(client); @@ -96,6 +252,10 @@ IOReturn VoodooInputMT1Simulator::getReport(MT1DeviceReportStruct *toFill) { UInt32 width, height; switch (toFill->reportId) { + case MT1ReportDetectConfig: + toFill->data[0] = 0x08; + toFill->dataSize = 1; + break; case MT1ReportSensorParam: memcpy(toFill->data, MT1SensorParams, SensorParamsLength); toFill->dataSize = SensorParamsLength; @@ -134,3 +294,150 @@ IOReturn VoodooInputMT1Simulator::getReport(MT1DeviceReportStruct *toFill) { return kIOReturnSuccess; } + +void VoodooInputMT1Simulator::constructReport(VoodooInputEvent& event) { + AbsoluteTime timestamp = event.timestamp; + size_t inputSize = sizeof(MT1_INPUT_REPORT) + (sizeof(MT1_INPUT_REPORT_FINGER) * event.contact_count); + MT1_INPUT_REPORT *inputReport = reinterpret_cast(IOMalloc(inputSize)); + + IOLog("MT1Sim: Constructing report\n"); + if (inputReport == nullptr) return; + + inputReport->ReportID = 0x28; + inputReport->Timestamp = 0; + inputReport->Button = event.transducers[0].isPhysicalButtonDown; + + // rotation check + UInt8 transform = engine->getTransformKey(); + + // timestamp + AbsoluteTime relativeTimestamp = timestamp; + + SUB_ABSOLUTETIME(&relativeTimestamp, &startTimestamp); + + UInt64 milliTimestamp; + + absolutetime_to_nanoseconds(relativeTimestamp, &milliTimestamp); + + milliTimestamp /= 1000000; + inputReport->Timestamp = milliTimestamp; + + // finger data + bool input_active = inputReport->Button; + bool is_error_input_active = false; + + for (int i = 0; i < event.contact_count; i++) { + const VoodooInputTransducer &transducer = event.transducers[i]; + + if (!transducer.isValid) + continue; + + if (transducer.type == VoodooInputTransducerType::STYLUS) { + continue; + } + + // in case the obtained id is greater than 14, usually 0~4 for common devices. + UInt16 touch_id = transducer.secondaryId % 15; + input_active |= transducer.isTransducerActive; + + MT1_INPUT_REPORT_FINGER& fingerData = inputReport->FINGERS[i]; + + IOFixed scaled_x = ((transducer.currentCoordinates.x * 1.0f) / engine->getLogicalMaxX()) * MT1_MAX_X; + IOFixed scaled_y = ((transducer.currentCoordinates.y * 1.0f) / engine->getLogicalMaxY()) * MT1_MAX_Y; + + if (scaled_x < 1 && scaled_y >= MT1_MAX_Y) { + is_error_input_active = true; + } + + if (transform) { + if (transform & kIOFBSwapAxes) { + scaled_x = ((transducer.currentCoordinates.y * 1.0f) / engine->getLogicalMaxY()) * MT1_MAX_X; + scaled_y = ((transducer.currentCoordinates.x * 1.0f) / engine->getLogicalMaxX()) * MT1_MAX_Y; + } + + if (transform & kIOFBInvertX) { + scaled_x = MT1_MAX_X - scaled_x; + } + if (transform & kIOFBInvertY) { + scaled_y = MT1_MAX_Y - scaled_y; + } + } + + fingerData.State = touchActive[touch_id] ? kTouchStateActive : kTouchStateStart; + touchActive[touch_id] = transducer.isTransducerActive || transducer.isPhysicalButtonDown; + + fingerData.Finger = transducer.fingerType; + + if (transducer.supportsPressure) { + fingerData.Pressure = transducer.currentCoordinates.pressure; + fingerData.Size = transducer.currentCoordinates.width; + fingerData.Touch_Major = transducer.currentCoordinates.width; + fingerData.Touch_Minor = transducer.currentCoordinates.width; + } else { + fingerData.Pressure = 5; + fingerData.Size = 10; + fingerData.Touch_Major = 20; + fingerData.Touch_Minor = 20; + } + + if (!transducer.isTransducerActive && !transducer.isPhysicalButtonDown) { + fingerData.State = kTouchStateStop; + fingerData.Size = 0x0; + fingerData.Touch_Minor = 0; + fingerData.Touch_Major = 0; + } + + fingerData.X = (SInt16)(scaled_x - (MT1_MAX_X / 2)); + fingerData.Y = (SInt16)(scaled_y - (MT1_MAX_Y / 2)) * -1; + + fingerData.Orientation = 0x4; // pi/2 + fingerData.Identifier = touch_id + 1; + } + + inputReport->TouchActive = input_active; + + if (!is_error_input_active) { + OSCollectionIterator* iter = OSCollectionIterator::withCollection(userClients); + while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { + IOLog("MT1Sim: Sending report\n"); + client->enqueueData(inputReport, inputSize); + } + OSSafeReleaseNULL(iter); + } + + if (!input_active) { + memset(touchActive, false, sizeof(touchActive)); + + inputReport->FINGERS[0].Size = 0x0; + inputReport->FINGERS[0].Touch_Major = 0x0; + inputReport->FINGERS[0].Touch_Minor = 0x0; + + milliTimestamp += 10; + inputReport->Timestamp = milliTimestamp; + + OSCollectionIterator* iter = OSCollectionIterator::withCollection(userClients); + while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { + client->enqueueData(inputReport, inputSize); + } + OSSafeReleaseNULL(iter); + + inputReport->FINGERS[0].Finger = kMT2FingerTypeUndefined; + inputReport->FINGERS[0].State = kTouchStateInactive; + iter = OSCollectionIterator::withCollection(userClients); + while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { + client->enqueueData(inputReport, inputSize); + } + OSSafeReleaseNULL(iter); + + // Blank report + milliTimestamp += 10; + inputReport->Timestamp = milliTimestamp; + iter = OSCollectionIterator::withCollection(userClients); + while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { + client->enqueueData(inputReport, sizeof(MT1_INPUT_REPORT)); + } + OSSafeReleaseNULL(iter); + } + + IOFree(inputReport, inputSize); +} diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp index 36b9e2d..0a41ec9 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp @@ -9,17 +9,26 @@ #ifndef AppleUSBMultitouchDriver_hpp #define AppleUSBMultitouchDriver_hpp -#include +#include #include #include #include #include +#include "./VoodooInputMT1UserClient.hpp" #include "../VoodooInput.hpp" #include "../VoodooInputMultitouch/VoodooInputTransducer.h" #include "../VoodooInputMultitouch/VoodooInputEvent.h" #include "../VoodooInputMultitouch/MultitouchHelpers.h" +#define MT1_MAX_X 6067 +#define MT1_MAX_Y 5021 + +/* State bits reference: linux/drivers/hid/hid-magicmouse.c#L58-L63 */ +#define MT2_TOUCH_STATE_BIT_TRANSITION (0x1) +#define MT2_TOUCH_STATE_BIT_NEAR (0x1 << 1) +#define MT2_TOUCH_STATE_BIT_CONTACT (0x1 << 2) + /* Finger Packet +---+---+---+---+---+---+---+---+---+ | | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | @@ -29,10 +38,10 @@ | 1 | | | +---+ +-------------------+ | 2 | y: SInt13 | -+---+-----------+-----------+ + -| 3 | | | -| | | | -+---+-----------+-----------+-------+ ++---+-----------------------+ + +| 3 | ?? | | +| | ?! | | ++---+-----------------------+-------+ | 4 | touchMajor: UInt8 | +---+-------------------------------+ | 5 | touchMinor: UInt8 | @@ -40,38 +49,40 @@ | 6 | id | size: UInt6 | +---+-------+---------------+-------+ | 7 | orientation: UInt6 | id: 4 | -+---+---------------+-------+-------+ -| 8 | state | | -| | UInt4 | | -+---+---------------+---------------+ ++---+---+-----------+-------+-------+ +| 8 | ? | state | finger | +| | | UInt3 | UInt4 | ++---+---+-----------+---------------+ */ -struct __attribute__((__packed__)) MT_1_INPUT_REPORT_FINGER { +struct __attribute__((__packed__)) MT1_INPUT_REPORT_FINGER { SInt16 X: 13; SInt16 Y: 13; - UInt8 : 6; + UInt8 Pressure: 6; UInt8 Touch_Major; UInt8 Touch_Minor; UInt8 Size: 6; UInt8 Identifier: 4; UInt8 Orientation: 6; - UInt8 State: 4; - UInt8 : 4; + UInt8 Finger: 4; + UInt8 State: 3; + UInt8 : 1; }; -// Missing angle and finger (Maybe they are in Byte 3?) +// Missing finger (Maybe they are in Byte 3?) struct __attribute__((__packed__)) MT1_INPUT_REPORT { UInt8 ReportID; - UInt8 Button: 6; - UInt32 Timestamp: 18; + UInt8 Button: 1; + UInt8 TouchActive: 1; + UInt32 Timestamp: 22; - MT_1_INPUT_REPORT_FINGER FINGERS[]; // May support more fingers + MT1_INPUT_REPORT_FINGER FINGERS[]; // May support more fingers // UInt16 Checksum; }; static_assert(sizeof(MT1_INPUT_REPORT) == 4, "Unexpected MT1_INPUT_REPORT size"); -static_assert(sizeof(MT_1_INPUT_REPORT_FINGER) == 9, "Unexpected MT1_INPUT_REPORT_FINGER size"); +static_assert(sizeof(MT1_INPUT_REPORT_FINGER) == 9, "Unexpected MT1_INPUT_REPORT_FINGER size"); // Missing finger type @@ -81,28 +92,49 @@ struct MT1DeviceReportStruct { uint32_t dataSize; }; +#define MT1ReportDetectConfig 0xC8 #define MT1ReportSensorParam 0xA1 #define MT1ReportSensorDescriptor 0xD0 #define MT1ReportFamilyId 0xD1 #define MT1ReportSensorRows 0xD3 #define MT1ReportSensorSize 0xD9 -class EXPORT VoodooInputMT1Simulator : public IOService { +class EXPORT VoodooInputMT1Simulator : public IOHIDDevice { OSDeclareDefaultStructors(VoodooInputMT1Simulator); public: - + virtual bool init(OSDictionary *) override; virtual bool start(IOService *provider) override; virtual void stop(IOService *provider) override; + virtual bool setProperty(const char *aKey, OSObject *anObject) override; + virtual bool setProperty(const char *aKey, unsigned long long aValue, unsigned int aNumberOfBits) override; + virtual bool setProperty(const char *aKey, const char *aString) override; + virtual bool setProperty(const OSSymbol *aKey, OSObject *anObject) override; + virtual bool setProperty(const OSString *aKey, OSObject *anObject) override; + + virtual IOReturn newReportDescriptor(IOMemoryDescriptor** descriptor) const override; + virtual OSNumber* newPrimaryUsageNumber() const override; + virtual OSNumber* newPrimaryUsagePageNumber() const override; + virtual OSNumber* newProductIDNumber() const override; + virtual OSNumber* newVendorIDNumber() const override; + virtual OSNumber* newLocationIDNumber() const override; + virtual OSNumber* newVersionNumber() const override; + virtual OSString* newProductString() const override; + virtual OSString* newSerialNumberString() const override; + virtual OSString* newTransportString() const override; + bool registerUserClient(IOService *client); void unregisterUserClient(IOService *client); IOReturn getReport(MT1DeviceReportStruct *toFill); + void constructReport(VoodooInputEvent& event); private: OSSet *userClients {nullptr}; + bool touchActive[15] {false}; IOWorkLoop *workloop {nullptr}; IOCommandGate *cmdGate {nullptr}; VoodooInput *engine {nullptr}; + AbsoluteTime startTimestamp {}; }; #endif /* AppleUSBMultitouchDriver_hpp */ diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp index a2ca5a7..09b32de 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp @@ -12,32 +12,34 @@ OSDefineMetaClassAndStructors(VoodooInputMT1UserClient, IOUserClient); #if defined(__x86_64__) -// { Object, Func pointer, Padding, Flags, Count 0, Count 1 } -IOExternalMethodACID VoodooInputMT1UserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { +// { Object, Func pointer, Padding, Flags, Inputs, Outputs } +static const IOExternalMethod sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { // VoodooInputMT1UserClientMethodsSetSendsFrames - {0, static_cast(&VoodooInputMT1UserClient::sSetSendFrames), kIOExternalMethodACIDPadding, 0, 0, 1}, + {0, static_cast(&VoodooInputMT1UserClient::sSetSendFrames), kIOUCScalarIScalarO, 1, 0}, // VoodooInputMT1UserClientMethodsGetReport - {0, static_cast(&VoodooInputMT1UserClient::sGetReport), kIOExternalMethodACIDPadding, 0, 3, 0x208}, + {0, static_cast(&VoodooInputMT1UserClient::sGetReport), kIOUCStructIStructO, 0x208, 0x208}, // VoodooInputMT1UserClientMethodsSetReport - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOExternalMethodACIDPadding, 0, 3, 0x208}, + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCStructIStructO, 0x208, 0x208}, // VoodooInputMT1UserClientMethodsSetSendLogs - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOExternalMethodACIDPadding, 0, 0, 1}, + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 1, 0}, // VoodooInputMT1UserClientMethodsIssueDriverRequest - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOExternalMethodACIDPadding, 0, 3, 204}, - {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 3}, // Relative Mouse Movement - {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 3}, // Scroll Wheel - {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 2}, // Keyboard - {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 1}, // Map Clicks + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCStructIStructO, 0x204, 0x204}, + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Relative Mouse Movement + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Scroll Wheel + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 2, 0}, // Keyboard + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 1, 0}, // Map Clicks // VoodooInputMT1UserClientMethodsRecacheProperties - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOExternalMethodACIDPadding, 0, 0, 0}, - {0, nullptr, kIOExternalMethodACIDPadding, 0, 0, 3}, // Momentum Scroll + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 0, 0}, + {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Momentum Scroll }; + #else // __defined(__x86_64__) // TODO: Switch where padding is in struct #error "Invalid architecture" #endif // __defined(__x86_64__) bool VoodooInputMT1UserClient::start(IOService *provider) { + IOLog("%s Start\n", getName()); if (!super::start(provider)) return false; simulator = OSDynamicCast(VoodooInputMT1Simulator, provider); @@ -69,13 +71,15 @@ void VoodooInputMT1UserClient::stop(IOService *provider) { } IOReturn VoodooInputMT1UserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { + IOLog("%s client notif port\n", getName()); dataQueue->setNotificationPort(port); logQueue->setNotificationPort(port); return kIOReturnSuccess; } IOReturn VoodooInputMT1UserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { - if (type == 0x10) { + IOLog("%s clientMem\n", getName()); + if (type != 0x10) { dataQueueDesc->retain(); *memory = dataQueueDesc; } else { @@ -88,17 +92,18 @@ IOReturn VoodooInputMT1UserClient::clientMemoryForType(UInt32 type, IOOptionBits } IOExternalMethod *VoodooInputMT1UserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { + IOLog("%s External Method %d\n", getName(), index); if (index >= VoodooInputMT1UserClientMethodsNumMethods) { return nullptr; } *targetP = this; - sMethods[index].object = this; - return reinterpret_cast(&sMethods[index]); + return const_cast(&sMethods[index]); } -IOReturn VoodooInputMT1UserClient::sSetSendFrames(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { +IOReturn VoodooInputMT1UserClient::sSetSendFrames(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { bool success = true; + IOLog("%s Get Report: %d\n", getName(), static_cast(p1)); if (static_cast(p1)) { success = simulator->registerUserClient(this); @@ -110,13 +115,15 @@ IOReturn VoodooInputMT1UserClient::sSetSendFrames(IOService *svc, void *p1, void } // I'm not really sure why they use two different structs here??? -IOReturn VoodooInputMT1UserClient::sGetReport(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { +IOReturn VoodooInputMT1UserClient::sGetReport(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { MT1DeviceReportStruct *input = static_cast(p1); MT1DeviceReportStruct *output = static_cast(p2); if (input == nullptr || output == nullptr) { return kIOReturnBadArgument; } + IOLog("%s Get Report: %d\n", getName(), input->reportId); + IOReturn ret = simulator->getReport(input); if (ret == kIOReturnSuccess) { memmove(output->data, input->data, input->dataSize); @@ -126,6 +133,12 @@ IOReturn VoodooInputMT1UserClient::sGetReport(IOService *svc, void *p1, void *p2 return ret; } -IOReturn VoodooInputMT1UserClient::sNoop(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { +void VoodooInputMT1UserClient::enqueueData(void *data, UInt32 size) { + if (dataQueue == nullptr) return; + IOLog("%s Enqueue Data\n", getName()); + dataQueue->enqueue(data, size); +} + +IOReturn VoodooInputMT1UserClient::sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { return kIOReturnSuccess; // noop } diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp index 88e1ca9..c1762e3 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp @@ -47,9 +47,11 @@ class EXPORT VoodooInputMT1UserClient : public IOUserClient { virtual IOReturn clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) override; virtual IOExternalMethod *getTargetAndMethodForIndex(IOService **targetP, UInt32 index) override; - IOReturn sSetSendFrames(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); - IOReturn sGetReport(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); - IOReturn sNoop(IOService *svc, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + IOReturn sSetSendFrames(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + IOReturn sGetReport(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + IOReturn sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + + void enqueueData(void *data, UInt32 size); private: VoodooInputMT1Simulator *simulator {nullptr}; @@ -57,8 +59,6 @@ class EXPORT VoodooInputMT1UserClient : public IOUserClient { IOSharedDataQueue *logQueue {nullptr}; IOMemoryDescriptor *dataQueueDesc {nullptr}; IOMemoryDescriptor *logQueueDesc {nullptr}; - - static IOExternalMethodACID sMethods[VoodooInputMT1UserClientMethodsNumMethods]; }; #endif /* VoodooInputMT1UserClient_hpp */ diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.hpp b/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.hpp index 17eadb7..71426c6 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.hpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.hpp @@ -25,18 +25,6 @@ #define MT2_MAX_X 8134 #define MT2_MAX_Y 5206 -/* State bits reference: linux/drivers/hid/hid-magicmouse.c#L58-L63 */ -#define MT2_TOUCH_STATE_BIT_TRANSITION (0x1) -#define MT2_TOUCH_STATE_BIT_NEAR (0x1 << 1) -#define MT2_TOUCH_STATE_BIT_CONTACT (0x1 << 2) - -enum TouchStates { - kTouchStateInactive = 0x0, - kTouchStateStart = MT2_TOUCH_STATE_BIT_NEAR | MT2_TOUCH_STATE_BIT_TRANSITION, - kTouchStateActive = MT2_TOUCH_STATE_BIT_CONTACT, - kTouchStateStop = MT2_TOUCH_STATE_BIT_CONTACT | MT2_TOUCH_STATE_BIT_NEAR | MT2_TOUCH_STATE_BIT_TRANSITION -}; - /* Finger Packet +---+---+---+---+---+---+---+---+---+ | | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | From 02c55830b81d63011f1d1248ec792df035a969a0 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Thu, 5 Jan 2023 14:10:56 -0800 Subject: [PATCH 04/32] Switch to wellspring reports, add more properties --- VoodooInput/Info.plist | 264 ++++++++++++++++++ VoodooInput/VoodooInput.cpp | 2 +- .../VoodooInputMT1Simulator.cpp | 189 +++++++------ .../VoodooInputMT1Simulator.hpp | 103 +++++-- .../VoodooInputMT1UserClient.cpp | 4 +- .../VoodooInputMT1UserClient.hpp | 2 +- 6 files changed, 455 insertions(+), 109 deletions(-) diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index 2b476ad..624c301 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -24,6 +24,270 @@ CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) + MT1Props + + IOUserClientClass + VoodooInputMT1UserClient + parser-type + 1000 + parser-options + 39 + MTHIDDevice + + HIDDefaultBehavior + Mouse + HIDPointerAccelerationType + HIDTrackpadAcceleration + HIDPointerResolution + 26214400 + HIDScrollAccelerationType + HIDTrackpadScrollAcceleration + HIDScrollResolution + 26214400 + HIDServiceSupport + + TrackpadFourFingerGestures + + TrackpadMomentumScroll + + TrackpadSecondaryClickCorners + + TrackpadThreeFingerDrag + + TrackpadUserPreferences + + IOCFPlugInTypes + + 0516B563-B15B-11DA-96EB-0014519758EF + AppleMultitouchDriver.kext/Contents/PlugIns/MultitouchHID.plugin + + HIDScrollAccelCurves + + + HIDAccelGainLinear + 85197 + HIDAccelGainParabolic + 13107 + HIDAccelIndex + 8192 + HIDAccelTangentSpeedLinear + 851968 + HIDAccelTangentSpeedParabolicRoot + 1310720 + + + HIDAccelGainLinear + 95027 + HIDAccelGainParabolic + 32768 + HIDAccelIndex + 14090 + HIDAccelTangentSpeedLinear + 786432 + HIDAccelTangentSpeedParabolicRoot + 1245184 + + + HIDAccelGainLinear + 104858 + HIDAccelGainParabolic + 45875 + HIDAccelIndex + 20480 + HIDAccelTangentSpeedLinear + 720896 + HIDAccelTangentSpeedParabolicRoot + 1179648 + + + HIDAccelGainLinear + 114688 + HIDAccelGainParabolic + 57017 + HIDAccelIndex + 32768 + HIDAccelTangentSpeedLinear + 655360 + HIDAccelTangentSpeedParabolicRoot + 1114112 + + + HIDAccelGainLinear + 124519 + HIDAccelGainParabolic + 68813 + HIDAccelIndex + 49152 + HIDAccelTangentSpeedLinear + 589824 + HIDAccelTangentSpeedParabolicRoot + 1048576 + + + HIDAccelGainLinear + 134349 + HIDAccelGainParabolic + 81920 + HIDAccelIndex + 65536 + HIDAccelTangentSpeedLinear + 524288 + HIDAccelTangentSpeedParabolicRoot + 983040 + + + HIDAccelGainLinear + 144179 + HIDAccelGainParabolic + 98304 + HIDAccelIndex + 111411 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 917504 + + + HIDAccelCurves + + + HIDAccelGainLinear + 65536 + HIDAccelIndex + 0 + HIDAccelTangentSpeedLinear + 484966 + HIDAccelTangentSpeedParabolicRoot + 1376256 + + + HIDAccelGainCubic + 5243 + HIDAccelGainLinear + 70779 + HIDAccelGainParabolic + 32768 + HIDAccelIndex + 8192 + HIDAccelTangentSpeedLinear + 478413 + HIDAccelTangentSpeedParabolicRoot + 1310720 + + + HIDAccelGainCubic + 6554 + HIDAccelGainLinear + 76022 + HIDAccelGainParabolic + 43254 + HIDAccelIndex + 32768 + HIDAccelTangentSpeedLinear + 471859 + HIDAccelTangentSpeedParabolicRoot + 1245184 + + + HIDAccelGainCubic + 7864 + HIDAccelGainLinear + 81265 + HIDAccelGainParabolic + 54395 + HIDAccelIndex + 45056 + HIDAccelTangentSpeedLinear + 465306 + HIDAccelTangentSpeedParabolicRoot + 1179648 + + + HIDAccelGainCubic + 9830 + HIDAccelGainLinear + 86508 + HIDAccelGainParabolic + 65536 + HIDAccelIndex + 57344 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 1114112 + + + HIDAccelGainCubic + 11796 + HIDAccelGainLinear + 91750 + HIDAccelGainParabolic + 75366 + HIDAccelIndex + 65536 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 1048576 + + + HIDAccelGainCubic + 13763 + HIDAccelGainLinear + 96993 + HIDAccelGainParabolic + 85197 + HIDAccelIndex + 98304 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 983040 + + + HIDAccelGainCubic + 15729 + HIDAccelGainLinear + 102236 + HIDAccelGainParabolic + 95027 + HIDAccelIndex + 131072 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 917504 + + + HIDAccelGainCubic + 18350 + HIDAccelGainLinear + 106824 + HIDAccelGainParabolic + 108790 + HIDAccelIndex + 163840 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 851968 + + + HIDAccelGainCubic + 23593 + HIDAccelGainLinear + 111411 + HIDAccelGainParabolic + 123208 + HIDAccelIndex + 196608 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 786432 + + + IOClass VoodooInput IOProbeScore diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index 4152892..7e854de 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -47,7 +47,7 @@ bool VoodooInput::start(IOService *provider) { } // Initialize simulator device - if (!simulator->init(NULL) || !simulator->attach(this)) { + if (!simulator->init(OSDynamicCast(OSDictionary, getProperty("MT1Props"))) || !simulator->attach(this)) { IOLog("VoodooInput could not attach simulator!\n"); goto exit; } diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp index 86c1cb8..1592b58 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp @@ -59,48 +59,31 @@ bool VoodooInputMT1Simulator::setProperty(const OSString *aKey, OSObject *anObje bool VoodooInputMT1Simulator::init(OSDictionary *props) { // Hidd tries to set a new user client, so we block setProperty writes to the user client key. // This means that we need to set the user here in the props dictionary - props = OSDictionary::withCapacity(1); - OSString* userClient = OSString::withCString("VoodooInputMT1UserClient"); - props->setObject(kIOUserClientClassKey, userClient); - props->setObject("Clicking", kOSBooleanTrue); - props->setObject("TrackpadScroll", kOSBooleanTrue); - props->setObject("TrackpadHorizScroll", kOSBooleanTrue); bool success = super::init(props); - OSSafeReleaseNULL(userClient); - OSSafeReleaseNULL(props); if (!success) { return false; } - setProperty("MTHIDDevice", kOSBooleanTrue); + setProperty("Clicking", kOSBooleanTrue); + setProperty("TrackpadScroll", kOSBooleanTrue); + setProperty("TrackpadHorizScroll", kOSBooleanTrue); + setProperty("AlwaysNeedsVelocityCalculated", kOSBooleanTrue); + setProperty("Endianness", MT1_LITTLE_ENDIAN, 32); setProperty("Multitouch ID", 0x30000001d183000, 64); setProperty("Family ID", 0x62, 8); setProperty("bcdVersion", 0x109, 16); - setProperty("parser-type", 0x3e8, 32); - setProperty("parser-options", 39, 32); - setProperty("HIDDefaultBehavior", "Mouse"); - setProperty("HIDServiceSupport", kOSBooleanTrue); setProperty("Max Packet Size", 0x200, 32); if (version_major >= 16) { setProperty("SupportsGestureScrolling", kOSBooleanTrue); - setProperty("TrackpadFourFingerGestures", kOSBooleanTrue); setProperty("ApplePreferenceIdentifier", "com.apple.AppleMultitouchTrackpad"); setProperty("MT Built-in", kOSBooleanTrue); setProperty("ApplePreferenceCapability", kOSBooleanTrue); setProperty("TrackpadEmbedded", kOSBooleanTrue); - setProperty("TrackpadThreeFingerDrag", kOSBooleanTrue); } setProperty("TrackpadCornerSecondaryClick", kOSBooleanTrue); - OSDictionary* dict = OSDictionary::withCapacity(1); - OSString* str = OSString::withCString("AppleMultitouchDriver.kext/Contents/PlugIns/MultitouchHID.plugin"); - dict->setObject("0516B563-B15B-11DA-96EB-0014519758EF", str); - - setProperty(kIOCFPlugInTypesKey, dict); - OSSafeReleaseNULL(str); - OSSafeReleaseNULL(dict); OSDictionary* trackpadPrefs = OSDictionary::withCapacity(1); setProperty("TrackpadUserPreferences", trackpadPrefs); @@ -141,14 +124,42 @@ bool VoodooInputMT1Simulator::start(IOService *provider) { return false; } + size_t inputSize = sizeof(WELLSPRING3_REPORT) + (sizeof(WELLSPRING3_FINGER) * VOODOO_INPUT_MAX_TRANSDUCERS); + inputReport = reinterpret_cast(IOMalloc(inputSize)); + bzero(inputReport, inputSize); + + if (inputReport == nullptr) return false; + clock_get_uptime(&startTimestamp); +// IOServiceMatchingNotificationHandler notificationHandler = OSMemberFunctionCast(IOServiceMatchingNotificationHandler, this, &VoodooInputMT1Simulator::notificationEventDriverPublish); +// OSDictionary *matching = serviceMatching("AppleUSBMultitouchEventDriver"); +// eventDriverPublish = addMatchingNotification(gIOFirstPublishNotification, matching, notificationHandler, this); +// OSSafeReleaseNULL(matching); + registerService(); return true; } +void VoodooInputMT1Simulator::notificationEventDriverPublish(IOService * newService, IONotifier * notifier) { + if (notifier == eventDriverPublish) { + IOHIDEventService *eventDriver = OSDynamicCast(IOHIDEventService, newService); + if (eventDriver == nullptr) return; + + OSNumber *loc = OSDynamicCast(OSNumber, eventDriver->getProperty("LocationID")); + if (loc == nullptr) return; + + if (!loc->isEqualTo(newLocationIDNumber())) return; +// eventDriver->setSystemProperties(); + } +} + void VoodooInputMT1Simulator::stop(IOService *provider) { + if (eventDriverPublish != nullptr) { + eventDriverPublish->remove(); + } + if (workloop) { workloop->removeEventSource(cmdGate); } @@ -160,6 +171,11 @@ void VoodooInputMT1Simulator::stop(IOService *provider) { OSSafeReleaseNULL(userClients); } + if (inputReport != nullptr) { + size_t inputSize = sizeof(WELLSPRING3_REPORT) + (sizeof(WELLSPRING3_FINGER) * VOODOO_INPUT_MAX_TRANSDUCERS); + IOFree(inputReport, inputSize); + } + super::stop(provider); } @@ -197,7 +213,7 @@ OSNumber* VoodooInputMT1Simulator::newProductIDNumber() const { } OSString* VoodooInputMT1Simulator::newProductString() const { - return OSString::withCString("Apple Internal Trackpad"); + return OSString::withCString("Wellspring3 Emulator"); } OSString* VoodooInputMT1Simulator::newSerialNumberString() const { @@ -239,7 +255,7 @@ static const UInt8 MT1SensorDesc[SensorDescLength] = {0x01, 0x01, 0x00, 0x0c, 0x #define SensorRowsLength 5 static const UInt8 MT1SensorRows[SensorRowsLength] = { - 0x01, // Endianness (no clue what 1 means) + 0x01, // Is little Endian 0x0C, // Rows 0x14, // Columns 0x01, 0x09 // BCD Version @@ -297,15 +313,23 @@ IOReturn VoodooInputMT1Simulator::getReport(MT1DeviceReportStruct *toFill) { void VoodooInputMT1Simulator::constructReport(VoodooInputEvent& event) { AbsoluteTime timestamp = event.timestamp; - size_t inputSize = sizeof(MT1_INPUT_REPORT) + (sizeof(MT1_INPUT_REPORT_FINGER) * event.contact_count); - MT1_INPUT_REPORT *inputReport = reinterpret_cast(IOMalloc(inputSize)); + size_t inputSize = sizeof(WELLSPRING3_REPORT) + (sizeof(WELLSPRING3_FINGER) * event.contact_count); IOLog("MT1Sim: Constructing report\n"); if (inputReport == nullptr) return; - inputReport->ReportID = 0x28; - inputReport->Timestamp = 0; - inputReport->Button = event.transducers[0].isPhysicalButtonDown; + inputReport->ReportID = 0x74; + inputReport->Counter = counter++; + inputReport->unkown1 = 0x03; + inputReport->HeaderSize = sizeof(WELLSPRING3_REPORT); + inputReport->unk2[0] = 0x00; // Magic + inputReport->unk2[1] = 0x17; + inputReport->unk2[2] = 0x07; + inputReport->unk2[3] = 0x97; + inputReport->TotalFingerDataSize = sizeof(WELLSPRING3_FINGER) * event.contact_count; + inputReport->NumFingers = event.contact_count; + inputReport->Button = event.transducers[0].isPhysicalButtonDown || event.transducers[0].currentCoordinates.pressure > 100; + inputReport->unknown1 = 0x00000010; // rotation check UInt8 transform = engine->getTransformKey(); @@ -320,7 +344,7 @@ void VoodooInputMT1Simulator::constructReport(VoodooInputEvent& event) { absolutetime_to_nanoseconds(relativeTimestamp, &milliTimestamp); milliTimestamp /= 1000000; - inputReport->Timestamp = milliTimestamp; + inputReport->Timestamp = static_cast(milliTimestamp); // finger data bool input_active = inputReport->Button; @@ -340,7 +364,7 @@ void VoodooInputMT1Simulator::constructReport(VoodooInputEvent& event) { UInt16 touch_id = transducer.secondaryId % 15; input_active |= transducer.isTransducerActive; - MT1_INPUT_REPORT_FINGER& fingerData = inputReport->FINGERS[i]; + WELLSPRING3_FINGER& fingerData = inputReport->Fingers[i]; IOFixed scaled_x = ((transducer.currentCoordinates.x * 1.0f) / engine->getLogicalMaxX()) * MT1_MAX_X; IOFixed scaled_y = ((transducer.currentCoordinates.y * 1.0f) / engine->getLogicalMaxY()) * MT1_MAX_Y; @@ -369,75 +393,82 @@ void VoodooInputMT1Simulator::constructReport(VoodooInputEvent& event) { fingerData.Finger = transducer.fingerType; if (transducer.supportsPressure) { - fingerData.Pressure = transducer.currentCoordinates.pressure; - fingerData.Size = transducer.currentCoordinates.width; - fingerData.Touch_Major = transducer.currentCoordinates.width; - fingerData.Touch_Minor = transducer.currentCoordinates.width; + fingerData.Size = transducer.currentCoordinates.width * 4; + fingerData.ToolMajor = transducer.currentCoordinates.width * 16; + fingerData.ToolMinor = transducer.currentCoordinates.width * 16; } else { - fingerData.Pressure = 5; - fingerData.Size = 10; - fingerData.Touch_Major = 20; - fingerData.Touch_Minor = 20; + fingerData.Size = 200; + fingerData.ToolMajor = 800; + fingerData.ToolMinor = 800; } if (!transducer.isTransducerActive && !transducer.isPhysicalButtonDown) { + touchActive[touch_id] = false; fingerData.State = kTouchStateStop; fingerData.Size = 0x0; - fingerData.Touch_Minor = 0; - fingerData.Touch_Major = 0; + fingerData.ToolMajor = 0; + fingerData.ToolMinor = 0; } fingerData.X = (SInt16)(scaled_x - (MT1_MAX_X / 2)); - fingerData.Y = (SInt16)(scaled_y - (MT1_MAX_Y / 2)) * -1; + fingerData.Y = (SInt16)(scaled_y); + fingerData.Unknown = touchActive[touch_id] ? 0xFF : 0; // Always set to 1 in MT2 logic, though my MBP9,2 sets this to 0xFF once it starts moving - fingerData.Orientation = 0x4; // pi/2 - fingerData.Identifier = touch_id + 1; + fingerData.Orientation = 0x4000; // pi/2 + fingerData.Id = touch_id + 1; } - inputReport->TouchActive = input_active; +// inputReport->TouchActive = input_active; if (!is_error_input_active) { - OSCollectionIterator* iter = OSCollectionIterator::withCollection(userClients); - while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { - IOLog("MT1Sim: Sending report\n"); - client->enqueueData(inputReport, inputSize); - } - OSSafeReleaseNULL(iter); + IOLog("MT1Sim: Sending report\n"); + enqueueData(inputReport, (UInt32) inputSize); } if (!input_active) { memset(touchActive, false, sizeof(touchActive)); - - inputReport->FINGERS[0].Size = 0x0; - inputReport->FINGERS[0].Touch_Major = 0x0; - inputReport->FINGERS[0].Touch_Minor = 0x0; - - milliTimestamp += 10; - inputReport->Timestamp = milliTimestamp; - OSCollectionIterator* iter = OSCollectionIterator::withCollection(userClients); - while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { - client->enqueueData(inputReport, inputSize); - } - OSSafeReleaseNULL(iter); - - inputReport->FINGERS[0].Finger = kMT2FingerTypeUndefined; - inputReport->FINGERS[0].State = kTouchStateInactive; - iter = OSCollectionIterator::withCollection(userClients); - while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { - client->enqueueData(inputReport, inputSize); - } - OSSafeReleaseNULL(iter); + // Stop finger + inputReport->Counter++; + inputReport->Fingers[0].State = kTouchStateStop; + inputReport->Fingers[0].Size = 0x0; + inputReport->Fingers[0].ToolMajor = 0x0; + inputReport->Fingers[0].ToolMinor = 0x0; + + inputReport->Counter++; + inputReport->Timestamp += 10; + enqueueData(inputReport, inputSize); + + // Undefined/Zeroed out finger + inputReport->Counter++; + inputReport->Timestamp += 10; + inputReport->Fingers[0].Finger = kMT2FingerTypeUndefined; + inputReport->Fingers[0].State = kTouchStateInactive; + enqueueData(inputReport, inputSize); // Blank report - milliTimestamp += 10; - inputReport->Timestamp = milliTimestamp; - iter = OSCollectionIterator::withCollection(userClients); - while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { - client->enqueueData(inputReport, sizeof(MT1_INPUT_REPORT)); - } - OSSafeReleaseNULL(iter); + inputReport->NumFingers = 0; + inputReport->TotalFingerDataSize = 0; + inputReport->Counter++; + inputReport->Timestamp += 10; + enqueueData(inputReport, sizeof(WELLSPRING3_REPORT)); + } + + bzero(inputReport, inputSize); +} + +void VoodooInputMT1Simulator::enqueueData(WELLSPRING3_REPORT *report, size_t dataLen) { +#if DEBUG + IOLog("Sending report with button %d, finger count %hhu, at %dms\n", report->Button, report->NumFingers, report->Timestamp); + for (size_t i = 0; i < report->NumFingers; i++) { + WELLSPRING3_FINGER &f = report->Fingers[i]; + IOLog("[%zu] (%d, %d) (%d, %d)dx F%d St%d Maj%d Min%d Sz%d ID%d A%d\n", i, f.X, f.Y, f.XVelocity, f.YVelocity, f.Finger, f.State, f.ToolMajor, f.ToolMinor, f.Size, f.Id, f.Orientation); } +#endif - IOFree(inputReport, inputSize); + OSCollectionIterator *iter = OSCollectionIterator::withCollection(userClients); + while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { + client->enqueueData(report, dataLen); + } + OSSafeReleaseNULL(iter); } diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp index 0a41ec9..290c14f 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp @@ -10,6 +10,7 @@ #define AppleUSBMultitouchDriver_hpp #include +#include #include #include #include @@ -21,8 +22,10 @@ #include "../VoodooInputMultitouch/VoodooInputEvent.h" #include "../VoodooInputMultitouch/MultitouchHelpers.h" -#define MT1_MAX_X 6067 -#define MT1_MAX_Y 5021 +#define MT1_MAX_X 8920 +#define MT1_MAX_Y 6600 + +#define MT1_LITTLE_ENDIAN 1 /* State bits reference: linux/drivers/hid/hid-magicmouse.c#L58-L63 */ #define MT2_TOUCH_STATE_BIT_TRANSITION (0x1) @@ -54,37 +57,78 @@ | | | UInt3 | UInt4 | +---+---+-----------+---------------+ */ -struct __attribute__((__packed__)) MT1_INPUT_REPORT_FINGER { - SInt16 X: 13; - SInt16 Y: 13; - UInt8 Pressure: 6; - UInt8 Touch_Major; - UInt8 Touch_Minor; - UInt8 Size: 6; - UInt8 Identifier: 4; - UInt8 Orientation: 6; - UInt8 Finger: 4; - UInt8 State: 3; - UInt8 : 1; +//struct __attribute__((__packed__)) MT1_INPUT_REPORT_FINGER { +// SInt16 X: 13; +// SInt16 Y: 13; +// UInt8 Pressure: 6; +// UInt8 Touch_Major; +// UInt8 Touch_Minor; +// UInt8 Size: 6; +// UInt8 Identifier: 4; +// UInt8 Orientation: 6; +// UInt8 Finger: 4; +// UInt8 State: 3; +// UInt8 : 1; +//}; +// +//struct __attribute__((__packed__)) MT1_INPUT_REPORT { +// UInt8 ReportID; +// UInt8 Button: 1; +// UInt8 TouchActive: 1; +// UInt32 Timestamp: 22; +// +// MT1_INPUT_REPORT_FINGER FINGERS[]; // May support more fingers +// +// // UInt16 Checksum; +//}; +// +//static_assert(sizeof(MT1_INPUT_REPORT) == 4, "Unexpected MT1_INPUT_REPORT size"); +//static_assert(sizeof(MT1_INPUT_REPORT_FINGER) == 9, "Unexpected MT1_INPUT_REPORT_FINGER size"); + +struct __attribute__((__packed__)) WELLSPRING3_FINGER { + UInt8 Id; + UInt8 State; + UInt8 Finger; + UInt8 Unknown; // 0 -> 1 -> 0xFF + SInt16 X; + SInt16 Y; + // Velocity can be calculated in MultitouchSupport.plugin for us + // as long as "AlwaysNeedVelocityCalculated" is set. + SInt16 XVelocity; + SInt16 YVelocity; + UInt16 ToolMajor; + UInt16 ToolMinor; + UInt16 Orientation; + UInt16 Size; + // ContactDensity can be calculated in MultitouchSupport.plugin + /*UInt16 ContactDensity; + UInt16 Unused[2]; + UInt16 Pressure; // Not a thing on Wellspring3 */ }; -// Missing finger (Maybe they are in Byte 3?) +// There's no finger field + +static_assert(sizeof(WELLSPRING3_FINGER) == 20, "Unexpected WELLSPRING3_FINGER size"); -struct __attribute__((__packed__)) MT1_INPUT_REPORT { +struct __attribute__((__packed__)) WELLSPRING3_REPORT { UInt8 ReportID; - UInt8 Button: 1; - UInt8 TouchActive: 1; - UInt32 Timestamp: 22; + UInt8 Counter; // Unknown, always seems to count up though? + UInt8 HeaderSize; + UInt8 unkown1; // Always 3 + UInt32 Timestamp; + UInt8 unk2[4]; // 0x00, 0x17, 0x07, 0x97 + UInt16 TotalFingerDataSize; + UInt8 NumFingers; + UInt8 Button; + UInt32 unknown1; // 0x00000010 + UInt16 unknown2[4]; // Sometimes Changes + WELLSPRING3_FINGER Fingers[]; - MT1_INPUT_REPORT_FINGER FINGERS[]; // May support more fingers - - // UInt16 Checksum; + // End of packet always contains Checksum (though this is never checked in MultitouchSupport) + // UInt16 checksum; }; -static_assert(sizeof(MT1_INPUT_REPORT) == 4, "Unexpected MT1_INPUT_REPORT size"); -static_assert(sizeof(MT1_INPUT_REPORT_FINGER) == 9, "Unexpected MT1_INPUT_REPORT_FINGER size"); - -// Missing finger type +static_assert(sizeof(WELLSPRING3_REPORT) == 28, "Unexpected WELLSPRING3_REPORT size"); struct MT1DeviceReportStruct { uint8_t reportId; @@ -128,6 +172,7 @@ class EXPORT VoodooInputMT1Simulator : public IOHIDDevice { IOReturn getReport(MT1DeviceReportStruct *toFill); void constructReport(VoodooInputEvent& event); + void notificationEventDriverPublish(IOService * newService, IONotifier * notifier); private: OSSet *userClients {nullptr}; bool touchActive[15] {false}; @@ -135,6 +180,12 @@ class EXPORT VoodooInputMT1Simulator : public IOHIDDevice { IOCommandGate *cmdGate {nullptr}; VoodooInput *engine {nullptr}; AbsoluteTime startTimestamp {}; + WELLSPRING3_REPORT *inputReport{nullptr}; + UInt8 counter {0}; + + IONotifier *eventDriverPublish {nullptr}; + + void enqueueData(WELLSPRING3_REPORT *report, size_t dataLen); }; #endif /* AppleUSBMultitouchDriver_hpp */ diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp index 09b32de..6500762 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp @@ -133,10 +133,10 @@ IOReturn VoodooInputMT1UserClient::sGetReport(void *p1, void *p2, void *p3, void return ret; } -void VoodooInputMT1UserClient::enqueueData(void *data, UInt32 size) { +void VoodooInputMT1UserClient::enqueueData(void *data, size_t size) { if (dataQueue == nullptr) return; IOLog("%s Enqueue Data\n", getName()); - dataQueue->enqueue(data, size); + dataQueue->enqueue(data, (UInt32) size); } IOReturn VoodooInputMT1UserClient::sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp index c1762e3..8100459 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp +++ b/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp @@ -51,7 +51,7 @@ class EXPORT VoodooInputMT1UserClient : public IOUserClient { IOReturn sGetReport(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); IOReturn sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); - void enqueueData(void *data, UInt32 size); + void enqueueData(void *data, size_t size); private: VoodooInputMT1Simulator *simulator {nullptr}; From c48693984c047d43a673fb3af2713d86b02f5888 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Thu, 5 Jan 2023 21:25:59 -0800 Subject: [PATCH 05/32] It works! Rename to Wellspring simulator --- VoodooInput.xcodeproj/project.pbxproj | 38 +++--- VoodooInput/Info.plist | 2 +- VoodooInput/VoodooInput.cpp | 28 ++-- VoodooInput/VoodooInput.hpp | 6 +- .../VoodooInputActuatorDevice.cpp | 21 +-- .../VoodooInputWellspringSimulator.cpp} | 121 +++++++++--------- .../VoodooInputWellspringSimulator.hpp} | 12 +- .../VoodooInputWellspringUserClient.cpp} | 55 ++++---- .../VoodooInputWellspringUserClient.hpp} | 16 ++- 9 files changed, 156 insertions(+), 143 deletions(-) rename VoodooInput/{VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp => VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp} (80%) rename VoodooInput/{VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp => VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp} (94%) rename VoodooInput/{VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp => VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp} (54%) rename VoodooInput/{VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp => VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp} (82%) diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index 23b86f9..f78db47 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -17,10 +17,10 @@ 7BBAB21B22E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 7BBAB21522E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp */; }; CE8DA19D2518354A008C44E8 /* libkmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE8DA19C2518354A008C44E8 /* libkmod.a */; }; EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EEC13CEA2C1DFD270080F2D1 /* VoodooInputIDs.hpp */; }; - EE7EE27F296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE27D296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp */; }; - EE7EE280296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE27E296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp */; }; - EE7EE283296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE281296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp */; }; - EE7EE284296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE282296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp */; }; + EE7EE27F296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */; }; + EE7EE280296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */; }; + EE7EE283296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */; }; + EE7EE284296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -43,10 +43,10 @@ CEFB081D2397003600215B0B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; CEFB081E2397003600215B0B /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE.txt; sourceTree = SOURCE_ROOT; }; EEC13CEA2C1DFD270080F2D1 /* VoodooInputIDs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputIDs.hpp; sourceTree = ""; }; - EE7EE27D296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputMT1Simulator.cpp; sourceTree = ""; }; - EE7EE27E296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputMT1Simulator.hpp; sourceTree = ""; }; - EE7EE281296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputMT1UserClient.cpp; sourceTree = ""; }; - EE7EE282296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputMT1UserClient.hpp; sourceTree = ""; }; + EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputWellspringSimulator.cpp; sourceTree = ""; }; + EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputWellspringSimulator.hpp; sourceTree = ""; }; + EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputWellspringUserClient.cpp; sourceTree = ""; }; + EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputWellspringUserClient.hpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -92,7 +92,7 @@ 7BBAB1FB22E3A2F800B2941A /* VoodooInput */ = { isa = PBXGroup; children = ( - EE7EE27C296116B1005EFCC4 /* VoodooInputMT1Simulator */, + EE7EE27C296116B1005EFCC4 /* VoodooInputWellspringSimulator */, 358914F125798FA5007A0B58 /* Trackpoint */, CEC086442439FD3E00F5B701 /* VoodooInputMultitouch */, 7BBAB20F22E3AC7E00B2941A /* VoodooInputSimulator */, @@ -145,15 +145,15 @@ path = VoodooInput; sourceTree = ""; }; - EE7EE27C296116B1005EFCC4 /* VoodooInputMT1Simulator */ = { + EE7EE27C296116B1005EFCC4 /* VoodooInputWellspringSimulator */ = { isa = PBXGroup; children = ( - EE7EE27D296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp */, - EE7EE27E296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp */, - EE7EE281296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp */, - EE7EE282296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp */, + EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */, + EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */, + EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */, + EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */, ); - path = VoodooInputMT1Simulator; + path = VoodooInputWellspringSimulator; sourceTree = ""; }; /* End PBXGroup section */ @@ -166,8 +166,8 @@ 7BBAB21722E3AD0E00B2941A /* VoodooInputSimulatorDevice.hpp in Headers */, 358914F425798FA5007A0B58 /* TrackpointDevice.hpp in Headers */, 7BBAB21B22E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp in Headers */, - EE7EE280296116D7005EFCC4 /* VoodooInputMT1Simulator.hpp in Headers */, - EE7EE284296119AB005EFCC4 /* VoodooInputMT1UserClient.hpp in Headers */, + EE7EE280296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp in Headers */, + EE7EE284296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp in Headers */, 7BBAB1FD22E3A2F800B2941A /* VoodooInput.hpp in Headers */, EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */, ); @@ -274,8 +274,8 @@ 358914F525798FA5007A0B58 /* TrackpointDevice.cpp in Sources */, 7BBAB1FF22E3A2F800B2941A /* VoodooInput.cpp in Sources */, 7BBAB21922E3AD0E00B2941A /* VoodooInputActuatorDevice.cpp in Sources */, - EE7EE283296119AB005EFCC4 /* VoodooInputMT1UserClient.cpp in Sources */, - EE7EE27F296116D7005EFCC4 /* VoodooInputMT1Simulator.cpp in Sources */, + EE7EE283296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp in Sources */, + EE7EE27F296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp in Sources */, 7BBAB21822E3AD0E00B2941A /* VoodooInputSimulatorDevice.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index 624c301..a8ba452 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -27,7 +27,7 @@ MT1Props IOUserClientClass - VoodooInputMT1UserClient + VoodooInputWellspringUserClient parser-type 1000 parser-options diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index 7e854de..3fe4683 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -11,7 +11,7 @@ #include "VoodooInputMultitouch/VoodooInputMessages.h" #include "VoodooInputSimulator/VoodooInputActuatorDevice.hpp" #include "VoodooInputSimulator/VoodooInputSimulatorDevice.hpp" -#include "VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp" +#include "VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp" #include "Trackpoint/TrackpointDevice.hpp" #include "libkern/version.h" @@ -34,14 +34,14 @@ bool VoodooInput::start(IOService *provider) { // Allocate the simulator and actuator devices // simulator = OSTypeAlloc(VoodooInputSimulatorDevice); -// actuator = OSTypeAlloc(VoodooInputActuatorDevice); - simulator = OSTypeAlloc(VoodooInputMT1Simulator); + actuator = OSTypeAlloc(VoodooInputActuatorDevice); + simulator = OSTypeAlloc(VoodooInputWellspringSimulator); trackpoint = OSTypeAlloc(TrackpointDevice); - if (!simulator /*|| !actuator*/ || !trackpoint) { + if (!simulator || !actuator || !trackpoint) { IOLog("VoodooInput could not alloc simulator, actuator or trackpoint!\n"); OSSafeReleaseNULL(simulator); -// OSSafeReleaseNULL(actuator); + OSSafeReleaseNULL(actuator); OSSafeReleaseNULL(trackpoint); return false; } @@ -58,15 +58,15 @@ bool VoodooInput::start(IOService *provider) { } // Initialize actuator device -// if (!actuator->init(NULL) || !actuator->attach(this)) { -// IOLog("VoodooInput could not init or attach actuator!\n"); -// goto exit; -// } -// else if (!actuator->start(this)) { -// IOLog("VoodooInput could not start actuator!\n"); -// actuator->detach(this); -// goto exit; -// } + if (!actuator->init(NULL) || !actuator->attach(this)) { + IOLog("VoodooInput could not init or attach actuator!\n"); + goto exit; + } + else if (!actuator->start(this)) { + IOLog("VoodooInput could not start actuator!\n"); + actuator->detach(this); + goto exit; + } // Initialize trackpoint device if (!trackpoint->init(NULL) || !trackpoint->attach(this)) { diff --git a/VoodooInput/VoodooInput.hpp b/VoodooInput/VoodooInput.hpp index 8e594c5..df0bcfa 100644 --- a/VoodooInput/VoodooInput.hpp +++ b/VoodooInput/VoodooInput.hpp @@ -12,7 +12,7 @@ class VoodooInputSimulatorDevice; class VoodooInputActuatorDevice; -class VoodooInputMT1Simulator; +class VoodooInputWellspringSimulator; class TrackpointDevice; #ifndef EXPORT @@ -37,8 +37,8 @@ class EXPORT VoodooInput : public IOService { IOService* parentProvider; // VoodooInputSimulatorDevice* simulator; -// VoodooInputActuatorDevice* actuator; - VoodooInputMT1Simulator* simulator; + VoodooInputActuatorDevice* actuator; + VoodooInputWellspringSimulator* simulator; TrackpointDevice* trackpoint; UInt8 transformKey; diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp index 17db4a3..ccd94a2 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp @@ -11,7 +11,12 @@ #define super IOHIDDevice OSDefineMetaClassAndStructors(VoodooInputActuatorDevice, IOHIDDevice); -const unsigned char actuator_report_descriptor[] = {0x06, 0x00, 0xff, 0x09, 0x0d, 0xa1, 0x01, 0x06, 0x00, 0xff, 0x09, 0x0d, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x85, 0x3f, 0x96, 0x0f, 0x00, 0x81, 0x02, 0x09, 0x0d, 0x85, 0x53, 0x96, 0x3f, 0x00, 0x91, 0x02, 0xc0}; +//const unsigned char actuator_report_descriptor[] = {0x06, 0x00, 0xff, 0x09, 0x0d, 0xa1, 0x01, 0x06, 0x00, 0xff, 0x09, 0x0d, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x85, 0x3f, 0x96, 0x0f, 0x00, 0x81, 0x02, 0x09, 0x0d, 0x85, 0x53, 0x96, 0x3f, 0x00, 0x91, 0x02, 0xc0}; +const unsigned char actuator_report_descriptor[] = { + 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, 0x85, 0x02, 0x95, 0x03, + 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x02, + 0x81, 0x06, 0xc0, 0xc0 +}; IOReturn VoodooInputActuatorDevice::setReport(IOMemoryDescriptor* report, IOHIDReportType reportType, IOOptionBits options) { return kIOReturnSuccess; @@ -36,11 +41,11 @@ OSString* VoodooInputActuatorDevice::newManufacturerString() const { } OSNumber* VoodooInputActuatorDevice::newPrimaryUsageNumber() const { - return OSNumber::withNumber(0xd, 32); + return OSNumber::withNumber(0x2, 32); } OSNumber* VoodooInputActuatorDevice::newPrimaryUsagePageNumber() const { - return OSNumber::withNumber(0xff00, 32); + return OSNumber::withNumber(0x1, 32); } OSNumber* VoodooInputActuatorDevice::newProductIDNumber() const { @@ -48,15 +53,15 @@ OSNumber* VoodooInputActuatorDevice::newProductIDNumber() const { } OSString* VoodooInputActuatorDevice::newProductString() const { - return OSString::withCString("Magic Trackpad 2"); + return OSString::withCString("Wellspring Emulation Top Case Buttons"); } OSString* VoodooInputActuatorDevice::newSerialNumberString() const { - return OSString::withCString("VoodooI2C Magic Trackpad 2 Actuator"); + return OSString::withCString("None"); } OSString* VoodooInputActuatorDevice::newTransportString() const { - return OSString::withCString("I2C"); + return OSString::withCString("USB"); } OSNumber* VoodooInputActuatorDevice::newVendorIDNumber() const { @@ -64,9 +69,9 @@ OSNumber* VoodooInputActuatorDevice::newVendorIDNumber() const { } OSNumber* VoodooInputActuatorDevice::newLocationIDNumber() const { - return OSNumber::withNumber(0x14400000, 32); + return OSNumber::withNumber(0x1d183000, 32); } OSNumber* VoodooInputActuatorDevice::newVersionNumber() const { - return OSNumber::withNumber(0x804, 32); + return OSNumber::withNumber(0x219, 32); } diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp similarity index 80% rename from VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp rename to VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 1592b58..7616118 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -6,13 +6,31 @@ // Copyright © 2022 Kishor Prins. All rights reserved. // -#include "VoodooInputMT1Simulator.hpp" +#include "VoodooInputWellspringSimulator.hpp" #include #define super IOHIDDevice -OSDefineMetaClassAndStructors(VoodooInputMT1Simulator, IOHIDDevice); +OSDefineMetaClassAndStructors(VoodooInputWellspringSimulator, IOHIDDevice); -bool VoodooInputMT1Simulator::setProperty(const char *aKey, OSObject *anObject) { +// Reports come from a MacbookPro9,2 +#define SensorParamsLength 6 +static const UInt8 MTSensorParams[SensorParamsLength] = {0x00, 0x00, 0x03, 0x00, 0xD6, 0x01}; + +#define SensorDescLength 8 +static const UInt8 MTSensorDesc[SensorDescLength] = {0x01, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x14, 0x00}; + +#define SensorRowsLength 5 +static const UInt8 MTSensorRows[SensorRowsLength] = { + 0x01, // Is little Endian + 0x0C, // Rows + 0x14, // Columns + 0x01, 0x09 // BCD Version +}; + +#define FamilyID 0x62 +#define FamilyIDLength 1 + +bool VoodooInputWellspringSimulator::setProperty(const char *aKey, OSObject *anObject) { IOLog("MT1Sim: Attempting to set Property! %s\n", aKey); OSString *str = OSString::withCString(aKey); bool ret = false; @@ -23,11 +41,15 @@ bool VoodooInputMT1Simulator::setProperty(const char *aKey, OSObject *anObject) return ret; } -bool VoodooInputMT1Simulator::setProperty(const char *aKey, unsigned long long aValue, unsigned int aNumberOfBits) { +bool VoodooInputWellspringSimulator::setProperty(const char *aKey, void *bytes, unsigned int length) { + return super::setProperty(aKey, bytes, length); +} + +bool VoodooInputWellspringSimulator::setProperty(const char *aKey, unsigned long long aValue, unsigned int aNumberOfBits) { return super::setProperty(aKey, aValue, aNumberOfBits); } -bool VoodooInputMT1Simulator::setProperty(const char *aKey, const char *aString) { +bool VoodooInputWellspringSimulator::setProperty(const char *aKey, const char *aString) { IOLog("MT1Sim: Attempting to set String Property! %s\n", aKey); OSString *str = OSString::withCString(aKey); bool ret = false; @@ -38,7 +60,7 @@ bool VoodooInputMT1Simulator::setProperty(const char *aKey, const char *aString) return ret; } -bool VoodooInputMT1Simulator::setProperty(const OSSymbol *aKey, OSObject *anObject) { +bool VoodooInputWellspringSimulator::setProperty(const OSSymbol *aKey, OSObject *anObject) { IOLog("MT1Sim: Attempting to set OSSymbol Object Property! %s\n", aKey->getCStringNoCopy()); bool ret = false; if (!aKey->isEqualTo("IOUserClientClass")) { @@ -47,7 +69,8 @@ bool VoodooInputMT1Simulator::setProperty(const OSSymbol *aKey, OSObject *anObje return ret; } -bool VoodooInputMT1Simulator::setProperty(const OSString *aKey, OSObject *anObject) { +bool VoodooInputWellspringSimulator::setProperty(const OSString *aKey, OSObject *anObject) { + // Hidd tries to set a new user client, so we block setProperty writes to the user client key. IOLog("MT1Sim: Attempting to set OSString Object Property! %s\n", aKey->getCStringNoCopy()); bool ret = false; if (!aKey->isEqualTo("IOUserClientClass")) { @@ -56,9 +79,7 @@ bool VoodooInputMT1Simulator::setProperty(const OSString *aKey, OSObject *anObje return ret; } -bool VoodooInputMT1Simulator::init(OSDictionary *props) { - // Hidd tries to set a new user client, so we block setProperty writes to the user client key. - // This means that we need to set the user here in the props dictionary +bool VoodooInputWellspringSimulator::init(OSDictionary *props) { bool success = super::init(props); if (!success) { @@ -91,7 +112,7 @@ bool VoodooInputMT1Simulator::init(OSDictionary *props) { return true; } -bool VoodooInputMT1Simulator::start(IOService *provider) { +bool VoodooInputWellspringSimulator::start(IOService *provider) { if (!super::start(provider)) return false; engine = OSDynamicCast(VoodooInput, provider); @@ -101,6 +122,8 @@ bool VoodooInputMT1Simulator::start(IOService *provider) { setProperty("Sensor Surface Width", engine->getPhysicalMaxX(), 32); setProperty("Sensor Surface Height", engine->getPhysicalMaxY(), 32); + setProperty("Sensor Region Param", const_cast(MTSensorParams), SensorParamsLength); + setProperty("Sensor Region Descriptor", const_cast(MTSensorDesc), SensorDescLength); workloop = getWorkLoop(); if (workloop == nullptr) { @@ -142,20 +165,20 @@ bool VoodooInputMT1Simulator::start(IOService *provider) { return true; } -void VoodooInputMT1Simulator::notificationEventDriverPublish(IOService * newService, IONotifier * notifier) { - if (notifier == eventDriverPublish) { - IOHIDEventService *eventDriver = OSDynamicCast(IOHIDEventService, newService); - if (eventDriver == nullptr) return; +void VoodooInputWellspringSimulator::notificationEventDriverPublish(IOService * newService, IONotifier * notifier) { +// if (notifier == eventDriverPublish) { +// IOHIDEventService *eventDriver = OSDynamicCast(IOHIDEventService, newService); +// if (eventDriver == nullptr) return; - OSNumber *loc = OSDynamicCast(OSNumber, eventDriver->getProperty("LocationID")); - if (loc == nullptr) return; +// OSNumber *loc = OSDynamicCast(OSNumber, eventDriver->getProperty("LocationID")); +// if (loc == nullptr) return; - if (!loc->isEqualTo(newLocationIDNumber())) return; +// if (!loc->isEqualTo(newLocationIDNumber())) return; // eventDriver->setSystemProperties(); - } +// } } -void VoodooInputMT1Simulator::stop(IOService *provider) { +void VoodooInputWellspringSimulator::stop(IOService *provider) { if (eventDriverPublish != nullptr) { eventDriverPublish->remove(); } @@ -186,7 +209,7 @@ const unsigned char report_descriptor[] = { 0x81, 0x00, 0xC0 }; -IOReturn VoodooInputMT1Simulator::newReportDescriptor(IOMemoryDescriptor** descriptor) const { +IOReturn VoodooInputWellspringSimulator::newReportDescriptor(IOMemoryDescriptor** descriptor) const { IOBufferMemoryDescriptor* report_descriptor_buffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, sizeof(report_descriptor)); if (!report_descriptor_buffer) { @@ -200,71 +223,53 @@ IOReturn VoodooInputMT1Simulator::newReportDescriptor(IOMemoryDescriptor** descr return kIOReturnSuccess; } -OSNumber* VoodooInputMT1Simulator::newPrimaryUsageNumber() const { +OSNumber* VoodooInputWellspringSimulator::newPrimaryUsageNumber() const { return OSNumber::withNumber(kHIDUsage_GD_Mouse, 32); } -OSNumber* VoodooInputMT1Simulator::newPrimaryUsagePageNumber() const { +OSNumber* VoodooInputWellspringSimulator::newPrimaryUsagePageNumber() const { return OSNumber::withNumber(kHIDPage_GenericDesktop, 32); } -OSNumber* VoodooInputMT1Simulator::newProductIDNumber() const { +OSNumber* VoodooInputWellspringSimulator::newProductIDNumber() const { return OSNumber::withNumber(0x252, 32); } -OSString* VoodooInputMT1Simulator::newProductString() const { +OSString* VoodooInputWellspringSimulator::newProductString() const { return OSString::withCString("Wellspring3 Emulator"); } -OSString* VoodooInputMT1Simulator::newSerialNumberString() const { +OSString* VoodooInputWellspringSimulator::newSerialNumberString() const { return OSString::withCString("None"); } -OSString* VoodooInputMT1Simulator::newTransportString() const { +OSString* VoodooInputWellspringSimulator::newTransportString() const { return OSString::withCString("USB"); } -OSNumber* VoodooInputMT1Simulator::newVendorIDNumber() const { +OSNumber* VoodooInputWellspringSimulator::newVendorIDNumber() const { return OSNumber::withNumber(0x5ac, 16); } -OSNumber* VoodooInputMT1Simulator::newLocationIDNumber() const { +OSNumber* VoodooInputWellspringSimulator::newLocationIDNumber() const { return OSNumber::withNumber(0x1d183000, 32); } -OSNumber* VoodooInputMT1Simulator::newVersionNumber() const { +OSNumber* VoodooInputWellspringSimulator::newVersionNumber() const { return OSNumber::withNumber(0x219, 32); } -bool VoodooInputMT1Simulator::registerUserClient(IOService *client) { +bool VoodooInputWellspringSimulator::registerUserClient(IOService *client) { IOLog("MT1Sim: Adding user client\n"); return userClients->setObject(client); } -void VoodooInputMT1Simulator::unregisterUserClient(IOService *client) { +void VoodooInputWellspringSimulator::unregisterUserClient(IOService *client) { IOLog("MT1Sim: Removing user client\n"); userClients->removeObject(client); } -// Reports come from a MacbookPro9,2 -#define SensorParamsLength 6 -static const UInt8 MT1SensorParams[SensorParamsLength] = {0x00, 0x00, 0x03, 0x00, 0xD6, 0x01}; - -#define SensorDescLength 8 -static const UInt8 MT1SensorDesc[SensorDescLength] = {0x01, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x14, 0x00}; - -#define SensorRowsLength 5 -static const UInt8 MT1SensorRows[SensorRowsLength] = { - 0x01, // Is little Endian - 0x0C, // Rows - 0x14, // Columns - 0x01, 0x09 // BCD Version -}; - -#define FamilyID 0x62 -#define FamilyIDLength 1 - -IOReturn VoodooInputMT1Simulator::getReport(MT1DeviceReportStruct *toFill) { +IOReturn VoodooInputWellspringSimulator::getReport(MTDeviceReportStruct *toFill) { UInt32 width, height; switch (toFill->reportId) { @@ -273,11 +278,11 @@ IOReturn VoodooInputMT1Simulator::getReport(MT1DeviceReportStruct *toFill) { toFill->dataSize = 1; break; case MT1ReportSensorParam: - memcpy(toFill->data, MT1SensorParams, SensorParamsLength); + memcpy(toFill->data, MTSensorParams, SensorParamsLength); toFill->dataSize = SensorParamsLength; break; case MT1ReportSensorDescriptor: - memcpy(toFill->data, MT1SensorDesc, SensorDescLength); + memcpy(toFill->data, MTSensorDesc, SensorDescLength); toFill->dataSize = SensorDescLength; break; case MT1ReportSensorSize: @@ -297,7 +302,7 @@ IOReturn VoodooInputMT1Simulator::getReport(MT1DeviceReportStruct *toFill) { toFill->dataSize = sizeof(UInt32) * 2; break; case MT1ReportSensorRows: - memcpy(toFill->data, MT1SensorRows, SensorRowsLength); + memcpy(toFill->data, MTSensorRows, SensorRowsLength); toFill->dataSize = SensorRowsLength; break; case MT1ReportFamilyId: @@ -311,7 +316,7 @@ IOReturn VoodooInputMT1Simulator::getReport(MT1DeviceReportStruct *toFill) { return kIOReturnSuccess; } -void VoodooInputMT1Simulator::constructReport(VoodooInputEvent& event) { +void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { AbsoluteTime timestamp = event.timestamp; size_t inputSize = sizeof(WELLSPRING3_REPORT) + (sizeof(WELLSPRING3_FINGER) * event.contact_count); @@ -386,6 +391,8 @@ void VoodooInputMT1Simulator::constructReport(VoodooInputEvent& event) { scaled_y = MT1_MAX_Y - scaled_y; } } + + scaled_y = MT1_MAX_Y - scaled_y; fingerData.State = touchActive[touch_id] ? kTouchStateActive : kTouchStateStart; touchActive[touch_id] = transducer.isTransducerActive || transducer.isPhysicalButtonDown; @@ -457,7 +464,7 @@ void VoodooInputMT1Simulator::constructReport(VoodooInputEvent& event) { bzero(inputReport, inputSize); } -void VoodooInputMT1Simulator::enqueueData(WELLSPRING3_REPORT *report, size_t dataLen) { +void VoodooInputWellspringSimulator::enqueueData(WELLSPRING3_REPORT *report, size_t dataLen) { #if DEBUG IOLog("Sending report with button %d, finger count %hhu, at %dms\n", report->Button, report->NumFingers, report->Timestamp); for (size_t i = 0; i < report->NumFingers; i++) { @@ -467,7 +474,7 @@ void VoodooInputMT1Simulator::enqueueData(WELLSPRING3_REPORT *report, size_t dat #endif OSCollectionIterator *iter = OSCollectionIterator::withCollection(userClients); - while (VoodooInputMT1UserClient *client = OSDynamicCast(VoodooInputMT1UserClient, iter->getNextObject())) { + while (VoodooInputWellspringUserClient *client = OSDynamicCast(VoodooInputWellspringUserClient, iter->getNextObject())) { client->enqueueData(report, dataLen); } OSSafeReleaseNULL(iter); diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp similarity index 94% rename from VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp rename to VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index 290c14f..73c3ee7 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1Simulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -10,13 +10,12 @@ #define AppleUSBMultitouchDriver_hpp #include -#include #include #include #include #include -#include "./VoodooInputMT1UserClient.hpp" +#include "./VoodooInputWellspringUserClient.hpp" #include "../VoodooInput.hpp" #include "../VoodooInputMultitouch/VoodooInputTransducer.h" #include "../VoodooInputMultitouch/VoodooInputEvent.h" @@ -130,7 +129,7 @@ struct __attribute__((__packed__)) WELLSPRING3_REPORT { static_assert(sizeof(WELLSPRING3_REPORT) == 28, "Unexpected WELLSPRING3_REPORT size"); -struct MT1DeviceReportStruct { +struct MTDeviceReportStruct { uint8_t reportId; uint8_t data[512]; uint32_t dataSize; @@ -143,8 +142,8 @@ struct MT1DeviceReportStruct { #define MT1ReportSensorRows 0xD3 #define MT1ReportSensorSize 0xD9 -class EXPORT VoodooInputMT1Simulator : public IOHIDDevice { - OSDeclareDefaultStructors(VoodooInputMT1Simulator); +class EXPORT VoodooInputWellspringSimulator : public IOHIDDevice { + OSDeclareDefaultStructors(VoodooInputWellspringSimulator); public: virtual bool init(OSDictionary *) override; virtual bool start(IOService *provider) override; @@ -155,6 +154,7 @@ class EXPORT VoodooInputMT1Simulator : public IOHIDDevice { virtual bool setProperty(const char *aKey, const char *aString) override; virtual bool setProperty(const OSSymbol *aKey, OSObject *anObject) override; virtual bool setProperty(const OSString *aKey, OSObject *anObject) override; + virtual bool setProperty(const char *aKey, void *bytes, unsigned int length) override; virtual IOReturn newReportDescriptor(IOMemoryDescriptor** descriptor) const override; virtual OSNumber* newPrimaryUsageNumber() const override; @@ -170,7 +170,7 @@ class EXPORT VoodooInputMT1Simulator : public IOHIDDevice { bool registerUserClient(IOService *client); void unregisterUserClient(IOService *client); - IOReturn getReport(MT1DeviceReportStruct *toFill); + IOReturn getReport(MTDeviceReportStruct *toFill); void constructReport(VoodooInputEvent& event); void notificationEventDriverPublish(IOService * newService, IONotifier * notifier); private: diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp similarity index 54% rename from VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp rename to VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 6500762..063dca4 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -6,31 +6,32 @@ // Copyright © 2022 Kishor Prins. All rights reserved. // -#include "VoodooInputMT1UserClient.hpp" +#include "VoodooInputWellspringUserClient.hpp" +#include "VoodooInputWellspringSimulator.hpp" #define super IOUserClient -OSDefineMetaClassAndStructors(VoodooInputMT1UserClient, IOUserClient); +OSDefineMetaClassAndStructors(VoodooInputWellspringUserClient, IOUserClient); #if defined(__x86_64__) -// { Object, Func pointer, Padding, Flags, Inputs, Outputs } +// { Object, Func pointer, Flags, Inputs, Outputs } static const IOExternalMethod sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { // VoodooInputMT1UserClientMethodsSetSendsFrames - {0, static_cast(&VoodooInputMT1UserClient::sSetSendFrames), kIOUCScalarIScalarO, 1, 0}, + {0, reinterpret_cast(&VoodooInputWellspringUserClient::sSetSendFrames), kIOUCScalarIScalarO, 1, 0}, // VoodooInputMT1UserClientMethodsGetReport - {0, static_cast(&VoodooInputMT1UserClient::sGetReport), kIOUCStructIStructO, 0x208, 0x208}, + {0, reinterpret_cast(&VoodooInputWellspringUserClient::sGetReport), kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)}, // VoodooInputMT1UserClientMethodsSetReport - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCStructIStructO, 0x208, 0x208}, + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCStructIStructO, 0x208, 0x208}, // VoodooInputMT1UserClientMethodsSetSendLogs - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 1, 0}, + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 1, 0}, // VoodooInputMT1UserClientMethodsIssueDriverRequest - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCStructIStructO, 0x204, 0x204}, - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Relative Mouse Movement - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Scroll Wheel - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 2, 0}, // Keyboard - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 1, 0}, // Map Clicks + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCStructIStructO, 0x204, 0x204}, + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Relative Mouse Movement + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Scroll Wheel + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 2, 0}, // Keyboard + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 1, 0}, // Map Clicks // VoodooInputMT1UserClientMethodsRecacheProperties - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 0, 0}, - {0, static_cast(&VoodooInputMT1UserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Momentum Scroll + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 0, 0}, + {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Momentum Scroll }; #else // __defined(__x86_64__) @@ -38,10 +39,10 @@ static const IOExternalMethod sMethods[VoodooInputMT1UserClientMethodsNumMethods #error "Invalid architecture" #endif // __defined(__x86_64__) -bool VoodooInputMT1UserClient::start(IOService *provider) { +bool VoodooInputWellspringUserClient::start(IOService *provider) { IOLog("%s Start\n", getName()); if (!super::start(provider)) return false; - simulator = OSDynamicCast(VoodooInputMT1Simulator, provider); + simulator = OSDynamicCast(VoodooInputWellspringSimulator, provider); if (simulator == nullptr) { IOLog("%s Invalid provider!\n", getName()); @@ -65,19 +66,19 @@ bool VoodooInputMT1UserClient::start(IOService *provider) { return true; } -void VoodooInputMT1UserClient::stop(IOService *provider) { +void VoodooInputWellspringUserClient::stop(IOService *provider) { OSSafeReleaseNULL(dataQueue); OSSafeReleaseNULL(logQueue); } -IOReturn VoodooInputMT1UserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { +IOReturn VoodooInputWellspringUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { IOLog("%s client notif port\n", getName()); dataQueue->setNotificationPort(port); logQueue->setNotificationPort(port); return kIOReturnSuccess; } -IOReturn VoodooInputMT1UserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { +IOReturn VoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { IOLog("%s clientMem\n", getName()); if (type != 0x10) { dataQueueDesc->retain(); @@ -91,7 +92,7 @@ IOReturn VoodooInputMT1UserClient::clientMemoryForType(UInt32 type, IOOptionBits return kIOReturnSuccess; } -IOExternalMethod *VoodooInputMT1UserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { +IOExternalMethod *VoodooInputWellspringUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { IOLog("%s External Method %d\n", getName(), index); if (index >= VoodooInputMT1UserClientMethodsNumMethods) { return nullptr; @@ -101,11 +102,11 @@ IOExternalMethod *VoodooInputMT1UserClient::getTargetAndMethodForIndex(IOService return const_cast(&sMethods[index]); } -IOReturn VoodooInputMT1UserClient::sSetSendFrames(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { +IOReturn VoodooInputWellspringUserClient::sSetSendFrames(bool enableReports) { bool success = true; - IOLog("%s Get Report: %d\n", getName(), static_cast(p1)); + IOLog("%s Set Send Frames: %d\n", getName(), enableReports); - if (static_cast(p1)) { + if (enableReports) { success = simulator->registerUserClient(this); } else { simulator->unregisterUserClient(this); @@ -115,9 +116,7 @@ IOReturn VoodooInputMT1UserClient::sSetSendFrames(void *p1, void *p2, void *p3, } // I'm not really sure why they use two different structs here??? -IOReturn VoodooInputMT1UserClient::sGetReport(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { - MT1DeviceReportStruct *input = static_cast(p1); - MT1DeviceReportStruct *output = static_cast(p2); +IOReturn VoodooInputWellspringUserClient::sGetReport(MTDeviceReportStruct *input, MTDeviceReportStruct *output) { if (input == nullptr || output == nullptr) { return kIOReturnBadArgument; } @@ -133,12 +132,12 @@ IOReturn VoodooInputMT1UserClient::sGetReport(void *p1, void *p2, void *p3, void return ret; } -void VoodooInputMT1UserClient::enqueueData(void *data, size_t size) { +void VoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { if (dataQueue == nullptr) return; IOLog("%s Enqueue Data\n", getName()); dataQueue->enqueue(data, (UInt32) size); } -IOReturn VoodooInputMT1UserClient::sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { +IOReturn VoodooInputWellspringUserClient::sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { return kIOReturnSuccess; // noop } diff --git a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp similarity index 82% rename from VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp rename to VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp index 8100459..bd6031e 100644 --- a/VoodooInput/VoodooInputMT1Simulator/VoodooInputMT1UserClient.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp @@ -12,14 +12,13 @@ #include #include #include -#include "./VoodooInputMT1Simulator.hpp" #include "../VoodooInput.hpp" #include "../VoodooInputMultitouch/VoodooInputTransducer.h" #include "../VoodooInputMultitouch/VoodooInputEvent.h" #include "../VoodooInputMultitouch/MultitouchHelpers.h" -enum VoodooInputMT1UserClientMethods { +enum VoodooInputWellspringUserClientMethods { VoodooInputMT1UserClientMethodsSetSendsFrames, VoodooInputMT1UserClientMethodsGetReport, VoodooInputMT1UserClientMethodsSetReport, @@ -36,8 +35,11 @@ enum VoodooInputMT1UserClientMethods { static_assert(VoodooInputMT1UserClientMethodsNumMethods == 11, "Invalid number of Userclient methods"); -class EXPORT VoodooInputMT1UserClient : public IOUserClient { - OSDeclareDefaultStructors(VoodooInputMT1UserClient); +struct MTDeviceReportStruct; +class VoodooInputWellspringSimulator; + +class EXPORT VoodooInputWellspringUserClient : public IOUserClient { + OSDeclareDefaultStructors(VoodooInputWellspringUserClient); public: virtual bool start(IOService *provider) override; @@ -47,13 +49,13 @@ class EXPORT VoodooInputMT1UserClient : public IOUserClient { virtual IOReturn clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) override; virtual IOExternalMethod *getTargetAndMethodForIndex(IOService **targetP, UInt32 index) override; - IOReturn sSetSendFrames(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); - IOReturn sGetReport(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + IOReturn sSetSendFrames(bool enableFrames); + IOReturn sGetReport(MTDeviceReportStruct *input, MTDeviceReportStruct *output); IOReturn sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); void enqueueData(void *data, size_t size); private: - VoodooInputMT1Simulator *simulator {nullptr}; + VoodooInputWellspringSimulator *simulator {nullptr}; IOSharedDataQueue *dataQueue {nullptr}; IOSharedDataQueue *logQueue {nullptr}; From 2b6755f44b0600d0c369af2e289c3a3183e55cdc Mon Sep 17 00:00:00 2001 From: Avery Black Date: Fri, 6 Jan 2023 23:57:42 -0800 Subject: [PATCH 06/32] 10.12+ buttons work --- VoodooInput.xcodeproj/project.pbxproj | 2 + VoodooInput/Info.plist | 2 + VoodooInput/VoodooInput.cpp | 51 +++++++---- .../VoodooInputMessages.h | 1 + .../VoodooInputActuatorDevice.cpp | 23 +++++ .../VoodooInputActuatorDevice.hpp | 4 + .../VoodooInputWellspringSimulator.cpp | 88 +++++++++++++----- .../VoodooInputWellspringSimulator.hpp | 90 +++++++------------ .../VoodooInputWellspringUserClient.cpp | 1 - 9 files changed, 165 insertions(+), 97 deletions(-) diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index f78db47..1e998ab 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -414,6 +414,7 @@ "$(inherited)", "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", ); + MACOSX_DEPLOYMENT_TARGET = 10.7; MODULE_NAME = me.kishorprins.VoodooInput; MODULE_VERSION = 1.1.6; PRODUCT_BUNDLE_IDENTIFIER = me.kishorprins.VoodooInput; @@ -434,6 +435,7 @@ "$(inherited)", "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", ); + MACOSX_DEPLOYMENT_TARGET = 10.7; MODULE_NAME = me.kishorprins.VoodooInput; MODULE_VERSION = 1.1.6; PRODUCT_BUNDLE_IDENTIFIER = me.kishorprins.VoodooInput; diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index a8ba452..00d37bc 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -305,6 +305,8 @@ Copyright © 2019 Kishor Prins. All rights reserved. OSBundleLibraries + com.apple.driver.AppleUSBMultitouch + 1.0.0 com.apple.iokit.IOHIDFamily 2.0 com.apple.kpi.iokit diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index 3fe4683..57f646e 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -34,11 +34,11 @@ bool VoodooInput::start(IOService *provider) { // Allocate the simulator and actuator devices // simulator = OSTypeAlloc(VoodooInputSimulatorDevice); - actuator = OSTypeAlloc(VoodooInputActuatorDevice); +// actuator = OSTypeAlloc(VoodooInputActuatorDevice); simulator = OSTypeAlloc(VoodooInputWellspringSimulator); trackpoint = OSTypeAlloc(TrackpointDevice); - if (!simulator || !actuator || !trackpoint) { + if (!simulator /*|| !actuator*/ || !trackpoint) { IOLog("VoodooInput could not alloc simulator, actuator or trackpoint!\n"); OSSafeReleaseNULL(simulator); OSSafeReleaseNULL(actuator); @@ -46,6 +46,9 @@ bool VoodooInput::start(IOService *provider) { return false; } +// OSDictionary *dict = nullptr; +// OSNumber *bootProtocol = nullptr; + // Initialize simulator device if (!simulator->init(OSDynamicCast(OSDictionary, getProperty("MT1Props"))) || !simulator->attach(this)) { IOLog("VoodooInput could not attach simulator!\n"); @@ -57,16 +60,30 @@ bool VoodooInput::start(IOService *provider) { goto exit; } - // Initialize actuator device - if (!actuator->init(NULL) || !actuator->attach(this)) { - IOLog("VoodooInput could not init or attach actuator!\n"); - goto exit; - } - else if (!actuator->start(this)) { - IOLog("VoodooInput could not start actuator!\n"); - actuator->detach(this); - goto exit; - } +// dict = OSDictionary::withCapacity(1); +// bootProtocol = OSNumber::withNumber(2, 32); +// // Initialize actuator device +// dict->setObject("MTEventSource", kOSBooleanTrue); +// dict->setObject("BootProtocol", bootProtocol); +// dict->setObject("HIDDefaultBehavior", OSString::withCString("")); +// dict->setObject("HIDPointerAccelerationType", OSString::withCString("HIDTrackpadAcceleratoin")); +// dict->setObject("bConfigurationValue", OSNumber::withNumber(1, 32)); +// dict->setObject("bInterfaceNumber", OSNumber::withNumber(2, 32)); +// if (!actuator->init(dict) || !actuator->attach(this)) { +// IOLog("VoodooInput could not init or attach actuator!\n"); +// OSSafeReleaseNULL(bootProtocol); +// OSSafeReleaseNULL(dict); +// goto exit; +// } +// else if (!actuator->start(this)) { +// IOLog("VoodooInput could not start actuator!\n"); +// actuator->detach(this); +// OSSafeReleaseNULL(bootProtocol); +// OSSafeReleaseNULL(dict); +// goto exit; +// } +// OSSafeReleaseNULL(bootProtocol); +// OSSafeReleaseNULL(dict); // Initialize trackpoint device if (!trackpoint->init(NULL) || !trackpoint->attach(this)) { @@ -107,11 +124,11 @@ void VoodooInput::stop(IOService *provider) { OSSafeReleaseNULL(simulator); } -// if (actuator) { -// actuator->stop(this); -// actuator->detach(this); -// OSSafeReleaseNULL(actuator); -// } + if (actuator) { + actuator->stop(this); + actuator->detach(this); + OSSafeReleaseNULL(actuator); + } if (trackpoint) { trackpoint->stop(this); diff --git a/VoodooInput/VoodooInputMultitouch/VoodooInputMessages.h b/VoodooInput/VoodooInputMultitouch/VoodooInputMessages.h index c180cd6..918242c 100644 --- a/VoodooInput/VoodooInputMultitouch/VoodooInputMessages.h +++ b/VoodooInput/VoodooInputMultitouch/VoodooInputMessages.h @@ -24,6 +24,7 @@ #define kIOMessageVoodooTrackpointScrollWheel iokit_vendor_specific_msg(431) #define kIOMessageVoodooTrackpointMessage iokit_vendor_specific_msg(432) #define kIOMessageVoodooTrackpointUpdatePropertiesNotification iokit_vendor_specific_msg(433) +#define kIOMessageVoodooInputUpdateBtn 12348 #define kVoodooInputTransducerFingerType 1 #define kVoodooInputTransducerStylusType 2 diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp index ccd94a2..2b2d841 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp @@ -7,6 +7,7 @@ #include "VoodooInputActuatorDevice.hpp" #include "VoodooInputIDs.hpp" +#include "VoodooInputMessages.h" #define super IOHIDDevice OSDefineMetaClassAndStructors(VoodooInputActuatorDevice, IOHIDDevice); @@ -75,3 +76,25 @@ OSNumber* VoodooInputActuatorDevice::newLocationIDNumber() const { OSNumber* VoodooInputActuatorDevice::newVersionNumber() const { return OSNumber::withNumber(0x219, 32); } + +IOReturn VoodooInputActuatorDevice::message(UInt32 type, IOService *provider, void *arg) { + UInt8 btns = (UInt8)(size_t)arg; + IOLog("%s Message with type %d with %zu\n", getName(), type, (size_t) arg); + if (type == kIOMessageVoodooInputUpdateBtn) { + if (btns == buttonState) return kIOReturnSuccess; + IOBufferMemoryDescriptor *report = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, 4); + UInt8 *bytes = reinterpret_cast(report->getBytesNoCopy()); + bytes[0] = 0x02; // Report ID + bytes[1] = btns; + bytes[2] = 0x00; // dx + bytes[3] = 0x00; // dy + + buttonState = btns; + + handleReport(report); + OSSafeReleaseNULL(report); + return kIOReturnSuccess; + } + + return super::message(type, provider, arg); +} diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.hpp b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.hpp index 01a1f2c..0354e73 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.hpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.hpp @@ -45,6 +45,10 @@ class EXPORT VoodooInputActuatorDevice : public IOHIDDevice { OSString* newSerialNumberString() const override; OSNumber* newLocationIDNumber() const override; + + virtual IOReturn message(UInt32 type, IOService *provider, void *arg) override; +private: + UInt8 buttonState {0}; }; diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 7616118..78a14b9 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -7,7 +7,10 @@ // #include "VoodooInputWellspringSimulator.hpp" +#include "VoodooInputWellspringUserClient.hpp" +#include "VoodooInputActuatorDevice.hpp" #include +#include "VoodooInputMessages.h" #define super IOHIDDevice OSDefineMetaClassAndStructors(VoodooInputWellspringSimulator, IOHIDDevice); @@ -155,27 +158,29 @@ bool VoodooInputWellspringSimulator::start(IOService *provider) { clock_get_uptime(&startTimestamp); -// IOServiceMatchingNotificationHandler notificationHandler = OSMemberFunctionCast(IOServiceMatchingNotificationHandler, this, &VoodooInputMT1Simulator::notificationEventDriverPublish); -// OSDictionary *matching = serviceMatching("AppleUSBMultitouchEventDriver"); -// eventDriverPublish = addMatchingNotification(gIOFirstPublishNotification, matching, notificationHandler, this); -// OSSafeReleaseNULL(matching); + IOServiceMatchingNotificationHandler notificationHandler = OSMemberFunctionCast(IOServiceMatchingNotificationHandler, this, &VoodooInputWellspringSimulator::notificationEventDriver); + + OSDictionary *matching = serviceMatching("AppleUSBMultitouchHIDEventDriver"); + propertyMatching(OSSymbol::withCString("LocationID"), newLocationIDNumber(), matching); + eventDriverPublish = addMatchingNotification(gIOFirstPublishNotification, matching, notificationHandler, this); + eventDriverTerminate = addMatchingNotification(gIOTerminatedNotification, matching, notificationHandler, this); + OSSafeReleaseNULL(matching); registerService(); return true; } -void VoodooInputWellspringSimulator::notificationEventDriverPublish(IOService * newService, IONotifier * notifier) { -// if (notifier == eventDriverPublish) { -// IOHIDEventService *eventDriver = OSDynamicCast(IOHIDEventService, newService); -// if (eventDriver == nullptr) return; - -// OSNumber *loc = OSDynamicCast(OSNumber, eventDriver->getProperty("LocationID")); -// if (loc == nullptr) return; - -// if (!loc->isEqualTo(newLocationIDNumber())) return; -// eventDriver->setSystemProperties(); -// } +void VoodooInputWellspringSimulator::notificationEventDriver(IOService * newService, IONotifier * notifier) { + IOLog("%s Event Driver Published/Terminated\n", getName()); + if (notifier == eventDriverPublish && eventDriver == nullptr) { + eventDriver = OSDynamicCast(AppleUSBMultitouchHIDEventDriver, newService); + if (eventDriver != nullptr) eventDriver->retain(); + else IOLog("%s is null!?!?!?!\n", getName()); + } else if (notifier == eventDriverTerminate && eventDriver != nullptr) { + eventDriver->release(); + eventDriver = nullptr; + } } void VoodooInputWellspringSimulator::stop(IOService *provider) { @@ -183,12 +188,14 @@ void VoodooInputWellspringSimulator::stop(IOService *provider) { eventDriverPublish->remove(); } + if (eventDriverTerminate != nullptr) { + eventDriverTerminate->remove(); + } + if (workloop) { workloop->removeEventSource(cmdGate); } - OSSafeReleaseNULL(workloop); - OSSafeReleaseNULL(cmdGate); if (userClients != nullptr) { userClients->flushCollection(); OSSafeReleaseNULL(userClients); @@ -199,6 +206,10 @@ void VoodooInputWellspringSimulator::stop(IOService *provider) { IOFree(inputReport, inputSize); } + OSSafeReleaseNULL(eventDriverPublish); + OSSafeReleaseNULL(eventDriverTerminate); + OSSafeReleaseNULL(workloop); + OSSafeReleaseNULL(cmdGate); super::stop(provider); } @@ -316,15 +327,45 @@ IOReturn VoodooInputWellspringSimulator::getReport(MTDeviceReportStruct *toFill) return kIOReturnSuccess; } +void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { + MTRelativePointerReport report; + AbsoluteTime timestamp; + + clock_get_uptime(×tamp); + + if (btnState == lastButtonState) return; + lastButtonState = btnState; + + // macOS Sierra changed how button handling works + // There is now a hid report to send into the abyss of the MT stack + if (version_major >= 17) { + bzero(&report, sizeof(MTRelativePointerReport)); + + report.Buttons = btnState; + report.ReportID = 0x82; + report.Unknown1 = 1; + report.Timestamp = timestamp; + OSCollectionIterator *iter = OSCollectionIterator::withCollection(userClients); + while (VoodooInputWellspringUserClient *client = OSDynamicCast(VoodooInputWellspringUserClient, iter->getNextObject())) { + client->enqueueData(&report, sizeof(MTRelativePointerReport)); + } + OSSafeReleaseNULL(iter); + } else if (eventDriver != nullptr) { + // TODO: There is some weird logic to do with the "mapClick" property. + // I'm not even sure this is ever set though, so this is a don't care for now! + + eventDriver->dispatchRelativePointerEvent(timestamp, 0, 0, btnState, 0); + } +} + void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { AbsoluteTime timestamp = event.timestamp; size_t inputSize = sizeof(WELLSPRING3_REPORT) + (sizeof(WELLSPRING3_FINGER) * event.contact_count); - IOLog("MT1Sim: Constructing report\n"); if (inputReport == nullptr) return; inputReport->ReportID = 0x74; - inputReport->Counter = counter++; + inputReport->Counter++; inputReport->unkown1 = 0x03; inputReport->HeaderSize = sizeof(WELLSPRING3_REPORT); inputReport->unk2[0] = 0x00; // Magic @@ -335,6 +376,8 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { inputReport->NumFingers = event.contact_count; inputReport->Button = event.transducers[0].isPhysicalButtonDown || event.transducers[0].currentCoordinates.pressure > 100; inputReport->unknown1 = 0x00000010; + + constructButtonReport(inputReport->Button); // rotation check UInt8 transform = engine->getTransformKey(); @@ -434,6 +477,7 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { if (!input_active) { memset(touchActive, false, sizeof(touchActive)); + constructButtonReport(0); // Stop finger inputReport->Counter++; @@ -461,15 +505,15 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { enqueueData(inputReport, sizeof(WELLSPRING3_REPORT)); } - bzero(inputReport, inputSize); + bzero(inputReport->Fingers, inputReport->TotalFingerDataSize); } void VoodooInputWellspringSimulator::enqueueData(WELLSPRING3_REPORT *report, size_t dataLen) { #if DEBUG - IOLog("Sending report with button %d, finger count %hhu, at %dms\n", report->Button, report->NumFingers, report->Timestamp); + IOLog("%s Sending report with button %d, finger count %hhu, at %dms\n", getName(), report->Button, report->NumFingers, report->Timestamp); for (size_t i = 0; i < report->NumFingers; i++) { WELLSPRING3_FINGER &f = report->Fingers[i]; - IOLog("[%zu] (%d, %d) (%d, %d)dx F%d St%d Maj%d Min%d Sz%d ID%d A%d\n", i, f.X, f.Y, f.XVelocity, f.YVelocity, f.Finger, f.State, f.ToolMajor, f.ToolMinor, f.Size, f.Id, f.Orientation); + IOLog("%s [%zu] (%d, %d) (%d, %d)dx F%d St%d Maj%d Min%d Sz%d ID%d A%d\n", getName(), i, f.X, f.Y, f.XVelocity, f.YVelocity, f.Finger, f.State, f.ToolMajor, f.ToolMinor, f.Size, f.Id, f.Orientation); } #endif diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index 73c3ee7..614305c 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -10,12 +10,12 @@ #define AppleUSBMultitouchDriver_hpp #include +#include #include #include #include #include -#include "./VoodooInputWellspringUserClient.hpp" #include "../VoodooInput.hpp" #include "../VoodooInputMultitouch/VoodooInputTransducer.h" #include "../VoodooInputMultitouch/VoodooInputEvent.h" @@ -31,58 +31,27 @@ #define MT2_TOUCH_STATE_BIT_NEAR (0x1 << 1) #define MT2_TOUCH_STATE_BIT_CONTACT (0x1 << 2) -/* Finger Packet -+---+---+---+---+---+---+---+---+---+ -| | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | -+---+---+---+---+---+---+---+---+---+ -| 0 | x: SInt13 | -+---+-----------+ + -| 1 | | | -+---+ +-------------------+ -| 2 | y: SInt13 | -+---+-----------------------+ + -| 3 | ?? | | -| | ?! | | -+---+-----------------------+-------+ -| 4 | touchMajor: UInt8 | -+---+-------------------------------+ -| 5 | touchMinor: UInt8 | -+---+-------+-----------------------+ -| 6 | id | size: UInt6 | -+---+-------+---------------+-------+ -| 7 | orientation: UInt6 | id: 4 | -+---+---+-----------+-------+-------+ -| 8 | ? | state | finger | -| | | UInt3 | UInt4 | -+---+---+-----------+---------------+ -*/ -//struct __attribute__((__packed__)) MT1_INPUT_REPORT_FINGER { -// SInt16 X: 13; -// SInt16 Y: 13; -// UInt8 Pressure: 6; -// UInt8 Touch_Major; -// UInt8 Touch_Minor; -// UInt8 Size: 6; -// UInt8 Identifier: 4; -// UInt8 Orientation: 6; -// UInt8 Finger: 4; -// UInt8 State: 3; -// UInt8 : 1; -//}; -// -//struct __attribute__((__packed__)) MT1_INPUT_REPORT { -// UInt8 ReportID; -// UInt8 Button: 1; -// UInt8 TouchActive: 1; -// UInt32 Timestamp: 22; -// -// MT1_INPUT_REPORT_FINGER FINGERS[]; // May support more fingers -// -// // UInt16 Checksum; -//}; -// -//static_assert(sizeof(MT1_INPUT_REPORT) == 4, "Unexpected MT1_INPUT_REPORT size"); -//static_assert(sizeof(MT1_INPUT_REPORT_FINGER) == 9, "Unexpected MT1_INPUT_REPORT_FINGER size"); +class VoodooInputWellspringSimulator; +class VoodooInputWellspringUserClient; +class VoodooInputActuatorDevice; + +class AppleUSBMultitouchHIDEventDriver : public IOHIDEventService { + OSDeclareDefaultStructorsWithDispatch(AppleUSBMultitouchHIDEventDriver); + friend class VoodooInputWellspringSimulator; +public: + virtual IOReturn setSystemProperties(OSDictionary *) override; +}; + +// This report does not come from the hardware, but instead comes from within AppleUSBMultitouch in 10.12+ +// This gets sent to userspace on any button presses +struct __attribute__((__packed__)) MTRelativePointerReport { + UInt8 ReportID; + UInt8 Unknown1; // Always set to one + UInt16 Unknown2; + UInt32 Buttons; + UInt32 Unknown3[4]; // A dx/dy probably exists in here + AbsoluteTime Timestamp; +}; struct __attribute__((__packed__)) WELLSPRING3_FINGER { UInt8 Id; @@ -172,20 +141,27 @@ class EXPORT VoodooInputWellspringSimulator : public IOHIDDevice { IOReturn getReport(MTDeviceReportStruct *toFill); void constructReport(VoodooInputEvent& event); - void notificationEventDriverPublish(IOService * newService, IONotifier * notifier); + void notificationEventDriver(IOService * newService, IONotifier * notifier); private: - OSSet *userClients {nullptr}; bool touchActive[15] {false}; + IOWorkLoop *workloop {nullptr}; IOCommandGate *cmdGate {nullptr}; + + OSSet *userClients {nullptr}; VoodooInput *engine {nullptr}; + AppleUSBMultitouchHIDEventDriver *eventDriver {nullptr}; + AbsoluteTime startTimestamp {}; - WELLSPRING3_REPORT *inputReport{nullptr}; - UInt8 counter {0}; + WELLSPRING3_REPORT *inputReport {nullptr}; IONotifier *eventDriverPublish {nullptr}; + IONotifier *eventDriverTerminate {nullptr}; + + UInt8 lastButtonState {0}; void enqueueData(WELLSPRING3_REPORT *report, size_t dataLen); + void constructButtonReport(UInt8 btnState); }; #endif /* AppleUSBMultitouchDriver_hpp */ diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 063dca4..58b4928 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -134,7 +134,6 @@ IOReturn VoodooInputWellspringUserClient::sGetReport(MTDeviceReportStruct *input void VoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { if (dataQueue == nullptr) return; - IOLog("%s Enqueue Data\n", getName()); dataQueue->enqueue(data, (UInt32) size); } From 533faa07c78dea6bc8ac3b6f1fdc6ce76a5216c5 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 00:01:00 -0800 Subject: [PATCH 07/32] Remove actuator device --- VoodooInput/VoodooInput.cpp | 40 +------------------------------------ VoodooInput/VoodooInput.hpp | 2 -- 2 files changed, 1 insertion(+), 41 deletions(-) diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index 57f646e..8a2cdf1 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -32,23 +32,16 @@ bool VoodooInput::start(IOService *provider) { return false; } - // Allocate the simulator and actuator devices -// simulator = OSTypeAlloc(VoodooInputSimulatorDevice); -// actuator = OSTypeAlloc(VoodooInputActuatorDevice); simulator = OSTypeAlloc(VoodooInputWellspringSimulator); trackpoint = OSTypeAlloc(TrackpointDevice); - if (!simulator /*|| !actuator*/ || !trackpoint) { + if (!simulator || !trackpoint) { IOLog("VoodooInput could not alloc simulator, actuator or trackpoint!\n"); OSSafeReleaseNULL(simulator); - OSSafeReleaseNULL(actuator); OSSafeReleaseNULL(trackpoint); return false; } -// OSDictionary *dict = nullptr; -// OSNumber *bootProtocol = nullptr; - // Initialize simulator device if (!simulator->init(OSDynamicCast(OSDictionary, getProperty("MT1Props"))) || !simulator->attach(this)) { IOLog("VoodooInput could not attach simulator!\n"); @@ -60,31 +53,6 @@ bool VoodooInput::start(IOService *provider) { goto exit; } -// dict = OSDictionary::withCapacity(1); -// bootProtocol = OSNumber::withNumber(2, 32); -// // Initialize actuator device -// dict->setObject("MTEventSource", kOSBooleanTrue); -// dict->setObject("BootProtocol", bootProtocol); -// dict->setObject("HIDDefaultBehavior", OSString::withCString("")); -// dict->setObject("HIDPointerAccelerationType", OSString::withCString("HIDTrackpadAcceleratoin")); -// dict->setObject("bConfigurationValue", OSNumber::withNumber(1, 32)); -// dict->setObject("bInterfaceNumber", OSNumber::withNumber(2, 32)); -// if (!actuator->init(dict) || !actuator->attach(this)) { -// IOLog("VoodooInput could not init or attach actuator!\n"); -// OSSafeReleaseNULL(bootProtocol); -// OSSafeReleaseNULL(dict); -// goto exit; -// } -// else if (!actuator->start(this)) { -// IOLog("VoodooInput could not start actuator!\n"); -// actuator->detach(this); -// OSSafeReleaseNULL(bootProtocol); -// OSSafeReleaseNULL(dict); -// goto exit; -// } -// OSSafeReleaseNULL(bootProtocol); -// OSSafeReleaseNULL(dict); - // Initialize trackpoint device if (!trackpoint->init(NULL) || !trackpoint->attach(this)) { IOLog("VoodooInput could not init or attach trackpoint!\n"); @@ -124,12 +92,6 @@ void VoodooInput::stop(IOService *provider) { OSSafeReleaseNULL(simulator); } - if (actuator) { - actuator->stop(this); - actuator->detach(this); - OSSafeReleaseNULL(actuator); - } - if (trackpoint) { trackpoint->stop(this); trackpoint->detach(this); diff --git a/VoodooInput/VoodooInput.hpp b/VoodooInput/VoodooInput.hpp index df0bcfa..97e43ab 100644 --- a/VoodooInput/VoodooInput.hpp +++ b/VoodooInput/VoodooInput.hpp @@ -36,8 +36,6 @@ class EXPORT VoodooInput : public IOService { IOService* parentProvider; -// VoodooInputSimulatorDevice* simulator; - VoodooInputActuatorDevice* actuator; VoodooInputWellspringSimulator* simulator; TrackpointDevice* trackpoint; From 58acffbae0e2dbb869568e28321625d377834c0a Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 00:38:16 -0800 Subject: [PATCH 08/32] Clean up --- .../VoodooInputMessages.h | 1 - .../VoodooInputActuatorDevice.cpp | 46 +++++-------------- .../VoodooInputActuatorDevice.hpp | 4 -- .../VoodooInputWellspringSimulator.cpp | 2 +- 4 files changed, 12 insertions(+), 41 deletions(-) diff --git a/VoodooInput/VoodooInputMultitouch/VoodooInputMessages.h b/VoodooInput/VoodooInputMultitouch/VoodooInputMessages.h index 918242c..c180cd6 100644 --- a/VoodooInput/VoodooInputMultitouch/VoodooInputMessages.h +++ b/VoodooInput/VoodooInputMultitouch/VoodooInputMessages.h @@ -24,7 +24,6 @@ #define kIOMessageVoodooTrackpointScrollWheel iokit_vendor_specific_msg(431) #define kIOMessageVoodooTrackpointMessage iokit_vendor_specific_msg(432) #define kIOMessageVoodooTrackpointUpdatePropertiesNotification iokit_vendor_specific_msg(433) -#define kIOMessageVoodooInputUpdateBtn 12348 #define kVoodooInputTransducerFingerType 1 #define kVoodooInputTransducerStylusType 2 diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp index 2b2d841..ff3fb8c 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp @@ -6,18 +6,16 @@ // #include "VoodooInputActuatorDevice.hpp" +<<<<<<< HEAD #include "VoodooInputIDs.hpp" #include "VoodooInputMessages.h" +======= +>>>>>>> 28aae45 (Clean up) #define super IOHIDDevice OSDefineMetaClassAndStructors(VoodooInputActuatorDevice, IOHIDDevice); -//const unsigned char actuator_report_descriptor[] = {0x06, 0x00, 0xff, 0x09, 0x0d, 0xa1, 0x01, 0x06, 0x00, 0xff, 0x09, 0x0d, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x85, 0x3f, 0x96, 0x0f, 0x00, 0x81, 0x02, 0x09, 0x0d, 0x85, 0x53, 0x96, 0x3f, 0x00, 0x91, 0x02, 0xc0}; -const unsigned char actuator_report_descriptor[] = { - 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, 0x15, 0x00, 0x25, 0x01, 0x85, 0x02, 0x95, 0x03, - 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95, 0x02, - 0x81, 0x06, 0xc0, 0xc0 -}; +const unsigned char actuator_report_descriptor[] = {0x06, 0x00, 0xff, 0x09, 0x0d, 0xa1, 0x01, 0x06, 0x00, 0xff, 0x09, 0x0d, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x85, 0x3f, 0x96, 0x0f, 0x00, 0x81, 0x02, 0x09, 0x0d, 0x85, 0x53, 0x96, 0x3f, 0x00, 0x91, 0x02, 0xc0}; IOReturn VoodooInputActuatorDevice::setReport(IOMemoryDescriptor* report, IOHIDReportType reportType, IOOptionBits options) { return kIOReturnSuccess; @@ -42,11 +40,11 @@ OSString* VoodooInputActuatorDevice::newManufacturerString() const { } OSNumber* VoodooInputActuatorDevice::newPrimaryUsageNumber() const { - return OSNumber::withNumber(0x2, 32); + return OSNumber::withNumber(0xd, 32); } OSNumber* VoodooInputActuatorDevice::newPrimaryUsagePageNumber() const { - return OSNumber::withNumber(0x1, 32); + return OSNumber::withNumber(0xff00, 32); } OSNumber* VoodooInputActuatorDevice::newProductIDNumber() const { @@ -54,15 +52,15 @@ OSNumber* VoodooInputActuatorDevice::newProductIDNumber() const { } OSString* VoodooInputActuatorDevice::newProductString() const { - return OSString::withCString("Wellspring Emulation Top Case Buttons"); + return OSString::withCString("Magic Trackpad 2"); } OSString* VoodooInputActuatorDevice::newSerialNumberString() const { - return OSString::withCString("None"); + return OSString::withCString("VoodooI2C Magic Trackpad 2 Actuator"); } OSString* VoodooInputActuatorDevice::newTransportString() const { - return OSString::withCString("USB"); + return OSString::withCString("I2C"); } OSNumber* VoodooInputActuatorDevice::newVendorIDNumber() const { @@ -70,31 +68,9 @@ OSNumber* VoodooInputActuatorDevice::newVendorIDNumber() const { } OSNumber* VoodooInputActuatorDevice::newLocationIDNumber() const { - return OSNumber::withNumber(0x1d183000, 32); + return OSNumber::withNumber(0x14400000, 32); } OSNumber* VoodooInputActuatorDevice::newVersionNumber() const { - return OSNumber::withNumber(0x219, 32); -} - -IOReturn VoodooInputActuatorDevice::message(UInt32 type, IOService *provider, void *arg) { - UInt8 btns = (UInt8)(size_t)arg; - IOLog("%s Message with type %d with %zu\n", getName(), type, (size_t) arg); - if (type == kIOMessageVoodooInputUpdateBtn) { - if (btns == buttonState) return kIOReturnSuccess; - IOBufferMemoryDescriptor *report = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, 4); - UInt8 *bytes = reinterpret_cast(report->getBytesNoCopy()); - bytes[0] = 0x02; // Report ID - bytes[1] = btns; - bytes[2] = 0x00; // dx - bytes[3] = 0x00; // dy - - buttonState = btns; - - handleReport(report); - OSSafeReleaseNULL(report); - return kIOReturnSuccess; - } - - return super::message(type, provider, arg); + return OSNumber::withNumber(0x804, 32); } diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.hpp b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.hpp index 0354e73..01a1f2c 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.hpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.hpp @@ -45,10 +45,6 @@ class EXPORT VoodooInputActuatorDevice : public IOHIDDevice { OSString* newSerialNumberString() const override; OSNumber* newLocationIDNumber() const override; - - virtual IOReturn message(UInt32 type, IOService *provider, void *arg) override; -private: - UInt8 buttonState {0}; }; diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 78a14b9..e648714 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -337,7 +337,7 @@ void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { lastButtonState = btnState; // macOS Sierra changed how button handling works - // There is now a hid report to send into the abyss of the MT stack + // There is now a hid report to send into the abyss of the MT stack directly if (version_major >= 17) { bzero(&report, sizeof(MTRelativePointerReport)); From 66f878847da75d772d5eecd461d2691bc8f0ec93 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 10:39:40 -0800 Subject: [PATCH 09/32] Target MB5,1 --- .../VoodooInputWellspringSimulator.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index e648714..ab7c3d7 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -243,7 +243,7 @@ OSNumber* VoodooInputWellspringSimulator::newPrimaryUsagePageNumber() const { } OSNumber* VoodooInputWellspringSimulator::newProductIDNumber() const { - return OSNumber::withNumber(0x252, 32); + return OSNumber::withNumber(0x237, 32); } OSString* VoodooInputWellspringSimulator::newProductString() const { @@ -267,7 +267,7 @@ OSNumber* VoodooInputWellspringSimulator::newLocationIDNumber() const { } OSNumber* VoodooInputWellspringSimulator::newVersionNumber() const { - return OSNumber::withNumber(0x219, 32); + return OSNumber::withNumber(0x77, 32); } bool VoodooInputWellspringSimulator::registerUserClient(IOService *client) { @@ -471,7 +471,6 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { // inputReport->TouchActive = input_active; if (!is_error_input_active) { - IOLog("MT1Sim: Sending report\n"); enqueueData(inputReport, (UInt32) inputSize); } From c992ee1ab4a83ea8906b9b0ddf0f405c6bd8e109 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 11:36:44 -0800 Subject: [PATCH 10/32] Start trying to add 32bit support This doesn't actually build a 32bit binary yet --- VoodooInput.xcodeproj/project.pbxproj | 33 +++++++-- .../VoodooInputWellspringUserClient.cpp | 69 ++++++++++++------- .../VoodooInputWellspringUserClient.hpp | 8 ++- 3 files changed, 77 insertions(+), 33 deletions(-) diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index 1e998ab..04a1d15 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -288,6 +288,8 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = x86_64; + CC = "$(inherited)"; + "CC[arch=ACID32]" = "$(PROJECT_DIR)/clang32/clang-12"; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -317,7 +319,10 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; + "COMPILER_INDEX_STORE_ENABLE[arch=ACID32]" = NO; COPY_PHASE_STRIP = NO; + CXX = "$(inherited)"; + "CXX[arch=ACID32]" = "$(PROJECT_DIR)/clang32/clang-12"; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -337,11 +342,14 @@ GCC_WARN_UNUSED_VARIABLE = YES; KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; KERNEL_FRAMEWORK_HEADERS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; + LDPLUSPLUS = "$(inherited)"; + "LDPLUSPLUS[arch=ACID32]" = "$(PROJECT_DIR)/clang32/clang-12"; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; + ONLY_ACTIVE_ARCH = NO; SDKROOT = macosx; + VALID_ARCHS = x86_64; }; name = Debug; }; @@ -350,6 +358,8 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = x86_64; + CC = "$(inherited)"; + "CC[arch=ACID32]" = "$(PROJECT_DIR)/clang32/clang-12"; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -379,7 +389,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; + COMPILER_INDEX_STORE_ENABLE = YES; + "COMPILER_INDEX_STORE_ENABLE[arch=ACID32]" = NO; COPY_PHASE_STRIP = NO; + CXX = "$(inherited)"; + "CXX[arch=ACID32]" = "$(PROJECT_DIR)/clang32/clang-12"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -393,10 +407,13 @@ GCC_WARN_UNUSED_VARIABLE = YES; KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; KERNEL_FRAMEWORK_HEADERS = "$(PROJECT_DIR)/MacKernelSDK/Headers"; + LDPLUSPLUS = "$(inherited)"; + "LDPLUSPLUS[arch=ACID32]" = "$(PROJECT_DIR)/clang32/clang-12"; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; + VALID_ARCHS = x86_64; }; name = Release; }; @@ -412,14 +429,17 @@ INFOPLIST_FILE = VoodooInput/Info.plist; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", + "$(PROJECT_DIR)/MacKernelSDK/Library/universal", ); - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.6; + "MACOSX_DEPLOYMENT_TARGET[arch=ACID32]" = 10.5; MODULE_NAME = me.kishorprins.VoodooInput; MODULE_VERSION = 1.1.6; + OTHER_CFLAGS = "-Wno-stdlibcxx-not-found"; PRODUCT_BUNDLE_IDENTIFIER = me.kishorprins.VoodooInput; PRODUCT_NAME = "$(TARGET_NAME)"; RUN_CLANG_STATIC_ANALYZER = YES; + VALID_ARCHS = "x86_64 ACID32"; WRAPPER_EXTENSION = kext; }; name = Debug; @@ -433,13 +453,16 @@ INFOPLIST_FILE = VoodooInput/Info.plist; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/MacKernelSDK/Library/x86_64", + "$(PROJECT_DIR)/MacKernelSDK/Library/universal", ); - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.6; + "MACOSX_DEPLOYMENT_TARGET[arch=ACID32]" = 10.5; MODULE_NAME = me.kishorprins.VoodooInput; MODULE_VERSION = 1.1.6; + OTHER_CFLAGS = "-Wno-stdlibcxx-not-found"; PRODUCT_BUNDLE_IDENTIFIER = me.kishorprins.VoodooInput; PRODUCT_NAME = "$(TARGET_NAME)"; + VALID_ARCHS = "x86_64 ACID32"; WRAPPER_EXTENSION = kext; }; name = Release; diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 58b4928..8975637 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -13,29 +13,48 @@ OSDefineMetaClassAndStructors(VoodooInputWellspringUserClient, IOUserClient); #if defined(__x86_64__) -// { Object, Func pointer, Flags, Inputs, Outputs } -static const IOExternalMethod sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { +// { Object, Func pointer, Padding, Flags, Inputs, Outputs } +IOExternalMethodACID VoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { // VoodooInputMT1UserClientMethodsSetSendsFrames - {0, reinterpret_cast(&VoodooInputWellspringUserClient::sSetSendFrames), kIOUCScalarIScalarO, 1, 0}, + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sSetSendFrames, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 1, 0}, // VoodooInputMT1UserClientMethodsGetReport - {0, reinterpret_cast(&VoodooInputWellspringUserClient::sGetReport), kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)}, + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sGetReport, kIOExternalMethodACIDPadding, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)}, // VoodooInputMT1UserClientMethodsSetReport - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCStructIStructO, 0x208, 0x208}, + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCStructIStructO, 0x208, 0x208}, // VoodooInputMT1UserClientMethodsSetSendLogs - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 1, 0}, + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 1, 0}, // VoodooInputMT1UserClientMethodsIssueDriverRequest - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCStructIStructO, 0x204, 0x204}, - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Relative Mouse Movement - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Scroll Wheel - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 2, 0}, // Keyboard - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 1, 0}, // Map Clicks + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCStructIStructO, 0x204, 0x204}, + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 3, 0}, // Relative Mouse Movement + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 3, 0}, // Scroll Wheel + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 2, 0}, // Keyboard + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 1, 0}, // Map Clicks // VoodooInputMT1UserClientMethodsRecacheProperties - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 0, 0}, - {0, static_cast(&VoodooInputWellspringUserClient::sNoop), kIOUCScalarIScalarO, 3, 0}, // Momentum Scroll + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 0, 0}, + {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 3, 0}, // Momentum Scroll }; - -#else // __defined(__x86_64__) -// TODO: Switch where padding is in struct +#elif defined(__i386__) +// { Object, Padding, Func pointer, Flags, Inputs, Outputs } +IOExternalMethodACID VoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { + // VoodooInputMT1UserClientMethodsSetSendsFrames + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0}, + // VoodooInputMT1UserClientMethodsGetReport + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)}, + // VoodooInputMT1UserClientMethodsSetReport + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x208, 0x208}, + // VoodooInputMT1UserClientMethodsSetSendLogs + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0}, + // VoodooInputMT1UserClientMethodsIssueDriverRequest + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204}, + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0}, // Relative Mouse Movement + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0}, // Scroll Wheel + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0}, // Keyboard + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0}, // Map Clicks + // VoodooInputMT1UserClientMethodsRecacheProperties + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0}, + {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0}, // Momentum Scroll +}; +#else #error "Invalid architecture" #endif // __defined(__x86_64__) @@ -99,31 +118,31 @@ IOExternalMethod *VoodooInputWellspringUserClient::getTargetAndMethodForIndex(IO } *targetP = this; - return const_cast(&sMethods[index]); + return reinterpret_cast(&sMethods[index]); } -IOReturn VoodooInputWellspringUserClient::sSetSendFrames(bool enableReports) { +IOReturn VoodooInputWellspringUserClient::sSetSendFrames(VoodooInputWellspringUserClient *that, bool enableReports) { bool success = true; - IOLog("%s Set Send Frames: %d\n", getName(), enableReports); + IOLog("%s Set Send Frames: %d\n", that->getName(), enableReports); if (enableReports) { - success = simulator->registerUserClient(this); + success = that->simulator->registerUserClient(that); } else { - simulator->unregisterUserClient(this); + that->simulator->unregisterUserClient(that); } return success ? kIOReturnSuccess : kIOReturnError; } // I'm not really sure why they use two different structs here??? -IOReturn VoodooInputWellspringUserClient::sGetReport(MTDeviceReportStruct *input, MTDeviceReportStruct *output) { +IOReturn VoodooInputWellspringUserClient::sGetReport(VoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output) { if (input == nullptr || output == nullptr) { return kIOReturnBadArgument; } - IOLog("%s Get Report: %d\n", getName(), input->reportId); + IOLog("%s Get Report: %d\n", that->getName(), input->reportId); - IOReturn ret = simulator->getReport(input); + IOReturn ret = that->simulator->getReport(input); if (ret == kIOReturnSuccess) { memmove(output->data, input->data, input->dataSize); output->dataSize = input->dataSize; @@ -137,6 +156,6 @@ void VoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { dataQueue->enqueue(data, (UInt32) size); } -IOReturn VoodooInputWellspringUserClient::sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { +IOReturn VoodooInputWellspringUserClient::sNoop(VoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { return kIOReturnSuccess; // noop } diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp index bd6031e..f96426f 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp @@ -49,9 +49,9 @@ class EXPORT VoodooInputWellspringUserClient : public IOUserClient { virtual IOReturn clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) override; virtual IOExternalMethod *getTargetAndMethodForIndex(IOService **targetP, UInt32 index) override; - IOReturn sSetSendFrames(bool enableFrames); - IOReturn sGetReport(MTDeviceReportStruct *input, MTDeviceReportStruct *output); - IOReturn sNoop(void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + static IOReturn sSetSendFrames(VoodooInputWellspringUserClient *that, bool enableFrames); + static IOReturn sGetReport(VoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output); + static IOReturn sNoop(VoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); void enqueueData(void *data, size_t size); private: @@ -61,6 +61,8 @@ class EXPORT VoodooInputWellspringUserClient : public IOUserClient { IOSharedDataQueue *logQueue {nullptr}; IOMemoryDescriptor *dataQueueDesc {nullptr}; IOMemoryDescriptor *logQueueDesc {nullptr}; + + static IOExternalMethodACID sMethods[VoodooInputMT1UserClientMethodsNumMethods]; }; #endif /* VoodooInputMT1UserClient_hpp */ From f6a8ffd261c16fa08235e9ef59b0c91f70a3291c Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 12:43:59 -0800 Subject: [PATCH 11/32] 32bit build --- .github/workflows/main.yml | 4 +- VoodooInput.xcodeproj/project.pbxproj | 93 +++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 252b6a4..4166ecf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,8 +26,8 @@ jobs: run: | src=$(/usr/bin/curl -Lfs https://raw.githubusercontent.com/acidanthera/ocbuild/master/ci-bootstrap.sh) && eval "$src" || exit 1 - - run: xcodebuild -jobs 1 -configuration Debug - - run: xcodebuild -jobs 1 -configuration Release + - run: xcodebuild -jobs 1 -arch x86_64 -arch ACID32 -configuration Debug + - run: xcodebuild -jobs 1 -arch x86_64 -arch ACID32 -configuration Release - name: Upload to Artifacts uses: actions/upload-artifact@v4 diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index 04a1d15..3f5c793 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -292,8 +292,8 @@ "CC[arch=ACID32]" = "$(PROJECT_DIR)/clang32/clang-12"; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "compiler-default"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; @@ -362,8 +362,8 @@ "CC[arch=ACID32]" = "$(PROJECT_DIR)/clang32/clang-12"; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "compiler-default"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; @@ -435,7 +435,48 @@ "MACOSX_DEPLOYMENT_TARGET[arch=ACID32]" = 10.5; MODULE_NAME = me.kishorprins.VoodooInput; MODULE_VERSION = 1.1.6; - OTHER_CFLAGS = "-Wno-stdlibcxx-not-found"; + OTHER_CFLAGS = ( + "-mmmx", + "-msse", + "-msse2", + "-msse3", + "-mfpmath=sse", + "-mssse3", + "-ftree-vectorize", + "-fno-non-call-exceptions", + "-fno-builtin", + "-fno-asynchronous-unwind-tables", + "-Wno-unknown-warning-option", + "-Wno-ossharedptr-misuse", + "-Wno-vla", + "-Wno-stdlibcxx-not-found", + ); + "OTHER_CFLAGS[arch=ACID32]" = ( + "-mmmx", + "-msse", + "-msse2", + "-mfpmath=sse", + "-ftree-vectorize", + "-fno-non-call-exceptions", + "-fno-builtin", + "-fno-asynchronous-unwind-tables", + "-Wno-unknown-warning-option", + "-Wno-ossharedptr-misuse", + "-Wno-vla", + "-Wno-stdlibcxx-not-found", + "-static", + "-fallow-unsupported", + "-fno-jump-tables", + "-fno-stack-protector", + "-target", + "i386-apple-macos10.5", + ); + OTHER_LDFLAGS = "-static"; + "OTHER_LDFLAGS[arch=ACID32]" = ( + "-static", + "-target", + "i386-apple-macos10.5", + ); PRODUCT_BUNDLE_IDENTIFIER = me.kishorprins.VoodooInput; PRODUCT_NAME = "$(TARGET_NAME)"; RUN_CLANG_STATIC_ANALYZER = YES; @@ -460,6 +501,48 @@ MODULE_NAME = me.kishorprins.VoodooInput; MODULE_VERSION = 1.1.6; OTHER_CFLAGS = "-Wno-stdlibcxx-not-found"; + OTHER_CFLAGS = ( + "-mmmx", + "-msse", + "-msse2", + "-msse3", + "-mfpmath=sse", + "-mssse3", + "-ftree-vectorize", + "-fno-non-call-exceptions", + "-fno-builtin", + "-fno-asynchronous-unwind-tables", + "-Wno-unknown-warning-option", + "-Wno-ossharedptr-misuse", + "-Wno-vla", + "-Wno-stdlibcxx-not-found", + ); + "OTHER_CFLAGS[arch=ACID32]" = ( + "-mmmx", + "-msse", + "-msse2", + "-mfpmath=sse", + "-ftree-vectorize", + "-fno-non-call-exceptions", + "-fno-builtin", + "-fno-asynchronous-unwind-tables", + "-Wno-unknown-warning-option", + "-Wno-ossharedptr-misuse", + "-Wno-vla", + "-Wno-stdlibcxx-not-found", + "-static", + "-fallow-unsupported", + "-fno-jump-tables", + "-fno-stack-protector", + "-target", + "i386-apple-macos10.5", + ); + OTHER_LDFLAGS = "-static"; + "OTHER_LDFLAGS[arch=ACID32]" = ( + "-static", + "-target", + "i386-apple-macos10.5", + ); PRODUCT_BUNDLE_IDENTIFIER = me.kishorprins.VoodooInput; PRODUCT_NAME = "$(TARGET_NAME)"; VALID_ARCHS = "x86_64 ACID32"; From caf04f70f5d8b564a76dd435d7d5634ca056d537 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 12:51:25 -0800 Subject: [PATCH 12/32] Add post-process step and set ACID32 in CI boostrap --- .github/workflows/main.yml | 1 + VoodooInput.xcodeproj/project.pbxproj | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4166ecf..55a018e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,6 +9,7 @@ on: env: PROJECT_TYPE: KEXT + ACID32: 1 jobs: build: diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index 3f5c793..d786e2a 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -184,6 +184,7 @@ 7BBAB1F522E3A2F800B2941A /* Sources */, 7BBAB1F622E3A2F800B2941A /* Frameworks */, CEC086492439FD5D00F5B701 /* Copy SDK */, + 286BF99E296A122A00542FAA /* Post-process Binary */, CEFB081C239659D000215B0B /* Archive */, ); buildRules = ( @@ -228,6 +229,24 @@ /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ + 286BF99E296A122A00542FAA /* Post-process Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Post-process Binary"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cd \"${TARGET_BUILD_DIR}\"\n\nstrip -S \"${EXECUTABLE_PATH}\"\nif [ \"$CONFIGURATION\" == \"Release\" ]; then\n strip -x -T \"${EXECUTABLE_PATH}\" &>/dev/null || strip -x \"${EXECUTABLE_PATH}\"\nfi\n"; + }; CEC086492439FD5D00F5B701 /* Copy SDK */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -500,7 +519,6 @@ "MACOSX_DEPLOYMENT_TARGET[arch=ACID32]" = 10.5; MODULE_NAME = me.kishorprins.VoodooInput; MODULE_VERSION = 1.1.6; - OTHER_CFLAGS = "-Wno-stdlibcxx-not-found"; OTHER_CFLAGS = ( "-mmmx", "-msse", From 92c2c1948fc09e5d265039a74f36dc3416e4a037 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 13:09:18 -0800 Subject: [PATCH 13/32] Compile fixes --- .../VoodooInputWellspringSimulator.cpp | 6 +++--- .../VoodooInputWellspringUserClient.cpp | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index ab7c3d7..258a570 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -162,8 +162,8 @@ bool VoodooInputWellspringSimulator::start(IOService *provider) { OSDictionary *matching = serviceMatching("AppleUSBMultitouchHIDEventDriver"); propertyMatching(OSSymbol::withCString("LocationID"), newLocationIDNumber(), matching); - eventDriverPublish = addMatchingNotification(gIOFirstPublishNotification, matching, notificationHandler, this); - eventDriverTerminate = addMatchingNotification(gIOTerminatedNotification, matching, notificationHandler, this); + eventDriverPublish = addMatchingNotification(gIOFirstPublishNotification, matching, notificationHandler, this, NULL, 10000); + eventDriverTerminate = addMatchingNotification(gIOTerminatedNotification, matching, notificationHandler, this, NULL, 10000); OSSafeReleaseNULL(matching); registerService(); @@ -509,7 +509,7 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { void VoodooInputWellspringSimulator::enqueueData(WELLSPRING3_REPORT *report, size_t dataLen) { #if DEBUG - IOLog("%s Sending report with button %d, finger count %hhu, at %dms\n", getName(), report->Button, report->NumFingers, report->Timestamp); + IOLog("%s Sending report with button %u, finger count %hhu, at %ums\n", getName(), report->Button, report->NumFingers, report->Timestamp); for (size_t i = 0; i < report->NumFingers; i++) { WELLSPRING3_FINGER &f = report->Fingers[i]; IOLog("%s [%zu] (%d, %d) (%d, %d)dx F%d St%d Maj%d Min%d Sz%d ID%d A%d\n", getName(), i, f.X, f.Y, f.XVelocity, f.YVelocity, f.Finger, f.State, f.ToolMajor, f.ToolMinor, f.Size, f.Id, f.Orientation); diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 8975637..843cd86 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -59,7 +59,6 @@ IOExternalMethodACID VoodooInputWellspringUserClient::sMethods[VoodooInputMT1Use #endif // __defined(__x86_64__) bool VoodooInputWellspringUserClient::start(IOService *provider) { - IOLog("%s Start\n", getName()); if (!super::start(provider)) return false; simulator = OSDynamicCast(VoodooInputWellspringSimulator, provider); @@ -98,7 +97,6 @@ IOReturn VoodooInputWellspringUserClient::registerNotificationPort(mach_port_t p } IOReturn VoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { - IOLog("%s clientMem\n", getName()); if (type != 0x10) { dataQueueDesc->retain(); *memory = dataQueueDesc; @@ -112,7 +110,7 @@ IOReturn VoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOpt } IOExternalMethod *VoodooInputWellspringUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { - IOLog("%s External Method %d\n", getName(), index); + IOLog("%s External Method %u\n", getName(), index); if (index >= VoodooInputMT1UserClientMethodsNumMethods) { return nullptr; } @@ -140,7 +138,7 @@ IOReturn VoodooInputWellspringUserClient::sGetReport(VoodooInputWellspringUserCl return kIOReturnBadArgument; } - IOLog("%s Get Report: %d\n", that->getName(), input->reportId); + IOLog("%s Get Report: %u\n", that->getName(), input->reportId); IOReturn ret = that->simulator->getReport(input); if (ret == kIOReturnSuccess) { @@ -157,5 +155,6 @@ void VoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { } IOReturn VoodooInputWellspringUserClient::sNoop(VoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { + IOLog("%s Noop was called!\n", that->getName()); return kIOReturnSuccess; // noop } From ba95d8907c245b1fb43614aea8a5e24aef3044d1 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 13:36:40 -0800 Subject: [PATCH 14/32] Fix notifications on old macOS versions --- .../VoodooInputWellspringSimulator.cpp | 38 +++++++++++++++---- .../VoodooInputWellspringSimulator.hpp | 6 +++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 258a570..b8fdfbb 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -158,31 +158,53 @@ bool VoodooInputWellspringSimulator::start(IOService *provider) { clock_get_uptime(&startTimestamp); - IOServiceMatchingNotificationHandler notificationHandler = OSMemberFunctionCast(IOServiceMatchingNotificationHandler, this, &VoodooInputWellspringSimulator::notificationEventDriver); - OSDictionary *matching = serviceMatching("AppleUSBMultitouchHIDEventDriver"); propertyMatching(OSSymbol::withCString("LocationID"), newLocationIDNumber(), matching); - eventDriverPublish = addMatchingNotification(gIOFirstPublishNotification, matching, notificationHandler, this, NULL, 10000); - eventDriverTerminate = addMatchingNotification(gIOTerminatedNotification, matching, notificationHandler, this, NULL, 10000); + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 + IOServiceMatchingNotificationHandler notificationHandler = OSMemberFunctionCast(IOServiceMatchingNotificationHandler, this, &VoodooInputWellspringSimulator::notificationEventDriver); + + eventDriverPublish = addMatchingNotification(gIOFirstPublishNotification, matching, notificationHandler, this); + eventDriverTerminate = addMatchingNotification(gIOTerminatedNotification, matching, notificationHandler, this); OSSafeReleaseNULL(matching); +#else + IOServiceNotificationHandler publishHandler = OSMemberFunctionCast(IOServiceNotificationHandler, this, + &VoodooInputWellspringSimulator::notificationEventDriverPublished); + IOServiceNotificationHandler terminateHandler = OSMemberFunctionCast(IOServiceNotificationHandler, this, + &VoodooInputWellspringSimulator::notificationEventDriverTerminated); + // addNotification releases the matching dictionary, but we need it for two notifications! + matching->retain(); + eventDriverPublish = addNotification(gIOFirstPublishNotification, matching, publishHandler, this); + eventDriverTerminate = addNotification(gIOTerminatedNotification, matching, terminateHandler, this); + matching = nullptr; +#endif registerService(); return true; } + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 void VoodooInputWellspringSimulator::notificationEventDriver(IOService * newService, IONotifier * notifier) { IOLog("%s Event Driver Published/Terminated\n", getName()); - if (notifier == eventDriverPublish && eventDriver == nullptr) { + if (notifier == eventDriverPublish) notificationEventDriverPublished(newService); + else if (notifier == eventDriverTerminate) notificationEventDriverTerminated(newService); +} +#endif + +void VoodooInputWellspringSimulator::notificationEventDriverPublished(IOService *newService) { + if (eventDriver == nullptr) { eventDriver = OSDynamicCast(AppleUSBMultitouchHIDEventDriver, newService); if (eventDriver != nullptr) eventDriver->retain(); else IOLog("%s is null!?!?!?!\n", getName()); - } else if (notifier == eventDriverTerminate && eventDriver != nullptr) { - eventDriver->release(); - eventDriver = nullptr; } } +void VoodooInputWellspringSimulator::notificationEventDriverTerminated(IOService *terminatedService) { + OSSafeReleaseNULL(eventDriver); +} + void VoodooInputWellspringSimulator::stop(IOService *provider) { if (eventDriverPublish != nullptr) { eventDriverPublish->remove(); diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index 614305c..aba5390 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -141,7 +141,13 @@ class EXPORT VoodooInputWellspringSimulator : public IOHIDDevice { IOReturn getReport(MTDeviceReportStruct *toFill); void constructReport(VoodooInputEvent& event); + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 void notificationEventDriver(IOService * newService, IONotifier * notifier); +#endif + void notificationEventDriverPublished(IOService *newService); + void notificationEventDriverTerminated(IOService *terminatedService); + private: bool touchActive[15] {false}; From 7e2a903344b05a843a3c47d2d34d59054cab8359 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 13:41:24 -0800 Subject: [PATCH 15/32] Codesign fixes --- VoodooInput.xcodeproj/project.pbxproj | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index d786e2a..8e8c795 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -337,7 +337,9 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; + CODE_SIGN_STYLE = Manual; "COMPILER_INDEX_STORE_ENABLE[arch=ACID32]" = NO; COPY_PHASE_STRIP = NO; CXX = "$(inherited)"; @@ -407,7 +409,9 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; + CODE_SIGN_STYLE = Manual; COMPILER_INDEX_STORE_ENABLE = YES; "COMPILER_INDEX_STORE_ENABLE[arch=ACID32]" = NO; COPY_PHASE_STRIP = NO; From d85378dbdab3a4f3fc32919007715dc4c6bf110f Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 14:21:47 -0800 Subject: [PATCH 16/32] Use macro for IOExternalMethods --- .../VoodooInputWellspringSimulator.hpp | 1 - .../VoodooInputWellspringUserClient.cpp | 55 +++++++------------ 2 files changed, 19 insertions(+), 37 deletions(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index aba5390..5eb70cd 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -33,7 +33,6 @@ class VoodooInputWellspringSimulator; class VoodooInputWellspringUserClient; -class VoodooInputActuatorDevice; class AppleUSBMultitouchHIDEventDriver : public IOHIDEventService { OSDeclareDefaultStructorsWithDispatch(AppleUSBMultitouchHIDEventDriver); diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 843cd86..9c94fab 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -13,50 +13,32 @@ OSDefineMetaClassAndStructors(VoodooInputWellspringUserClient, IOUserClient); #if defined(__x86_64__) -// { Object, Func pointer, Padding, Flags, Inputs, Outputs } -IOExternalMethodACID VoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { - // VoodooInputMT1UserClientMethodsSetSendsFrames - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sSetSendFrames, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 1, 0}, - // VoodooInputMT1UserClientMethodsGetReport - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sGetReport, kIOExternalMethodACIDPadding, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)}, - // VoodooInputMT1UserClientMethodsSetReport - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCStructIStructO, 0x208, 0x208}, - // VoodooInputMT1UserClientMethodsSetSendLogs - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 1, 0}, - // VoodooInputMT1UserClientMethodsIssueDriverRequest - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCStructIStructO, 0x204, 0x204}, - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 3, 0}, // Relative Mouse Movement - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 3, 0}, // Scroll Wheel - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 2, 0}, // Keyboard - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 1, 0}, // Map Clicks - // VoodooInputMT1UserClientMethodsRecacheProperties - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 0, 0}, - {0, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOExternalMethodACIDPadding, kIOUCScalarIScalarO, 3, 0}, // Momentum Scroll -}; +#define MTExternalMethod(method, flags, inputs, outputs) {0, method, kIOExternalMethodACIDPadding, flags, inputs, outputs} #elif defined(__i386__) -// { Object, Padding, Func pointer, Flags, Inputs, Outputs } +#define MTExternalMethod(method, flags, inputs, outputs) {0, kIOExternalMETHODACIDPadding, method, flags, inputs, outputs} +#else +#error "Invalid architecture" +#endif + IOExternalMethodACID VoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { // VoodooInputMT1UserClientMethodsSetSendsFrames - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0}, + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0), // VoodooInputMT1UserClientMethodsGetReport - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)}, + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), // VoodooInputMT1UserClientMethodsSetReport - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x208, 0x208}, + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), // VoodooInputMT1UserClientMethodsSetSendLogs - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0}, + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // VoodooInputMT1UserClientMethodsIssueDriverRequest - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204}, - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0}, // Relative Mouse Movement - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0}, // Scroll Wheel - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0}, // Keyboard - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0}, // Map Clicks + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Relative Mouse Movement + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Scroll Wheel + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0), // Keyboard + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // Map Clicks // VoodooInputMT1UserClientMethodsRecacheProperties - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0}, - {0, kIOExternalMethodACIDPadding, (IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0}, // Momentum Scroll + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Momentum Scroll }; -#else -#error "Invalid architecture" -#endif // __defined(__x86_64__) bool VoodooInputWellspringUserClient::start(IOService *provider) { if (!super::start(provider)) return false; @@ -68,7 +50,8 @@ bool VoodooInputWellspringUserClient::start(IOService *provider) { } dataQueue = IOSharedDataQueue::withCapacity(0x10004); - // Don't think we need to use this? Setting a small size for now + // I haven't seen the log queue used yet. + // Leaving this here with a small size in case userspace decides to ask for it at some point. logQueue = IOSharedDataQueue::withCapacity(0x1); if (dataQueue == nullptr || logQueue == nullptr) { From f03039b96eedd8a75e026a026950f0425d5b0971 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 7 Jan 2023 14:57:12 -0800 Subject: [PATCH 17/32] Fix compile --- .../VoodooInputWellspringUserClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 9c94fab..5de0c19 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -15,7 +15,7 @@ OSDefineMetaClassAndStructors(VoodooInputWellspringUserClient, IOUserClient); #if defined(__x86_64__) #define MTExternalMethod(method, flags, inputs, outputs) {0, method, kIOExternalMethodACIDPadding, flags, inputs, outputs} #elif defined(__i386__) -#define MTExternalMethod(method, flags, inputs, outputs) {0, kIOExternalMETHODACIDPadding, method, flags, inputs, outputs} +#define MTExternalMethod(method, flags, inputs, outputs) {0, kIOExternalMethodACIDPadding, method, flags, inputs, outputs} #else #error "Invalid architecture" #endif From 2d01dda32e0311f5c5685f78631a0d1d9629ed63 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sun, 8 Jan 2023 12:59:43 -0800 Subject: [PATCH 18/32] Fix version --- .../VoodooInputWellspringSimulator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index b8fdfbb..37c4521 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -360,7 +360,7 @@ void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { // macOS Sierra changed how button handling works // There is now a hid report to send into the abyss of the MT stack directly - if (version_major >= 17) { + if (version_major >= 16) { bzero(&report, sizeof(MTRelativePointerReport)); report.Buttons = btnState; From 78d26b463e716d4be605171ef931d25406812752 Mon Sep 17 00:00:00 2001 From: Michael Belyaev Date: Fri, 13 Jan 2023 21:40:46 +0300 Subject: [PATCH 19/32] Make it loadable on 10.6 --- VoodooInput.xcodeproj/project.pbxproj | 4 ++-- VoodooInput/Info.plist | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index 8e8c795..59f60cc 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -244,8 +244,8 @@ outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "cd \"${TARGET_BUILD_DIR}\"\n\nstrip -S \"${EXECUTABLE_PATH}\"\nif [ \"$CONFIGURATION\" == \"Release\" ]; then\n strip -x -T \"${EXECUTABLE_PATH}\" &>/dev/null || strip -x \"${EXECUTABLE_PATH}\"\nfi\n"; + shellPath = /bin/bash; + shellScript = "cd \"${TARGET_BUILD_DIR}\"\n\nstrip -S \"${EXECUTABLE_PATH}\"\n\ndist=(\"$FULL_PRODUCT_NAME\")\nif [ -d \"$DWARF_DSYM_FILE_NAME\" ]; then dist+=(\"$DWARF_DSYM_FILE_NAME\"); fi\n\narchive=\"${PRODUCT_NAME}-${MODULE_VERSION}-$(echo $CONFIGURATION | tr /a-z/ /A-Z/).zip\"\nrm -rf *.zip\nif [ \"$CONFIGURATION\" == \"Release\" ]; then\n strip -x -T \"${EXECUTABLE_PATH}\" &>/dev/null || strip -x \"${EXECUTABLE_PATH}\"\nfi\n\nif [ -z \"${OVERRIDE_PYTHON3}\" ]; then\n # Use whatever is in PATH\n OVERRIDE_PYTHON3=python3\nfi\n\nif [[ \"$ARCHS\" == *\"ACID32\"* ]]; then\n \"${OVERRIDE_PYTHON3}\" ${SRCROOT}/clang32/fix-macho32 \"${EXECUTABLE_PATH}\" || exit 1\nfi\nzip -qry -FS \"${archive}\" \"${dist[@]}\"\n"; }; CEC086492439FD5D00F5B701 /* Copy SDK */ = { isa = PBXShellScriptBuildPhase; diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index 00d37bc..f18d005 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -308,13 +308,13 @@ com.apple.driver.AppleUSBMultitouch 1.0.0 com.apple.iokit.IOHIDFamily - 2.0 + 1.6 com.apple.kpi.iokit - 14 + 1.0.8 com.apple.kpi.libkern - 14 + 1.0.8 com.apple.kpi.mach - 13.0 + 1.0.8 OSBundleRequired Root From e45297bd138a32c015c32476febf5c1ba7fe50ae Mon Sep 17 00:00:00 2001 From: Avery Black Date: Fri, 13 Jan 2023 23:01:56 -0800 Subject: [PATCH 20/32] Fix object ref counts, add pressure support This is way easier to work on now that I can load/unload from within Catalina Also woops...got a bit carried away with this commit --- VoodooInput/Info.plist | 59 +++++- VoodooInput/VoodooInput.cpp | 33 ++- VoodooInput/VoodooInput.hpp | 3 + .../VoodooInputActuatorDevice.cpp | 12 +- .../VoodooInputWellspringSimulator.cpp | 189 ++++++++---------- .../VoodooInputWellspringSimulator.hpp | 38 ++-- .../VoodooInputWellspringUserClient.cpp | 6 +- .../VoodooInputWellspringUserClient.hpp | 2 +- 8 files changed, 199 insertions(+), 143 deletions(-) diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index f18d005..df596f3 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -34,6 +34,8 @@ 39 MTHIDDevice + Clicking + 0 HIDDefaultBehavior Mouse HIDPointerAccelerationType @@ -46,6 +48,12 @@ 26214400 HIDServiceSupport + TrackpadCornerSecondaryClick + 0 + TrackpadHorizScroll + 1 + TrackpadScroll + TrackpadFourFingerGestures TrackpadMomentumScroll @@ -54,8 +62,55 @@ TrackpadThreeFingerDrag - TrackpadUserPreferences - + MultitouchPreferences + + UserPreferences + + version + 12 + ActuateDetents + 1 + Clicking + 0 + DragLock + 0 + Dragging + 0 + FirstClickThreshold + 1 + ForceSuppressed + + SecondClickThreshold + 1 + TrackpadCornerSecondaryClick + 0 + TrackpadFiveFingerPinchGesture + 2 + TrackpadFourFingerHorizSwipeGesture + 2 + TrackpadFourFingerPinchGesture + 2 + TrackpadFourFingerVertSwipeGesture + 2 + TrackpadHorizScroll + 1 + TrackpadMomentumScroll + + TrackpadPinch + 1 + TrackpadRightClick + + TrackpadRotate + 1 + TrackpadScroll + + TrackpadThreeFingerDrag + + TrackpadThreeFingerHorizSwipeGesture + 2 + TrackpadThreeFingerVertSwipeGesture + 2 + IOCFPlugInTypes 0516B563-B15B-11DA-96EB-0014519758EF diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index 8a2cdf1..03e83d8 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -13,6 +13,7 @@ #include "VoodooInputSimulator/VoodooInputSimulatorDevice.hpp" #include "VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp" #include "Trackpoint/TrackpointDevice.hpp" +#include #include "libkern/version.h" @@ -36,12 +37,12 @@ bool VoodooInput::start(IOService *provider) { trackpoint = OSTypeAlloc(TrackpointDevice); if (!simulator || !trackpoint) { - IOLog("VoodooInput could not alloc simulator, actuator or trackpoint!\n"); + IOLog("VoodooInput could not alloc simulator or trackpoint!\n"); OSSafeReleaseNULL(simulator); OSSafeReleaseNULL(trackpoint); return false; } - + // Initialize simulator device if (!simulator->init(OSDynamicCast(OSDictionary, getProperty("MT1Props"))) || !simulator->attach(this)) { IOLog("VoodooInput could not attach simulator!\n"); @@ -64,6 +65,24 @@ bool VoodooInput::start(IOService *provider) { goto exit; } + // Actuator is only needed for pressure, which is only useful for newer macOS versions with force touch + if (isSierraOrNewer()) { + actuator = OSTypeAlloc(VoodooInputActuatorDevice); + + if (!actuator) { + IOLog("VoodooInput could not alloc actuator!\n"); + goto exit; + } else if (!actuator->init(NULL) || !actuator->attach(this)) { + IOLog("VoodooInput could not init or attach actuator!\n"); + goto exit; + } + else if (!actuator->start(this)) { + IOLog("VoodooInput could not start actuator!\n"); + trackpoint->detach(this); + goto exit; + } + } + setProperty(VOODOO_INPUT_IDENTIFIER, kOSBooleanTrue); if (!parentProvider->open(this)) { @@ -92,6 +111,12 @@ void VoodooInput::stop(IOService *provider) { OSSafeReleaseNULL(simulator); } + if (actuator) { + actuator->stop(this); + actuator->detach(this); + OSSafeReleaseNULL(actuator); + } + if (trackpoint) { trackpoint->stop(this); trackpoint->detach(this); @@ -142,6 +167,10 @@ UInt32 VoodooInput::getLogicalMaxY() { return logicalMaxY; } +bool VoodooInput::isSierraOrNewer() { + return version_major > 16; +} + IOReturn VoodooInput::message(UInt32 type, IOService *provider, void *argument) { switch (type) { case kIOMessageVoodooInputMessage: diff --git a/VoodooInput/VoodooInput.hpp b/VoodooInput/VoodooInput.hpp index 97e43ab..b27ee50 100644 --- a/VoodooInput/VoodooInput.hpp +++ b/VoodooInput/VoodooInput.hpp @@ -37,6 +37,7 @@ class EXPORT VoodooInput : public IOService { IOService* parentProvider; VoodooInputWellspringSimulator* simulator; + VoodooInputActuatorDevice* actuator; TrackpointDevice* trackpoint; UInt8 transformKey; @@ -57,6 +58,8 @@ class EXPORT VoodooInput : public IOService { UInt32 getLogicalMaxX(); UInt32 getLogicalMaxY(); + + bool isSierraOrNewer(); bool updateProperties(); diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp index ff3fb8c..68dccfa 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp @@ -6,11 +6,7 @@ // #include "VoodooInputActuatorDevice.hpp" -<<<<<<< HEAD #include "VoodooInputIDs.hpp" -#include "VoodooInputMessages.h" -======= ->>>>>>> 28aae45 (Clean up) #define super IOHIDDevice OSDefineMetaClassAndStructors(VoodooInputActuatorDevice, IOHIDDevice); @@ -52,15 +48,15 @@ OSNumber* VoodooInputActuatorDevice::newProductIDNumber() const { } OSString* VoodooInputActuatorDevice::newProductString() const { - return OSString::withCString("Magic Trackpad 2"); + return OSString::withCString("Wellspring Emulator"); } OSString* VoodooInputActuatorDevice::newSerialNumberString() const { - return OSString::withCString("VoodooI2C Magic Trackpad 2 Actuator"); + return OSString::withCString("Wellspring Actuator"); } OSString* VoodooInputActuatorDevice::newTransportString() const { - return OSString::withCString("I2C"); + return OSString::withCString("USB"); } OSNumber* VoodooInputActuatorDevice::newVendorIDNumber() const { @@ -68,7 +64,7 @@ OSNumber* VoodooInputActuatorDevice::newVendorIDNumber() const { } OSNumber* VoodooInputActuatorDevice::newLocationIDNumber() const { - return OSNumber::withNumber(0x14400000, 32); + return OSNumber::withNumber(0x1d183000, 32); } OSNumber* VoodooInputActuatorDevice::newVersionNumber() const { diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 37c4521..a6192f9 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -9,29 +9,32 @@ #include "VoodooInputWellspringSimulator.hpp" #include "VoodooInputWellspringUserClient.hpp" #include "VoodooInputActuatorDevice.hpp" -#include #include "VoodooInputMessages.h" #define super IOHIDDevice OSDefineMetaClassAndStructors(VoodooInputWellspringSimulator, IOHIDDevice); -// Reports come from a MacbookPro9,2 -#define SensorParamsLength 6 -static const UInt8 MTSensorParams[SensorParamsLength] = {0x00, 0x00, 0x03, 0x00, 0xD6, 0x01}; +// Reports come from a MacbookPro9,2/MacbookPro12,1 +static const UInt8 MTSensorParams[] = {0x00, 0x00, 0x03, 0x00, 0xD6, 0x01}; -#define SensorDescLength 8 -static const UInt8 MTSensorDesc[SensorDescLength] = {0x01, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x14, 0x00}; +// Region descriptor +// {Num regions, [type (1 = multitouch, 2 = force), start row, rows, row skip, start col, cols, hardware coloffset]} +static const UInt8 MTSensorDescOld[] = { + 0x01, + 0x01, 0x00, 0x0c, 0x01, 0x00, 0x14, 0x00 +}; -#define SensorRowsLength 5 -static const UInt8 MTSensorRows[SensorRowsLength] = { - 0x01, // Is little Endian - 0x0C, // Rows - 0x14, // Columns - 0x01, 0x09 // BCD Version +static const UInt8 MTSensorDescSierra[] = { + 0x02, + 0x01, 0x00, 0x0c, 0x01, 0x00, 0x14, 0x00, + 0x02, 0x0c, 0x02, 0x01, 0x09, 0x02, 0x00 }; -#define FamilyID 0x62 -#define FamilyIDLength 1 +static const unsigned char report_descriptor[] = { + 0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x03, 0x06, 0x00, + 0xFF, 0x09, 0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x85, + 0x44, 0x75, 0x08, 0x96, 0xFF, 0x01, 0x81, 0x00, 0xC0 +}; bool VoodooInputWellspringSimulator::setProperty(const char *aKey, OSObject *anObject) { IOLog("MT1Sim: Attempting to set Property! %s\n", aKey); @@ -73,7 +76,7 @@ bool VoodooInputWellspringSimulator::setProperty(const OSSymbol *aKey, OSObject } bool VoodooInputWellspringSimulator::setProperty(const OSString *aKey, OSObject *anObject) { - // Hidd tries to set a new user client, so we block setProperty writes to the user client key. + // A new user client keeps trying to get set, so we block setProperty writes to the user client key. IOLog("MT1Sim: Attempting to set OSString Object Property! %s\n", aKey->getCStringNoCopy()); bool ret = false; if (!aKey->isEqualTo("IOUserClientClass")) { @@ -89,30 +92,41 @@ bool VoodooInputWellspringSimulator::init(OSDictionary *props) { return false; } - setProperty("Clicking", kOSBooleanTrue); - setProperty("TrackpadScroll", kOSBooleanTrue); - setProperty("TrackpadHorizScroll", kOSBooleanTrue); - setProperty("AlwaysNeedsVelocityCalculated", kOSBooleanTrue); + return true; +} + +void VoodooInputWellspringSimulator::setMTProperties() { + setProperty("Sensor Surface Width", engine->getPhysicalMaxX(), 32); + setProperty("Sensor Surface Height", engine->getPhysicalMaxY(), 32); + + // TODO: Not sure how many of these properties below are needed. + // The Info.plist properties are also in dire need of being checked + setProperty("Sensor Region Param", const_cast(MTSensorParams), sizeof(MTSensorParams)); setProperty("Endianness", MT1_LITTLE_ENDIAN, 32); + setProperty("AlwaysNeedsVelocityCalculated", kOSBooleanTrue); setProperty("Multitouch ID", 0x30000001d183000, 64); setProperty("Family ID", 0x62, 8); setProperty("bcdVersion", 0x109, 16); setProperty("Max Packet Size", 0x200, 32); - if (version_major >= 16) { - setProperty("SupportsGestureScrolling", kOSBooleanTrue); + if (engine->isSierraOrNewer()) { + setProperty("Sensor Region Descriptor", const_cast(MTSensorDescSierra), sizeof(MTSensorDescSierra)); + setProperty("ApplePreferenceIdentifier", "com.apple.AppleMultitouchTrackpad"); + setProperty("ApplePreferenceCapability", 2, 32); + setProperty("SupportsGestureScrolling", kOSBooleanTrue); setProperty("MT Built-in", kOSBooleanTrue); - setProperty("ApplePreferenceCapability", kOSBooleanTrue); setProperty("TrackpadEmbedded", kOSBooleanTrue); + setProperty("ForceSupported", kOSBooleanTrue); + setProperty("ActuationSupported", kOSBooleanTrue); + } else { + setProperty("Sensor Region Descriptor", const_cast(MTSensorDescOld), sizeof(MTSensorDescOld)); + + removeProperty("MultitouchPreferences"); + OSDictionary* trackpadPrefs = OSDictionary::withCapacity(1); + setProperty("TrackpadUserPreferences", trackpadPrefs); + OSSafeReleaseNULL(trackpadPrefs); } - - setProperty("TrackpadCornerSecondaryClick", kOSBooleanTrue); - - OSDictionary* trackpadPrefs = OSDictionary::withCapacity(1); - setProperty("TrackpadUserPreferences", trackpadPrefs); - OSSafeReleaseNULL(trackpadPrefs); - return true; } bool VoodooInputWellspringSimulator::start(IOService *provider) { @@ -123,10 +137,7 @@ bool VoodooInputWellspringSimulator::start(IOService *provider) { return false; } - setProperty("Sensor Surface Width", engine->getPhysicalMaxX(), 32); - setProperty("Sensor Surface Height", engine->getPhysicalMaxY(), 32); - setProperty("Sensor Region Param", const_cast(MTSensorParams), SensorParamsLength); - setProperty("Sensor Region Descriptor", const_cast(MTSensorDesc), SensorDescLength); + setMTProperties(); workloop = getWorkLoop(); if (workloop == nullptr) { @@ -150,14 +161,20 @@ bool VoodooInputWellspringSimulator::start(IOService *provider) { return false; } - size_t inputSize = sizeof(WELLSPRING3_REPORT) + (sizeof(WELLSPRING3_FINGER) * VOODOO_INPUT_MAX_TRANSDUCERS); - inputReport = reinterpret_cast(IOMalloc(inputSize)); - bzero(inputReport, inputSize); + inputReportSize = sizeof(WELLSPRING_REPORT) + (sizeof(WELLSPRING_FINGER) * VOODOO_INPUT_MAX_TRANSDUCERS); + inputReport = reinterpret_cast(IOMalloc(inputReportSize)); + bzero(inputReport, inputReportSize); if (inputReport == nullptr) return false; + createEventDriverNotifiers(); clock_get_uptime(&startTimestamp); + registerService(); + return true; +} + +void VoodooInputWellspringSimulator::createEventDriverNotifiers() { OSDictionary *matching = serviceMatching("AppleUSBMultitouchHIDEventDriver"); propertyMatching(OSSymbol::withCString("LocationID"), newLocationIDNumber(), matching); @@ -178,13 +195,8 @@ bool VoodooInputWellspringSimulator::start(IOService *provider) { eventDriverTerminate = addNotification(gIOTerminatedNotification, matching, terminateHandler, this); matching = nullptr; #endif - - registerService(); - - return true; } - #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 void VoodooInputWellspringSimulator::notificationEventDriver(IOService * newService, IONotifier * notifier) { IOLog("%s Event Driver Published/Terminated\n", getName()); @@ -202,10 +214,12 @@ void VoodooInputWellspringSimulator::notificationEventDriverPublished(IOService } void VoodooInputWellspringSimulator::notificationEventDriverTerminated(IOService *terminatedService) { - OSSafeReleaseNULL(eventDriver); + if (eventDriver == terminatedService) { + OSSafeReleaseNULL(eventDriver); + } } -void VoodooInputWellspringSimulator::stop(IOService *provider) { +void VoodooInputWellspringSimulator::free() { if (eventDriverPublish != nullptr) { eventDriverPublish->remove(); } @@ -218,30 +232,16 @@ void VoodooInputWellspringSimulator::stop(IOService *provider) { workloop->removeEventSource(cmdGate); } - if (userClients != nullptr) { - userClients->flushCollection(); - OSSafeReleaseNULL(userClients); - } - if (inputReport != nullptr) { - size_t inputSize = sizeof(WELLSPRING3_REPORT) + (sizeof(WELLSPRING3_FINGER) * VOODOO_INPUT_MAX_TRANSDUCERS); - IOFree(inputReport, inputSize); + IOFree(inputReport, inputReportSize); } - OSSafeReleaseNULL(eventDriverPublish); - OSSafeReleaseNULL(eventDriverTerminate); + OSSafeReleaseNULL(userClients); OSSafeReleaseNULL(workloop); OSSafeReleaseNULL(cmdGate); - super::stop(provider); + super::free(); } -const unsigned char report_descriptor[] = { - 0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x03, 0x06, - 0x00, 0xFF, 0x09, 0x01, 0x15, 0x00, 0x26, 0xFF, - 0x00, 0x85, 0x44, 0x75, 0x08, 0x96, 0xFF, 0x01, - 0x81, 0x00, 0xC0 -}; - IOReturn VoodooInputWellspringSimulator::newReportDescriptor(IOMemoryDescriptor** descriptor) const { IOBufferMemoryDescriptor* report_descriptor_buffer = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, sizeof(report_descriptor)); @@ -265,7 +265,8 @@ OSNumber* VoodooInputWellspringSimulator::newPrimaryUsagePageNumber() const { } OSNumber* VoodooInputWellspringSimulator::newProductIDNumber() const { - return OSNumber::withNumber(0x237, 32); +// return OSNumber::withNumber(0x237, 32); // MacBookPro9,1 + return OSNumber::withNumber(0x273, 32); // MacBookPro12,1 } OSString* VoodooInputWellspringSimulator::newProductString() const { @@ -292,56 +293,24 @@ OSNumber* VoodooInputWellspringSimulator::newVersionNumber() const { return OSNumber::withNumber(0x77, 32); } +// MARK: User Client Interface + bool VoodooInputWellspringSimulator::registerUserClient(IOService *client) { - IOLog("MT1Sim: Adding user client\n"); + IOLog("%s: Adding user client\n", getName()); return userClients->setObject(client); } void VoodooInputWellspringSimulator::unregisterUserClient(IOService *client) { - IOLog("MT1Sim: Removing user client\n"); + IOLog("%s: Removing user client\n", getName()); userClients->removeObject(client); } IOReturn VoodooInputWellspringSimulator::getReport(MTDeviceReportStruct *toFill) { - UInt32 width, height; - switch (toFill->reportId) { case MT1ReportDetectConfig: toFill->data[0] = 0x08; toFill->dataSize = 1; break; - case MT1ReportSensorParam: - memcpy(toFill->data, MTSensorParams, SensorParamsLength); - toFill->dataSize = SensorParamsLength; - break; - case MT1ReportSensorDescriptor: - memcpy(toFill->data, MTSensorDesc, SensorDescLength); - toFill->dataSize = SensorDescLength; - break; - case MT1ReportSensorSize: - width = engine->getPhysicalMaxX(); - height = engine->getPhysicalMaxY(); - - for (int i = 0; i < sizeof(UInt32); i++) { - toFill->data[i] = width & 0xFF; - width >>= 8; - } - - for (int i = 4; i < sizeof(UInt32) + 4; i++) { - toFill->data[i] = height & 0xFF; - height >>= 8; - } - - toFill->dataSize = sizeof(UInt32) * 2; - break; - case MT1ReportSensorRows: - memcpy(toFill->data, MTSensorRows, SensorRowsLength); - toFill->dataSize = SensorRowsLength; - break; - case MT1ReportFamilyId: - toFill->data[0] = FamilyID; - toFill->dataSize = FamilyIDLength; - break; default: return kIOReturnError; } @@ -349,6 +318,8 @@ IOReturn VoodooInputWellspringSimulator::getReport(MTDeviceReportStruct *toFill) return kIOReturnSuccess; } +// MARK: Create Reports + void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { MTRelativePointerReport report; AbsoluteTime timestamp; @@ -360,7 +331,7 @@ void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { // macOS Sierra changed how button handling works // There is now a hid report to send into the abyss of the MT stack directly - if (version_major >= 16) { + if (engine->isSierraOrNewer()) { bzero(&report, sizeof(MTRelativePointerReport)); report.Buttons = btnState; @@ -382,19 +353,19 @@ void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { AbsoluteTime timestamp = event.timestamp; - size_t inputSize = sizeof(WELLSPRING3_REPORT) + (sizeof(WELLSPRING3_FINGER) * event.contact_count); + size_t inputSize = sizeof(WELLSPRING_REPORT) + (sizeof(WELLSPRING_FINGER) * event.contact_count); if (inputReport == nullptr) return; inputReport->ReportID = 0x74; inputReport->Counter++; inputReport->unkown1 = 0x03; - inputReport->HeaderSize = sizeof(WELLSPRING3_REPORT); + inputReport->HeaderSize = sizeof(WELLSPRING_REPORT); inputReport->unk2[0] = 0x00; // Magic inputReport->unk2[1] = 0x17; inputReport->unk2[2] = 0x07; inputReport->unk2[3] = 0x97; - inputReport->TotalFingerDataSize = sizeof(WELLSPRING3_FINGER) * event.contact_count; + inputReport->TotalFingerDataSize = sizeof(WELLSPRING_FINGER) * event.contact_count; inputReport->NumFingers = event.contact_count; inputReport->Button = event.transducers[0].isPhysicalButtonDown || event.transducers[0].currentCoordinates.pressure > 100; inputReport->unknown1 = 0x00000010; @@ -434,7 +405,7 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { UInt16 touch_id = transducer.secondaryId % 15; input_active |= transducer.isTransducerActive; - WELLSPRING3_FINGER& fingerData = inputReport->Fingers[i]; + WELLSPRING_FINGER& fingerData = inputReport->Fingers[i]; IOFixed scaled_x = ((transducer.currentCoordinates.x * 1.0f) / engine->getLogicalMaxX()) * MT1_MAX_X; IOFixed scaled_y = ((transducer.currentCoordinates.y * 1.0f) / engine->getLogicalMaxY()) * MT1_MAX_Y; @@ -465,15 +436,19 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { fingerData.Finger = transducer.fingerType; if (transducer.supportsPressure) { - fingerData.Size = transducer.currentCoordinates.width * 4; + fingerData.Pressure = transducer.currentCoordinates.pressure * 0xFF; + fingerData.Size = transducer.currentCoordinates.width * 8; fingerData.ToolMajor = transducer.currentCoordinates.width * 16; fingerData.ToolMinor = transducer.currentCoordinates.width * 16; } else { + fingerData.Pressure = 100; fingerData.Size = 200; fingerData.ToolMajor = 800; fingerData.ToolMinor = 800; } + fingerData.DensityMajor = fingerData.DensityMinor = fingerData.Size; + if (!transducer.isTransducerActive && !transducer.isPhysicalButtonDown) { touchActive[touch_id] = false; fingerData.State = kTouchStateStop; @@ -489,8 +464,6 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { fingerData.Orientation = 0x4000; // pi/2 fingerData.Id = touch_id + 1; } - -// inputReport->TouchActive = input_active; if (!is_error_input_active) { enqueueData(inputReport, (UInt32) inputSize); @@ -523,17 +496,17 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { inputReport->TotalFingerDataSize = 0; inputReport->Counter++; inputReport->Timestamp += 10; - enqueueData(inputReport, sizeof(WELLSPRING3_REPORT)); + enqueueData(inputReport, sizeof(WELLSPRING_REPORT)); } bzero(inputReport->Fingers, inputReport->TotalFingerDataSize); } -void VoodooInputWellspringSimulator::enqueueData(WELLSPRING3_REPORT *report, size_t dataLen) { +void VoodooInputWellspringSimulator::enqueueData(WELLSPRING_REPORT *report, size_t dataLen) { #if DEBUG IOLog("%s Sending report with button %u, finger count %hhu, at %ums\n", getName(), report->Button, report->NumFingers, report->Timestamp); for (size_t i = 0; i < report->NumFingers; i++) { - WELLSPRING3_FINGER &f = report->Fingers[i]; + WELLSPRING_FINGER &f = report->Fingers[i]; IOLog("%s [%zu] (%d, %d) (%d, %d)dx F%d St%d Maj%d Min%d Sz%d ID%d A%d\n", getName(), i, f.X, f.Y, f.XVelocity, f.YVelocity, f.Finger, f.State, f.ToolMajor, f.ToolMinor, f.Size, f.Id, f.Orientation); } #endif diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index 5eb70cd..3f37ade 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -52,11 +52,12 @@ struct __attribute__((__packed__)) MTRelativePointerReport { AbsoluteTime Timestamp; }; -struct __attribute__((__packed__)) WELLSPRING3_FINGER { +struct __attribute__((__packed__)) WELLSPRING_FINGER { UInt8 Id; UInt8 State; UInt8 Finger; - UInt8 Unknown; // 0 -> 1 -> 0xFF + // Goes from 0 -> 1 -> 0xFF on my MBP9,2 + UInt8 Unknown; SInt16 X; SInt16 Y; // Velocity can be calculated in MultitouchSupport.plugin for us @@ -67,17 +68,17 @@ struct __attribute__((__packed__)) WELLSPRING3_FINGER { UInt16 ToolMinor; UInt16 Orientation; UInt16 Size; - // ContactDensity can be calculated in MultitouchSupport.plugin - /*UInt16 ContactDensity; - UInt16 Unused[2]; - UInt16 Pressure; // Not a thing on Wellspring3 */ + UInt16 DensityMajor; + UInt16 DensityMinor; + UInt16 Unused[1]; + UInt16 Pressure; }; // There's no finger field -static_assert(sizeof(WELLSPRING3_FINGER) == 20, "Unexpected WELLSPRING3_FINGER size"); +static_assert(sizeof(WELLSPRING_FINGER) == 28, "Unexpected WELLSPRING3_FINGER size"); -struct __attribute__((__packed__)) WELLSPRING3_REPORT { +struct __attribute__((__packed__)) WELLSPRING_REPORT { UInt8 ReportID; UInt8 Counter; // Unknown, always seems to count up though? UInt8 HeaderSize; @@ -89,13 +90,10 @@ struct __attribute__((__packed__)) WELLSPRING3_REPORT { UInt8 Button; UInt32 unknown1; // 0x00000010 UInt16 unknown2[4]; // Sometimes Changes - WELLSPRING3_FINGER Fingers[]; - - // End of packet always contains Checksum (though this is never checked in MultitouchSupport) - // UInt16 checksum; + WELLSPRING_FINGER Fingers[]; }; -static_assert(sizeof(WELLSPRING3_REPORT) == 28, "Unexpected WELLSPRING3_REPORT size"); +static_assert(sizeof(WELLSPRING_REPORT) == 28, "Unexpected WELLSPRING3_REPORT size"); struct MTDeviceReportStruct { uint8_t reportId; @@ -104,18 +102,13 @@ struct MTDeviceReportStruct { }; #define MT1ReportDetectConfig 0xC8 -#define MT1ReportSensorParam 0xA1 -#define MT1ReportSensorDescriptor 0xD0 -#define MT1ReportFamilyId 0xD1 -#define MT1ReportSensorRows 0xD3 -#define MT1ReportSensorSize 0xD9 class EXPORT VoodooInputWellspringSimulator : public IOHIDDevice { OSDeclareDefaultStructors(VoodooInputWellspringSimulator); public: virtual bool init(OSDictionary *) override; virtual bool start(IOService *provider) override; - virtual void stop(IOService *provider) override; + virtual void free() override; virtual bool setProperty(const char *aKey, OSObject *anObject) override; virtual bool setProperty(const char *aKey, unsigned long long aValue, unsigned int aNumberOfBits) override; @@ -158,15 +151,18 @@ class EXPORT VoodooInputWellspringSimulator : public IOHIDDevice { AppleUSBMultitouchHIDEventDriver *eventDriver {nullptr}; AbsoluteTime startTimestamp {}; - WELLSPRING3_REPORT *inputReport {nullptr}; + size_t inputReportSize {}; + WELLSPRING_REPORT *inputReport {nullptr}; IONotifier *eventDriverPublish {nullptr}; IONotifier *eventDriverTerminate {nullptr}; UInt8 lastButtonState {0}; - void enqueueData(WELLSPRING3_REPORT *report, size_t dataLen); + void enqueueData(WELLSPRING_REPORT *report, size_t dataLen); void constructButtonReport(UInt8 btnState); + void setMTProperties(); + void createEventDriverNotifiers(); }; #endif /* AppleUSBMultitouchDriver_hpp */ diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 5de0c19..83e1dd0 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -67,9 +67,12 @@ bool VoodooInputWellspringUserClient::start(IOService *provider) { return true; } -void VoodooInputWellspringUserClient::stop(IOService *provider) { +void VoodooInputWellspringUserClient::free() { + OSSafeReleaseNULL(dataQueueDesc); OSSafeReleaseNULL(dataQueue); + OSSafeReleaseNULL(logQueueDesc); OSSafeReleaseNULL(logQueue); + super::free(); } IOReturn VoodooInputWellspringUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { @@ -80,6 +83,7 @@ IOReturn VoodooInputWellspringUserClient::registerNotificationPort(mach_port_t p } IOReturn VoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { + // The memory descriptors get released when being mapped in IOUserClient::mapClientMemory if (type != 0x10) { dataQueueDesc->retain(); *memory = dataQueueDesc; diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp index f96426f..27875fc 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp @@ -43,7 +43,7 @@ class EXPORT VoodooInputWellspringUserClient : public IOUserClient { public: virtual bool start(IOService *provider) override; - virtual void stop(IOService *provider) override; + virtual void free() override; virtual IOReturn registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) override; virtual IOReturn clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) override; From c53b9bee250fc5846437e919680639639946e474 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Fri, 13 Jan 2023 23:07:04 -0800 Subject: [PATCH 21/32] Revert product number I'm surprised this works tbh --- VoodooInput/Info.plist | 6 +++--- .../VoodooInputWellspringSimulator.cpp | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index df596f3..39b872a 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -365,11 +365,11 @@ com.apple.iokit.IOHIDFamily 1.6 com.apple.kpi.iokit - 1.0.8 + 14 com.apple.kpi.libkern - 1.0.8 + 14 com.apple.kpi.mach - 1.0.8 + 13 OSBundleRequired Root diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index a6192f9..e163b09 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -265,8 +265,7 @@ OSNumber* VoodooInputWellspringSimulator::newPrimaryUsagePageNumber() const { } OSNumber* VoodooInputWellspringSimulator::newProductIDNumber() const { -// return OSNumber::withNumber(0x237, 32); // MacBookPro9,1 - return OSNumber::withNumber(0x273, 32); // MacBookPro12,1 + return OSNumber::withNumber(0x237, 32); } OSString* VoodooInputWellspringSimulator::newProductString() const { From 002e3a29cdd88c85b69ba0a7f1ba3554c83cb829 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Fri, 13 Jan 2023 23:08:22 -0800 Subject: [PATCH 22/32] Fix OSBundleLibraries versions --- VoodooInput/Info.plist | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index 39b872a..df596f3 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -365,11 +365,11 @@ com.apple.iokit.IOHIDFamily 1.6 com.apple.kpi.iokit - 14 + 1.0.8 com.apple.kpi.libkern - 14 + 1.0.8 com.apple.kpi.mach - 13 + 1.0.8 OSBundleRequired Root From 3424df119e7e3585e0cece4167a7f96f799ad876 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 14 Jan 2023 11:54:17 -0800 Subject: [PATCH 23/32] Event driver --- VoodooInput.xcodeproj/project.pbxproj | 10 +- VoodooInput/Info.plist | 264 +++++++++++++++++- .../VoodooInputWellspringEventDriver.cpp | 11 + .../VoodooInputWellspringEventDriver.hpp | 23 ++ .../VoodooInputWellspringSimulator.cpp | 4 +- .../VoodooInputWellspringSimulator.hpp | 12 +- 6 files changed, 309 insertions(+), 15 deletions(-) create mode 100644 VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.cpp create mode 100644 VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.hpp diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index 59f60cc..f1b5f30 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 28783C5329733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 28783C5129733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp */; }; + 28783C5429733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 28783C5229733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp */; }; 358914F425798FA5007A0B58 /* TrackpointDevice.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 358914F225798FA5007A0B58 /* TrackpointDevice.hpp */; }; 358914F525798FA5007A0B58 /* TrackpointDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 358914F325798FA5007A0B58 /* TrackpointDevice.cpp */; }; 7BBAB1FD22E3A2F800B2941A /* VoodooInput.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 7BBAB1FC22E3A2F800B2941A /* VoodooInput.hpp */; }; @@ -24,6 +26,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 28783C5129733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputWellspringEventDriver.cpp; sourceTree = ""; }; + 28783C5229733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputWellspringEventDriver.hpp; sourceTree = ""; }; 358914F225798FA5007A0B58 /* TrackpointDevice.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrackpointDevice.hpp; sourceTree = ""; }; 358914F325798FA5007A0B58 /* TrackpointDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackpointDevice.cpp; sourceTree = ""; }; 7BBAB1F922E3A2F800B2941A /* VoodooInput.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VoodooInput.kext; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -152,6 +156,8 @@ EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */, EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */, EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */, + 28783C5129733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp */, + 28783C5229733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp */, ); path = VoodooInputWellspringSimulator; sourceTree = ""; @@ -168,6 +174,7 @@ 7BBAB21B22E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp in Headers */, EE7EE280296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp in Headers */, EE7EE284296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp in Headers */, + 28783C5429733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp in Headers */, 7BBAB1FD22E3A2F800B2941A /* VoodooInput.hpp in Headers */, EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */, ); @@ -245,7 +252,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "cd \"${TARGET_BUILD_DIR}\"\n\nstrip -S \"${EXECUTABLE_PATH}\"\n\ndist=(\"$FULL_PRODUCT_NAME\")\nif [ -d \"$DWARF_DSYM_FILE_NAME\" ]; then dist+=(\"$DWARF_DSYM_FILE_NAME\"); fi\n\narchive=\"${PRODUCT_NAME}-${MODULE_VERSION}-$(echo $CONFIGURATION | tr /a-z/ /A-Z/).zip\"\nrm -rf *.zip\nif [ \"$CONFIGURATION\" == \"Release\" ]; then\n strip -x -T \"${EXECUTABLE_PATH}\" &>/dev/null || strip -x \"${EXECUTABLE_PATH}\"\nfi\n\nif [ -z \"${OVERRIDE_PYTHON3}\" ]; then\n # Use whatever is in PATH\n OVERRIDE_PYTHON3=python3\nfi\n\nif [[ \"$ARCHS\" == *\"ACID32\"* ]]; then\n \"${OVERRIDE_PYTHON3}\" ${SRCROOT}/clang32/fix-macho32 \"${EXECUTABLE_PATH}\" || exit 1\nfi\nzip -qry -FS \"${archive}\" \"${dist[@]}\"\n"; + shellScript = "cd \"${TARGET_BUILD_DIR}\"\n\nstrip -S \"${EXECUTABLE_PATH}\"\n\ndist=(\"$FULL_PRODUCT_NAME\")\nif [ -d \"$DWARF_DSYM_FILE_NAME\" ]; then dist+=(\"$DWARF_DSYM_FILE_NAME\"); fi\n\narchive=\"${PRODUCT_NAME}-${MODULE_VERSION}-$(echo $CONFIGURATION | tr /a-z/ /A-Z/).zip\"\nrm -rf *.zip\nif [ \"$CONFIGURATION\" == \"Release\" ]; then\n strip -x -T \"${EXECUTABLE_PATH}\" &>/dev/null || strip -x \"${EXECUTABLE_PATH}\"\nfi\n\nif [ -z \"${OVERRIDE_PYTHON3}\" ]; then\n # Use whatever is in PATH\n OVERRIDE_PYTHON3=python3\nfi\n\nif [[ \"$ARCHS\" == *\"ACID32\"* ]]; then\n \"${OVERRIDE_PYTHON3}\" ${SRCROOT}/clang32/fix-macho32 \"${EXECUTABLE_PATH}\" || exit 1\nfi\nzip -qry -FS \"${archive}\" \"${dist[@]}\"\n"; }; CEC086492439FD5D00F5B701 /* Copy SDK */ = { isa = PBXShellScriptBuildPhase; @@ -291,6 +298,7 @@ buildActionMask = 2147483647; files = ( 358914F525798FA5007A0B58 /* TrackpointDevice.cpp in Sources */, + 28783C5329733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp in Sources */, 7BBAB1FF22E3A2F800B2941A /* VoodooInput.cpp in Sources */, 7BBAB21922E3AD0E00B2941A /* VoodooInputActuatorDevice.cpp in Sources */, EE7EE283296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp in Sources */, diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index df596f3..3bf89a0 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -20,6 +20,268 @@ $(CURRENT_PROJECT_VERSION) IOKitPersonalities + VoodooInput Wellspring Event Driver + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + DeviceUsagePairs + + + DeviceUsage + 1 + DeviceUsagePage + 65280 + + + HIDAccelCurves + + + HIDAccelGainLinear + 65536 + HIDAccelIndex + 0 + HIDAccelTangentSpeedLinear + 484966 + HIDAccelTangentSpeedParabolicRoot + 1376256 + + + HIDAccelGainCubic + 5243 + HIDAccelGainLinear + 70779 + HIDAccelGainParabolic + 32768 + HIDAccelIndex + 8192 + HIDAccelTangentSpeedLinear + 478413 + HIDAccelTangentSpeedParabolicRoot + 1310720 + + + HIDAccelGainCubic + 6554 + HIDAccelGainLinear + 76022 + HIDAccelGainParabolic + 43254 + HIDAccelIndex + 32768 + HIDAccelTangentSpeedLinear + 471859 + HIDAccelTangentSpeedParabolicRoot + 1245184 + + + HIDAccelGainCubic + 7864 + HIDAccelGainLinear + 81265 + HIDAccelGainParabolic + 54395 + HIDAccelIndex + 45056 + HIDAccelTangentSpeedLinear + 465306 + HIDAccelTangentSpeedParabolicRoot + 1179648 + + + HIDAccelGainCubic + 9830 + HIDAccelGainLinear + 86508 + HIDAccelGainParabolic + 65536 + HIDAccelIndex + 57344 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 1114112 + + + HIDAccelGainCubic + 11796 + HIDAccelGainLinear + 91750 + HIDAccelGainParabolic + 75366 + HIDAccelIndex + 65536 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 1048576 + + + HIDAccelGainCubic + 13763 + HIDAccelGainLinear + 96993 + HIDAccelGainParabolic + 85197 + HIDAccelIndex + 98304 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 983040 + + + HIDAccelGainCubic + 15729 + HIDAccelGainLinear + 102236 + HIDAccelGainParabolic + 95027 + HIDAccelIndex + 131072 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 917504 + + + HIDAccelGainCubic + 18350 + HIDAccelGainLinear + 106824 + HIDAccelGainParabolic + 108790 + HIDAccelIndex + 163840 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 851968 + + + HIDAccelGainCubic + 23593 + HIDAccelGainLinear + 111411 + HIDAccelGainParabolic + 123208 + HIDAccelIndex + 196608 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 786432 + + + HIDDefaultBehavior + + HIDPointerAccelerationType + HIDTrackpadAcceleration + HIDScrollAccelCurves + + + HIDAccelGainLinear + 85197 + HIDAccelGainParabolic + 13107 + HIDAccelIndex + 8192 + HIDAccelTangentSpeedLinear + 851968 + HIDAccelTangentSpeedParabolicRoot + 1310720 + + + HIDAccelGainLinear + 95027 + HIDAccelGainParabolic + 32768 + HIDAccelIndex + 14090 + HIDAccelTangentSpeedLinear + 786432 + HIDAccelTangentSpeedParabolicRoot + 1245184 + + + HIDAccelGainLinear + 104858 + HIDAccelGainParabolic + 45875 + HIDAccelIndex + 20480 + HIDAccelTangentSpeedLinear + 720896 + HIDAccelTangentSpeedParabolicRoot + 1179648 + + + HIDAccelGainLinear + 114688 + HIDAccelGainParabolic + 57017 + HIDAccelIndex + 32768 + HIDAccelTangentSpeedLinear + 655360 + HIDAccelTangentSpeedParabolicRoot + 1114112 + + + HIDAccelGainLinear + 124519 + HIDAccelGainParabolic + 68813 + HIDAccelIndex + 49152 + HIDAccelTangentSpeedLinear + 589824 + HIDAccelTangentSpeedParabolicRoot + 1048576 + + + HIDAccelGainLinear + 134349 + HIDAccelGainParabolic + 81920 + HIDAccelIndex + 65536 + HIDAccelTangentSpeedLinear + 524288 + HIDAccelTangentSpeedParabolicRoot + 983040 + + + HIDAccelGainLinear + 144179 + HIDAccelGainParabolic + 98304 + HIDAccelIndex + 111411 + HIDAccelTangentSpeedLinear + 458752 + HIDAccelTangentSpeedParabolicRoot + 917504 + + + HIDScrollAccelerationType + HIDTrackpadScrollAcceleration + HIDScrollResolution + 26214400 + IOClass + VoodooInputWellspringEventDriver + IOProviderClass + IOHIDInterface + MTEventSource + + ProductIDArray + + 567 + + TrackpadSecondaryClickCorners + + VendorID + 1452 + Voodoo Input CFBundleIdentifier @@ -360,8 +622,6 @@ Copyright © 2019 Kishor Prins. All rights reserved. OSBundleLibraries - com.apple.driver.AppleUSBMultitouch - 1.0.0 com.apple.iokit.IOHIDFamily 1.6 com.apple.kpi.iokit diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.cpp new file mode 100644 index 0000000..329b226 --- /dev/null +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.cpp @@ -0,0 +1,11 @@ +// +// VoodooInputWellspringEventDriver.cpp +// VoodooInput +// +// Created by Avery Black on 1/14/23. +// Copyright © 2023 Kishor Prins. All rights reserved. +// + +#include "VoodooInputWellspringEventDriver.hpp" + +OSDefineMetaClassAndStructors(VoodooInputWellspringEventDriver, IOHIDEventService); diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.hpp new file mode 100644 index 0000000..9633422 --- /dev/null +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.hpp @@ -0,0 +1,23 @@ +// +// VoodooInputWellspringEventDriver.hpp +// VoodooInput +// +// Created by Sheika Slate on 1/14/23. +// Copyright © 2023 Kishor Prins. All rights reserved. +// + +#ifndef VoodooInputWellspringEventDriver_hpp +#define VoodooInputWellspringEventDriver_hpp + +#include + +class VoodooInputWellspringSimulator; + +class VoodooInputWellspringEventDriver : public IOHIDEventService { + OSDeclareDefaultStructorsWithDispatch(VoodooInputWellspringEventDriver); + friend class VoodooInputWellspringSimulator; +public: + virtual IOReturn setSystemProperties(OSDictionary *) override; +}; + +#endif /* VoodooInputWellspringEventDriver_hpp */ diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index e163b09..f4ee2e6 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -175,7 +175,7 @@ bool VoodooInputWellspringSimulator::start(IOService *provider) { } void VoodooInputWellspringSimulator::createEventDriverNotifiers() { - OSDictionary *matching = serviceMatching("AppleUSBMultitouchHIDEventDriver"); + OSDictionary *matching = serviceMatching("VoodooInputWellspringEventDriver"); propertyMatching(OSSymbol::withCString("LocationID"), newLocationIDNumber(), matching); #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6 @@ -207,7 +207,7 @@ void VoodooInputWellspringSimulator::notificationEventDriver(IOService * newServ void VoodooInputWellspringSimulator::notificationEventDriverPublished(IOService *newService) { if (eventDriver == nullptr) { - eventDriver = OSDynamicCast(AppleUSBMultitouchHIDEventDriver, newService); + eventDriver = OSDynamicCast(VoodooInputWellspringEventDriver, newService); if (eventDriver != nullptr) eventDriver->retain(); else IOLog("%s is null!?!?!?!\n", getName()); } diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index 3f37ade..c0aee6f 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -10,12 +10,12 @@ #define AppleUSBMultitouchDriver_hpp #include -#include #include #include #include #include +#include "VoodooInputWellspringEventDriver.hpp" #include "../VoodooInput.hpp" #include "../VoodooInputMultitouch/VoodooInputTransducer.h" #include "../VoodooInputMultitouch/VoodooInputEvent.h" @@ -31,16 +31,8 @@ #define MT2_TOUCH_STATE_BIT_NEAR (0x1 << 1) #define MT2_TOUCH_STATE_BIT_CONTACT (0x1 << 2) -class VoodooInputWellspringSimulator; class VoodooInputWellspringUserClient; -class AppleUSBMultitouchHIDEventDriver : public IOHIDEventService { - OSDeclareDefaultStructorsWithDispatch(AppleUSBMultitouchHIDEventDriver); - friend class VoodooInputWellspringSimulator; -public: - virtual IOReturn setSystemProperties(OSDictionary *) override; -}; - // This report does not come from the hardware, but instead comes from within AppleUSBMultitouch in 10.12+ // This gets sent to userspace on any button presses struct __attribute__((__packed__)) MTRelativePointerReport { @@ -148,7 +140,7 @@ class EXPORT VoodooInputWellspringSimulator : public IOHIDDevice { OSSet *userClients {nullptr}; VoodooInput *engine {nullptr}; - AppleUSBMultitouchHIDEventDriver *eventDriver {nullptr}; + VoodooInputWellspringEventDriver *eventDriver {nullptr}; AbsoluteTime startTimestamp {}; size_t inputReportSize {}; From 13569b67da6e0ba72431fa6d614f037e2cbf7e29 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 14 Jan 2023 11:58:49 -0800 Subject: [PATCH 24/32] Set probe score so event driver attaches --- VoodooInput/Info.plist | 2 ++ .../VoodooInputWellspringEventDriver.hpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index 3bf89a0..08d7e9a 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -269,6 +269,8 @@ 26214400 IOClass VoodooInputWellspringEventDriver + IOProbeScore + 500 IOProviderClass IOHIDInterface MTEventSource diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.hpp index 9633422..1c28f4e 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringEventDriver.hpp @@ -16,8 +16,6 @@ class VoodooInputWellspringSimulator; class VoodooInputWellspringEventDriver : public IOHIDEventService { OSDeclareDefaultStructorsWithDispatch(VoodooInputWellspringEventDriver); friend class VoodooInputWellspringSimulator; -public: - virtual IOReturn setSystemProperties(OSDictionary *) override; }; #endif /* VoodooInputWellspringEventDriver_hpp */ From 076008b44501c30175af2a6a56f51de9613cf28e Mon Sep 17 00:00:00 2001 From: Avery Black Date: Sat, 14 Jan 2023 19:40:56 -0800 Subject: [PATCH 25/32] Rename to workaround Sandbox --- VoodooInput.xcodeproj/project.pbxproj | 16 +- VoodooInput/Info.plist | 2 +- .../IOHIDVoodooInputWellspringUserClient.cpp | 147 ++++++++++++++++++ ... IOHIDVoodooInputWellspringUserClient.hpp} | 10 +- .../VoodooInputWellspringSimulator.cpp | 6 +- .../VoodooInputWellspringSimulator.hpp | 2 +- .../VoodooInputWellspringUserClient.cpp | 46 +++--- 7 files changed, 188 insertions(+), 41 deletions(-) create mode 100644 VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.cpp rename VoodooInput/VoodooInputWellspringSimulator/{VoodooInputWellspringUserClient.hpp => IOHIDVoodooInputWellspringUserClient.hpp} (81%) diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index f1b5f30..e073de0 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -21,8 +21,8 @@ EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EEC13CEA2C1DFD270080F2D1 /* VoodooInputIDs.hpp */; }; EE7EE27F296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */; }; EE7EE280296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */; }; - EE7EE283296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */; }; - EE7EE284296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */; }; + EE7EE283296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE281296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp */; }; + EE7EE284296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE282296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -49,8 +49,8 @@ EEC13CEA2C1DFD270080F2D1 /* VoodooInputIDs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputIDs.hpp; sourceTree = ""; }; EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputWellspringSimulator.cpp; sourceTree = ""; }; EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputWellspringSimulator.hpp; sourceTree = ""; }; - EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputWellspringUserClient.cpp; sourceTree = ""; }; - EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputWellspringUserClient.hpp; sourceTree = ""; }; + EE7EE281296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IOHIDVoodooInputWellspringUserClient.cpp; sourceTree = ""; }; + EE7EE282296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IOHIDVoodooInputWellspringUserClient.hpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -154,8 +154,8 @@ children = ( EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */, EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */, - EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */, - EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */, + EE7EE281296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp */, + EE7EE282296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp */, 28783C5129733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp */, 28783C5229733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp */, ); @@ -173,7 +173,7 @@ 358914F425798FA5007A0B58 /* TrackpointDevice.hpp in Headers */, 7BBAB21B22E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp in Headers */, EE7EE280296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp in Headers */, - EE7EE284296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp in Headers */, + EE7EE284296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp in Headers */, 28783C5429733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp in Headers */, 7BBAB1FD22E3A2F800B2941A /* VoodooInput.hpp in Headers */, EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */, @@ -301,7 +301,7 @@ 28783C5329733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp in Sources */, 7BBAB1FF22E3A2F800B2941A /* VoodooInput.cpp in Sources */, 7BBAB21922E3AD0E00B2941A /* VoodooInputActuatorDevice.cpp in Sources */, - EE7EE283296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp in Sources */, + EE7EE283296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp in Sources */, EE7EE27F296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp in Sources */, 7BBAB21822E3AD0E00B2941A /* VoodooInputSimulatorDevice.cpp in Sources */, ); diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index 08d7e9a..be04c99 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -291,7 +291,7 @@ MT1Props IOUserClientClass - VoodooInputWellspringUserClient + IOHIDVoodooInputWellspringUserClient parser-type 1000 parser-options diff --git a/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.cpp new file mode 100644 index 0000000..db028dc --- /dev/null +++ b/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.cpp @@ -0,0 +1,147 @@ +// +// VoodooInputMT1UserClient.cpp +// VoodooInput +// +// Created by Avery Black on 12/31/22. +// Copyright © 2022 Kishor Prins. All rights reserved. +// + +#include "IOHIDVoodooInputWellspringUserClient.hpp" +#include "VoodooInputWellspringSimulator.hpp" + +#define super IOUserClient +OSDefineMetaClassAndStructors(IOHIDVoodooInputWellspringUserClient, IOUserClient); + +#if defined(__x86_64__) +#define MTExternalMethod(method, flags, inputs, outputs) {0, method, kIOExternalMethodACIDPadding, flags, inputs, outputs} +#elif defined(__i386__) +#define MTExternalMethod(method, flags, inputs, outputs) {0, kIOExternalMethodACIDPadding, method, flags, inputs, outputs} +#else +#error "Invalid architecture" +#endif + +IOExternalMethodACID IOHIDVoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { + // VoodooInputMT1UserClientMethodsSetSendsFrames + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0), + // VoodooInputMT1UserClientMethodsGetReport + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), + // VoodooInputMT1UserClientMethodsSetReport + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), + // VoodooInputMT1UserClientMethodsSetSendLogs + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), + // VoodooInputMT1UserClientMethodsIssueDriverRequest + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204), + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Relative Mouse Movement + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Scroll Wheel + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0), // Keyboard + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // Map Clicks + // VoodooInputMT1UserClientMethodsRecacheProperties + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0), + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Momentum Scroll +}; + +bool IOHIDVoodooInputWellspringUserClient::start(IOService *provider) { + if (!super::start(provider)) return false; + simulator = OSDynamicCast(VoodooInputWellspringSimulator, provider); + + if (simulator == nullptr) { + IOLog("%s Invalid provider!\n", getName()); + return false; + } + + dataQueue = IOSharedDataQueue::withCapacity(0x10004); + // I haven't seen the log queue used yet. + // Leaving this here with a small size in case userspace decides to ask for it at some point. + logQueue = IOSharedDataQueue::withCapacity(0x1); + + if (dataQueue == nullptr || logQueue == nullptr) { + return false; + } + + dataQueueDesc = dataQueue->getMemoryDescriptor(); + logQueueDesc = logQueue->getMemoryDescriptor(); + if (dataQueueDesc == nullptr || logQueueDesc == nullptr) { + return false; + } + + return true; +} + +void IOHIDVoodooInputWellspringUserClient::free() { + OSSafeReleaseNULL(dataQueueDesc); + OSSafeReleaseNULL(dataQueue); + OSSafeReleaseNULL(logQueueDesc); + OSSafeReleaseNULL(logQueue); + super::free(); +} + +IOReturn IOHIDVoodooInputWellspringUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { + IOLog("%s client notif port\n", getName()); + dataQueue->setNotificationPort(port); + logQueue->setNotificationPort(port); + return kIOReturnSuccess; +} + +IOReturn IOHIDVoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { + // The memory descriptors get released when being mapped in IOUserClient::mapClientMemory + if (type != 0x10) { + dataQueueDesc->retain(); + *memory = dataQueueDesc; + } else { + logQueueDesc->retain(); + *memory = logQueue->getMemoryDescriptor(); + } + + *options = 0; + return kIOReturnSuccess; +} + +IOExternalMethod *IOHIDVoodooInputWellspringUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { + IOLog("%s External Method %u\n", getName(), index); + if (index >= VoodooInputMT1UserClientMethodsNumMethods) { + return nullptr; + } + + *targetP = this; + return reinterpret_cast(&sMethods[index]); +} + +IOReturn IOHIDVoodooInputWellspringUserClient::sSetSendFrames(IOHIDVoodooInputWellspringUserClient *that, bool enableReports) { + bool success = true; + IOLog("%s Set Send Frames: %d\n", that->getName(), enableReports); + + if (enableReports) { + success = that->simulator->registerUserClient(that); + } else { + that->simulator->unregisterUserClient(that); + } + + return success ? kIOReturnSuccess : kIOReturnError; +} + +// I'm not really sure why they use two different structs here??? +IOReturn IOHIDVoodooInputWellspringUserClient::sGetReport(IOHIDVoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output) { + if (input == nullptr || output == nullptr) { + return kIOReturnBadArgument; + } + + IOLog("%s Get Report: %u\n", that->getName(), input->reportId); + + IOReturn ret = that->simulator->getReport(input); + if (ret == kIOReturnSuccess) { + memmove(output->data, input->data, input->dataSize); + output->dataSize = input->dataSize; + } + + return ret; +} + +void IOHIDVoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { + if (dataQueue == nullptr) return; + dataQueue->enqueue(data, (UInt32) size); +} + +IOReturn IOHIDVoodooInputWellspringUserClient::sNoop(IOHIDVoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { + IOLog("%s Noop was called!\n", that->getName()); + return kIOReturnSuccess; // noop +} diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp b/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.hpp similarity index 81% rename from VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp rename to VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.hpp index 27875fc..0149dd4 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.hpp @@ -38,8 +38,8 @@ static_assert(VoodooInputMT1UserClientMethodsNumMethods == 11, "Invalid number o struct MTDeviceReportStruct; class VoodooInputWellspringSimulator; -class EXPORT VoodooInputWellspringUserClient : public IOUserClient { - OSDeclareDefaultStructors(VoodooInputWellspringUserClient); +class EXPORT IOHIDVoodooInputWellspringUserClient : public IOUserClient { + OSDeclareDefaultStructors(IOHIDVoodooInputWellspringUserClient); public: virtual bool start(IOService *provider) override; @@ -49,9 +49,9 @@ class EXPORT VoodooInputWellspringUserClient : public IOUserClient { virtual IOReturn clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) override; virtual IOExternalMethod *getTargetAndMethodForIndex(IOService **targetP, UInt32 index) override; - static IOReturn sSetSendFrames(VoodooInputWellspringUserClient *that, bool enableFrames); - static IOReturn sGetReport(VoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output); - static IOReturn sNoop(VoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + static IOReturn sSetSendFrames(IOHIDVoodooInputWellspringUserClient *that, bool enableFrames); + static IOReturn sGetReport(IOHIDVoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output); + static IOReturn sNoop(IOHIDVoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); void enqueueData(void *data, size_t size); private: diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index f4ee2e6..6eded26 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -7,7 +7,7 @@ // #include "VoodooInputWellspringSimulator.hpp" -#include "VoodooInputWellspringUserClient.hpp" +#include "IOHIDVoodooInputWellspringUserClient.hpp" #include "VoodooInputActuatorDevice.hpp" #include "VoodooInputMessages.h" @@ -338,7 +338,7 @@ void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { report.Unknown1 = 1; report.Timestamp = timestamp; OSCollectionIterator *iter = OSCollectionIterator::withCollection(userClients); - while (VoodooInputWellspringUserClient *client = OSDynamicCast(VoodooInputWellspringUserClient, iter->getNextObject())) { + while (IOHIDVoodooInputWellspringUserClient *client = OSDynamicCast(IOHIDVoodooInputWellspringUserClient, iter->getNextObject())) { client->enqueueData(&report, sizeof(MTRelativePointerReport)); } OSSafeReleaseNULL(iter); @@ -511,7 +511,7 @@ void VoodooInputWellspringSimulator::enqueueData(WELLSPRING_REPORT *report, size #endif OSCollectionIterator *iter = OSCollectionIterator::withCollection(userClients); - while (VoodooInputWellspringUserClient *client = OSDynamicCast(VoodooInputWellspringUserClient, iter->getNextObject())) { + while (IOHIDVoodooInputWellspringUserClient *client = OSDynamicCast(IOHIDVoodooInputWellspringUserClient, iter->getNextObject())) { client->enqueueData(report, dataLen); } OSSafeReleaseNULL(iter); diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index c0aee6f..b85e7fd 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -31,7 +31,7 @@ #define MT2_TOUCH_STATE_BIT_NEAR (0x1 << 1) #define MT2_TOUCH_STATE_BIT_CONTACT (0x1 << 2) -class VoodooInputWellspringUserClient; +class IOHIDVoodooInputWellspringUserClient; // This report does not come from the hardware, but instead comes from within AppleUSBMultitouch in 10.12+ // This gets sent to userspace on any button presses diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 83e1dd0..db028dc 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -6,11 +6,11 @@ // Copyright © 2022 Kishor Prins. All rights reserved. // -#include "VoodooInputWellspringUserClient.hpp" +#include "IOHIDVoodooInputWellspringUserClient.hpp" #include "VoodooInputWellspringSimulator.hpp" #define super IOUserClient -OSDefineMetaClassAndStructors(VoodooInputWellspringUserClient, IOUserClient); +OSDefineMetaClassAndStructors(IOHIDVoodooInputWellspringUserClient, IOUserClient); #if defined(__x86_64__) #define MTExternalMethod(method, flags, inputs, outputs) {0, method, kIOExternalMethodACIDPadding, flags, inputs, outputs} @@ -20,27 +20,27 @@ OSDefineMetaClassAndStructors(VoodooInputWellspringUserClient, IOUserClient); #error "Invalid architecture" #endif -IOExternalMethodACID VoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { +IOExternalMethodACID IOHIDVoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { // VoodooInputMT1UserClientMethodsSetSendsFrames - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0), + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0), // VoodooInputMT1UserClientMethodsGetReport - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), // VoodooInputMT1UserClientMethodsSetReport - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), // VoodooInputMT1UserClientMethodsSetSendLogs - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // VoodooInputMT1UserClientMethodsIssueDriverRequest - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204), - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Relative Mouse Movement - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Scroll Wheel - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0), // Keyboard - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // Map Clicks + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204), + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Relative Mouse Movement + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Scroll Wheel + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0), // Keyboard + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // Map Clicks // VoodooInputMT1UserClientMethodsRecacheProperties - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0), - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Momentum Scroll + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0), + MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Momentum Scroll }; -bool VoodooInputWellspringUserClient::start(IOService *provider) { +bool IOHIDVoodooInputWellspringUserClient::start(IOService *provider) { if (!super::start(provider)) return false; simulator = OSDynamicCast(VoodooInputWellspringSimulator, provider); @@ -67,7 +67,7 @@ bool VoodooInputWellspringUserClient::start(IOService *provider) { return true; } -void VoodooInputWellspringUserClient::free() { +void IOHIDVoodooInputWellspringUserClient::free() { OSSafeReleaseNULL(dataQueueDesc); OSSafeReleaseNULL(dataQueue); OSSafeReleaseNULL(logQueueDesc); @@ -75,14 +75,14 @@ void VoodooInputWellspringUserClient::free() { super::free(); } -IOReturn VoodooInputWellspringUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { +IOReturn IOHIDVoodooInputWellspringUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { IOLog("%s client notif port\n", getName()); dataQueue->setNotificationPort(port); logQueue->setNotificationPort(port); return kIOReturnSuccess; } -IOReturn VoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { +IOReturn IOHIDVoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { // The memory descriptors get released when being mapped in IOUserClient::mapClientMemory if (type != 0x10) { dataQueueDesc->retain(); @@ -96,7 +96,7 @@ IOReturn VoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOpt return kIOReturnSuccess; } -IOExternalMethod *VoodooInputWellspringUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { +IOExternalMethod *IOHIDVoodooInputWellspringUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { IOLog("%s External Method %u\n", getName(), index); if (index >= VoodooInputMT1UserClientMethodsNumMethods) { return nullptr; @@ -106,7 +106,7 @@ IOExternalMethod *VoodooInputWellspringUserClient::getTargetAndMethodForIndex(IO return reinterpret_cast(&sMethods[index]); } -IOReturn VoodooInputWellspringUserClient::sSetSendFrames(VoodooInputWellspringUserClient *that, bool enableReports) { +IOReturn IOHIDVoodooInputWellspringUserClient::sSetSendFrames(IOHIDVoodooInputWellspringUserClient *that, bool enableReports) { bool success = true; IOLog("%s Set Send Frames: %d\n", that->getName(), enableReports); @@ -120,7 +120,7 @@ IOReturn VoodooInputWellspringUserClient::sSetSendFrames(VoodooInputWellspringUs } // I'm not really sure why they use two different structs here??? -IOReturn VoodooInputWellspringUserClient::sGetReport(VoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output) { +IOReturn IOHIDVoodooInputWellspringUserClient::sGetReport(IOHIDVoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output) { if (input == nullptr || output == nullptr) { return kIOReturnBadArgument; } @@ -136,12 +136,12 @@ IOReturn VoodooInputWellspringUserClient::sGetReport(VoodooInputWellspringUserCl return ret; } -void VoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { +void IOHIDVoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { if (dataQueue == nullptr) return; dataQueue->enqueue(data, (UInt32) size); } -IOReturn VoodooInputWellspringUserClient::sNoop(VoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { +IOReturn IOHIDVoodooInputWellspringUserClient::sNoop(IOHIDVoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { IOLog("%s Noop was called!\n", that->getName()); return kIOReturnSuccess; // noop } From b7a4c4a9019fec6aa75f9ea1cf11be54c5de23b1 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Mon, 23 Jan 2023 21:31:54 -0800 Subject: [PATCH 26/32] Remove space, set button to zero when all fingers are gone --- .../VoodooInputWellspringSimulator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 6eded26..84b7ecc 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -393,7 +393,7 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { for (int i = 0; i < event.contact_count; i++) { const VoodooInputTransducer &transducer = event.transducers[i]; - if (!transducer.isValid) + if (!transducer.isValid) continue; if (transducer.type == VoodooInputTransducerType::STYLUS) { @@ -471,6 +471,7 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { if (!input_active) { memset(touchActive, false, sizeof(touchActive)); constructButtonReport(0); + inputReport->Button = 0; // Stop finger inputReport->Counter++; From 2b0caa887728b18bf22b25be3ec687b0d0f06934 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Tue, 14 Feb 2023 14:00:19 -0800 Subject: [PATCH 27/32] Revert IOHID changes It's easier to keep the current MT2 emulation for newer macOS versions, instead of trying to work around Sandbox --- VoodooInput.xcodeproj/project.pbxproj | 16 +- .../IOHIDVoodooInputWellspringUserClient.cpp | 147 ------------------ .../VoodooInputWellspringSimulator.hpp | 2 +- .../VoodooInputWellspringUserClient.cpp | 46 +++--- ...pp => VoodooInputWellspringUserClient.hpp} | 10 +- 5 files changed, 37 insertions(+), 184 deletions(-) delete mode 100644 VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.cpp rename VoodooInput/VoodooInputWellspringSimulator/{IOHIDVoodooInputWellspringUserClient.hpp => VoodooInputWellspringUserClient.hpp} (81%) diff --git a/VoodooInput.xcodeproj/project.pbxproj b/VoodooInput.xcodeproj/project.pbxproj index e073de0..f1b5f30 100644 --- a/VoodooInput.xcodeproj/project.pbxproj +++ b/VoodooInput.xcodeproj/project.pbxproj @@ -21,8 +21,8 @@ EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EEC13CEA2C1DFD270080F2D1 /* VoodooInputIDs.hpp */; }; EE7EE27F296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */; }; EE7EE280296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */; }; - EE7EE283296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE281296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp */; }; - EE7EE284296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE282296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp */; }; + EE7EE283296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */; }; + EE7EE284296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -49,8 +49,8 @@ EEC13CEA2C1DFD270080F2D1 /* VoodooInputIDs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputIDs.hpp; sourceTree = ""; }; EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputWellspringSimulator.cpp; sourceTree = ""; }; EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputWellspringSimulator.hpp; sourceTree = ""; }; - EE7EE281296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = IOHIDVoodooInputWellspringUserClient.cpp; sourceTree = ""; }; - EE7EE282296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = IOHIDVoodooInputWellspringUserClient.hpp; sourceTree = ""; }; + EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VoodooInputWellspringUserClient.cpp; sourceTree = ""; }; + EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = VoodooInputWellspringUserClient.hpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -154,8 +154,8 @@ children = ( EE7EE27D296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp */, EE7EE27E296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp */, - EE7EE281296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp */, - EE7EE282296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp */, + EE7EE281296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp */, + EE7EE282296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp */, 28783C5129733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp */, 28783C5229733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp */, ); @@ -173,7 +173,7 @@ 358914F425798FA5007A0B58 /* TrackpointDevice.hpp in Headers */, 7BBAB21B22E3AD0E00B2941A /* VoodooInputActuatorDevice.hpp in Headers */, EE7EE280296116D7005EFCC4 /* VoodooInputWellspringSimulator.hpp in Headers */, - EE7EE284296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.hpp in Headers */, + EE7EE284296119AB005EFCC4 /* VoodooInputWellspringUserClient.hpp in Headers */, 28783C5429733DA7002025A5 /* VoodooInputWellspringEventDriver.hpp in Headers */, 7BBAB1FD22E3A2F800B2941A /* VoodooInput.hpp in Headers */, EEC13CEB2C1DFD300080F2D1 /* VoodooInputIDs.hpp in Headers */, @@ -301,7 +301,7 @@ 28783C5329733DA7002025A5 /* VoodooInputWellspringEventDriver.cpp in Sources */, 7BBAB1FF22E3A2F800B2941A /* VoodooInput.cpp in Sources */, 7BBAB21922E3AD0E00B2941A /* VoodooInputActuatorDevice.cpp in Sources */, - EE7EE283296119AB005EFCC4 /* IOHIDVoodooInputWellspringUserClient.cpp in Sources */, + EE7EE283296119AB005EFCC4 /* VoodooInputWellspringUserClient.cpp in Sources */, EE7EE27F296116D7005EFCC4 /* VoodooInputWellspringSimulator.cpp in Sources */, 7BBAB21822E3AD0E00B2941A /* VoodooInputSimulatorDevice.cpp in Sources */, ); diff --git a/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.cpp deleted file mode 100644 index db028dc..0000000 --- a/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// VoodooInputMT1UserClient.cpp -// VoodooInput -// -// Created by Avery Black on 12/31/22. -// Copyright © 2022 Kishor Prins. All rights reserved. -// - -#include "IOHIDVoodooInputWellspringUserClient.hpp" -#include "VoodooInputWellspringSimulator.hpp" - -#define super IOUserClient -OSDefineMetaClassAndStructors(IOHIDVoodooInputWellspringUserClient, IOUserClient); - -#if defined(__x86_64__) -#define MTExternalMethod(method, flags, inputs, outputs) {0, method, kIOExternalMethodACIDPadding, flags, inputs, outputs} -#elif defined(__i386__) -#define MTExternalMethod(method, flags, inputs, outputs) {0, kIOExternalMethodACIDPadding, method, flags, inputs, outputs} -#else -#error "Invalid architecture" -#endif - -IOExternalMethodACID IOHIDVoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { - // VoodooInputMT1UserClientMethodsSetSendsFrames - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0), - // VoodooInputMT1UserClientMethodsGetReport - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), - // VoodooInputMT1UserClientMethodsSetReport - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), - // VoodooInputMT1UserClientMethodsSetSendLogs - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), - // VoodooInputMT1UserClientMethodsIssueDriverRequest - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204), - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Relative Mouse Movement - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Scroll Wheel - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0), // Keyboard - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // Map Clicks - // VoodooInputMT1UserClientMethodsRecacheProperties - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0), - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Momentum Scroll -}; - -bool IOHIDVoodooInputWellspringUserClient::start(IOService *provider) { - if (!super::start(provider)) return false; - simulator = OSDynamicCast(VoodooInputWellspringSimulator, provider); - - if (simulator == nullptr) { - IOLog("%s Invalid provider!\n", getName()); - return false; - } - - dataQueue = IOSharedDataQueue::withCapacity(0x10004); - // I haven't seen the log queue used yet. - // Leaving this here with a small size in case userspace decides to ask for it at some point. - logQueue = IOSharedDataQueue::withCapacity(0x1); - - if (dataQueue == nullptr || logQueue == nullptr) { - return false; - } - - dataQueueDesc = dataQueue->getMemoryDescriptor(); - logQueueDesc = logQueue->getMemoryDescriptor(); - if (dataQueueDesc == nullptr || logQueueDesc == nullptr) { - return false; - } - - return true; -} - -void IOHIDVoodooInputWellspringUserClient::free() { - OSSafeReleaseNULL(dataQueueDesc); - OSSafeReleaseNULL(dataQueue); - OSSafeReleaseNULL(logQueueDesc); - OSSafeReleaseNULL(logQueue); - super::free(); -} - -IOReturn IOHIDVoodooInputWellspringUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { - IOLog("%s client notif port\n", getName()); - dataQueue->setNotificationPort(port); - logQueue->setNotificationPort(port); - return kIOReturnSuccess; -} - -IOReturn IOHIDVoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { - // The memory descriptors get released when being mapped in IOUserClient::mapClientMemory - if (type != 0x10) { - dataQueueDesc->retain(); - *memory = dataQueueDesc; - } else { - logQueueDesc->retain(); - *memory = logQueue->getMemoryDescriptor(); - } - - *options = 0; - return kIOReturnSuccess; -} - -IOExternalMethod *IOHIDVoodooInputWellspringUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { - IOLog("%s External Method %u\n", getName(), index); - if (index >= VoodooInputMT1UserClientMethodsNumMethods) { - return nullptr; - } - - *targetP = this; - return reinterpret_cast(&sMethods[index]); -} - -IOReturn IOHIDVoodooInputWellspringUserClient::sSetSendFrames(IOHIDVoodooInputWellspringUserClient *that, bool enableReports) { - bool success = true; - IOLog("%s Set Send Frames: %d\n", that->getName(), enableReports); - - if (enableReports) { - success = that->simulator->registerUserClient(that); - } else { - that->simulator->unregisterUserClient(that); - } - - return success ? kIOReturnSuccess : kIOReturnError; -} - -// I'm not really sure why they use two different structs here??? -IOReturn IOHIDVoodooInputWellspringUserClient::sGetReport(IOHIDVoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output) { - if (input == nullptr || output == nullptr) { - return kIOReturnBadArgument; - } - - IOLog("%s Get Report: %u\n", that->getName(), input->reportId); - - IOReturn ret = that->simulator->getReport(input); - if (ret == kIOReturnSuccess) { - memmove(output->data, input->data, input->dataSize); - output->dataSize = input->dataSize; - } - - return ret; -} - -void IOHIDVoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { - if (dataQueue == nullptr) return; - dataQueue->enqueue(data, (UInt32) size); -} - -IOReturn IOHIDVoodooInputWellspringUserClient::sNoop(IOHIDVoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { - IOLog("%s Noop was called!\n", that->getName()); - return kIOReturnSuccess; // noop -} diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index b85e7fd..c0aee6f 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -31,7 +31,7 @@ #define MT2_TOUCH_STATE_BIT_NEAR (0x1 << 1) #define MT2_TOUCH_STATE_BIT_CONTACT (0x1 << 2) -class IOHIDVoodooInputWellspringUserClient; +class VoodooInputWellspringUserClient; // This report does not come from the hardware, but instead comes from within AppleUSBMultitouch in 10.12+ // This gets sent to userspace on any button presses diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index db028dc..83e1dd0 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -6,11 +6,11 @@ // Copyright © 2022 Kishor Prins. All rights reserved. // -#include "IOHIDVoodooInputWellspringUserClient.hpp" +#include "VoodooInputWellspringUserClient.hpp" #include "VoodooInputWellspringSimulator.hpp" #define super IOUserClient -OSDefineMetaClassAndStructors(IOHIDVoodooInputWellspringUserClient, IOUserClient); +OSDefineMetaClassAndStructors(VoodooInputWellspringUserClient, IOUserClient); #if defined(__x86_64__) #define MTExternalMethod(method, flags, inputs, outputs) {0, method, kIOExternalMethodACIDPadding, flags, inputs, outputs} @@ -20,27 +20,27 @@ OSDefineMetaClassAndStructors(IOHIDVoodooInputWellspringUserClient, IOUserClient #error "Invalid architecture" #endif -IOExternalMethodACID IOHIDVoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { +IOExternalMethodACID VoodooInputWellspringUserClient::sMethods[VoodooInputMT1UserClientMethodsNumMethods] = { // VoodooInputMT1UserClientMethodsSetSendsFrames - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sSetSendFrames, kIOUCScalarIScalarO, 1, 0), // VoodooInputMT1UserClientMethodsGetReport - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sGetReport, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), // VoodooInputMT1UserClientMethodsSetReport - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, sizeof(MTDeviceReportStruct), sizeof(MTDeviceReportStruct)), // VoodooInputMT1UserClientMethodsSetSendLogs - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // VoodooInputMT1UserClientMethodsIssueDriverRequest - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204), - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Relative Mouse Movement - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Scroll Wheel - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0), // Keyboard - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // Map Clicks + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Relative Mouse Movement + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Scroll Wheel + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0), // Keyboard + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // Map Clicks // VoodooInputMT1UserClientMethodsRecacheProperties - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0), - MTExternalMethod((IOMethodACID) &IOHIDVoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Momentum Scroll + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Momentum Scroll }; -bool IOHIDVoodooInputWellspringUserClient::start(IOService *provider) { +bool VoodooInputWellspringUserClient::start(IOService *provider) { if (!super::start(provider)) return false; simulator = OSDynamicCast(VoodooInputWellspringSimulator, provider); @@ -67,7 +67,7 @@ bool IOHIDVoodooInputWellspringUserClient::start(IOService *provider) { return true; } -void IOHIDVoodooInputWellspringUserClient::free() { +void VoodooInputWellspringUserClient::free() { OSSafeReleaseNULL(dataQueueDesc); OSSafeReleaseNULL(dataQueue); OSSafeReleaseNULL(logQueueDesc); @@ -75,14 +75,14 @@ void IOHIDVoodooInputWellspringUserClient::free() { super::free(); } -IOReturn IOHIDVoodooInputWellspringUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { +IOReturn VoodooInputWellspringUserClient::registerNotificationPort(mach_port_t port, UInt32 type, UInt32 refCon) { IOLog("%s client notif port\n", getName()); dataQueue->setNotificationPort(port); logQueue->setNotificationPort(port); return kIOReturnSuccess; } -IOReturn IOHIDVoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { +IOReturn VoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) { // The memory descriptors get released when being mapped in IOUserClient::mapClientMemory if (type != 0x10) { dataQueueDesc->retain(); @@ -96,7 +96,7 @@ IOReturn IOHIDVoodooInputWellspringUserClient::clientMemoryForType(UInt32 type, return kIOReturnSuccess; } -IOExternalMethod *IOHIDVoodooInputWellspringUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { +IOExternalMethod *VoodooInputWellspringUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) { IOLog("%s External Method %u\n", getName(), index); if (index >= VoodooInputMT1UserClientMethodsNumMethods) { return nullptr; @@ -106,7 +106,7 @@ IOExternalMethod *IOHIDVoodooInputWellspringUserClient::getTargetAndMethodForInd return reinterpret_cast(&sMethods[index]); } -IOReturn IOHIDVoodooInputWellspringUserClient::sSetSendFrames(IOHIDVoodooInputWellspringUserClient *that, bool enableReports) { +IOReturn VoodooInputWellspringUserClient::sSetSendFrames(VoodooInputWellspringUserClient *that, bool enableReports) { bool success = true; IOLog("%s Set Send Frames: %d\n", that->getName(), enableReports); @@ -120,7 +120,7 @@ IOReturn IOHIDVoodooInputWellspringUserClient::sSetSendFrames(IOHIDVoodooInputWe } // I'm not really sure why they use two different structs here??? -IOReturn IOHIDVoodooInputWellspringUserClient::sGetReport(IOHIDVoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output) { +IOReturn VoodooInputWellspringUserClient::sGetReport(VoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output) { if (input == nullptr || output == nullptr) { return kIOReturnBadArgument; } @@ -136,12 +136,12 @@ IOReturn IOHIDVoodooInputWellspringUserClient::sGetReport(IOHIDVoodooInputWellsp return ret; } -void IOHIDVoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { +void VoodooInputWellspringUserClient::enqueueData(void *data, size_t size) { if (dataQueue == nullptr) return; dataQueue->enqueue(data, (UInt32) size); } -IOReturn IOHIDVoodooInputWellspringUserClient::sNoop(IOHIDVoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { +IOReturn VoodooInputWellspringUserClient::sNoop(VoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) { IOLog("%s Noop was called!\n", that->getName()); return kIOReturnSuccess; // noop } diff --git a/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp similarity index 81% rename from VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.hpp rename to VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp index 0149dd4..27875fc 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/IOHIDVoodooInputWellspringUserClient.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp @@ -38,8 +38,8 @@ static_assert(VoodooInputMT1UserClientMethodsNumMethods == 11, "Invalid number o struct MTDeviceReportStruct; class VoodooInputWellspringSimulator; -class EXPORT IOHIDVoodooInputWellspringUserClient : public IOUserClient { - OSDeclareDefaultStructors(IOHIDVoodooInputWellspringUserClient); +class EXPORT VoodooInputWellspringUserClient : public IOUserClient { + OSDeclareDefaultStructors(VoodooInputWellspringUserClient); public: virtual bool start(IOService *provider) override; @@ -49,9 +49,9 @@ class EXPORT IOHIDVoodooInputWellspringUserClient : public IOUserClient { virtual IOReturn clientMemoryForType(UInt32 type, IOOptionBits *options, IOMemoryDescriptor **memory) override; virtual IOExternalMethod *getTargetAndMethodForIndex(IOService **targetP, UInt32 index) override; - static IOReturn sSetSendFrames(IOHIDVoodooInputWellspringUserClient *that, bool enableFrames); - static IOReturn sGetReport(IOHIDVoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output); - static IOReturn sNoop(IOHIDVoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + static IOReturn sSetSendFrames(VoodooInputWellspringUserClient *that, bool enableFrames); + static IOReturn sGetReport(VoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output); + static IOReturn sNoop(VoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); void enqueueData(void *data, size_t size); private: From 95452a7dfd6e0fe1f5835e3ba4f793bb2116eb10 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Tue, 14 Feb 2023 14:23:42 -0800 Subject: [PATCH 28/32] Remove pressure support, only use Wellspring in older versions --- VoodooInput/Info.plist | 49 ------------------ VoodooInput/VoodooInput.cpp | 8 ++- .../VoodooInputActuatorDevice.cpp | 8 +-- .../VoodooInputWellspringSimulator.cpp | 50 ++++++++----------- .../VoodooInputWellspringSimulator.hpp | 14 +++--- 5 files changed, 37 insertions(+), 92 deletions(-) diff --git a/VoodooInput/Info.plist b/VoodooInput/Info.plist index be04c99..087516c 100644 --- a/VoodooInput/Info.plist +++ b/VoodooInput/Info.plist @@ -326,55 +326,6 @@ TrackpadThreeFingerDrag - MultitouchPreferences - - UserPreferences - - version - 12 - ActuateDetents - 1 - Clicking - 0 - DragLock - 0 - Dragging - 0 - FirstClickThreshold - 1 - ForceSuppressed - - SecondClickThreshold - 1 - TrackpadCornerSecondaryClick - 0 - TrackpadFiveFingerPinchGesture - 2 - TrackpadFourFingerHorizSwipeGesture - 2 - TrackpadFourFingerPinchGesture - 2 - TrackpadFourFingerVertSwipeGesture - 2 - TrackpadHorizScroll - 1 - TrackpadMomentumScroll - - TrackpadPinch - 1 - TrackpadRightClick - - TrackpadRotate - 1 - TrackpadScroll - - TrackpadThreeFingerDrag - - TrackpadThreeFingerHorizSwipeGesture - 2 - TrackpadThreeFingerVertSwipeGesture - 2 - IOCFPlugInTypes 0516B563-B15B-11DA-96EB-0014519758EF diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index 03e83d8..f1cc3f3 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -32,9 +32,13 @@ bool VoodooInput::start(IOService *provider) { IOLog("VoodooInput could not get provider properties!\n"); return false; } - - simulator = OSTypeAlloc(VoodooInputWellspringSimulator); + trackpoint = OSTypeAlloc(TrackpointDevice); + if (isSierraOrNewer()) { + simulator = OSTypeAlloc(VoodooInputSimulatorDevice); + } else { + simulator = OSTypeAlloc(VoodooInputWellspringSimulator); + } if (!simulator || !trackpoint) { IOLog("VoodooInput could not alloc simulator or trackpoint!\n"); diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp index 68dccfa..17db4a3 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputActuatorDevice.cpp @@ -48,15 +48,15 @@ OSNumber* VoodooInputActuatorDevice::newProductIDNumber() const { } OSString* VoodooInputActuatorDevice::newProductString() const { - return OSString::withCString("Wellspring Emulator"); + return OSString::withCString("Magic Trackpad 2"); } OSString* VoodooInputActuatorDevice::newSerialNumberString() const { - return OSString::withCString("Wellspring Actuator"); + return OSString::withCString("VoodooI2C Magic Trackpad 2 Actuator"); } OSString* VoodooInputActuatorDevice::newTransportString() const { - return OSString::withCString("USB"); + return OSString::withCString("I2C"); } OSNumber* VoodooInputActuatorDevice::newVendorIDNumber() const { @@ -64,7 +64,7 @@ OSNumber* VoodooInputActuatorDevice::newVendorIDNumber() const { } OSNumber* VoodooInputActuatorDevice::newLocationIDNumber() const { - return OSNumber::withNumber(0x1d183000, 32); + return OSNumber::withNumber(0x14400000, 32); } OSNumber* VoodooInputActuatorDevice::newVersionNumber() const { diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 84b7ecc..c2b775b 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -7,7 +7,7 @@ // #include "VoodooInputWellspringSimulator.hpp" -#include "IOHIDVoodooInputWellspringUserClient.hpp" +#include "VoodooInputWellspringUserClient.hpp" #include "VoodooInputActuatorDevice.hpp" #include "VoodooInputMessages.h" @@ -17,19 +17,20 @@ OSDefineMetaClassAndStructors(VoodooInputWellspringSimulator, IOHIDDevice); // Reports come from a MacbookPro9,2/MacbookPro12,1 static const UInt8 MTSensorParams[] = {0x00, 0x00, 0x03, 0x00, 0xD6, 0x01}; -// Region descriptor -// {Num regions, [type (1 = multitouch, 2 = force), start row, rows, row skip, start col, cols, hardware coloffset]} -static const UInt8 MTSensorDescOld[] = { +/* + * Region Descriptor { + * Num Regions + * [{ + * type (1 = multitouch, 2 = force), + * start row, rows, row skip, start col, cols, hardware coloffset + * }] + * } + */ +static const UInt8 MTSensorDesc[] = { 0x01, 0x01, 0x00, 0x0c, 0x01, 0x00, 0x14, 0x00 }; -static const UInt8 MTSensorDescSierra[] = { - 0x02, - 0x01, 0x00, 0x0c, 0x01, 0x00, 0x14, 0x00, - 0x02, 0x0c, 0x02, 0x01, 0x09, 0x02, 0x00 -}; - static const unsigned char report_descriptor[] = { 0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x03, 0x06, 0x00, 0xFF, 0x09, 0x01, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x85, @@ -108,25 +109,18 @@ void VoodooInputWellspringSimulator::setMTProperties() { setProperty("Family ID", 0x62, 8); setProperty("bcdVersion", 0x109, 16); setProperty("Max Packet Size", 0x200, 32); + setProperty("Sensor Region Descriptor", const_cast(MTSensorDesc), sizeof(MTSensorDesc)); - if (engine->isSierraOrNewer()) { - setProperty("Sensor Region Descriptor", const_cast(MTSensorDescSierra), sizeof(MTSensorDescSierra)); - + OSDictionary* trackpadPrefs = OSDictionary::withCapacity(1); + setProperty("TrackpadUserPreferences", trackpadPrefs); + + /*if (engine->isSierraOrNewer()) { setProperty("ApplePreferenceIdentifier", "com.apple.AppleMultitouchTrackpad"); - setProperty("ApplePreferenceCapability", 2, 32); + setProperty("ApplePreferenceCapability", kOSBooleanTrue); setProperty("SupportsGestureScrolling", kOSBooleanTrue); setProperty("MT Built-in", kOSBooleanTrue); setProperty("TrackpadEmbedded", kOSBooleanTrue); - setProperty("ForceSupported", kOSBooleanTrue); - setProperty("ActuationSupported", kOSBooleanTrue); - } else { - setProperty("Sensor Region Descriptor", const_cast(MTSensorDescOld), sizeof(MTSensorDescOld)); - - removeProperty("MultitouchPreferences"); - OSDictionary* trackpadPrefs = OSDictionary::withCapacity(1); - setProperty("TrackpadUserPreferences", trackpadPrefs); - OSSafeReleaseNULL(trackpadPrefs); - } + }*/ } bool VoodooInputWellspringSimulator::start(IOService *provider) { @@ -338,7 +332,7 @@ void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { report.Unknown1 = 1; report.Timestamp = timestamp; OSCollectionIterator *iter = OSCollectionIterator::withCollection(userClients); - while (IOHIDVoodooInputWellspringUserClient *client = OSDynamicCast(IOHIDVoodooInputWellspringUserClient, iter->getNextObject())) { + while (VoodooInputWellspringUserClient *client = OSDynamicCast(VoodooInputWellspringUserClient, iter->getNextObject())) { client->enqueueData(&report, sizeof(MTRelativePointerReport)); } OSSafeReleaseNULL(iter); @@ -435,19 +429,15 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { fingerData.Finger = transducer.fingerType; if (transducer.supportsPressure) { - fingerData.Pressure = transducer.currentCoordinates.pressure * 0xFF; fingerData.Size = transducer.currentCoordinates.width * 8; fingerData.ToolMajor = transducer.currentCoordinates.width * 16; fingerData.ToolMinor = transducer.currentCoordinates.width * 16; } else { - fingerData.Pressure = 100; fingerData.Size = 200; fingerData.ToolMajor = 800; fingerData.ToolMinor = 800; } - fingerData.DensityMajor = fingerData.DensityMinor = fingerData.Size; - if (!transducer.isTransducerActive && !transducer.isPhysicalButtonDown) { touchActive[touch_id] = false; fingerData.State = kTouchStateStop; @@ -512,7 +502,7 @@ void VoodooInputWellspringSimulator::enqueueData(WELLSPRING_REPORT *report, size #endif OSCollectionIterator *iter = OSCollectionIterator::withCollection(userClients); - while (IOHIDVoodooInputWellspringUserClient *client = OSDynamicCast(IOHIDVoodooInputWellspringUserClient, iter->getNextObject())) { + while (VoodooInputWellspringUserClient *client = OSDynamicCast(VoodooInputWellspringUserClient, iter->getNextObject())) { client->enqueueData(report, dataLen); } OSSafeReleaseNULL(iter); diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index c0aee6f..8bd2c67 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -60,15 +60,15 @@ struct __attribute__((__packed__)) WELLSPRING_FINGER { UInt16 ToolMinor; UInt16 Orientation; UInt16 Size; - UInt16 DensityMajor; - UInt16 DensityMinor; - UInt16 Unused[1]; - UInt16 Pressure; + /* + * ContactDensity can be calculated in MultitouchSupport.plugin + * UInt16 ContactDensity; + * UInt16 Unused[2]; + * UInt16 Pressure; // Not a thing on Wellspring3 + */ }; -// There's no finger field - -static_assert(sizeof(WELLSPRING_FINGER) == 28, "Unexpected WELLSPRING3_FINGER size"); +static_assert(sizeof(WELLSPRING_FINGER) == 20, "Unexpected WELLSPRING3_FINGER size"); struct __attribute__((__packed__)) WELLSPRING_REPORT { UInt8 ReportID; From 71a59c13eb8ac98396b5d757c4ddd7c9661d7d79 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Tue, 14 Feb 2023 14:46:43 -0800 Subject: [PATCH 29/32] Remove more sierra+ logic --- VoodooInput/VoodooInput.cpp | 2 +- VoodooInput/VoodooInput.hpp | 2 +- .../VoodooInputSimulatorDevice.cpp | 11 +++++++ .../VoodooInputSimulatorDevice.hpp | 1 + .../VoodooInputWellspringSimulator.cpp | 30 ++++++++----------- .../VoodooInputWellspringSimulator.hpp | 12 +------- 6 files changed, 28 insertions(+), 30 deletions(-) diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index f1cc3f3..9b1098c 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -179,7 +179,7 @@ IOReturn VoodooInput::message(UInt32 type, IOService *provider, void *argument) switch (type) { case kIOMessageVoodooInputMessage: if (provider == parentProvider && argument && simulator) - simulator->constructReport(*(VoodooInputEvent*)argument); + simulator->message(kIOMessageVoodooInputMessage, this, argument); break; case kIOMessageVoodooInputUpdateDimensionsMessage: diff --git a/VoodooInput/VoodooInput.hpp b/VoodooInput/VoodooInput.hpp index b27ee50..5bde6aa 100644 --- a/VoodooInput/VoodooInput.hpp +++ b/VoodooInput/VoodooInput.hpp @@ -36,7 +36,7 @@ class EXPORT VoodooInput : public IOService { IOService* parentProvider; - VoodooInputWellspringSimulator* simulator; + IOService* simulator; VoodooInputActuatorDevice* actuator; TrackpointDevice* trackpoint; diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.cpp b/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.cpp index 3a52f02..0aa5889 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.cpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.cpp @@ -8,6 +8,7 @@ #include "VoodooInput.hpp" #include "VoodooInputSimulatorDevice.hpp" #include "../VoodooInputMultitouch/MultitouchHelpers.h" +#include "../VoodooInputMultitouch/VoodooInputMessages.h" #include "VoodooInputIDs.hpp" #include @@ -528,3 +529,13 @@ OSNumber* VoodooInputSimulatorDevice::newLocationIDNumber() const { OSNumber* VoodooInputSimulatorDevice::newVersionNumber() const { return OSNumber::withNumber(0x804, 32); } + +IOReturn VoodooInputSimulatorDevice::message(UInt32 type, IOService *provider, void *argument) { + switch (type) { + case kIOMessageVoodooInputMessage: + if (argument) constructReport(*(VoodooInputEvent *) argument); + return kIOReturnSuccess; + } + + return super::message(type, provider, argument); +} diff --git a/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.hpp b/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.hpp index 71426c6..acb77f8 100644 --- a/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.hpp +++ b/VoodooInput/VoodooInputSimulator/VoodooInputSimulatorDevice.hpp @@ -107,6 +107,7 @@ class EXPORT VoodooInputSimulatorDevice : public IOHIDDevice { bool start(IOService* provider) override; void stop(IOService* provider) override; void releaseResources(); + virtual IOReturn message(UInt32 type, IOService *provider, void *argument) override; private: bool ready_for_reports {false}; diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index c2b775b..9de7927 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -113,6 +113,7 @@ void VoodooInputWellspringSimulator::setMTProperties() { OSDictionary* trackpadPrefs = OSDictionary::withCapacity(1); setProperty("TrackpadUserPreferences", trackpadPrefs); + OSSafeReleaseNULL(trackpadPrefs); /*if (engine->isSierraOrNewer()) { setProperty("ApplePreferenceIdentifier", "com.apple.AppleMultitouchTrackpad"); @@ -314,7 +315,6 @@ IOReturn VoodooInputWellspringSimulator::getReport(MTDeviceReportStruct *toFill) // MARK: Create Reports void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { - MTRelativePointerReport report; AbsoluteTime timestamp; clock_get_uptime(×tamp); @@ -322,21 +322,7 @@ void VoodooInputWellspringSimulator::constructButtonReport(UInt8 btnState) { if (btnState == lastButtonState) return; lastButtonState = btnState; - // macOS Sierra changed how button handling works - // There is now a hid report to send into the abyss of the MT stack directly - if (engine->isSierraOrNewer()) { - bzero(&report, sizeof(MTRelativePointerReport)); - - report.Buttons = btnState; - report.ReportID = 0x82; - report.Unknown1 = 1; - report.Timestamp = timestamp; - OSCollectionIterator *iter = OSCollectionIterator::withCollection(userClients); - while (VoodooInputWellspringUserClient *client = OSDynamicCast(VoodooInputWellspringUserClient, iter->getNextObject())) { - client->enqueueData(&report, sizeof(MTRelativePointerReport)); - } - OSSafeReleaseNULL(iter); - } else if (eventDriver != nullptr) { + if (eventDriver != nullptr) { // TODO: There is some weird logic to do with the "mapClick" property. // I'm not even sure this is ever set though, so this is a don't care for now! @@ -354,7 +340,7 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { inputReport->Counter++; inputReport->unkown1 = 0x03; inputReport->HeaderSize = sizeof(WELLSPRING_REPORT); - inputReport->unk2[0] = 0x00; // Magic + inputReport->unk2[0] = 0x00; inputReport->unk2[1] = 0x17; inputReport->unk2[2] = 0x07; inputReport->unk2[3] = 0x97; @@ -507,3 +493,13 @@ void VoodooInputWellspringSimulator::enqueueData(WELLSPRING_REPORT *report, size } OSSafeReleaseNULL(iter); } + +IOReturn VoodooInputWellspringSimulator::message(UInt32 type, IOService *provider, void *argument) { + switch (type) { + case kIOMessageVoodooInputMessage: + if (argument) constructReport(*(VoodooInputEvent *) argument); + return kIOReturnSuccess; + } + + return super::message(type, provider, argument); +} diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index 8bd2c67..380fa6c 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -33,17 +33,6 @@ class VoodooInputWellspringUserClient; -// This report does not come from the hardware, but instead comes from within AppleUSBMultitouch in 10.12+ -// This gets sent to userspace on any button presses -struct __attribute__((__packed__)) MTRelativePointerReport { - UInt8 ReportID; - UInt8 Unknown1; // Always set to one - UInt16 Unknown2; - UInt32 Buttons; - UInt32 Unknown3[4]; // A dx/dy probably exists in here - AbsoluteTime Timestamp; -}; - struct __attribute__((__packed__)) WELLSPRING_FINGER { UInt8 Id; UInt8 State; @@ -101,6 +90,7 @@ class EXPORT VoodooInputWellspringSimulator : public IOHIDDevice { virtual bool init(OSDictionary *) override; virtual bool start(IOService *provider) override; virtual void free() override; + virtual IOReturn message(UInt32 type, IOService *provider, void *argument) override; virtual bool setProperty(const char *aKey, OSObject *anObject) override; virtual bool setProperty(const char *aKey, unsigned long long aValue, unsigned int aNumberOfBits) override; From 26a580a9d09c61e598de031bcfb38b1df4608b79 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Tue, 14 Feb 2023 15:03:12 -0800 Subject: [PATCH 30/32] Fix init arguments --- VoodooInput/VoodooInput.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/VoodooInput/VoodooInput.cpp b/VoodooInput/VoodooInput.cpp index 9b1098c..ebb8f47 100644 --- a/VoodooInput/VoodooInput.cpp +++ b/VoodooInput/VoodooInput.cpp @@ -33,9 +33,11 @@ bool VoodooInput::start(IOService *provider) { return false; } + OSDictionary *simInitArg = nullptr; trackpoint = OSTypeAlloc(TrackpointDevice); if (isSierraOrNewer()) { simulator = OSTypeAlloc(VoodooInputSimulatorDevice); + simInitArg = OSDynamicCast(OSDictionary, getProperty("MT1Props")); } else { simulator = OSTypeAlloc(VoodooInputWellspringSimulator); } @@ -46,9 +48,9 @@ bool VoodooInput::start(IOService *provider) { OSSafeReleaseNULL(trackpoint); return false; } - + // Initialize simulator device - if (!simulator->init(OSDynamicCast(OSDictionary, getProperty("MT1Props"))) || !simulator->attach(this)) { + if (!simulator->init(simInitArg) || !simulator->attach(this)) { IOLog("VoodooInput could not attach simulator!\n"); goto exit; } @@ -69,7 +71,7 @@ bool VoodooInput::start(IOService *provider) { goto exit; } - // Actuator is only needed for pressure, which is only useful for newer macOS versions with force touch + // Actuator is only needed for Magic Trackpad 2 emulation if (isSierraOrNewer()) { actuator = OSTypeAlloc(VoodooInputActuatorDevice); From 2d84e13df51d213ed687cca262990f4fc515125c Mon Sep 17 00:00:00 2001 From: Avery Black Date: Fri, 6 Sep 2024 22:10:20 -0700 Subject: [PATCH 31/32] Add user client -> event service bridge --- .../VoodooInputWellspringSimulator.cpp | 41 +++++++++++++++++++ .../VoodooInputWellspringSimulator.hpp | 5 +++ .../VoodooInputWellspringUserClient.cpp | 29 +++++++++++-- .../VoodooInputWellspringUserClient.hpp | 5 +++ 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 9de7927..1979e1d 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -494,6 +494,47 @@ void VoodooInputWellspringSimulator::enqueueData(WELLSPRING_REPORT *report, size OSSafeReleaseNULL(iter); } +void VoodooInputWellspringSimulator::dispatchRelativePointerEvent(SInt32 dx, SInt32 dy, UInt32 buttonState) { + AbsoluteTime now; + clock_get_uptime(&now); + IOLog("%s Relative Pointer Event: %d %d %d\n", getName(), dx, dy, buttonState); + + if (eventDriver != nullptr) { + eventDriver->dispatchRelativePointerEvent(now, dx, dy, buttonState); + } +} + +void VoodooInputWellspringSimulator::dispatchScrollWheelEvent(SInt32 dlt1, SInt32 dlt2, SInt32 dlt3) { + AbsoluteTime now; + clock_get_uptime(&now); + IOLog("%s Scroll Wheel Event: %d %d %d\n", getName(), dlt1, dlt2, dlt3); + + if (eventDriver != nullptr) { + eventDriver->dispatchScrollWheelEvent(now, dlt1, dlt2, dlt3); + } +} + +void VoodooInputWellspringSimulator::dispatchKeyboardEvent(UInt32 UsagePage, UInt32 usage) { + AbsoluteTime now; + clock_get_uptime(&now); + IOLog("%s Keyboard Event: 0x%x 0x%x\n", getName(), UsagePage, usage); + + if (eventDriver != nullptr) { +// eventDriver->dispatchKeyboardEvent(now, 0, 0, 0); + } +} + +void VoodooInputWellspringSimulator::dispatchMomentumScrollWheelEvent(SInt32 dlt1, SInt32 dlt2, SInt32 dlt3) { + AbsoluteTime now; + clock_get_uptime(&now); + IOLog("%s Momentum Scroll Event: %d %d %d\n", getName(), dlt1, dlt2, dlt3); + + if (eventDriver != nullptr) { + //kHIDDispatchOptionScrollMomentumContinue +// eventDriver->dispatchRelativePointerEvent(now, dx, dy, buttonState); + } +} + IOReturn VoodooInputWellspringSimulator::message(UInt32 type, IOService *provider, void *argument) { switch (type) { case kIOMessageVoodooInputMessage: diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index 380fa6c..2674765 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -122,6 +122,11 @@ class EXPORT VoodooInputWellspringSimulator : public IOHIDDevice { void notificationEventDriverPublished(IOService *newService); void notificationEventDriverTerminated(IOService *terminatedService); + void dispatchRelativePointerEvent(SInt32 dx, SInt32 dy, UInt32 buttonState); + void dispatchScrollWheelEvent(SInt32 dlt1, SInt32 dlt2, SInt32 dlt3); + void dispatchKeyboardEvent(UInt32 UsagePage, UInt32 usage); + void dispatchMomentumScrollWheelEvent(SInt32 dlt1, SInt32 dlt2, SInt32 dlt3); + private: bool touchActive[15] {false}; diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp index 83e1dd0..a79f428 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.cpp @@ -31,13 +31,13 @@ IOExternalMethodACID VoodooInputWellspringUserClient::sMethods[VoodooInputMT1Use MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // VoodooInputMT1UserClientMethodsIssueDriverRequest MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCStructIStructO, 0x204, 0x204), - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Relative Mouse Movement - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Scroll Wheel - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 2, 0), // Keyboard + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sPostRelativeMouse, kIOUCScalarIScalarO, 3, 0), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sPostScrollWheel, kIOUCScalarIScalarO, 3, 0), + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sPostKeyboard, kIOUCScalarIScalarO, 2, 0), MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 1, 0), // Map Clicks // VoodooInputMT1UserClientMethodsRecacheProperties MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 0, 0), - MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sNoop, kIOUCScalarIScalarO, 3, 0), // Momentum Scroll + MTExternalMethod((IOMethodACID) &VoodooInputWellspringUserClient::sMomentumScroll, kIOUCScalarIScalarO, 3, 0), }; bool VoodooInputWellspringUserClient::start(IOService *provider) { @@ -145,3 +145,24 @@ IOReturn VoodooInputWellspringUserClient::sNoop(VoodooInputWellspringUserClient IOLog("%s Noop was called!\n", that->getName()); return kIOReturnSuccess; // noop } + + +IOReturn VoodooInputWellspringUserClient::sPostRelativeMouse(VoodooInputWellspringUserClient *that, SInt32 dx, SInt32 dy, UInt32 buttonState) { + that->simulator->dispatchRelativePointerEvent(dx, dy, buttonState); + return kIOReturnSuccess; +} + +IOReturn VoodooInputWellspringUserClient::sPostScrollWheel(VoodooInputWellspringUserClient *that, SInt32 dlt1, SInt32 dlt2, SInt32 dlt3) { + that->simulator->dispatchScrollWheelEvent(dlt1, dlt2, dlt3); + return kIOReturnSuccess; +} + +IOReturn VoodooInputWellspringUserClient::sPostKeyboard(VoodooInputWellspringUserClient *that, UInt32 usagePage, UInt32 usage) { + that->simulator->dispatchKeyboardEvent(usagePage, usage); + return kIOReturnSuccess; +} + +IOReturn VoodooInputWellspringUserClient::sMomentumScroll(VoodooInputWellspringUserClient *that, SInt32 dlt1, SInt32 dlt2, SInt32 dlt3) { + that->simulator->dispatchMomentumScrollWheelEvent(dlt1, dlt2, dlt3); + return kIOReturnSuccess; +} diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp index 27875fc..77cf01e 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringUserClient.hpp @@ -53,6 +53,11 @@ class EXPORT VoodooInputWellspringUserClient : public IOUserClient { static IOReturn sGetReport(VoodooInputWellspringUserClient *that, MTDeviceReportStruct *input, MTDeviceReportStruct *output); static IOReturn sNoop(VoodooInputWellspringUserClient *that, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6); + static IOReturn sPostRelativeMouse(VoodooInputWellspringUserClient *that, SInt32 dx, SInt32 dy, UInt32 buttonState); + static IOReturn sPostScrollWheel(VoodooInputWellspringUserClient *that, SInt32 dlt1, SInt32 dlt2, SInt32 dlt3); + static IOReturn sPostKeyboard(VoodooInputWellspringUserClient *that, UInt32 usagePage, UInt32 usage); + static IOReturn sMomentumScroll(VoodooInputWellspringUserClient *that, SInt32 dlt1, SInt32 dlt2, SInt32 dlt3); + void enqueueData(void *data, size_t size); private: VoodooInputWellspringSimulator *simulator {nullptr}; From 97b2f77226b64e119ac1326317a034ee6686a5f1 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Fri, 6 Sep 2024 22:10:39 -0700 Subject: [PATCH 32/32] Document possible version field --- .../VoodooInputWellspringSimulator.cpp | 2 +- .../VoodooInputWellspringSimulator.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp index 1979e1d..dfcca1c 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.cpp @@ -338,7 +338,7 @@ void VoodooInputWellspringSimulator::constructReport(VoodooInputEvent& event) { inputReport->ReportID = 0x74; inputReport->Counter++; - inputReport->unkown1 = 0x03; + inputReport->Version = 0x03; inputReport->HeaderSize = sizeof(WELLSPRING_REPORT); inputReport->unk2[0] = 0x00; inputReport->unk2[1] = 0x17; diff --git a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp index 2674765..842345f 100644 --- a/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp +++ b/VoodooInput/VoodooInputWellspringSimulator/VoodooInputWellspringSimulator.hpp @@ -63,7 +63,7 @@ struct __attribute__((__packed__)) WELLSPRING_REPORT { UInt8 ReportID; UInt8 Counter; // Unknown, always seems to count up though? UInt8 HeaderSize; - UInt8 unkown1; // Always 3 + UInt8 Version; // Always 3 UInt32 Timestamp; UInt8 unk2[4]; // 0x00, 0x17, 0x07, 0x97 UInt16 TotalFingerDataSize;