async def tcp_client(): reader, writer = await asyncio.open_connection(srv, 8888) writer.write(pickle_data(["client_devices", devs])) while True: try: data = unpickle_data(await reader.readline()) except EOFError: print("Connection lost...") break if data[0] == "srv_dev": address = writer.get_extra_info('peername') address_dns = socket.gethostbyaddr(address[0]) device = data[2] cap = device.capabilities() del cap[0] devices.append( evdev.UInput(cap, name=device.name + f' (via {address_dns[0]})', vendor=device.info.vendor, product=device.info.product)) print(f"Created UInput device {device.name} (via {srv})") if data[0] == "srv_dev_event": if not data[0]: break devices[data[1]].write_event(data[2])
def main(): """ Handles events for all keyboard devices. """ #Create a virtual keyboard device, which will be used to _send_ the resultant key-presses. output_device = evdev.UInput(events=None, name='Vim-Clutch Foot-Pedal') #And get a list of all foot-pedal devices which should be monitored for events. input_devices = compatible_devices() #Create generic press and release handlers which are closed over the output device. press_callback = lambda input_device, event : press_handler(output_device, input_device, event) release_callback = lambda input_device, event : release_handler(output_device, input_device, event) #For each foot-pedal detected. for device in input_devices: #Attain sole ownership of the device, so its events don't populate back up to X. device.grab() #And register handlers for the device's events. ClutchEventDispatcher(device, press_callback, release_callback) #Add a handler which releases devices on SIGTERM. signal.signal(signal.SIGTERM, lambda : cleanup(output_device, input_devices)) #And loop indefinitely, handling "asynchronous" press events. try: asyncore.loop() #Allow the program to be closed by CTRL+C. except KeyboardInterrupt: cleanup(output_device, input_devices)
def main(): with evdev.UInput( evdev.util.find_ecodes_by_regex(r"KEY_([A-Z0-9]|SPACE|LEFTSHIFT|ENTER)$") ) as ui: escape = False for letter in sys.argv[1]: if letter == " ": key = evdev.ecodes.KEY_SPACE elif letter == "\\": escape = True continue elif escape and letter == "r": escape = False key = evdev.ecodes.KEY_ENTER else: key = evdev.ecodes.ecodes["KEY_" + letter.upper()] if letter.isupper(): ui.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTSHIFT, 1) ui.write(evdev.ecodes.EV_KEY, key, 1) ui.write(evdev.ecodes.EV_KEY, key, 0) time.sleep(0.05) ui.syn() if letter.isupper(): ui.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTSHIFT, 0) ui.syn()
def __init__(self, mouse, keyboards, **kwargs): self.mouse = evdev.InputDevice(mouse) self.keyboards = [evdev.InputDevice(kbd) for kbd in keyboards] self.mouse.grab() #get mouse capabilities to forward to absolute device caps = self.mouse.capabilities() del caps[evdev.ecodes.EV_SYN] #modify capabilities to delete relative axes and add absolute axes caps[enums.EV_REL].remove(enums.REL_X) caps[enums.EV_REL].remove(enums.REL_Y) caps[enums.EV_ABS] = [(enums.ABS_X, (0, 0, resolution[0], 0, 0, 0)), (enums.ABS_Y, (0, 0, resolution[1], 0, 0, 0))] #merge keyboard and mouse capabilities for transfer self.capabilities = dict(caps) for kbd in self.keyboards: kcap = kbd.capabilities() for k, v in kcap.items(): if k == evdev.ecodes.EV_SYN: continue elif k not in self.capabilities: self.capabilities[k] = v else: self.capabilities[k].extend(v) self.dev = evdev.UInput(caps) super(LinuxServer, self).__init__(resolution, **kwargs)
def main(): logging.basicConfig(level=logging.INFO) rules = [Rule.from_string(s) for s in DEFAULT_RULES] assert len(rules) > 0 rules_by_last_event = {} for rule in rules: key = rule.patterns[-1] rules_by_last_event.setdefault(key, []).append(rule) uinput = evdev.UInput(name='evcape', phys='evcape') logger.info("created uinput device {0.device.fn}".format(uinput)) keyboard_monitor = KeyboardMonitor(ignored_devices=[uinput.device.fn]) # our buffer is as long as the longest sequence in rules window_size = max([len(rule.patterns) for rule in rules]) buffer = collections.deque(maxlen=window_size) # put keypresses into a buffer and try to match rules with uinput, keyboard_monitor: for event in keyboard_monitor: lookup_key = (event.value, event.code) buffer.append(lookup_key) possibly_matching_rules = rules_by_last_event.get(lookup_key) if not possibly_matching_rules: continue for rule in possibly_matching_rules: buffer_slice = list(buffer)[-len(rule.patterns):] if rule.patterns != buffer_slice: continue for value, code in rule.actions: uinput.write(evdev.ecodes.EV_KEY, code, value) uinput.syn()
def main(): with evdev.UInput() as ui: escape = False for letter in sys.argv[1]: if letter == ' ': key = evdev.ecodes.KEY_SPACE elif letter == '\\': escape = True continue elif escape and letter == 'r': escape = False key = evdev.ecodes.KEY_ENTER else: key = evdev.ecodes.ecodes['KEY_' + letter.upper()] if letter.isupper(): ui.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTSHIFT, 1) ui.write(evdev.ecodes.EV_KEY, key, 1) ui.write(evdev.ecodes.EV_KEY, key, 0) time.sleep(.05) ui.syn() if letter.isupper(): ui.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_LEFTSHIFT, 0) ui.syn()
def __init__(self): self._fds = {} self._delayed = [] self._logger = logging.getLogger() self._poll = None self._uinput = None try: signal.signal(signal.SIGHUP, signal.SIG_IGN) info = evmapy.util.get_app_info() app_with_user = (info['name'], info['user'].pw_name) # Create the control socket self._controller = evmapy.controller.Controller(self) # Try to open /dev/uinput, failing gracefully try: self._uinput = evdev.UInput(name='%s (%s)' % app_with_user) except evdev.uinput.UInputError as exc: self._logger.warning( "injecting keypresses will not be possible: %s", str(exc)) # Start processing events from all configured devices self._poll = select.poll() self._scan_devices() # Start monitoring the control socket self._fds[self._controller.fileno()] = self._controller self._poll.register(self._controller, select.POLLIN) except evmapy.controller.SocketInUseError: error_msg = "%s is already running as %s" % app_with_user self._logger.error(error_msg) exit(1) except: self._logger.exception("unhandled exception while initializing:") raise
async def connect(self, server): caps = await super(LinuxClient, self).connect(server, resolution) #caps may be None if user rejects server cert request if caps is not None: self.capabilities = dict((int(k), v) for k, v in caps.items()) self.dev = evdev.UInput(self.capabilities) logger.debug(f'Received capabilities: {self.capabilities}') await self.handle_event()
def __init__(self, routes=None, double_click=-1): self.current_route = None self.routes = routes self.active = False self.double_click = int(double_click) if self.routes is None: self.routes = [] self.ui = evdev.UInput()
def __init__(self): self.pulse = pulsectl.Pulse('nanokontrol') self.input = evdev.UInput() self.session_bus = dbus.SessionBus() self.gsproxy = self.session_bus.get_object('org.gnome.Shell', '/org/gnome/Shell') self.gsinterface = dbus.Interface(self.gsproxy, 'org.gnome.Shell')
def press_power_button(self): """ Simulate a power key press event """ uinput = evdev.UInput(name='push-autopilot-power-button', devnode='/dev/autopilot-uinput') # One press and release to turn screen off (locking unity) uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_POWER, 1) uinput.write(evdev.ecodes.EV_KEY, evdev.ecodes.KEY_POWER, 0) uinput.syn()
def write_events(output_events): device = evdev.UInput({ ecodes.EV_KEY: ecodes.keys, ecodes.EV_REL: [ecodes.REL_X, ecodes.REL_Y], }, name="apemouse") while True: for event in output_events.get(): device.write(event.type, event.code, event.value) device.syn()
def make_uinput(name, device_config): # either predefined or custom try: capabilities = frankengamepad.config.PREDEFINED_CAPABILITIES[device_config["type"]] except KeyError: capabilities = {} # TODO based on device_config["type"]["capabilities"] capabilities = {k: v for k, v in capabilities.items() if k not in {evdev.ecodes.EV_SYN, evdev.ecodes.EV_FF}} # Could set vendor etc but some games don't like it return evdev.UInput(capabilities, name=name)
def __init__(self, hw_kbd, hw_mouse, name, notify_key=None): self.name = name self.kbd = evdev.UInput.from_device(hw_kbd, name=f'{name}-virt-kbd') self.mouse = evdev.UInput(VirtualInputGroup.MOUSE_CAP, name=f'{name}-virt-mouse') self.notify_key = notify_key # active keys and mouse buttons self.active_keys = set() self.mouse_move_x = 0 self.mouse_move_y = 0
def mainloop(self): kodi_client = KodiClient(HOST, PORT) devices = get_mediakey_devices() with grab_all(devices): capabilities = all_capabilities(devices) with evdev.UInput(capabilities, name='DElauncher4Kodi-uinput') as ui: self.ready.set() for event in self.read_events(devices): if not kodi_client.handle_event(event): ui.write_event(event) ui.syn()
def main(): parser = argparse.ArgumentParser() parser.add_argument("rules", nargs="*", metavar="rule", default=DEFAULT_RULES) parser.add_argument("--timeout", type=int, default=DEFAULT_TIMEOUT) args = parser.parse_args() logging.basicConfig(level=logging.INFO) timeout = args.timeout / 1000 logger.info("using timeout {}ms".format(args.timeout)) for s in args.rules: logger.info("adding rule {!r}".format(s)) rules = [Rule.from_string(s) for s in args.rules] assert len(rules) > 0 rules_by_last_event = {} for rule in rules: key = rule.patterns[-1] rules_by_last_event.setdefault(key, []).append(rule) uinput = evdev.UInput(name="evcape") logger.info("created uinput device {0.device.path}".format(uinput)) keyboard_monitor = KeyboardMonitor(ignored_devices=[uinput.device.path]) # the buffer is as long as the longest sequence in rules window_size = max([len(rule.patterns) for rule in rules]) buffer = collections.deque(maxlen=window_size) # put keypresses into a buffer and try to match rules previous_event_timestamp = 0.0 with uinput, keyboard_monitor: for event in keyboard_monitor: lookup_key = (event.value, event.code) buffer.append(lookup_key) ts_diff = event.timestamp() - previous_event_timestamp previous_event_timestamp = event.timestamp() if ts_diff >= timeout: continue possibly_matching_rules = rules_by_last_event.get(lookup_key) if not possibly_matching_rules: continue for rule in possibly_matching_rules: offset = -len(rule.patterns) buffer_slice = list(buffer)[offset:] if rule.patterns != buffer_slice: continue for value, code in rule.actions: uinput.write(evdev.ecodes.EV_KEY, code, value) uinput.syn()
def run(): print('This program tests uinput by typing "catCAT"') ui = evdev.UInput() write(ui, 'cat') print("Pressing KEY_LEFTSHIFT") ui.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, KEY_PRESS) write(ui, 'cat') print("Releasing KEY_LEFTSHIFT") ui.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, KEY_RELEASE) ui.syn() ui.close()
def main(): """ Handles events for all keyboard devices. """ #Create a virtual keyboard device, which will be used to _send_ the resultant key-presses. output_device = evdev.UInput(events=None, name='Emacs-Clutch Foot-Pedal') #And get a list of all foot-pedal devices which should be monitored for events. input_devices = compatible_devices() #Create generic press and release handlers which are closed over the output device. press_callback = lambda input_device, event: press_handler( output_device, input_device, event) release_callback = lambda input_device, event: release_handler( output_device, input_device, event) #For each foot-pedal detected. #TODO: review if it matters that it is looking for more than one device to # grab, when [usually] we will only want to use 1 pedal; # and if we have more than one pedal, we may not want that pedal # to be grabbed by this program; should warn user at least if # more than one device and ask to proceed and recommend unplugging # any unused device that shouldn't be grabbed for device in input_devices: #Attain sole ownership of the device, so its events don't populate back up to X. device.grab() #And register handlers for the device's events. ClutchEventDispatcher(device, press_callback, release_callback) #Add a handler which releases devices on SIGTERM. signal.signal(signal.SIGTERM, lambda: cleanup(output_device, input_devices)) #And loop indefinitely, handling "asynchronous" press events. try: while True: time.sleep(TIME_SLEEP) asyncore.loop(count=1) #Allow the program to be closed by CTRL+C. except KeyboardInterrupt: cleanup(output_device, input_devices) print('\ncleanup on CTRL-C complete')
def __init__(self): res = self.get_resolution() allowed_events = { evdev.ecodes.EV_ABS: ((evdev.ecodes.ABS_MT_POSITION_X, (0, res[0], 0, 0)), (evdev.ecodes.ABS_MT_POSITION_Y, (0, res[1], 0, 0)), (evdev.ecodes.ABS_MT_TOUCH_MAJOR, (0, 30, 0, 0)), (evdev.ecodes.ABS_MT_TRACKING_ID, (0, 65535, 0, 0)), (evdev.ecodes.ABS_MT_PRESSURE, (0, 255, 0, 0)), (evdev.ecodes.ABS_MT_SLOT, (0, 9, 0, 0))), evdev.ecodes.EV_KEY: [ evdev.ecodes.BTN_TOUCH, ] } self.ui = evdev.UInput(events=allowed_events, name="autopilot-finger")
def main(): device_path = get_device_name_from_cli() or get_device_from_user_input() time.sleep(1) # waiting for key-up events after pressing previous Enter try: device = evdev.InputDevice(device_path) except: sys.exit('ERROR: Wrong device name: ' + device_path + ', try run without arguments') print('Device selected:', device) print('') print('Start listening for events...') fake_device = evdev.UInput() loop = asyncio.get_event_loop() loop.run_until_complete(action(device, fake_device))
def hps360pen(select_from_list: bool): """ hps360pen is a sample tool to map HP Spectre x360 ap00xxxx stock pen buttons. For now, only the pen's bottom button is supported and is mapped to emulate the right mouse button. """ devices = [evd.InputDevice(path) for path in evd.list_devices()] devices = [Device(id=idx, name=device.name, evdev=device) for idx, device in enumerate(devices)] if select_from_list: click.echo(message="Select the HP PEN device from the the list below") for device in devices: click.echo(f"[{device.id}] - '{device.name}'") selection = click.prompt(text='Your selection', type=click.IntRange(min=0, max=len(list(devices))-1), ) device = devices[selection] else: click.echo(message="Looking for default HP ELAN PEN signature...") for dev in devices: if dev.name == HP_ELAN_PEN: device = dev break else: click.echo(message=f"Unable to find '{HP_ELAN_PEN}' event device.") return -1 click.echo(message=f"Listening events for input device '{device.name} at '{device.evdev.path}'") capabilities = { # evdev input capabilities for simulating mouse click evd.ecodes.EV_KEY: (evd.ecodes.BTN_LEFT, evd.ecodes.BTN_RIGHT, evd.ecodes.BTN_MIDDLE), } with evd.UInput(capabilities) as ui: for event in device.evdev.read_loop(): if event.code == 321: # BTN_PEN_BOTTOM ui.write(evd.ecodes.EV_KEY, evd.ecodes.BTN_RIGHT, event.value) ui.syn() elif event.code == 331: # BTN_PEN_UPPER pass
def _write_keyb_events(self): dev_obj = evdev.UInput() """ write keyb bytes to the device file """ if self.device and self.device_file: # okay... everything exists. we are g to g try: for keyb_event in self.device.read_loop(): # check to make sure the byte is a key-code if keyb_event.type == evdev.ecodes.EV_KEY: dev_obj.write(keyb_event.type, keyb_event.code, keyb_event.value) except (OSError, Exception) as error_messge: sys.stdout.write("%s" % str(error_messge))
if not ks.finished(): return currentStateOptions = STATE_MAP.get(currentState) for item in currentStateOptions: if item.judge(ks.keycode, ks.keystate): currentState = item.nextState logState.append(currentState) for act in item.action: act(ks.keycode, ks.keystate) break ks.reset() dev = evdev.InputDevice('/dev/input/event3') ui = evdev.UInput() def main(): global dev global ui ks = keystroke() dev.grab() for event in dev.read_loop(): kev = evdev.categorize(event) ks.input(kev) handle(ks)
input_devices[device].grab() capabilities[device] = input_devices[device].capabilities() del capabilities[device][0] pickle.dump(capabilities[device], open(p,'wb')) # read stored capabilities otherwise elif os.path.exists(p): with open(p,'rb') as fp: capabilities[device] = pickle.load(open(p,'rb')) if not capabilities: exit(0) # create host devices host_devices = { key:evdev.UInput(cap) for (key,cap) in capabilities.items() } # create guest devices guest_devices = { key:evdev.UInput(cap) for (key,cap) in capabilities.items() } #prepare host device paths host_device_paths = [ os.path.join("/dev/input/by-id", "host-%s" % device) for device in config['inputs'] ]
def start(): path = os.path.join(os.path.dirname(__file__), "config.yaml") # Loading tablet configuration with open(path, "r") as f: config = yaml.load(f, Loader=yaml.FullLoader) # Get the required ecodes from configuration required_ecodes = [] for k, v in config["actions"].items(): if isinstance(v, list): required_ecodes.extend(v) else: required_ecodes.append(v) temp = [] for c in required_ecodes: temp.extend([evdev.ecodes.ecodes[x] for x in c.split("+")]) required_ecodes = temp pen_events = { evdev.ecodes.EV_KEY: required_ecodes, evdev.ecodes.EV_ABS: [ #AbsInfo input: value, min, max, fuzz, flat (evdev.ecodes.ABS_X, evdev.AbsInfo(0, 0, config['pen']['max_x'], 0, 0, config["pen"]["resolution_x"])), (evdev.ecodes.ABS_Y, evdev.AbsInfo(0, 0, config['pen']['max_y'], 0, 0, config["pen"]["resolution_y"])), (evdev.ecodes.ABS_PRESSURE, evdev.AbsInfo(0, 0, config['pen']['max_pressure'], 0, 0, 0)) ], } # Find the device dev = usb.core.find(idVendor=config["vendor_id"], idProduct=config["product_id"]) # Select end point for reading second interface [2] for actual data # I don't know what [0] and [1] are used for ep = dev[0].interfaces()[2].endpoints()[0] # Reset the device (don't know why, but till it works don't touch it) dev.reset() # Drop default kernel driver from all devices for j in [0, 1, 2]: if dev.is_kernel_driver_active(j): dev.detach_kernel_driver(j) # Set new configuration dev.set_configuration() vpen = evdev.UInput(events=pen_events, name=config["xinput_name"], version=0x3) pressed = -1 # Infinite loop while True: try: data = dev.read(ep.bEndpointAddress, ep.wMaxPacketSize) if data[1] in [192, 193]: # Pen actions pen_x = config['pen']['max_x'] - (data[5] * 255 + data[4]) pen_y = data[3] * 255 + data[2] pen_pressure = data[7] * 255 + data[6] vpen.write(evdev.ecodes.EV_ABS, evdev.ecodes.ABS_X, pen_x) vpen.write(evdev.ecodes.EV_ABS, evdev.ecodes.ABS_Y, pen_y) vpen.write(evdev.ecodes.EV_ABS, evdev.ecodes.ABS_PRESSURE, pen_pressure) if data[1] == 192: # Pen touch vpen.write(evdev.ecodes.EV_KEY, evdev.ecodes.BTN_TOUCH, 0) else: vpen.write(evdev.ecodes.EV_KEY, evdev.ecodes.BTN_TOUCH, 1) elif data[0] == 2: # Tablet button actions # press types: 0 - up; 1 - down; 2 - hold press_type = 1 if data[1] == 2: # First button pressed = 0 elif data[1] == 4: # Second button pressed = 1 elif data[3] == 44: # Third button pressed = 2 elif data[3] == 43: # Fourth button pressed = 3 else: press_type = 0 key_codes = config["actions"]["tablet_buttons"][pressed].split( "+") for key in key_codes: act = evdev.ecodes.ecodes[key] vpen.write(evdev.ecodes.EV_KEY, act, press_type) # Flush vpen.syn() except usb.core.USBError as e: if e.args[0] == 19: vpen.close() raise Exception('Device has been disconnected')
def create_virtual_keyboard(): global virtual_keyboard # accepts only KEY_* events by default, which is perfect virtual_keyboard = e.UInput(name="virtual uinput keyboard")
def open_uinput(self): assert (self.capabilities != None) self.uinput = evdev.UInput(self.capabilities, name=self.name) print("opened uinput", self.name)
import evdev import time import asyncio from EventHandler import EventHandler from InputHandler import InputHandler from ProgramHandler import ProgramHandler import KeyPressHandler from evdev.ecodes import * device = InputHandler("/dev/input/by-path/platform-i8042-serio-0-event-kbd", grabbed=True) e = evdev.ecodes uinput = evdev.UInput() @device.eventHandler(KEY_A) async def foo(event): ProgramHandler("cat /home/popcorn9499/iommuGroups.sh") if event.value == KeyPressHandler.KEY_STATE.KEY_DOWN: key = KeyPressHandler.KeyPress(keys=[KEY_LEFTCTRL, KEY_M]) await key.keyPress(keyState=KeyPressHandler.KEY_STATE.KEY_TOGGLE, pressDuration=0.1) @device.eventHandler(KEY_B) async def bar(event): print("This is bar's first handler") print(evdev.categorize(event))
def __init__(self, *args, **kwargs): super(Controller, self).__init__(*args, **kwargs) self._layout = LAYOUT self._dev = evdev.UInput()
def _start_injecting(self): """The injection worker that keeps injecting until terminated. Stuff is non-blocking by using asyncio in order to do multiple things somewhat concurrently. Use this function as starting point in a process. It creates the loops needed to read and map events and keeps running them. """ # create a new event loop, because somehow running an infinite loop # that sleeps on iterations (ev_abs_mapper) in one process causes # another injection process to screw up reading from the grabbed # device. loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) numlock_state = is_numlock_on() loop = asyncio.get_event_loop() coroutines = [] logger.info('Starting injecting the mapping for "%s"', self.device) paths = get_devices()[self.device]['paths'] # Watch over each one of the potentially multiple devices per hardware for path in paths: source, abs_to_rel = self._prepare_device(path) if source is None: continue # each device needs own macro instances to add a custom handler logger.debug('Parsing macros for %s', path) macros = {} for key, output in self.mapping: if is_this_a_macro(output): macro = parse(output, self.mapping) if macro is None: continue for permutation in key.get_permutations(): macros[permutation.keys] = macro if len(macros) == 0: logger.debug('No macros configured') # certain capabilities can have side effects apparently. with an # EV_ABS capability, EV_REL won't move the mouse pointer anymore. # so don't merge all InputDevices into one UInput device. uinput = evdev.UInput(name=f'{DEV_NAME} {self.device}', phys=DEV_NAME, events=self._modify_capabilities( macros, source, abs_to_rel)) logger.spam('Injected capabilities for "%s": %s', path, uinput.capabilities(verbose=True)) def handler(*args, uinput=uinput): # this ensures that the right uinput is used for macro_write, # because this is within a loop self._macro_write(*args, uinput) for macro in macros.values(): macro.set_handler(handler) # actual reading of events coroutines.append( self._event_consumer(macros, source, uinput, abs_to_rel)) # mouse movement injection based on the results of the # event consumer if abs_to_rel: self.abs_state[0] = 0 self.abs_state[1] = 0 coroutines.append( ev_abs_mapper(self.abs_state, source, uinput, self.mapping)) if len(coroutines) == 0: logger.error('Did not grab any device') return coroutines.append(self._msg_listener(loop)) # set the numlock state to what it was before injecting, because # grabbing devices screws this up set_numlock(numlock_state) try: loop.run_until_complete(asyncio.gather(*coroutines)) except RuntimeError: # stopped event loop most likely pass except OSError as error: logger.error(str(error)) if len(coroutines) > 0: logger.debug('asyncio coroutines ended')