Add a script to mopdify the lighting on a Redragon K621 Horus keyboard, along with an option to turn off the lights when the monitor turns off
This commit is contained in:
1 parent
41fd89f3f2
commit
f88957ea0d
1 file changed
+148
Executable
+148
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import argparse
|
||||
import atexit
|
||||
import dbus
|
||||
import dbus.mainloop.glib
|
||||
import gi.repository.GLib
|
||||
import pprint
|
||||
import sys
|
||||
import usb.core
|
||||
#import traceback
|
||||
|
||||
# Redragon K621 Horus
|
||||
vendor=0x258a
|
||||
product=0x0049
|
||||
|
||||
screensaver_list = [
|
||||
'org.gnome.ScreenSaver',
|
||||
'org.cinnamon.ScreenSaver',
|
||||
'org.kde.screensaver',
|
||||
'org.freedesktop.ScreenSaver'
|
||||
]
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Adjust backlight for Redgradon Horus K621',
|
||||
add_help=True,
|
||||
)
|
||||
parser.add_argument('--on', '-1', dest='switch', action='store_true',
|
||||
default=None, help='Turn keyboard backlight on')
|
||||
parser.add_argument('--off', '-0', dest='switch', action='store_false',
|
||||
default=None, help='Turn keyboard backlight off')
|
||||
parser.add_argument('--screensaver', '-s', dest='screensaver', action='store_true',
|
||||
default=None, help='Turn keyboard backlight off')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.switch is None and args.screensaver is None:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
if args.screensaver:
|
||||
dbus_loop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
session = dbus.SessionBus(mainloop=dbus_loop)
|
||||
for screensaver in screensaver_list:
|
||||
session.add_match_string_non_blocking("interface='{}'".format(screensaver))
|
||||
#session.add_match_string_non_blocking("interface='org.gnome.Mutter.IdleMonitor'")
|
||||
session.add_message_filter(message_callback)
|
||||
loop = gi.repository.GLib.MainLoop()
|
||||
loop.run()
|
||||
else:
|
||||
kbd = setup_usb()
|
||||
send_packets(kbd, args.switch)
|
||||
|
||||
|
||||
def message_callback(session, message):
|
||||
for screensaver in screensaver_list:
|
||||
if message.get_interface() == screensaver:
|
||||
pprint.pprint(message)
|
||||
# not supported in org.freedesktop.ScreenSaver:
|
||||
# Error org.freedesktop.DBus.Error.NotSupported: This method is not part of the idle inhibition specification: https://specifications.freedesktop.org/idle-inhibit-spec/latest/
|
||||
if message.get_member() == "ActiveChanged":
|
||||
screensaver_changed = bool(message.get_args_list()[0])
|
||||
#print("Screen saver {} changed. ActiveChanged: {}".format(screensaver, screensaver_changed))
|
||||
# Capture the GetActive method call in a try/except, or the screensavers that
|
||||
# don't support GetActive will block those that do
|
||||
try:
|
||||
screensaver_path = '/{0}'.format(screensaver.replace('.', '/'))
|
||||
screensaver_obj = session.get_object(screensaver, screensaver_path)
|
||||
screensaver_iface = dbus.Interface(screensaver_obj, screensaver)
|
||||
status = bool(screensaver_iface.GetActive())
|
||||
#print("Screen saver {} changed. GetActive: {}".format(screensaver, status))
|
||||
kbd = setup_usb()
|
||||
send_packets(kbd, not status)
|
||||
except:
|
||||
continue
|
||||
|
||||
|
||||
|
||||
# Set up USB
|
||||
def setup_usb():
|
||||
kbd = usb.core.find(idVendor=vendor, idProduct=product)
|
||||
|
||||
if kbd is None:
|
||||
raise ValueError('Keyboard not found; perhaps switch to USB mode?')
|
||||
|
||||
print("Product: ", kbd.product)
|
||||
print("Manufacturer: ", kbd.manufacturer)
|
||||
|
||||
return kbd
|
||||
|
||||
|
||||
# Send packet/s
|
||||
def send_packets(kbd, switch):
|
||||
if kbd is None:
|
||||
setup_usb()
|
||||
|
||||
if switch is True:
|
||||
#pattern = 0x01 # solid white
|
||||
#pattern = 0x02 #
|
||||
#pattern = 0x03 #
|
||||
#pattern = 0x04 #
|
||||
#pattern = 0x05 #
|
||||
#pattern = 0x06 #
|
||||
#pattern = 0x07 #
|
||||
#pattern = 0x08 #
|
||||
pattern = 0x09 # shadow_disappear
|
||||
#pattern = 0x10 #
|
||||
#pattern = 0x11 #
|
||||
#pattern = 0x12 #
|
||||
#pattern = 0x13 #
|
||||
#pattern = 0x14 #
|
||||
#pattern = 0x20 # custom pattern
|
||||
else:
|
||||
pattern = 0x00 # off
|
||||
|
||||
print("Sending pattern {} command".format(switch))
|
||||
|
||||
# This message tweaks the pattern between OFF (0x0) and the white shadow_disappear pattern (0x9)
|
||||
# with brightness 1/4 and speed 3/4 (I think)
|
||||
#
|
||||
# To modify the "on" pattern, capture the packets from the K621-RGB app with wireshark and usbpcap,
|
||||
# and find the last SET_REPORT request of a set of 4 with size 1068 bytes (1031 data bytes);
|
||||
# the first 20 bytes are identical in all four packets.
|
||||
#
|
||||
# You may need the preceeding three packets as well, and possibly the preceeding SET_REPORT request
|
||||
#(of size 42; I think this is a request for current settings) and GET_REPORT response (of size 290 bytes).
|
||||
#
|
||||
msg = [ 0x06, 0x03, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xa5, 0x03, 0x03, 0x00, 0x00, 0x00, pattern, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x31, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x00, 0x31, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x07, 0x39, 0x5a, 0xa5, 0x00, 0x10, 0x07, 0x49, 0x07, 0x49, 0x07, 0x49, 0x07, 0x49, 0x07, 0x49, 0x07, 0x49, 0x07, 0x49, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xa5, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00Line truncated
|
||||
|
||||
try:
|
||||
ret = kbd.ctrl_transfer(0x21, 0x09, 0x0306, 1, msg)
|
||||
assert ret == len(msg)
|
||||
# Prevent [Errno 32] Pipe error
|
||||
#time.sleep(0.25)
|
||||
except usb.core.USBError as e:
|
||||
print(e)
|
||||
if e.errno == 16:
|
||||
print("This issue needs more investigation... it may simply be previous invalid commands")
|
||||
# May need to reconfigure the device, or detach/reattach kernel driver, either for interface 0 or 0 _and_ 1
|
||||
elif e.errno == 2:
|
||||
print("Try unplugging and replugging the keyboard...")
|
||||
sys.exit()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#atexit.register(cleanup)
|
||||
main()
|
||||
Reference in new issue
Block a user