You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.2 KiB
Python
128 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
import socket
|
|
import json
|
|
from evdev import UInput, ecodes as e
|
|
|
|
# Capabilities for both gamepad and keyboard
|
|
capabilities = {
|
|
e.EV_KEY: [
|
|
e.BTN_A, e.BTN_B, e.BTN_START,
|
|
e.BTN_DPAD_UP, e.BTN_DPAD_DOWN, e.BTN_DPAD_LEFT, e.BTN_DPAD_RIGHT,
|
|
e.KEY_LEFTCTRL, e.KEY_1
|
|
]
|
|
}
|
|
|
|
# Mapping CEC keys to gamepad buttons or keyboard keys
|
|
key_map = {
|
|
'SELECT': e.BTN_A,
|
|
'EXIT': e.BTN_B,
|
|
'PLAY': e.BTN_START,
|
|
'PAUSE': e.BTN_START,
|
|
'UP': e.BTN_DPAD_UP,
|
|
'DOWN': e.BTN_DPAD_DOWN,
|
|
'LEFT': e.BTN_DPAD_LEFT,
|
|
'RIGHT': e.BTN_DPAD_RIGHT
|
|
# 'CLEAR' handled separately
|
|
}
|
|
|
|
|
|
import time
|
|
from evdev import InputDevice, ecodes, list_devices, UInput
|
|
|
|
# Define key codes for Ctrl and 1
|
|
SHIFT = ecodes.KEY_LEFTSHIFT
|
|
TAB = ecodes.KEY_TAB
|
|
|
|
# Define virtual keyboard capabilities (DO NOT include EV_SYN)
|
|
keyboard_events = {
|
|
ecodes.EV_KEY: [SHIFT,TAB],
|
|
}
|
|
|
|
# Create the virtual input device
|
|
keyboard_ui = UInput(events=keyboard_events, name="Virtual Ctrl+1 Injector", bustype=ecodes.BUS_USB)
|
|
|
|
|
|
def home():
|
|
print("Sending shift+home")
|
|
keyboard_ui.write(ecodes.EV_KEY, SHIFT, 1) # Press Ctrl
|
|
keyboard_ui.write(ecodes.EV_KEY, TAB, 1) # Press 1
|
|
keyboard_ui.syn()
|
|
time.sleep(0.1)
|
|
keyboard_ui.write(ecodes.EV_KEY, SHIFT, 0) # Release 1
|
|
keyboard_ui.write(ecodes.EV_KEY, TAB, 0) # Release Ctrl
|
|
keyboard_ui.syn()
|
|
|
|
|
|
last_pressed = None # Track last key to release
|
|
|
|
def create_virtual_device():
|
|
return UInput(capabilities, name='CEC Virtual Input', bustype=e.BUS_USB)
|
|
|
|
def handle_press(ui, key):
|
|
global last_pressed
|
|
|
|
if key == 'CLEAR':
|
|
home()
|
|
return
|
|
|
|
code = key_map.get(key)
|
|
if not code:
|
|
print(f"Unknown key: {key}")
|
|
return
|
|
|
|
if code == last_pressed:
|
|
return
|
|
|
|
handle_release(ui)
|
|
ui.write(e.EV_KEY, code, 1)
|
|
ui.syn()
|
|
last_pressed = code
|
|
print(f"Pressed {key} ({code})")
|
|
|
|
def handle_release(ui):
|
|
global last_pressed
|
|
if last_pressed is None:
|
|
return
|
|
|
|
if isinstance(last_pressed, tuple):
|
|
# Release both Ctrl and 1
|
|
for code in last_pressed:
|
|
ui.write(e.EV_KEY, code, 0)
|
|
print("Released Ctrl+1")
|
|
else:
|
|
ui.write(e.EV_KEY, last_pressed, 0)
|
|
print(f"Released {last_pressed}")
|
|
|
|
ui.syn()
|
|
last_pressed = None
|
|
|
|
def start_udp_listener():
|
|
ui = create_virtual_device()
|
|
print("Virtual input device ready")
|
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
sock.bind(('0.0.0.0', 41234))
|
|
print("Listening for UDP input...")
|
|
|
|
while True:
|
|
data, _ = sock.recvfrom(1024)
|
|
try:
|
|
print("new payload")
|
|
payload = json.loads(data.decode())
|
|
if payload['type'] == 'key':
|
|
event_type = payload.get('event')
|
|
key_name = payload.get('key', '').upper()
|
|
|
|
if event_type == 'press':
|
|
handle_press(ui, key_name)
|
|
elif event_type == 'release':
|
|
handle_release(ui)
|
|
except Exception as ex:
|
|
print(f"Error: {ex}")
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
start_udp_listener()
|
|
except KeyboardInterrupt:
|
|
print("Shutting down...")
|