#!/usr/bin/python3 import time import os import evdev from evdev import ecodes, UInput DEVICE_NAME = "XING WEI 2.4G USB USB Composite Device Consumer Control" def kodi_running(): for pid in os.listdir("/proc"): if not pid.isdigit(): continue try: with open(f"/proc/{pid}/comm") as f: if f.read().strip() in ("kodi", "kodi.bin"): return True except (OSError, PermissionError): pass return False def find_device(): while True: for path in evdev.list_devices(): try: dev = evdev.InputDevice(path) if dev.name == DEVICE_NAME: if ecodes.KEY_BACK in dev.capabilities().get(ecodes.EV_KEY, []): print(f"Found device: {path}", flush=True) return dev dev.close() except (OSError, PermissionError): pass print("Waiting for device...", flush=True) time.sleep(2) def run(): while True: dev = find_device() ui = None try: # Create a clean virtual keyboard ui = UInput( events={ ecodes.EV_KEY: [ ecodes.KEY_ESC, ecodes.KEY_BACKSPACE, ecodes.KEY_LEFTSHIFT, ecodes.KEY_TAB, ] + [ key for key in dev.capabilities().get(ecodes.EV_KEY, []) if key not in ( ecodes.KEY_BACK, ecodes.KEY_HOMEPAGE, ) ] }, name="XING WEI Remapped Keyboard", bustype=0x03, vendor=0x1915, product=0x1025, version=0x0201 ) dev.grab() print("Device grabbed successfully!", flush=True) print("BACK: ESC / BACKSPACE (Kodi)", flush=True) print("HOME: SHIFT + TAB", flush=True) for event in dev.read_loop(): if event.type == ecodes.EV_KEY: if event.code == ecodes.KEY_BACK: key = ( ecodes.KEY_BACKSPACE if kodi_running() else ecodes.KEY_ESC ) ui.write(ecodes.EV_KEY, key, event.value) ui.syn() elif event.code == ecodes.KEY_HOMEPAGE: if event.value == 1: ui.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 1) ui.write(ecodes.EV_KEY, ecodes.KEY_TAB, 1) ui.syn() ui.write(ecodes.EV_KEY, ecodes.KEY_TAB, 0) ui.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 0) ui.syn() else: ui.write_event(event) else: # Ignore non-key events from the consumer-control device pass except (OSError, IOError) as e: print(f"Device error: {e}", flush=True) finally: if dev: try: dev.ungrab() except OSError: pass dev.close() if ui: ui.close() print("Reconnecting in 2 seconds...", flush=True) time.sleep(2) if __name__ == "__main__": run()