#!/usr/bin/env python3
# RG Vita Pro: gamepad buttons -> keyboard + mouse buttons (evdev/uinput,
# X11/Wayland-safe).
import time, select, evdev
from evdev import ecodes as e, UInput

MAP = {
    e.BTN_DPAD_UP: e.KEY_UP,     e.BTN_DPAD_DOWN: e.KEY_DOWN,
    e.BTN_DPAD_LEFT: e.KEY_LEFT, e.BTN_DPAD_RIGHT: e.KEY_RIGHT,
    e.BTN_SOUTH:  e.KEY_ENTER,
    e.BTN_EAST:   e.KEY_ESC,
    e.BTN_WEST:   e.KEY_HOME,
    e.BTN_SELECT: e.KEY_SPACE,
    e.BTN_START:  e.KEY_LEFTMETA,
    e.BTN_TL:     e.KEY_PAGEUP,
    e.BTN_TR:     e.KEY_PAGEDOWN,
}

COMBO = {
    e.BTN_MODE:  (e.KEY_LEFTALT,  e.KEY_TAB),
    e.BTN_Z:     (e.KEY_LEFTALT,  e.KEY_TAB),
    e.BTN_NORTH: (e.KEY_LEFTCTRL, e.KEY_F4),
}
ALL = set(MAP) | set(COMBO)

def sources():
    out = {}
    for p in evdev.list_devices():
        try:
            d = evdev.InputDevice(p)
        except Exception:
            continue
        if d.name == "vita-pad2key":
            continue
        if any(k in d.capabilities().get(e.EV_KEY, []) for k in ALL):
            out[d.fd] = d
    return out

devs = {}
while not devs:
    devs = sources()
    if not devs:
        time.sleep(2)

_keys = set(MAP.values())
for _seq in COMBO.values():
    _keys.update(_seq)

ui = UInput({e.EV_KEY: sorted(_keys)}, name="vita-pad2key")

while True:
    if not devs:
        devs = sources()
        if not devs:
            time.sleep(2)
            continue
    r, _, _ = select.select(devs, [], [])
    for fd in r:
        try:
            events = list(devs[fd].read())
        except OSError:
            try: devs[fd].close()
            except Exception: pass
            del devs[fd]
            continue
        for ev in events:
            if ev.type != e.EV_KEY:
                continue
            if ev.code in COMBO:
                if ev.value == 1:
                    seq = COMBO[ev.code]
                    for k in seq: ui.write(e.EV_KEY, k, 1)
                    for k in reversed(seq): ui.write(e.EV_KEY, k, 0)
                    ui.syn()
            elif ev.code in MAP:
                ui.write(e.EV_KEY, MAP[ev.code], ev.value)
                ui.syn()
