Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add polling configuration #19

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.*

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
8 changes: 8 additions & 0 deletions VoodooI2CELAN/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
<true/>
<key>QuietTimeAfterTyping</key>
<integer>500</integer>
<key>ForcePolling</key>
<false/>
<key>PollingInterval</key>
<integer>200</integer>
</dict>
<key>VoodooI2CHIDDevice</key>
<dict>
Expand All @@ -59,6 +63,10 @@
<true/>
<key>QuietTimeAfterTyping</key>
<integer>100</integer>
<key>ForcePolling</key>
<false/>
<key>PollingInterval</key>
<integer>200</integer>
</dict>
</dict>
<key>NSHumanReadableCopyright</key>
Expand Down
71 changes: 46 additions & 25 deletions VoodooI2CELAN/VoodooI2CELANTouchpadDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions VoodooI2CELAN/VoodooI2CELANTouchpadDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};

Expand Down