From 003f7cbf9d2d43f257875bb4289e3879d5e6a556 Mon Sep 17 00:00:00 2001 From: localcc Date: Tue, 26 Oct 2021 04:10:44 +0300 Subject: [PATCH 1/2] Add forced polling support --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 +++ VoodooI2CELAN/Info.plist | 8 +++ VoodooI2CELAN/VoodooI2CELANTouchpadDriver.cpp | 71 ++++++++++++------- VoodooI2CELAN/VoodooI2CELANTouchpadDriver.hpp | 3 + 4 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 VoodooI2CELAN.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/VoodooI2CELAN.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/VoodooI2CELAN.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/VoodooI2CELAN.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/VoodooI2CELAN/Info.plist b/VoodooI2CELAN/Info.plist index c03ace4..b16e16f 100644 --- a/VoodooI2CELAN/Info.plist +++ b/VoodooI2CELAN/Info.plist @@ -39,6 +39,10 @@ QuietTimeAfterTyping 500 + ForcePolling + + PollingInterval + 200 VoodooI2CHIDDevice @@ -59,6 +63,10 @@ QuietTimeAfterTyping 100 + ForcePolling + + PollingInterval + 200 NSHumanReadableCopyright diff --git a/VoodooI2CELAN/VoodooI2CELANTouchpadDriver.cpp b/VoodooI2CELAN/VoodooI2CELANTouchpadDriver.cpp index 49e14f1..d5b26ff 100644 --- a/VoodooI2CELAN/VoodooI2CELANTouchpadDriver.cpp +++ b/VoodooI2CELAN/VoodooI2CELANTouchpadDriver.cpp @@ -468,10 +468,39 @@ IOReturn VoodooI2CELANTouchpadDriver::setPowerState(unsigned long longpowerState return kIOPMAckImplied; } +bool VoodooI2CELANTouchpadDriver::setupPolling() { + interrupt_simulator = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &VoodooI2CELANTouchpadDriver::simulateInterrupt)); + if (!interrupt_simulator) { + IOLog("%s::%s Could not get timer event source\n", getName(), elan_name); + return false; + } + publish_multitouch_interface(); + if (!init_device()) { + IOLog("%s::%s Failed to init device\n", getName(), elan_name); + return false; + } + workLoop->addEventSource(interrupt_simulator); + interrupt_simulator->setTimeoutMS(polling_interval); + IOLog("%s::%s Polling mode initialisation succeeded.", getName(), elan_name); + return true; +} + bool VoodooI2CELANTouchpadDriver::start(IOService* provider) { if (!super::start(provider)) return false; - + + OSBoolean* forcePollingProperty = OSDynamicCast(OSBoolean, getProperty("ForcePolling")); + if(forcePollingProperty != NULL) { + force_polling = forcePollingProperty->getValue(); + } + + OSNumber* pollingIntervalProperty = OSDynamicCast(OSNumber, getProperty("PollingInterval")); + if(pollingIntervalProperty != NULL) { + polling_interval = pollingIntervalProperty->unsigned32BitValue(); + }else { + polling_interval = 200; + } + // Read QuietTimeAfterTyping configuration value (if available) OSNumber* quietTimeAfterTyping = OSDynamicCast(OSNumber, getProperty("QuietTimeAfterTyping")); if (quietTimeAfterTyping != NULL) @@ -494,32 +523,24 @@ bool VoodooI2CELANTouchpadDriver::start(IOService* provider) { goto start_exit; } - // set interrupts AFTER device is initialised - interrupt_source = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventAction, this, &VoodooI2CELANTouchpadDriver::interrupt_occurred), api, 0); + if(this->force_polling) { + if(!this->setupPolling()) goto start_exit; + }else { + // set interrupts AFTER device is initialised + interrupt_source = IOInterruptEventSource::interruptEventSource(this, OSMemberFunctionCast(IOInterruptEventAction, this, &VoodooI2CELANTouchpadDriver::interrupt_occurred), api, 0); - if (!interrupt_source) { - IOLog("%s::%s Could not get interrupt event source, trying to fallback on polling\n", getName(), elan_name); - interrupt_simulator = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &VoodooI2CELANTouchpadDriver::simulateInterrupt)); - if (!interrupt_simulator) { - IOLog("%s::%s Could not get timer event source\n", getName(), elan_name); - goto start_exit; - } - publish_multitouch_interface(); - if (!init_device()) { - IOLog("%s::%s Failed to init device\n", getName(), elan_name); - goto start_exit; - } - workLoop->addEventSource(interrupt_simulator); - interrupt_simulator->setTimeoutMS(200); - IOLog("%s::%s Polling mode initialisation succeeded.", getName(), elan_name); - } else { - publish_multitouch_interface(); - if (!init_device()) { - IOLog("%s::%s Failed to init device\n", getName(), elan_name); - goto start_exit; + if (!interrupt_source) { + IOLog("%s::%s Could not get interrupt event source, trying to fallback on polling\n", getName(), elan_name); + if(!this->setupPolling()) goto start_exit; + } else { + publish_multitouch_interface(); + if (!init_device()) { + IOLog("%s::%s Failed to init device\n", getName(), elan_name); + goto start_exit; + } + workLoop->addEventSource(interrupt_source); + interrupt_source->enable(); } - workLoop->addEventSource(interrupt_source); - interrupt_source->enable(); } PMinit(); diff --git a/VoodooI2CELAN/VoodooI2CELANTouchpadDriver.hpp b/VoodooI2CELAN/VoodooI2CELANTouchpadDriver.hpp index f8d0f0d..184aef6 100644 --- a/VoodooI2CELAN/VoodooI2CELANTouchpadDriver.hpp +++ b/VoodooI2CELAN/VoodooI2CELANTouchpadDriver.hpp @@ -176,6 +176,9 @@ class VoodooI2CELANTouchpadDriver : public IOService { */ IOReturn message(UInt32 type, IOService* provider, void* argument) override; + uint32_t polling_interval; + bool force_polling; + bool setupPolling(); void simulateInterrupt(OSObject* owner, IOTimerEventSource* timer); }; From cdc79739db3a8de09b4b3c392bbf6a0062efeba8 Mon Sep 17 00:00:00 2001 From: localcc Date: Tue, 26 Oct 2021 04:16:44 +0300 Subject: [PATCH 2/2] Readme update --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 5d05a89..6395657 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ Please refer to https://voodooi2c.github.io/#Installation/Installation. * ELAN0000 * ELAN0100 * ELAN0651 +* ELAN0626 (use Force Polling with polling interval set to 5 recommended, see Polling Configuration) + +## Polling Configuration +Some trackpads may not work properly or at all with interrupt mode, even though it gets initialized successfully, that's why you may consider forcing polling. To force polling you need to open `VoodooI2CELAN.kext/Contents/Info.plist` in any editor and change `ForcePolling` to true. +You may also want to change the polling interval, for that you'll need to edit `PollingInterval`, you can determine yours by trying out a couple different ones. *Note: Newer versions of the ELAN touchpads supports another protocol called Precision Touchpad (PTP). Touchpads implementing this protocol need to use VoodooI2CHID. An example of a ELAN based touchpad PTP is the ELAN1200.*