diff --git a/redragon-lights.py b/redragon-lights.py index 0b42277..286a7a5 100755 --- a/redragon-lights.py +++ b/redragon-lights.py @@ -8,8 +8,8 @@ import gi.repository.GLib import pprint import sys import time +import traceback import usb.core -#import traceback # Redragon K621 Horus vendor=0x258a @@ -168,17 +168,60 @@ def send_packets(kbd, switch): try: ret = kbd.ctrl_transfer(0x21, 0x09, 0x0306, 1, msg) assert ret == len(msg) - # Prevent [Errno 32] Pipe error - #time.sleep(0.25) + # Prevent [Errno 32] Pipe error when running multiple commands, if we add any more ctrl_transfer()s after this one + 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") + # The issue seems to be that the device configuration loses the report descriptors for interface 1 (the second interface) # May need to reconfigure the device, or detach/reattach kernel driver, either for interface 0 or 0 _and_ 1 - # if detaching/reattaching, swallow errors with try/except + reset_driver(kbd) elif e.errno == 2: print("Try unplugging and replugging the keyboard...") - sys.exit() + + +def reset_driver(kbd): + global debug + interfaces = list() + for cfg in kbd: + for intf in cfg: + interfaces.append(intf.bInterfaceNumber) + + # Remove the driver + for intfNum in interfaces: + if kbd.is_kernel_driver_active(intfNum) is False: + print("kernel driver already detached") + else: + print("detaching kernel driver for interface {}".format(intfNum), flush=True) + try: + kbd.detach_kernel_driver(intfNum) + except usb.core.USBError as e: + print('Could not detach kernel driver: %s' % str(e), flush=True) + print(traceback.format_exc(), flush=True) + + # Send a command (I think this is a short command to get the current keyboard state) + # This seems to reset things + msg = [ 0x05, 0x83, 0xc6, 0x00, 0x00, 0x00 ] + try: + print("trying to get kbd state") + ret = kbd.ctrl_transfer(0x21, 0x09, 0x0305, 1, msg) + #print(len(msg)) + #print(ret) + assert ret == len(msg) + except: + pass + + # Re-add driver + for intfNum in interfaces: + if kbd.is_kernel_driver_active(intfNum): + print("kernel driver already attached") + else: + print("reattaching kernel driver for interface {}".format(intfNum), flush=True) + try: + kbd.attach_kernel_driver(intfNum) + except usb.core.USBError as e: + print('Could not reattach kernel driver: %s' % str(e), flush=True) if __name__ == '__main__':