Skip to content

Commit

Permalink
Dispatch lux queue only for Asus' HID Usage Page
Browse files Browse the repository at this point in the history
Some ROG HID keyboards like 0x1866 have multiple IOHIDInterface nubs exposed. In my opinion, the two non-asus nubs handle the normal keyboard keys and have a GenericDesktop(kHIDPage_GenericDesktop) usage page. The nub with Asus' usage page is responsible for handling special Fn key features. Attaching to all three nubs caused backlight inactivity timer issues as our `lastDispatchTime` var is static (meant to be) and multiple queues from different threads wrote to this value causing the value to be overwritten and inconsistent. In this patch, we don't dispatch any queues for non Asus HID pages. So we are assured that only a single thread will read and write to the variable and will hence fix this issue. See issue #4 for detailed discussion on this.

Signed-off-by: black.dragon74 <[email protected]>
  • Loading branch information
black-dragon74 committed Aug 7, 2020
1 parent eeddf81 commit 27b60fc
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 17 deletions.
71 changes: 58 additions & 13 deletions ROG-HID-Driver/ROG_HID_Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,6 @@ kern_return_t IMPL(ROG_HID_Driver, Start)
}

_hid_interface = interface;

ret = IODispatchQueue::Create("lux_dispatch_queue", 0, 0, &_lux_queue);
if (ret != kIOReturnSuccess)
{
OSLOG("Failed to create lux dispatch queue");
return kIOReturnError;
}

// Load the keyboard backlight inactivity monitor
loadKbdLuxMonitor();

OSArray *elements = _hid_interface->getElements();
elements->retain();
Expand All @@ -102,13 +92,16 @@ kern_return_t IMPL(ROG_HID_Driver, Start)
asusKbdGetFunctions();

// Reflect the intital value on lux
DBGLOG("Trying to set initial kbd lux to 0x%x", _current_lux);
DBGLOG("Trying to set initial kbd lux to: 0x%x", _current_lux);
asusKbdBacklightSet(_current_lux);

// And register ourselves with the system
DBGLOG("Register service");
RegisterService();

// Lastly, init the lux queue
initLuxQueue();

return ret;
}

Expand Down Expand Up @@ -324,7 +317,7 @@ void IMPL(ROG_HID_Driver, loadKbdLuxMonitor)
}

// Otherwise, init the hook
DBGLOG("Lux queue initialized successfully");
DBGLOG("Lux queue loaded successfully");
_last_dispatch_time = mach_absolute_time();
_lux_queue->DispatchAsync(^{
do {
Expand All @@ -343,6 +336,58 @@ void IMPL(ROG_HID_Driver, loadKbdLuxMonitor)
});
}

void IMPL(ROG_HID_Driver, initLuxQueue)
{
OSDictionary* deviceProps { nullptr };
OSObject* usagePageProp { nullptr };
OSNumber* kbdUsagePage { nullptr };
bool luxQueueSupported { false };

// Copy device primary properties
_hid_interface->CopyProperties(&deviceProps);
if (!deviceProps)
goto exit;

// Read the primary usage page
usagePageProp = deviceProps->getObject("PrimaryUsagePage");
if (!usagePageProp)
{
DBGLOG("PrimaryUsagePage key does not exist for this device");
goto exit;
}

// PrimaryUsagePage is a 16bit number in native byte order
kbdUsagePage = OSDynamicCast(OSNumber, usagePageProp);
if (!kbdUsagePage)
{
DBGLOG("Dynamic cast to OSNumber failed.");
goto exit;
}

// Create queue only if vendor is anything but GD
luxQueueSupported = kbdUsagePage->unsigned16BitValue() != kHIDPage_GenericDesktop;

if (luxQueueSupported)
{
DBGLOG("Creating lux queue for Asus usagePage: 0x%X", kbdUsagePage->unsigned16BitValue());
if (IODispatchQueue::Create("lux_dispatch_queue", 0, 0, &_lux_queue) != kIOReturnSuccess)
{
OSLOG("Failed to create lux queue");
goto exit;
}

DBGLOG("Backlight auto turn off is supported, lux queue created successfully");
loadKbdLuxMonitor();
}
else
{
DBGLOG("Skipping lux queue for non Asus usagePage: 0x%X", kbdUsagePage->unsigned16BitValue());
}

exit:
OSSafeReleaseNULL(deviceProps);
}

kern_return_t IMPL(ROG_HID_Driver, Stop)
{
DBGLOG("Stop");
Expand Down Expand Up @@ -439,7 +484,7 @@ void IMPL(ROG_HID_Driver, asusKbdGetFunctions)
}

_kbd_function = readBuffer[6];
DBGLOG("Keyboard feature report is %02x", _kbd_function);
DBGLOG("Keyboard feature report is: 0x%.2X", _kbd_function);

exit:
report->release();
Expand Down
1 change: 1 addition & 0 deletions ROG-HID-Driver/ROG_HID_Driver.iig
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public:
private:
virtual void parseKeyboardElementsHook(OSArray* elements);
virtual void setKbdLux(kLuxEvent luxEvent);
virtual void initLuxQueue();
virtual void loadKbdLuxMonitor();
virtual void fadeInLux();
virtual void fadeOutLux();
Expand Down
8 changes: 4 additions & 4 deletions ROG-HID.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.1;
MARKETING_VERSION = 1.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.black-dragon74.ROG-HID";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand All @@ -460,7 +460,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.1;
MARKETING_VERSION = 1.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.black-dragon74.ROG-HID";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
Expand All @@ -482,7 +482,7 @@
"$(SDKROOT)/System/DriverKit/System/Library/Frameworks",
);
INFOPLIST_FILE = "ROG-HID-Driver/Info.plist";
MARKETING_VERSION = 1.1;
MARKETING_VERSION = 1.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.black-dragon74.ROG-HID-Driver";
PRODUCT_NAME = "$(inherited)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -506,7 +506,7 @@
"$(SDKROOT)/System/DriverKit/System/Library/Frameworks",
);
INFOPLIST_FILE = "ROG-HID-Driver/Info.plist";
MARKETING_VERSION = 1.1;
MARKETING_VERSION = 1.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.black-dragon74.ROG-HID-Driver";
PRODUCT_NAME = "$(inherited)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down

0 comments on commit 27b60fc

Please sign in to comment.