class KeyboardOutputDevice: device = None def isConnected(self): return self.device is not None def __init__(self, deviceName='LilyFrog'): print 'Open keyboard output device.' self.device = UInput(name=deviceName) def stop(self): if self.isConnected(): print 'Close keyboard output device.' self.device.close() self.device = None def pressKeyString(self, keystr): # print 'pressKeyString => %s' % keystr if not len(keystr): return scancodes = [] for keychr in keystr: if keychr in KeyChrToCodeMap: scancode = KeyChrToCodeMap[keychr] scancodes.extend(scancode) else: raise ValueError('Invalid key string value \'%s\'!' % keychr) self.pressKeys(scancodes) def pressKeys(self, scancodes): if not len(scancodes): return for scancode in scancodes: isShiftRequired = isinstance(scancode, list) if not isShiftRequired: self.device.write(EV_KEY, scancode, KeyEvent.key_down) self.device.write(EV_KEY, scancode, KeyEvent.key_up) else: self.device.write(EV_KEY, KEY_LEFTSHIFT, KeyEvent.key_down) self.device.write(EV_KEY, scancode[0], KeyEvent.key_down) self.device.write(EV_KEY, scancode[0], KeyEvent.key_up) self.device.write(EV_KEY, KEY_LEFTSHIFT, KeyEvent.key_up) self.device.syn()
def main(argv): thumb_board = identify_thumb_board() if thumb_board is None: print("could not find a Thumb Keyboard") return 1 print( "binding to %s (%x %x)" % (thumb_board.path, thumb_board.info.vendor, thumb_board.info.product)) alias_map = AliasMap(open("halfquerty-v2.bin", "rb").read()) event_buffer = CircleBuffer(5) print("forward_aliases", alias_map.forward_aliases) print("alias_target_keys", alias_map.alias_target_keys) try: ui = UInput() for event in thumb_board.read_loop(): if event.type == ecodes.EV_KEY: process_ev( event_buffer, alias_map.forward_aliases, event, ui, alias_map.alias_target_keys, ) except KeyboardInterrupt as e: return 0 except Exception as e: print(full_stack()) finally: ui.close() return 1
class EvdevWriter(Writer): def __init__(self): self.event_to_ecode_translator = EventToEcodeTranslator() self.ui = UInput() def write_iterable(self, events_iterable): for event in events_iterable: if isinstance(event, list): self.write_combo(event) else: self.__buffer_event(event) self.ui.syn() def write_event(self, event): self.__buffer_event(event) self.ui.syn() def __buffer_event(self, event): ecode = self.event_to_ecode_translator.translate(event) self.ui.write(ecodes.EV_KEY, ecode, 1) self.ui.write(ecodes.EV_KEY, ecode, 0) def write_combo(self, events): for event in events: ecode = self.event_to_ecode_translator.translate(event) self.ui.write(ecodes.EV_KEY, ecode, 1) self.ui.syn() for event in reversed(events): ecode = self.event_to_ecode_translator.translate(event) self.ui.write(ecodes.EV_KEY, ecode, 0) self.ui.syn() def close(self): self.ui.close()
class KeyboardOutputDevice: device = None def isConnected(self): return self.device is not None def __init__(self, deviceName='LilyFrog'): print 'Open keyboard output device.' self.device = UInput(name=deviceName) def stop(self): if self.isConnected(): print 'Close keyboard output device.' self.device.close() self.device = None def pressKeyString(self, keystr): # print 'pressKeyString => %s' % keystr if not len(keystr): return scancodes = [] for keychr in keystr: if keychr in KeyChrToCodeMap: scancode = KeyChrToCodeMap[keychr] scancodes.extend(scancode) else: raise ValueError('Invalid key string value \'%s\'!' % keychr) self.pressKeys(scancodes) def pressKeys(self, scancodes): if not len(scancodes): return for scancode in scancodes: isShiftRequired = isinstance(scancode, list) if not isShiftRequired: self.device.write(EV_KEY, scancode, KeyEvent.key_down) self.device.write(EV_KEY, scancode, KeyEvent.key_up) else: self.device.write(EV_KEY, KEY_LEFTSHIFT, KeyEvent.key_down) self.device.write(EV_KEY, scancode[0], KeyEvent.key_down) self.device.write(EV_KEY, scancode[0], KeyEvent.key_up) self.device.write(EV_KEY, KEY_LEFTSHIFT, KeyEvent.key_up) self.device.syn()
def execute(self): print "Executing " + e.KEY[self.macroKey] + " macro." ui = UInput() for i in range(len(self.keySequence)): ui.write(e.EV_KEY, self.keySequence[i], self.keyState[i]); ui.syn() ui.close()
class Keyboard: def __init__(self): self.uinput = UInput() def close(self): self.uinput.close() def send_key(self, js_keycode, state): self.uinput.write(ecodes.EV_KEY, js_map[js_keycode], 1 if state else 0) self.uinput.syn()
class Keyboard(object): def __init__(self): self.ui = UInput() def press(self, key): self.ui.write(e.EV_KEY, key, 1) self.ui.write(e.EV_KEY, key, 0) self.ui.syn() def __del__(self): self.ui.close()
class vjoy(object): """ send virtual joystick data to linux event system """ def __init__(self, can_id): self.can_id = can_id axis_cap = AbsInfo(-32700, 32700, 0, 0, 0, 0) self._ev = UInput( name='vjoy', events={ ecodes.EV_ABS: [(ecodes.ABS_X, axis_cap), (ecodes.ABS_Y, axis_cap), (ecodes.ABS_Z, axis_cap)], ecodes.EV_KEY: [ecodes.BTN_TRIGGER, ecodes.BTN_TOP, ecodes.BTN_TOP2] }) def __enter__(self): return self def __exit__(self, type, value, tb): self._ev.close() def signal(self, x, y, z, b0, b1, b2): self._ev.write(ecodes.EV_ABS, ecodes.ABS_X, x) self._ev.write(ecodes.EV_ABS, ecodes.ABS_Y, y) self._ev.write(ecodes.EV_ABS, ecodes.ABS_Z, z) self._ev.write(ecodes.EV_KEY, ecodes.BTN_TRIGGER, b0) self._ev.write(ecodes.EV_KEY, ecodes.BTN_TOP, b1) self._ev.write(ecodes.EV_KEY, ecodes.BTN_TOP2, b2) self._ev.syn() def process_can_data(self, msg): #print(msg) if (msg.mid == (0x180 + self.can_id)): # convert axis data to signed abs_x = (msg[0] - 256) if (msg[0] > 127) else msg[0] abs_y = (msg[1] - 256) if (msg[1] > 127) else msg[1] abs_z = (msg[2] - 256) if (msg[2] > 127) else msg[2] # flip y abs_y = -abs_y # rescale from -100..100 to -32700..32700: abs_x = abs_x * 327 abs_y = abs_y * 327 abs_z = abs_z * 327 # fetch buttons b0 = 1 if (msg[5] & 32) else 0 b1 = 1 if (msg[5] & 1) else 0 b2 = 1 if (msg[5] & 8) else 0 # debug data print(" X: " + str(abs_x) + " Y: " + str(abs_y) + " Z: " + str(abs_z) + " B0: " + str(b0) + " B1: " + str(b1) + " B2: " + str(b2)) # send data self.signal(abs_x, abs_y, abs_z, b0, b1, b2)
class Device(object): def __init__(self): self.ui = UInput() def send(self, data): for d in data: self.ui.write(e.EV_KEY, keydict[d], 1) self.ui.syn() self.ui.write(e.EV_KEY, keydict[d], 0) self.ui.syn() def close(self): self.ui.close()
def trigger_display_switch (self): ''' Trigger super+p twice ''' ui = UInput() ui.write(e.EV_KEY, e.KEY_LEFTMETA, 1) ui.syn() time.sleep(1) ui.write(e.EV_KEY, e.KEY_P, 1) ui.write(e.EV_KEY, e.KEY_P, 0) ui.write(e.EV_KEY, e.KEY_P, 1) ui.write(e.EV_KEY, e.KEY_P, 0) ui.write(e.EV_KEY, e.KEY_LEFTMETA, 0) ui.syn() ui.close()
class PointerWatcher(Thread): def __init__(self): Thread.__init__(self) self.ui = UInput() self.devices = [] self.running = True self.device_search() def device_search(self): devices_list = [] files = [] for (dirpath, dirnames, filenames) in walk(INPUTDIR): files.extend(filenames) break for f in files: try: dev = InputDevice(path.join(INPUTDIR, f)) if dev.name == "W WirelessUSB": devices_list.append(dev) except (IOError, OSError, TypeError): pass self.devices = {dev.fd: dev for dev in devices_list} def run(self): c = 0 if len(self.devices) > 0: while self.running: r, w, x = select(self.devices, [], []) for fd in r: try: for event in self.devices[fd].read(): if event.code == ecodes.KEY_UP and event.value == 1: self.ui.write(ecodes.EV_KEY, ecodes.KEY_DOWN, 1) self.ui.write(ecodes.EV_KEY, ecodes.KEY_DOWN, 0) self.ui.write(ecodes.EV_KEY, ecodes.KEY_LEFT, 1) self.ui.write(ecodes.EV_KEY, ecodes.KEY_LEFT, 0) self.ui.syn() c += 1 elif event.code == ecodes.KEY_DOWN and event.value == 1: self.ui.write(ecodes.EV_KEY, ecodes.KEY_UP, 1) self.ui.write(ecodes.EV_KEY, ecodes.KEY_UP, 0) self.ui.write(ecodes.EV_KEY, ecodes.KEY_RIGHT, 1) self.ui.write(ecodes.EV_KEY, ecodes.KEY_RIGHT, 0) self.ui.syn() c -= 1 except IOError: self.running = False break self.ui.close()
def call(k, conf=False): if conf: keys = defns._k[k] else: keys = defns.default[k] try: ui = UInput() for key in keys: ui.write(defns.k["EV_KEY"], defns.k["KEY_" + key.upper()], 1) defns._k[k].reverse() for key in keys: ui.write(defns.k["EV_KEY"], defns.k["KEY_" + key.upper()], 0) ui.syn() ui.close() except err: print "Not enough permissions. Are you root?"
def call(k, conf=False): if conf: keys = defns._k[k] else: keys = defns.default[k] try: ui = UInput() for key in keys: ui.write(defns.k["EV_KEY"], defns.k["KEY_" + key.upper()], 1) defns._k[k].reverse() for key in keys: ui.write(defns.k["EV_KEY"], defns.k["KEY_" + key.upper()], 0) ui.syn() ui.close() except err: print "Not enough permissions. Are you root?"
class App(object): _logger = logging.getLogger('evdev_mt_a') def __init__(self, hardware_version): logging.basicConfig(level=LOGGING_LEVEL, **LOGGING_FORMATS) self.electrodes = electrodes_by_hardware_version(hardware_version) self.electrodes.init() ev_multitouch = { ecodes.EV_ABS: [ (ecodes.ABS_MT_POSITION_X, (0, 0, self.electrodes.grid_sizes[0])), (ecodes.ABS_MT_POSITION_Y, (0, 0, self.electrodes.grid_sizes[1])), ] } self.ui_multitouch = UInput(ev_multitouch, name='capacitive_electrodes', version=0x3) def __loop__(self): self._logger.info('loop') while True: self.electrodes.update() if self.electrodes.get_newly_touched( ) or self.electrodes.get_newly_released(): touched = self.electrodes.get_touched() for i in touched: self.ui_multitouch.write(ecodes.EV_ABS, ecodes.ABS_MT_POSITION_X, i.grid_indexes[0]) self.ui_multitouch.write(ecodes.EV_ABS, ecodes.ABS_MT_POSITION_Y, i.grid_indexes[1]) self.ui_multitouch.write(ecodes.EV_SYN, ecodes.SYN_MT_REPORT, 0) if not touched: self.ui_multitouch.write(ecodes.EV_SYN, ecodes.SYN_MT_REPORT, 0) self._logger.info('send multitouch_a[%d] report', len(touched)) self.ui_multitouch.syn() time.sleep(0.01) def __exit__(self): self.ui_multitouch.close()
def writeWord(word): listOfLetters = list(word) ui = UInput() for letter in listOfLetters: if letter.isupper(): letter = letter.lower() case = 'upper' else: case = 'lower' writeUiCase(letter, ui, case) ui.syn() ui.close()
def call(vals): """ The call function receives a list of keys to be pressed and loops over them switching them to pressed state, then loops over the reversed list unpressing them. That way it can process key combinations. """ try: ui = UInput() for k in vals: ui.write(ecodes["EV_KEY"], ecodes["KEY_" + keys[k]], 1) vals.reverse() for k in vals: ui.write(ecodes["EV_KEY"], ecodes["KEY_" + keys[k]], 0) ui.syn() ui.close() except err: print "Not enough permissions. Are you root?"
def call(vals): ''' The call function receives a list of keys to be pressed and loops over them switching them to pressed state, then loops over the reversed list unpressing them. That way it can process key combinations. ''' try: ui = UInput() for k in vals: ui.write(ecodes["EV_KEY"], ecodes["KEY_" + keys[k]], 1) vals.reverse() for k in vals: ui.write(ecodes["EV_KEY"], ecodes["KEY_" + keys[k]], 0) ui.syn() ui.close() except err: print "Not enough permissions. Are you root?"
class MouseWatcher(Thread): def __init__(self, listener=MouseListener()): Thread.__init__(self) self.m = PyMouse() self.ui = UInput() self.devices = [] self.running = True self.lastPosition = None self.device_search() self.listener = listener def stop(self): print "Desligando mouse." self.running = False def device_search(self): devices_list = [] files = [] for (dirpath, dirnames, filenames) in walk(INPUTDIR): files.extend(filenames) break for f in files: try: dev = InputDevice(path.join(INPUTDIR, f)) keymap = dev.capabilities().get(1) if ecodes.BTN_MOUSE in keymap and ecodes.BTN_LEFT in keymap: devices_list.append(dev) except (IOError, OSError, TypeError): pass self.devices = {dev.fd: dev for dev in devices_list} def run(self): while self.running: r,w,x = select(self.devices, [], []) for fd in r: if not self.running: break for event in self.devices[fd].read(): if event.type == ecodes.EV_KEY and event.value == 1: self.lastPosition = self.m.position() if self.listener.__class__ != MouseListener: self.listener.call_me(self.lastPosition) self.ui.close()
class KeyboardSimuThread(Thread): def __init__(self, thNo): Thread.__init__(self) self.thNo = thNo self.ui = UInput() self.keep_running = True self.waitingOnKey = True self.key = ecodes.KEY_Q # def run(self): print "KeyboardSimuThread Started!" while self.keep_running: if self.waitingOnKey == False: #print "Buzzer " + str(self.thNo) #self.ui.write_event(InputEvent(1, 200, ecodes.EV_KEY, self.key, 1)) does not work in Blender self.ui.write(ecodes.EV_KEY, self.key, 1) #Press key down self.ui.syn() time.sleep( 0.3 ) #Hold it down for 300ms so that Blender is able to read it self.ui.write(ecodes.EV_KEY, self.key, 0) #Relase self.ui.syn() self.waitingOnKey = True #Now we can send a new key #If another key of this buzzer had been pressed it will not be taken in concideration # before waitingOnKey is set to True. So 300ms after last key was pressed time.sleep(0.1) self.ui.close() print "KeyboardSimuThread terminated!" def simulateKey(self, key): #If the thread is waiting for a key we send it, otherwise we ignore it because the thread is already managing one key if self.waitingOnKey == True: self.key = key self.waitingOnKey = False # Each thread runs until explicitly signaled to stop def signal(self): print "KeyboardSimuThread will terminate!" self.keep_running = False
class VirtualJoystick(object): def __init__(self, top_rpm, top_wheel): e = ecodes cap = { e.EV_ABS: [ (e.ABS_X, AbsInfo(value=top_wheel, min=0, max=top_wheel*2, fuzz=0, flat=15, resolution=0)), (e.ABS_Y, AbsInfo(value=128, min=0, max=255, fuzz=0, flat=15, resolution=0)), (e.ABS_Z, AbsInfo(value=top_rpm, min=0, max=top_rpm*2, fuzz=0, flat=15, resolution=0)), ], e.EV_KEY: [e.BTN_JOYSTICK, e.BTN_THUMB, e.BTN_THUMB2, e.BTN_TOP, e.BTN_TOP2, e.BTN_PINKIE, e.BTN_BASE, e.BTN_BASE2, e.BTN_BASE3, e.BTN_BASE4, e.BTN_BASE5, e.BTN_BASE6], } self.joystick = UInput(cap, name='gpad-bike') def __del__(self): self.joystick.close() def set_wheel(self, value): self.set_axis(ecodes.ABS_X, value) def set_rpm(self, value): self.set_axis(ecodes.ABS_Z, value) def set_axis(self, axis, value): #value = 255 self.joystick.write(ecodes.EV_ABS, axis, value) self.joystick.syn() def write(self, etype, code, value): self.joystick.write(etype, code, value)
async def generate_kb_input(keys=None): if not keys: raise ValueError("Can't iterate over nothing") ui = UInput() for k in keys: if isinstance(k, str) and ',' in k: for state in [1, 0]: for kk in k.split(','): kk = e.__getattribute__('KEY_' + kk) print("SENDING KEY", kk) ui.write(e.EV_KEY, kk, state) ui.syn() else: if isinstance(k, str): k = e.__getattribute__('KEY_' + k) print("SENDING KEY", k) ui.write(e.EV_KEY, k, 1) ui.write(e.EV_KEY, k, 0) ui.syn() ui.close()
class KbdOutput(object): def __init__(self): self.ui = UInput() logging.info('Creating uinput device: ' + to_str(self.ui)) def __enter__(self): return self def press(self, key): self.ui.write(e.EV_KEY, keycode(key), etype.KEY_PRESS) def release(self, key): self.ui.write(e.EV_KEY, keycode(key), etype.KEY_RELEASE) def sync(self): self.ui.syn() def close(self): self.ui.close() def __exit__(self, exc_type, exc_value, traceback): logging.info('Closing uinput device: ' + to_str(self.ui)) self.close()
class KeyHandler: def __init__(self, mod_mapping, key_mapping): self._ui = UInput() self._mod_mapping = mod_mapping self._key_mapping = key_mapping def chord_event(self, mods, virtual_mods, chord, value): chord_keys = self.map_chord(virtual_mods, chord) if value == 0: chord_keys = chord_keys + self.map_mods(mods) else: chord_keys = self.map_mods(mods) + chord_keys for key in chord_keys: self._ui.write(EV_KEY, key, value) self._ui.syn() def map_chord(self, virtual_mods, chord): frozen_vmods = frozenset(virtual_mods) if frozen_vmods not in self._key_mapping: return [] current_mapping = self._key_mapping[frozen_vmods] frozen_chord = frozenset(chord) if frozen_chord not in current_mapping: return [] return current_mapping[frozen_chord] def map_mods(self, keys): mods = [] for key in keys: mods.append(self._mod_mapping[key]) return mods def close(self): self._ui.close()
def _kp_monitor_loop(self): """ Keypad monitoring loop, running in a thread and responsible for sending the evdev key events corresponding to key actions. Th uinput instance life-cycle is entirely managed in this method. """ log = logging.getLogger('uinput') log.info('starting keypad monitor') dev = self.terminal.device try: keypad_map = dev.get_keypad_map() except AttributeError: keypad_map = [ ecodes.KEY_NUMERIC_1, ecodes.KEY_NUMERIC_2, ecodes.KEY_NUMERIC_3, ecodes.KEY_NUMERIC_4, ecodes.KEY_NUMERIC_5, ecodes.KEY_NUMERIC_6, ecodes.KEY_NUMERIC_7, ecodes.KEY_NUMERIC_8, ecodes.KEY_NUMERIC_9, ecodes.KEY_NUMERIC_STAR, ecodes.KEY_NUMERIC_0, ecodes.KEY_NUMERIC_POUND, ] keypad_mask = 0 for k in reversed(keypad_map): keypad_mask <<= 1 if k is not None: keypad_mask |= 1 cap = { ecodes.EV_KEY: [ecodes.KEY_PREVIOUS, ecodes.KEY_NEXT, ecodes.KEY_ESC, ecodes.KEY_OK] } ui = UInput(cap, name='ctrl-panel') log.info('uinput created') last_state = None self._kp_monitor_terminate = False while not self._kp_monitor_terminate: state = dev.get_keypad_state() & keypad_mask changes_mask = state if last_state is None else last_state ^ state if changes_mask: log.debug('change detected : state=%d last_state=%d', state, last_state) last_state = state for i, k in enumerate(keypad_map): if k is not None and (changes_mask & 1): key_state = state & 1 value = 1 if key_state else 0 ui.write(ecodes.EV_KEY, k, value) log.info('EV_KEY event sent (code=%s, value=%d)', ecodes.keys[k], value) state >>= 1 changes_mask >>= 1 ui.syn() log.debug('sync event sent') time.sleep(0.1) ui.close() log.info('uinput closed')
class PPMDecoder(object): """Decodes the audio data into PPM pulse data, and then into uinput joystick events. """ def __init__(self, rate): """ Parameters ---------- rate : int sample rate """ self._rate = float(rate) self._lf = None self._threshold = 15000 self._last_edge = None self._ch = None # Size in sampling intervals, of the frame space marker self._marker = int(2.0 * 0.0025 * self._rate) # Mapping of channels to events self._mapping = {0: ecodes.ABS_X, 1: ecodes.ABS_Y, 2: ecodes.ABS_Z, 3: ecodes.ABS_THROTTLE} events = [(v, (0, 255, 5, 0)) for v in self._mapping.values()] self._ev = UInput(name='ppmadapter', events={ ecodes.EV_ABS: events, ecodes.EV_KEY: {288: 'BTN_JOYSTICK'} }) def __enter__(self): return self def __exit__(self, type, value, tb): self._ev.close() def feed(self, data): """Feeds the decoder with a block of sample data. The data should be integer values, and should only be a single channel. Parameters ---------- data : list sample data """ sync_req = False for i in range(len(data)): this_edge = data[i] > self._threshold if self._last_edge is None: self._last_edge = this_edge continue if this_edge and not self._last_edge: # rising if self._lf is not None: sync_req |= self.signal(i - self._lf) elif not this_edge and self._last_edge: # falling self._lf = i self._last_edge = this_edge if sync_req: self._ev.syn() if self._lf is not None: self._lf = self._lf - len(data) if self._lf < (-self._rate): print("Lost sync") self._ch = None self._lf = None def signal(self, w): """Process the detected signal. The signal is the number of sampling intervals between the falling edge and the rising edge. Parameters ---------- w : int signal width Returns ------- bool does uinput require sync """ if w > self._marker: if self._ch is None: print("Got sync") self._ch = 0 return False if self._ch is None or self._ch not in self._mapping: return False duration = float(w) / self._rate value = int((duration - 0.0007) * 1000 * 255) self._ev.write(ecodes.EV_ABS, self._mapping[self._ch], value) self._ch += 1 return True
class PPMDecoder(object): """Decodes the audio data into PPM pulse data, and then into uinput joystick events. """ def __init__(self, rate, average_length): """ Parameters ---------- rate : int sample rate average_length : int average of past channel values for smoothing, set to 1 if undesired """ self.rate = float(rate) # Values that persist between windows so we can handle small windows # where not all the channels have been seen in a single window self.min_value = float("+inf") self.max_value = float("-inf") self.channel = 0 self.previous_value = None self.pulse_start_time = 0 self.samples_since_pulse = 0 # Should be 2ms, but sometimes not quite self.start_pulse_length = 2.0 / 1000 # Mapping of channels to events self.mapping = { 0: ecodes.ABS_X, 1: ecodes.ABS_Y, 2: ecodes.ABS_Z, 3: ecodes.ABS_THROTTLE, 4: ecodes.ABS_RUDDER, 5: ecodes.ABS_MISC, } # History of values (for averaging) self.history = { i: collections.deque(maxlen=average_length) for i in self.mapping.keys() } # Min/max values we'll output events = [(v, (0, -512, 512, 0)) for v in self.mapping.values()] self.ev = UInput(name='ppmadapter', events={ ecodes.EV_ABS: events, ecodes.EV_KEY: { 288: 'BTN_JOYSTICK' } }) def __enter__(self): return self def __exit__(self, type, value, tb): self.ev.close() def feed(self, data, plot=False, debug=False): """Feeds the decoder with a block of sample data. The data should be integer values, and should only be a single channel. Parameters ---------- data : list Sample data plot : bool Whether to display data in a matplotlib plot or not """ if plot: plot_start = np.zeros((len(data), )) plot_channels = { i: np.zeros((len(data), )) for i in self.mapping.keys() } # Process all audio samples for i in range(len(data)): # Hmm... maybe the problem was just that it needed to be negated? # This is what txppm does. current_value = -data[i] # Update extrema and threshold as a weighted average. In my case, # average ends up being close to 0, which then results in noise # triggering this. Thus, weight toward max. self.min_value = min(self.min_value, current_value) self.max_value = max(self.max_value, current_value) threshold = 1 / 4 * self.min_value + 3 / 4 * self.max_value # Keep track of the previous value for determining if between the # last sample and the current sample there was a rise if self.previous_value is None: self.previous_value = current_value continue # Detect rising edge: if the previous value is low and now it's # high rising = self.previous_value < threshold and current_value > threshold if rising: # Time when hitting threshold (measured in seconds) # See: https://github.com/nexx512/txppm/blob/master/software/ppm.c trigger_offset = (threshold - self.previous_value) / \ (current_value - self.previous_value) / self.rate trigger_time = self.samples_since_pulse / self.rate + trigger_offset pulse_length = trigger_time - self.pulse_start_time self.pulse_start_time = trigger_time # Start pulse if pulse_length > self.start_pulse_length: self.channel = 0 self.pulse_start_time = trigger_offset self.samples_since_pulse = 0 if plot: plot_start[i] = threshold # Channel measurement else: # If a channel we care about, save it. Note: still need to # increment the channel even if not in mapping since we # might care about non-consecutive channels (e.g. 1, 3, and # 5). if self.channel in self.mapping: # txppm says "According to the spec, the pulse length # ranges from 1..2ms" value = pulse_length * 1000 - 1.5 # To enable averaging, add current value to queue but # don't set it yet self.history[self.channel].append(value) if plot: plot_channels[self.channel][i] = threshold self.channel += 1 self.samples_since_pulse += 1 self.previous_value = current_value # Send joystick updates for ch, values in self.history.items(): value = 0 # Handle averaging if len(values) > 0: value = int(sum(values) / len(values) * 512) self.ev.write(ecodes.EV_ABS, self.mapping[ch], value) if debug: print("ch" + str(ch), "=", value) self.ev.syn() # Plot the audio data we received if desired if plot: # Plot negative since we negate when processing y = -np.array(list(data), dtype=np.float32) x = np.arange(0, len(y), 1) plt.plot(x, y, label="signal") plt.plot(x, plot_start, label="start") for ch, values in plot_channels.items(): plt.plot(x, values, label="ch" + str(ch)) plt.legend() plt.show()
class PointingTechnique: capabilities = { e.EV_REL: (e.REL_X, e.REL_Y), e.EV_KEY: (e.BTN_LEFT, e.BTN_RIGHT) } def __get_distance_to_target(self, pos): return math.dist([pos.x(), pos.y()], [self.__target_pos.x(), self.__target_pos.y()]) def __is_in_target(self, pos): return self.__get_distance_to_target(pos) <= (self.__target.width() / 2) # Code based on: # https://en.wikipedia.org/wiki/Linear_interpolation # https://stackoverflow.com/questions/49173095/how-to-move-an-object-along-a-line-given-two-points#49173439 def __move_to_target(self): if self.__moving or self.__is_in_target(self.__current_pos): return self.__moving = True n = self.__density # The smaller n is the "faster" the mouse becomes x0, y0 = self.__current_pos.x(), self.__current_pos.y() x1, y1 = self.__target_pos.x(), self.__target_pos.y() x_t0, y_t0 = x0, y0 for i in range(0, n): if self.__is_in_target(self.__current_pos): return t = i / n x_t = (1.0 - t) * x0 + t * x1 y_t = (1.0 - t) * y0 + t * y1 rel_x = int(x_t - x_t0) rel_y = int(y_t - y_t0) self.__device.write(e.EV_REL, e.REL_X, rel_x) self.__device.write(e.EV_REL, e.REL_Y, rel_y) self.__device.syn() x_t0, y_t0 = x_t, y_t time.sleep(0.01) QtWidgets.qApp.processEvents() self.__moving = False def __init__(self, target, threshold, density): self.__moving = False self.__device = UInput(self.capabilities) self.__target = target self.__target_pos = self.__target.geometry().center() self.__current_pos = None self.__threshold = threshold self.__density = density def __del__(self): self.__device.close() def filter(self, current_pos): self.__current_pos = current_pos threshold = int(self.__target.parent().width() * self.__threshold) if self.__get_distance_to_target(current_pos) < threshold: self.__move_to_target()
class EvPointer(object): def __init__(self): self.xdisplay = display.Display() screen = self.xdisplay.screen() self.screen_width = screen.width_in_pixels self.screen_height = screen.height_in_pixels self.xroot = screen.root pointer = self.xroot.query_pointer() self.position = MousePos(pointer.root_x, pointer.root_y) devices = [InputDevice(fn) for fn in list_devices()] self.pointer_devs = [] self.keyboard_devs = [] for device in devices: caps = device.capabilities() if ecodes.EV_REL in caps: self.pointer_devs.append(device) elif ecodes.EV_ABS in caps: self.pointer_devs.append(device) elif ecodes.EV_KEY in caps: self.keyboard_devs.append(device) self.queue = Queue() self.mainloop = Thread(target=self._mainloop, name='EvPointer mainloop') self.mainloop.start() self.stop = False self.hook_callback = None self.hook = Thread(target=self._hook, name='EvPointer hook loop') self.hook.start() caps = { ecodes.EV_REL: ( ecodes.REL_X, ecodes.REL_Y, ecodes.REL_WHEEL, ecodes.REL_HWHEEL), ecodes.EV_KEY: ( ecodes.BTN_LEFT, ecodes.BTN_RIGHT, ecodes.BTN_MIDDLE, ecodes.BTN_SIDE, ecodes.BTN_EXTRA)} self.uinput = UInput(caps, name='macpy pointer') def close(self): self.uinput.close() self.enqueue(None) if self.hook and self.hook.is_alive(): self.stop = True def _hook(self): li = LibInput(ContextType.PATH) for device in self.pointer_devs: li.add_device(device.fn) for event in li.events: if self.stop: break mods = { 'SHIFT': False, 'ALTGR': False, 'CTRL': False, 'ALT': False, 'META': False} active_mods = set() for device in self.keyboard_devs: active_mods |= set(device.active_keys()) for key in active_mods: key = Key.from_ec(key) if key in Mods.SHIFT: mods['SHIFT'] = True elif key in Mods.CTRL: mods['CTRL'] = True elif key in Mods.ALT: mods['ALT'] = True elif key in Mods.META: mods['META'] = True if event.type == EventType.POINTER_MOTION: dx, dy = event.delta x = self.position.x + round(dx) y = self.position.y + round(dy) if x < 0: x = 0 elif x > (self.screen_width - 1): x = self.screen_width - 1 if y < 0: y = 0 elif y > (self.screen_height - 1): y = self.screen_height - 1 self.position = MousePos(x, y) if self.hook_callback: self.enqueue(self.hook_callback, PointerEventMotion( self.position.x, self.position.y, mods)) elif event.type == EventType.POINTER_MOTION_ABSOLUTE: x, y = event.transform_absolute_coords( self.screen_width, self.screen_height) self.position = MousePos(round(x), round(y)) if self.hook_callback: self.enqueue(self.hook_callback, PointerEventMotion( self.position.x, self.position.y, mods)) elif event.type == EventType.POINTER_BUTTON: button = Key.from_ec(event.button) state = KeyState(event.button_state.value) if self.hook_callback: self.enqueue(self.hook_callback, PointerEventButton( self.position.x, self.position.y, button, state, mods)) elif event.type == EventType.POINTER_AXIS: if event.has_axis(LIPAxis.SCROLL_VERTICAL): axis = mPAxis.VERTICAL value = event.get_axis_value(LIPAxis.SCROLL_VERTICAL) else: axis = mPAxis.HORIZONTAL value = event.get_axis_value(LIPAxis.SCROLL_HORIZONTAL) if self.hook_callback: self.enqueue(self.hook_callback, PointerEventAxis( self.position.x, self.position.y, value, axis, mods)) def install_pointer_hook(self, callback, grab=False): self.hook_callback = callback def uninstall_pointer_hook(self): self.hook_callback = None def _mainloop(self): while True: method, args = self.queue.get() if method is None: break try: method(*args) except Exception as e: print( 'Error in EvPointer mainloop: \n', ''.join(traceback.format_exception( type(e), e, e.__traceback__))) self.queue.task_done() def enqueue(self, method, *args): self.queue.put_nowait((method, args)) def _warp(self, x, y, relative=False): if relative: dx = x dy = y else: dx = x - self.position.x dy = y - self.position.y self.uinput.write(ecodes.EV_REL, ecodes.REL_X, dx) self.uinput.write(ecodes.EV_REL, ecodes.REL_Y, dy) self.uinput.syn() def warp(self, x, y, relative=False): self.enqueue(self._warp, x, y, relative) def _scroll(self, axis, value): if axis is mPAxis.VERTICAL: self.uinput.write(ecodes.EV_REL, ecodes.REL_WHEEL, -value) elif axis is mPAxis.HORIZONTAL: self.uinput.write(ecodes.EV_REL, ecodes.REL_HWHEEL, value) else: raise TypeError('Invalid axis type') self.uinput.syn() def scroll(self, axis, value): self.enqueue(self._scroll, axis, value) def _click(self, key, state=None): if state is None: self.uinput.write(ecodes.EV_KEY, key.ec.value, 1) self.uinput.write(ecodes.EV_KEY, key.ec.value, 0) elif state is KeyState.PRESSED: self.uinput.write(ecodes.EV_KEY, key.ec.value, 1) elif state is KeyState.RELEASED: self.uinput.write(ecodes.EV_KEY, key.ec.value, 0) self.uinput.syn() def click(self, key, state=None): self.enqueue(self._click, key) def get_button_state(self, button): active_keys = set() for dev in self.pointer_devs: active_keys |= set(dev.active_keys()) if button.ec in active_keys: return KeyState.PRESSED else: return KeyState.RELEASED
class BaseDriver(ABC): @abstractmethod def __init__(self): self.create_node = True self.name = None self.input_dev = None self.capabilities = None self.vendor = None self.product = None self.version = None self.phys = None self.bustype = None self.auto_triggers = dict() def create(self): self.input_dev = UInput(self.capabilities, self.name, vendor=self.vendor, product=self.product, version=self.version, phys=self.phys) return self # Central write handler # handles all kind of writes, single writes and auto triggers def write(self, config: Config, drivers, e_type=None, e_sub_type=None, value=None, meta=None, periodical=0, frequency=0, event=None): auto_trigger_button_pressed, auto_trigger_button_released, auto_trigger_button_toggle, auto_trigger_press_ongoing, no_auto_trigger = self._calculate_toggle_state( e_sub_type, periodical, value) # Normal state first which is 90% of all triggers hence needs to be processed first if no_auto_trigger: self.input_dev.write(e_type, int(e_sub_type), value) return self # Autotrigger states elif auto_trigger_button_pressed: if len(self.auto_triggers) == 0: asyncio.ensure_future(self._loop_periodical()) elif e_sub_type in self.auto_triggers: return self self._register_auto_trigger(e_sub_type, e_type, frequency, value) self.input_dev.write(e_type, int(e_sub_type), value) elif auto_trigger_press_ongoing: return self elif auto_trigger_button_released: self._deregister_auto_trigger(e_sub_type) self.input_dev.write(e_type, int(e_sub_type), value) elif auto_trigger_button_toggle: self._toggle_auto_trigger(e_sub_type, e_type, frequency, value) else: self.input_dev.write(e_type, int(e_sub_type), value) return self # calculate the toggle states for the auto fire function def _calculate_toggle_state(self, e_sub_type, periodical, value): no_auto_trigger = periodical == 0 auto_trigger_button_pressed = periodical == 1 and value == 1 auto_trigger_button_released = periodical == 1 and value == 0 auto_trigger_press_ongoing = periodical == 1 and value > 1 and e_sub_type in self.auto_triggers auto_trigger_button_toggle = periodical == 2 and value == 1 return auto_trigger_button_pressed, auto_trigger_button_released, auto_trigger_button_toggle, auto_trigger_press_ongoing, no_auto_trigger def syn(self): self.input_dev.syn() return self def verify(self): self.input_dev.verify() return self def close(self): if self.input_dev is not None: self.input_dev.close() def transfer_dev_data(self): self.phys = self.input_dev.phys self.name = self.input_dev.name self.version = self.input_dev.version self.vendor = self.input_dev.vendor self.bustype = self.input_dev.bustype self.product = self.input_dev.product # periodic loop which triggers the autofire async def _loop_periodical(self): while len(self.auto_triggers) > 0: await asyncio.sleep(STD_DELAY) try: for key in self.auto_triggers: now = datetime.now().microsecond val = self.auto_triggers[key] access_difference = round( abs(now - val[LAST_ACCESSED]) / 1000) if access_difference > val[FREQUENCY]: val[LAST_ACCESSED] = now val[TRIGGER]() # 100ms delay because some emulators do not accept input which is lower than that # between button up and button down await asyncio.sleep(STD_DELAY) val[TRIGGER_OFF]() # we would get somtimes a collection changed exception, we safely can ignore that # (race condition due to external delete and await in the loop except Exception as e: pass def _deregister_auto_trigger(self, e_sub_type): del self.auto_triggers[e_sub_type] # registers an auto trigger into our trigger dictionary def _register_auto_trigger(self, e_sub_type, e_type, frequency, value): self.auto_triggers[e_sub_type] = dict() self.auto_triggers[e_sub_type][FREQUENCY] = frequency self.auto_triggers[e_sub_type][TRIGGER] = lambda: self._button_down( e_type, e_sub_type, value) self.auto_triggers[e_sub_type][TRIGGER_OFF] = lambda: self._button_up( e_type, e_sub_type, value) self.auto_triggers[e_sub_type][LAST_ACCESSED] = datetime.now( ).microsecond # simulates a button down def _button_down(self, e_type, e_sub_type, value): self.input_dev.write(e_type, int(e_sub_type), value) self.syn() # simulates a button up def _button_up(self, e_type, e_sub_type, value): self.input_dev.write(e_type, int(e_sub_type), 0) self.syn() # toggles the auto triggers either on or off def _toggle_auto_trigger(self, e_sub_type, e_type, frequency, value): if e_sub_type in self.auto_triggers: del self.auto_triggers[e_sub_type] else: if len(self.auto_triggers) == 0: asyncio.ensure_future(self._loop_periodical()) self._register_auto_trigger(e_sub_type, e_type, frequency, value)
def run_evdev(): # Define the events that will be triggered by the custom xinput device that we will create pen_events = { # Defining a pressure sensitive pen tablet area with 2 stylus buttons and no eraser ecodes.EV_KEY: get_required_ecodes(), ecodes.EV_ABS: [ #AbsInfo input: value, min, max, fuzz, flat, resolution (ecodes.ABS_X, AbsInfo(0, 0, args['pen']['max_x'], 0, 0, args['pen']['resolution'])), (ecodes.ABS_Y, AbsInfo(0, 0, args['pen']['max_y'], 0, 0, args['pen']['resolution'])), (ecodes.ABS_PRESSURE, AbsInfo(0, 0, args['pen']['max_pressure'], 0, 0, 0)), (ecodes.ABS_TILT_X, AbsInfo(0, 0, args['pen']['max_tilt_x'], 0, 0, 0)), (ecodes.ABS_TILT_Y, AbsInfo(0, 0, args['pen']['max_tilt_y'], 0, 0, 0)), ], } # Try to get a reference to the USB we need dev = usb.core.find(idVendor=args['<usb_vendor_id>'], idProduct=args['<usb_product_id>']) if not dev: raise Exception( "Could not find device. The device may be unavailable or already open" ) # Forcefully claim the interface from any other script that might have been using it for cfg in dev: for interface in cfg: if dev.is_kernel_driver_active(interface.index): dev.detach_kernel_driver(interface.index) usb.util.claim_interface(dev, interface.index) if not args['--quiet-mode']: print("grabbed interface {}".format(interface.index)) # The method needs to be called or otherwise the tablet may not be in the correct mode # and no output might be seen from the first endpoint after a tablet reboot read_tablet_info(dev) # Seems like we need to try and read atleast once from the second endpoint on the device # or else the output from the first endpoint may get blocked on a tablet reboot try: endpoint_1 = dev[0][(1, 0)][0] data = dev.read(endpoint_1.bEndpointAddress, endpoint_1.wMaxPacketSize) except: pass # Create a virtual pen in /dev/input/ so that it shows up as a XInput device global vpen vpen = UInput(events=pen_events, name=args['<xinput_name>'], version=0x3) # Get a reference to the end that the tablet's output will be read from usb_endpoint = dev[0][(0, 0)][0] xinput_map_to_display() # Read the tablet output in an infinite loop while True: try: # Read data from the USB data = dev.read(usb_endpoint.bEndpointAddress, usb_endpoint.wMaxPacketSize) # Only calculate these values if the event is a pen event and not tablet event if data[1] in [128, 129, 130, 131, 132, 133]: # Calculate the values pen_x = (data[3] << 8) + (data[2]) pen_y = (data[5] << 8) + data[4] pen_pressure = (data[7] << 8) + data[6] pen_tilt_x = data[10] >= 128 and (data[10] - 256) or data[10] pen_tilt_y = data[11] >= 128 and (data[11] - 256) or data[11] # Send data to the Xinput device so that cursor responds vpen.write(ecodes.EV_ABS, ecodes.ABS_X, pen_x) vpen.write(ecodes.EV_ABS, ecodes.ABS_Y, pen_y) vpen.write(ecodes.EV_ABS, ecodes.ABS_PRESSURE, pen_pressure) vpen.write(ecodes.EV_ABS, ecodes.ABS_TILT_X, pen_tilt_x) vpen.write(ecodes.EV_ABS, ecodes.ABS_TILT_Y, pen_tilt_y) if args['--print-calculated-data'] and not args['--quiet-mode']: print("X {} Y {} PRESS {} ".format( pen_x, pen_y, pen_pressure, ), end='\r') # Reset any actions because this code means that nothing is happening if data[1] == 128: run_action('') # Pen click if data[1] == 129: run_action(args['actions'].get('pen_touch', '')) # Pen button 1 if data[1] == 130: run_action(args['actions'].get('pen_button_1', '')) # Pen button 1 with pen touch if data[1] == 131: run_action(args['actions'].get('pen_button_1_touch', '')) # Pen button 2 if data[1] == 132: run_action(args['actions'].get('pen_button_2', '')) # Pen button 2 with pen touch if data[1] == 133: run_action(args['actions'].get('pen_button_2_touch', '')) # Tablet buttons if data[1] == 224: global previous_tablet_btn if data[4]: btn_index = int(math.log(data[4], 2)) if previous_tablet_btn != data[4] and args['actions'].get( 'tablet_buttons', ''): run_action( args['actions']['tablet_buttons'][btn_index]) previous_tablet_btn = btn_index else: run_action('') previous_tablet_btn = 0 # Scrollbar if data[1] == 240: global previous_scrollbar_state scrollbar_state = data[5] if scrollbar_state: if previous_scrollbar_state: if scrollbar_state > previous_scrollbar_state: run_action(args['actions'].get( 'tablet_scrollbar_increase', '')) elif scrollbar_state < previous_scrollbar_state: run_action(args['actions'].get( 'tablet_scrollbar_decrease', '')) if scrollbar_state != previous_scrollbar_state and args[ 'actions'].get('tablet_scrollbar', ''): run_action( args['actions']['tablet_scrollbar'][scrollbar_state - 1]) else: run_action('') previous_scrollbar_state = scrollbar_state # Dispatch the evdev events vpen.syn() if args['--print-usb-data']: print_raw_data(data, 6) except usb.core.USBError as e: if e.args[0] == 19: vpen.close() raise Exception('Device has been disconnected') # The usb read probably timed out for this cycle. Thats ok data = None
class WebKeyboard(WebSocket): k_alnum_lc = "qwertyuiopasdfghjklzxcvbnm1234567890" k_al_uc = "QWERTYUIOPASDFGHJKLZXCVBNM" k_rest = { " ": { "key": "KEY_SPACE" }, "!": { "key": "KEY_1", "mod": "KEY_LEFTSHIFT" }, "@": { "key": "KEY_2", "mod": "KEY_LEFTSHIFT" }, "#": { "key": "KEY_3", "mod": "KEY_LEFTSHIFT" }, "$": { "key": "KEY_4", "mod": "KEY_LEFTSHIFT" }, "%": { "key": "KEY_5", "mod": "KEY_LEFTSHIFT" }, "^": { "key": "KEY_6", "mod": "KEY_LEFTSHIFT" }, "&": { "key": "KEY_7", "mod": "KEY_LEFTSHIFT" }, "*": { "key": "KEY_8", "mod": "KEY_LEFTSHIFT" }, "(": { "key": "KEY_9", "mod": "KEY_LEFTSHIFT" }, ")": { "key": "KEY_0", "mod": "KEY_LEFTSHIFT" }, "-": { "key": "KEY_MINUS" }, "_": { "key": "KEY_MINUS", "mod": "KEY_LEFTSHIFT" }, "=": { "key": "KEY_EQUAL" }, "+": { "key": "KEY_EQUAL", "mod": "KEY_LEFTSHIFT" }, "[": { "key": "KEY_LEFTBRACE" }, "{": { "key": "KEY_LEFTBRACE", "mod": "KEY_LEFTSHIFT" }, "]": { "key": "KEY_RIGHTBRACE" }, "}": { "key": "KEY_RIGHTBRACE", "mod": "KEY_LEFTSHIFT" }, ";": { "key": "KEY_SEMICOLON" }, ":": { "key": "KEY_SEMICOLON", "mod": "KEY_LEFTSHIFT" }, "'": { "key": "KEY_APOSTROPHE" }, "\"": { "key": "KEY_APOSTROPHE", "mod": "KEY_LEFTSHIFT" }, "\\": { "key": "KEY_BACKSLASH" }, "|": { "key": "KEY_BACKSLASH", "mod": "KEY_LEFTSHIFT" }, ",": { "key": "KEY_COMMA" }, "<": { "key": "KEY_COMMA", "mod": "KEY_LEFTSHIFT" }, ".": { "key": "KEY_DOT" }, ">": { "key": "KEY_DOT", "mod": "KEY_LEFTSHIFT" }, "/": { "key": "KEY_SLASH" }, "?": { "key": "KEY_SLASH", "mod": "KEY_LEFTSHIFT" }, "`": { "key": "KEY_GRAVE" }, "~": { "key": "KEY_GRAVE", "mod": "KEY_LEFTSHIFT" }, } def connected(self): print(self.address, "connected") self.ui = UInput() def handle(self): print(self.data) self.key = self.mod = None # Set key value from valid KEY_s directly if "KEY_" in self.data: try: self.key = getattr(eco, self.data) self.key = self.data except (AttributeError): print("No such key " + self.data) pass # Set key value to alphanumeric lowercase elif self.data[0] in self.k_alnum_lc: self.key = "KEY_" + self.data[0].upper() # Set key value to alpha uppercase with modifier Shift key elif self.data[0] in self.k_al_uc: self.mod = "KEY_LEFTSHIFT" self.key = "KEY_" + self.data[0] # Set key value to one of k_rest with or without modifier Shift key elif self.data[0] in self.k_rest: self.key = self.k_rest[self.data[0]]["key"] if "mod" in self.k_rest[self.data[0]]: self.mod = self.k_rest[self.data[0]]["mod"] # Send recorded key to system along with modifier if available if self.key is not None: if self.mod is not None: self.ui.write(eco.EV_KEY, getattr(eco, self.mod), 1) self.ui.write(eco.EV_KEY, getattr(eco, self.key), 1) self.ui.write(eco.EV_KEY, getattr(eco, self.key), 0) self.ui.syn() if self.mod is not None: self.ui.write(eco.EV_KEY, getattr(eco, self.mod), 0) # Echo received data back to client self.send_message(self.data) def handle_close(self): print(self.address, "disconnected") self.ui.close()
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 = ecodes.ecodes[key] vbtn.write(ecodes.EV_KEY, act, press_type) # Flush vpen.syn() vbtn.syn() except usb.core.USBError as e: if e.args[0] == 19: vpen.close() raise Exception("Device has been disconnected") except KeyboardInterrupt: vpen.close() vbtn.close() sys.exit("\nDriver terminated successfully.") except Excception as e: print(e)
class PPMDecoder(object): """Decodes the audio data into PPM pulse data, and then into uinput joystick events. """ def __init__(self, rate): """ Parameters ---------- rate : int sample rate """ self._rate = float(rate) self._lf = None self._threshold = 15000 self._last_edge = None self._ch = None # Size in sampling intervals, of the frame space marker self._marker = int(2.0 * 0.0025 * self._rate) # Mapping of channels to events self._mapping = { 0: ecodes.ABS_X, 1: ecodes.ABS_Y, 2: ecodes.ABS_Z, 3: ecodes.ABS_THROTTLE } events = [(v, (0, 255, 5, 0)) for v in self._mapping.values()] self._ev = UInput(name='ppmadapter', events={ ecodes.EV_ABS: events, ecodes.EV_KEY: { 288: 'BTN_JOYSTICK' } }) def __enter__(self): return self def __exit__(self, type, value, tb): self._ev.close() def feed(self, data): """Feeds the decoder with a block of sample data. The data should be integer values, and should only be a single channel. Parameters ---------- data : list sample data """ sync_req = False for i in range(len(data)): this_edge = data[i] > self._threshold if self._last_edge is None: self._last_edge = this_edge continue if this_edge and not self._last_edge: # rising if self._lf is not None: sync_req |= self.signal(i - self._lf) elif not this_edge and self._last_edge: # falling self._lf = i self._last_edge = this_edge if sync_req: self._ev.syn() if self._lf is not None: self._lf = self._lf - len(data) if self._lf < (-self._rate): print("Lost sync") self._ch = None self._lf = None def signal(self, w): """Process the detected signal. The signal is the number of sampling intervals between the falling edge and the rising edge. Parameters ---------- w : int signal width Returns ------- bool does uinput require sync """ if w > self._marker: if self._ch is None: print("Got sync") self._ch = 0 return False if self._ch is None or self._ch not in self._mapping: return False duration = float(w) / self._rate value = int((duration - 0.0007) * 1000 * 255) self._ev.write(ecodes.EV_ABS, self._mapping[self._ch], value) self._ch += 1 return True
# Need to emit event BTN_TOOL_PEN = 1 when pen is hovering, # this way the system can recognize the device as a tablet. # https://www.kernel.org/doc/Documentation/input/event-codes.txt vpen.write(ecodes.EV_KEY, ecodes.BTN_TOOL_PEN, 1) pen_hovering = True pen_x = (data[5] * 255 + data[4]) pen_y = config['pen']['max_y'] - (data[3] * 255 + data[2]) pen_pressure = data[7] * 255 + data[6] vpen.write(ecodes.EV_ABS, ecodes.ABS_X, pen_x) vpen.write(ecodes.EV_ABS, ecodes.ABS_Y, pen_y) vpen.write(ecodes.EV_ABS, ecodes.ABS_PRESSURE, pen_pressure) if data[1] == 193: # Pen touch vpen.write(ecodes.EV_KEY, ecodes.BTN_TOUCH, 1) else: vpen.write(ecodes.EV_KEY, ecodes.BTN_TOUCH, 0) # Flush vpen.syn() except usb.core.USBError as e: if pen_hovering: # Need to emit event BTN_TOOL_PEN = 0 when pen is not hovering, # just for compliance with the specs. # https://www.kernel.org/doc/Documentation/input/event-codes.txt vpen.write(ecodes.EV_KEY, ecodes.BTN_TOOL_PEN, 0) pen_hovering = False vpen.syn() if e.args[0] == 19: vpen.close() raise Exception('Device has been disconnected')
class emulatedDevice(object): cap = { e.EV_KEY: [e.BTN_MOUSE, e.BTN_WHEEL, e.BTN_MIDDLE, e.BTN_RIGHT, e.BTN_SIDE, e.KEY_ZOOM, e.KEY_ZOOMIN, e.KEY_ZOOMOUT, e.KEY_ZOOMRESET, e.KEY_LEFTCTRL, e.KEY_SLASH, e.KEY_RIGHTBRACE, e.KEY_LEFT, e.KEY_UP, e.KEY_RIGHT, e.KEY_DOWN], e.EV_ABS: [ (e.ABS_X, AbsInfo(value=0, min=0, max=1023, fuzz=0, flat=0, resolution=0)), (e.ABS_Y, AbsInfo(value=0, min=0, max=599, fuzz=0, flat=0, resolution=0)) ], e.EV_REL: [ e.REL_WHEEL, e.REL_HWHEEL ], e.EV_MSC: [e.MSC_SCAN] } def __init__(self, id): print('Creating emulated touch device #%d' % id) self.id = id self.dev = UInput(self.cap, name='pytouchd-emutouchdev-%d' % id, version=0x0001) self.state = (0, 0, 0) # (x, y, which key pressed) self.keydownstamp = None self.movebuffer = [] def close(self): global debug if debug: print('Closing emulated touch device #%d' % self.id) self.dev.close() del(self) def release(self, key=None, quiet=False): global debug if not self.state[2] and key is None: return if debug and not quiet: print('REL #%d' % self.id) if key is None: key = self.state[2] noupdate = True else: noupdate = False self.dev.write(e.EV_KEY, key, 0) self.dev.syn() if not noupdate: self.state = (self.state[0], self.state[1], 0) def press(self, key=e.BTN_MOUSE, quiet=False, *, value=1): global debug if not key in self.cap[e.EV_KEY]: raise ValueError('Keycode %d is not valid!' % key) if debug and not quiet: print('PRS #%d, %d' % (self.id, key)) self.dev.write(e.EV_KEY, key, value) self.dev.syn() self.state = (self.state[0], self.state[1], key) def move(self, x, y, quiet=False): global debug if debug and not quiet: print('MOV #%d, (%d, %d)' % (self.id, x, y)) self.dev.write(e.EV_ABS, e.ABS_X, x) self.dev.write(e.EV_ABS, e.ABS_Y, y) self.dev.syn() self.state = (x, y, self.state[2]) def scroll(self, amount, horizontal=False): if horizontal: wheel = e.REL_HWHEEL else: wheel = e.REL_WHEEL self.dev.write(e.EV_REL, wheel, amount) self.dev.syn() def runBuffer(self): global debug if debug: print('BUF #%d' % self.id) for event in self.movebuffer: # TODO new-old handle function self.handle(event, True) self.movebuffer = []
def monitor_events(logf): active_keys = [] key_input = UInput() device_path = "" devices = [InputDevice(path) for path in list_devices()] for device in devices: if device.info.vendor == 6127 and device.info.product == 24646 and "input0" in device.phys: device_path = device.path def inject_input(*args): if len(args) > 0: for key in args: key_input.write(ecodes.EV_KEY, key, 1) for key in args: key_input.write(ecodes.EV_KEY, key, 0) key_input.syn() if device_path != "": device = InputDevice(device_path) device.grab() for event in device.read_loop(): if event.type == ecodes.EV_KEY: if event.value == 1: active_keys.append(event.code) elif event.value == 0: if len(active_keys) == 1: # Pinch in/out if active_keys[0] == 29: inject_input(ecodes.KEY_LEFTCTRL) # 4 Finger swipe up elif active_keys[0] == 125: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_PAGEDOWN) # 3 Finger swipe down elif active_keys[0] == 109: inject_input(ecodes.KEY_LEFTMETA) # 3 Finger swipe up elif active_keys[0] == 104: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_UP) elif len(active_keys) == 2: # Top to Bottom edge Swipe if [56, 62] == active_keys: inject_input(ecodes.KEY_LEFTALT, ecodes.KEY_F4) # Rotate Clockwise elif [29, 52] == active_keys: inject_input(ecodes.KEY_LEFTCTRL, ecodes.KEY_R) # Rotate Counterclockwise elif [29, 51] == active_keys: inject_input(ecodes.KEY_LEFTSHIFT, ecodes.KEY_LEFTCTRL, ecodes.KEY_R) # 3 Finger swipe left elif [56, 105] == active_keys: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_LEFT) # 3 Finger swipe right elif [56, 106] == active_keys: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_RIGHT) # 4 Finger swipe down elif [125, 32] == active_keys: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_PAGEUP) # 4 Finger swipe right elif [125, 38] == active_keys: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_L) elif len(active_keys) == 3: # Left edge swipe if [29, 125, 14] == active_keys: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_A) # Right edge swipe elif [56, 125, 193] == active_keys: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_TAB) # Top edge swipe elif [29, 125, 193] == active_keys: inject_input(ecodes.KEY_LEFTMETA, ecodes.KEY_DOWN) active_keys.clear() else: key_input.close()
class K: __space_mode_map = { ecodes.KEY_1: [ecodes.KEY_1, True], ecodes.KEY_2: [ecodes.KEY_2, True], ecodes.KEY_3: [ecodes.KEY_3, True], ecodes.KEY_4: [ecodes.KEY_4, True], ecodes.KEY_5: [ecodes.KEY_5, True], ecodes.KEY_6: [ecodes.KEY_6, True], ecodes.KEY_7: [ecodes.KEY_7, True], ecodes.KEY_8: [ecodes.KEY_8, True], ecodes.KEY_9: [ecodes.KEY_9, True], ecodes.KEY_0: [ecodes.KEY_0, True], ecodes.KEY_Q: [ecodes.KEY_1, True], ecodes.KEY_W: [ecodes.KEY_2, True], ecodes.KEY_E: [ecodes.KEY_3, True], ecodes.KEY_R: [ecodes.KEY_4, True], ecodes.KEY_T: [ecodes.KEY_5, True], ecodes.KEY_Y: [ecodes.KEY_6, True], ecodes.KEY_U: [ecodes.KEY_7, True], ecodes.KEY_I: [ecodes.KEY_8, True], ecodes.KEY_O: [ecodes.KEY_9, True], ecodes.KEY_P: [ecodes.KEY_0, True], ecodes.KEY_A: [ecodes.KEY_MINUS, True], ecodes.KEY_S: [ecodes.KEY_MINUS, False], ecodes.KEY_D: [ecodes.KEY_LEFTBRACE, False], ecodes.KEY_F: [ecodes.KEY_RIGHTBRACE, False], ecodes.KEY_G: [ecodes.KEY_APOSTROPHE, False], ecodes.KEY_H: [ecodes.KEY_APOSTROPHE, True], ecodes.KEY_J: [ecodes.KEY_LEFTBRACE, True], ecodes.KEY_K: [ecodes.KEY_RIGHTBRACE, True], ecodes.KEY_L: [ecodes.KEY_GRAVE, True], ecodes.KEY_SEMICOLON: [ecodes.KEY_SEMICOLON, True], #ecodes.KEY_Z: used for control mode! ecodes.KEY_X: [ecodes.KEY_GRAVE, False], ecodes.KEY_C: [ecodes.KEY_BACKSLASH, False], ecodes.KEY_V: [ecodes.KEY_EQUAL, False], ecodes.KEY_B: [ecodes.KEY_BACKSLASH, True], ecodes.KEY_N: [ecodes.KEY_EQUAL, True], ecodes.KEY_M: [ecodes.KEY_SPACE, False], ecodes.KEY_COMMA: [ecodes.KEY_COMMA, True], ecodes.KEY_DOT: [ecodes.KEY_DOT, True], ecodes.KEY_SLASH: [ecodes.KEY_SLASH, True], } __tenkey_mode_map = { ecodes.KEY_Q: [ecodes.KEY_1, False], ecodes.KEY_W: [ecodes.KEY_2, False], ecodes.KEY_E: [ecodes.KEY_3, False], ecodes.KEY_R: [ecodes.KEY_4, False], ecodes.KEY_T: [ecodes.KEY_5, False], ecodes.KEY_Y: [ecodes.KEY_6, False], ecodes.KEY_U: [ecodes.KEY_7, False], ecodes.KEY_I: [ecodes.KEY_8, False], ecodes.KEY_O: [ecodes.KEY_9, False], ecodes.KEY_P: [ecodes.KEY_0, False], ecodes.KEY_A: [ecodes.KEY_TAB, False], ecodes.KEY_S: [ecodes.KEY_DELETE, False], ecodes.KEY_D: [ecodes.KEY_BACKSPACE, False], ecodes.KEY_F: [ecodes.KEY_ESC, False], ecodes.KEY_G: [ecodes.KEY_F1, False], ecodes.KEY_H: [ecodes.KEY_LEFT, False], ecodes.KEY_J: [ecodes.KEY_DOWN, False], ecodes.KEY_K: [ecodes.KEY_UP, False], ecodes.KEY_L: [ecodes.KEY_RIGHT, False], ecodes.KEY_SEMICOLON: [ecodes.KEY_ENTER, False], } def __init__(self): self.sink = UInput() self.reset_state() self.buffered_event = None def set_state(self, state): self.__state = state def pop_state(self): self.__state.state_exit() self.__state.popState() def emit_with_space_mode(self, event): if event.event.scancode in self.__space_mode_map: translated_event = self.__space_mode_map[event.event.scancode] if translated_event[1]: self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 2) self.sink.write(ecodes.EV_KEY, translated_event[0], 1) self.sink.write(ecodes.EV_KEY, translated_event[0], 0) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 0) else: self.sink.write(ecodes.EV_KEY, translated_event[0], 1) self.sink.write(ecodes.EV_KEY, translated_event[0], 0) else: self.sink.write(ecodes.EV_KEY, event.event.scancode, 1) self.sink.write(ecodes.EV_KEY, event.event.scancode, 0) def emit_with_tenkey_mode(self, event): if event.event.scancode in self.__tenkey_mode_map: translated_event = self.__tenkey_mode_map[event.event.scancode] if translated_event[1]: self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 2) self.sink.write(ecodes.EV_KEY, translated_event[0], 1) self.sink.write(ecodes.EV_KEY, translated_event[0], 0) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 0) else: self.sink.write(ecodes.EV_KEY, translated_event[0], 1) self.sink.write(ecodes.EV_KEY, translated_event[0], 0) else: self.sink.write(ecodes.EV_KEY, event.event.scancode, 1) self.sink.write(ecodes.EV_KEY, event.event.scancode, 0) def emit_with_control_mode(self, event): self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTCTRL, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTCTRL, 2) if self.__space_mode: self.emit_with_space_mode(event) elif self.__tenkey_mode: #print("control tenkey") self.emit_with_tenkey_mode(event) else: self.sink.write(ecodes.EV_KEY, event.event.scancode, 1) self.sink.write(ecodes.EV_KEY, event.event.scancode, 0) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTCTRL, 0) def emit_with_shift_mode(self, event): self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 2) self.sink.write(ecodes.EV_KEY, event.event.scancode, 1) self.sink.write(ecodes.EV_KEY, event.event.scancode, 0) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 0) def emit_with_normal_mode(self, event): self.sink.write(ecodes.EV_KEY, event.event.scancode, event.event.keystate) def emit(self, event): #if event.event.scancode == ecodes.KEY_CAPSLOCK:# or event.event.scancode == ecodes.KEY_SYSRQ: # self.sink.write(ecodes.EV_KEY, ecodes.KEY_F1, event.event.keystate) #elif event.event.scancode == ecodes.KEY_LEFTMETA and event.event.keystate == events.KeyEvent.key_hold: # pass # #self.sink.write(ecodes.EV_KEY, ecodes.KEY_F1, event.event.keystate) if self.__control_mode and event.event.keystate != events.KeyEvent.key_up: self.emit_with_control_mode(event) elif self.__space_mode and event.event.keystate != events.KeyEvent.key_up: self.emit_with_space_mode(event) elif self.__shift_mode and event.event.keystate != events.KeyEvent.key_up: self.emit_with_shift_mode(event) elif self.__tenkey_mode and event.event.keystate != events.KeyEvent.key_up: self.emit_with_tenkey_mode(event) else: self.emit_with_normal_mode(event) self.sink.syn() def emit_space(self): self.sink.write(ecodes.EV_KEY, ecodes.KEY_SPACE, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_SPACE, 0) self.sink.syn() def emit_z(self): self.sink.write(ecodes.EV_KEY, ecodes.KEY_Z, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_Z, 0) self.sink.syn() def emit_slash(self): if self.__space_mode: self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 2) self.sink.write(ecodes.EV_KEY, ecodes.KEY_SLASH, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_SLASH, 0) self.sink.write(ecodes.EV_KEY, ecodes.KEY_LEFTSHIFT, 0) else: self.sink.write(ecodes.EV_KEY, ecodes.KEY_SLASH, 1) self.sink.write(ecodes.EV_KEY, ecodes.KEY_SLASH, 0) self.sink.syn() def emit_as_buffered(self, event): self.buffered_event = event def emit_buffered(self): self.emit(self.buffered_event) self.buffered_event = None def buffer(self, event): self.emit_as_buffered(event) def flush(self): self.emit_buffered() def reset_state(self): self.__buffer = None self.__space_mode = False self.__control_mode = False self.__meta_mode = False self.__tenkey_mode = False self.__shift_mode = False def space_mode(self, flag): self.__space_mode = flag def control_mode(self, flag): self.__control_mode = flag def meta_mode(self, flag): self.__meta_mode = flag def shift_mode(self, flag): self.__shift_mode = flag def tenkey_mode(self, flag): self.__tenkey_mode = flag def close(self): self.sink.close()
#!/usr/bin/python3 # # evdev_keyboard.py # Injecting input events. Display "hello" on the console # # http://python-evdev.readthedocs.org/en/latest/tutorial.html import time from evdev import UInput, ecodes as e ui = UInput() # accepts only KEY_* events by default ui.write(e.EV_KEY, e.KEY_H, 1) # KEY_H down ui.write(e.EV_KEY, e.KEY_H, 0) # KEY_H up time.sleep(0.1) ui.write(e.EV_KEY, e.KEY_E, 1) ui.write(e.EV_KEY, e.KEY_E, 0) time.sleep(0.1) ui.write(e.EV_KEY, e.KEY_L, 1) ui.write(e.EV_KEY, e.KEY_L, 0) time.sleep(0.1) ui.write(e.EV_KEY, e.KEY_L, 1) ui.write(e.EV_KEY, e.KEY_L, 0) time.sleep(0.1) ui.write(e.EV_KEY, e.KEY_O, 1) ui.write(e.EV_KEY, e.KEY_O, 0) time.sleep(0.1) ui.syn() ui.close()
class HIDMapperController (object): def __init__ (self): self._profile = None self._running = False self._input_devices = None self._file_descriptors = None self._allowed_event_types = None self._event_status = None self._gesture_codes = deque() self._last_queued = None self._virtual_input = None self._matcher = None @property def profile (self, profile_obj): self._profile=profile_obj @profile.setter def profile (self, profile_obj): self._profile=profile_obj def _prepare_device (self): #print("device: %s" % self._profile.device.name) self._event_status = {key:0 for key in self._profile.device.get_events_supported()} #print("Events supported",self._event_status) self._allowed_event_types = set([getattr(ecodes,i[-1].split(':')[0]) for i in self._event_status]) self._input_devices = map(InputDevice, self._profile.device.devices) self._file_descriptors = { dev.fd: i for i, dev in enumerate(self._input_devices) } print("Mappings for '" + self._profile.name+"' " + '-'*30) for k,v in sorted(self._profile.mapping.items()): print(str(k.replace("EV_KEY:KEY_","").replace("ENTER","<-'").replace("APOSTROPHE","'").replace(",","")).lower().rjust(20)+" as "+(', '.join(v)).replace("r_hand_tap_", "").replace("_vs_thumb", "")) # Prepare virtual device for event injection capabilities = {} for ev_chain in self._profile.mapping: for k in re.split('[+,]', ev_chain): et, ec = k.split(':', 1) etype = ecodes.ecodes[et] if etype in capabilities: capabilities[etype].append(ecodes.ecodes[ec]) else: capabilities[etype] = [ ecodes.ecodes[ec] ] #print("Capabilities", capabilities) self._virtual_input = UInput(events = capabilities) # Prepare matcher self._matcher = Matcher(self._profile) def start (self): """ Start capturing from the device(s) of the current profile """ self._prepare_device() try: for dev in self._input_devices: dev.grab() except Exception as e: print("Unable to grab device", e) self._running = True spawn(self._capture_loop) spawn(self._process_loop) sleep(0) def stop (self): """ Stop capturing and release the device(s) """ self._running = False try: for dev in self._input_devices: dev.ungrab() except: pass if self._virtual_input: self._virtual_input.close() def _capture_loop (self): try: devices = {dev.fd : dev for dev in self._input_devices} while self._running: r,_,_ = select(devices, [], [], timeout=self._profile.double_click_timeout/1000.0) for fd in r: for event in devices[fd].read(): #print("Lo que", event) if self.is_allowed_event(event, fd): event_code = self.get_event_code(event, fd) if event.value == 1: #print("Pressed!", event_code) self.set_event_status(event_code, 1) #print("Statuses", self._event_status) self._store_gestures() elif event.value == 0: #print("Released!", event_code) self.set_event_status(event_code, 0) #print("Statuses", self._event_status) #self._store_gestures() else: print("What is this?",event) except: self._running = False traceback.print_exc() def _store_gestures (self): """ Fetch current gestures, select those allowed in the profile and store them in the queue of gesture codes """ filtered_gestures = set([ gesture for gesture in self.get_current_gestures() if gesture in self._profile.gestures ]) if not filtered_gestures: return if filtered_gestures != self._last_queued: distance = 1.0 if self._last_queued: distance = self._profile.get_gestures_distance(filtered_gestures, self._last_queued) #print("Distance is", distance) self._last_queued = filtered_gestures if distance <= 0.5: try: timestamp, last_queued = self._gesture_codes.pop() #print("Time interval", time.time() - timestamp) if time.time() - timestamp > self._profile.double_click_timeout/6000.0: self._gesture_codes.append((timestamp, last_queued)) except IndexError: pass #print("Empty queue!") self._gesture_codes.append((time.time(), filtered_gestures)) def _process_loop (self): """ TODO: Process the queue of gestures and inject remapped events """ while self._running: try: timestamp, prefixes = self._gesture_codes.pop() reduced = self._profile.reduce_gestures(prefixes) self._matcher.add_prefix(timestamp, reduced) # With every possible option if any... for candidate, output_event in self._matcher.get_matching_codes(): #print("Candidate(s)",candidate, "would generate events(s)", output_event) self._inject_event(output_event) except IndexError: pass except: print("Processing error") traceback.print_exc() sleep(self._profile.double_click_timeout/5000.0) def _inject_event (self, event_codes): """ Insert one or several events in the virtual input event_code is a string, normally, that contains an event, like 'EV_KEY:KEY_A' event_code can have a sequence of events, like 'EV_KEY:KEY_A,EV_KEY:KEY_B,EV_KEY:KEY_C' event_code can contain chained events, to make combination of keys, like: 'EV_KEY:KEY_LEFTCTRL+EV_KEY:KEY_C' """ if isinstance(event_codes, str): event_codes = event_codes.split(",") for event_code_combo in event_codes: for operation in [1, 0]: for event_code in event_code_combo.split("+"): if isinstance(event_code, str): event_code = event_code.split(':') if len(event_code) == 1 and ':' in event_code[0]: event_code = event_code[0].split(':') etype = ecodes.ecodes[event_code[0]] ecode = ecodes.ecodes[event_code[1]] #names = ecodes.bytype[etype][ecode] #if not isinstance(names, list): # names = [names] #print("Inject event {} {}".format(names[0], "pressed" if operation==1 else "released")) self._virtual_input.write(etype, ecode, operation) # pressed self._virtual_input.syn() def find_event_keys (self, event_code, where): """ param event_code: Event code to search (as a tuple) param where: A dictionary whose keys are event codes Search and returns a list of matching keys for an event code, in the dictionary or list 'where' """ matches = [] event_keys = [event_code] if len(event_code) < 2: for dev_num, _ in enumerate(self._file_descriptors): event_keys.append(('DEV_%d' % dev_num, event_code[0])) else: event_keys.append((event_code[1],)) for ev in event_keys: if ev in where: matches.append(ev) return matches def is_allowed_event (self, event, fd = None): """ Decide if the controller must capture this event or not """ if event.type in self._allowed_event_types: event_code = self.get_event_code(event) if fd is not None: key1 = ('DEV_%d' % self._file_descriptors[fd], event_code[0]) key2 = event_code return key1 in self._event_status or key2 in self._event_status else: if not event_code in self._event_status: for dev_num, _ in enumerate(self._file_descriptors): key = ('DEV_%d' % dev_num, event_code[0]) if key in self._event_status: return True else: return True return False def get_event_code (self, event, fd = None): """ Returns the event code (type+code), prefixed by the device if 'fd' is present """ name = ecodes.bytype[event.type][event.code] #print("Event code from", event, "is", name) if isinstance(name, list): name = name[0] event_code = "%s:%s" % (ecodes.EV[event.type], name) if fd is not None: return ('DEV_%d' % self._file_descriptors[fd], event_code) return (event_code, ) def get_current_gestures (self, where_to_find = None, current_gestures = None): """ return: A set of gestures activated at this moment """ if where_to_find is None: where_to_find = self._profile.device.gestures_lut if current_gestures is None: current_gestures = set([]) for ev in self._event_status: if self._event_status[ev]: # Is pressed? for found in self.find_event_keys(ev, where_to_find): result = where_to_find[found] if isinstance(result, dict): self.get_current_gestures(result, current_gestures) else: current_gestures.add(result) return current_gestures def set_event_status (self, event_code, status): """ Sets the status for every event that matches the event_code """ for ev_key in self.find_event_keys(event_code, self._event_status): self._event_status[ev_key] = status def __del__ (self): print("Stopping capturer") if self._running: self.stop()
e.KEY_T, e.KEY_S, e.KEY_A, e.KEY_B, e.KEY_C, e.KEY_D, e.KEY_E, e.KEY_F, e.KEY_G, e.KEY_H, e.KEY_ENTER ] async def VKeybord(ui, name, longPause, shortPause, keys): while True: await asyncio.sleep(longPause) for key in keys: print(name, e.KEY[key]) # accepts only KEY_* events by default ui.write(e.EV_KEY, key, 1) # KEY_A down ui.write(e.EV_KEY, key, 0) # KEY_A up ui.syn() await asyncio.sleep(shortPause) loop = asyncio.get_event_loop() try: asyncio.ensure_future(VKeybord(ui, "first", 1, 0.08, A)) asyncio.ensure_future(VKeybord(ui2, "second", 2.3, 0.0715, B)) loop.run_forever() except KeyboardInterrupt: pass finally: print("Closing Loop") loop.close() ui.close() ui2.close()
i = 5 moves = 100000 print("Go to 2048 window. ["+str(i)+"] secs.") while i != 0: print(" " + str(i)) time.sleep(1) i -= 1 print("Commencing...\n") keys = ["e.KEY_UP", "e.KEY_DOWN", "e.KEY_LEFT", "e.KEY_RIGHT"] keys = [105, 106, 103, 108] # random.choice(foo) ui = UInput() current_title = GetActiveWindowTitle() if 'Firefox' in current_title: while moves != 0: temp_key = random.choice(keys) send_keys(ui, temp_key) time.sleep(0.1) moves -= 1 print("Done") else: print("You're not on the firefox window.") ui.close()
y -= SCROLL_SENSITIVITY # mouse button 4 and 5 if mouse_event.type == EV_KEY and mouse_event.code == BTN_SIDE and mouse_event.value == 1: keyboard.write(EV_KEY, KEY_M, 1) keyboard.write(EV_KEY, KEY_M, 0) keyboard.syn() sleep(0.05) mouse.write(EV_KEY, BTN_LEFT, 1) mouse.write(EV_SYN, SYN_REPORT, 0) sleep(0.05) mouse.write(EV_KEY, BTN_LEFT, 0) mouse.write(EV_SYN, SYN_REPORT, 0) ignore_count = 2 elif mouse_event.type == EV_KEY and mouse_event.code == BTN_EXTRA and mouse_event.value == 1: keyboard.write(EV_KEY, KEY_H, 1) keyboard.write(EV_KEY, KEY_H, 0) keyboard.write(EV_KEY, KEY_A, 1) keyboard.write(EV_KEY, KEY_A, 0) keyboard.syn() sleep(0.05) mouse.write(EV_KEY, BTN_LEFT, 1) mouse.write(EV_SYN, SYN_REPORT, 0) sleep(0.05) mouse.write(EV_KEY, BTN_LEFT, 0) mouse.write(EV_SYN, SYN_REPORT, 0) ignore_count = 2 keyboard.close() mouse.close()
class EvKeyboard(object): def __init__(self): self.translate = XTranslate() self.translate.install_layout_hook() self.keyboards = self.detect_keyboards() # ~ self.device = UInput.from_device(*self.keyboards, name='macpy keyboard') self.device = UInput(name='macpy keyboard') self.queue = Queue() self.mainloop = Thread(target=self._mainloop, name='EvKeyboard mainloop') self.mainloop.start() self.selector = DefaultSelector() self.events = Thread(target=self._events, name='EvKeyboard event loop') self.stop = False self.hook = False self.hook_callback = None self.hotkeys = False self.hk_callbacks = {} self.input = deque(maxlen=128) self.hotstrings = {} def detect_keyboards(self): keyboards = [] for device in list_devices(): input_device = InputDevice(device) if ecodes.EV_KEY in input_device.capabilities(): keyboards.append(input_device) return tuple(keyboards) def _mainloop(self): while True: method, args = self.queue.get() if method is None: break try: method(*args) except Exception as e: print( 'Error in EvKeyboard mainloop: \n', ''.join( traceback.format_exception(type(e), e, e.__traceback__))) self.queue.task_done() def enqueue(self, method, *args): self.queue.put_nowait((method, args)) def close(self): self.device.close() self.enqueue(None) self.translate.close() self.stop = True def get_key_state(self, key): keycodes = [ keycode for keyboard in self.keyboards for keycode in keyboard.active_keys() ] if key.ec.value in keycodes: return KeyState(True) else: return KeyState(False) def _events(self): for keyboard in self.keyboards: self.selector.register(keyboard, EVENT_READ) while not self.stop: for key, mask in self.selector.select(timeout=0.3): device = key.fileobj for event in device.read(): event = categorize(event) if isinstance(event, KeyEvent): if event.keystate < 2: key = Key.from_ec(event.event.code) keystate = (KeyState.PRESSED if event.keystate == 1 else KeyState.RELEASED) mask = 0 leds = [ led for keyboard in self.keyboards for led in keyboard.leds() ] if ecodes.LED_NUML in leds: mask |= self.translate.lockmask['NUMLOCK'] if ecodes.LED_CAPSL in leds: mask |= self.translate.lockmask['CAPSLOCK'] if ecodes.LED_SCROLLL in leds: mask |= self.translate.lockmask['SCROLLLOCK'] keycodes = [ keycode for keyboard in self.keyboards for keycode in keyboard.active_keys() ] for keycode in keycodes: for mod, codes in self.translate.modmap.items( ): if ((keycode + self.translate.min_keycode) in codes): mask |= self.translate.modmask[mod] if self.translate.modmap['ALTGR'][0] in keycodes: mask |= self.translate.modmask['ALTGR'] keysym, mods, locks = self.translate. \ keycode_to_keysym( key.ec + self.translate.min_keycode, mask) char = None if keysym in PRINT: char = PRINT[keysym] if self.hook: self.enqueue( self.hook_callback, KeyboardEvent(key, keystate, char, mods, locks)) if self.hotkeys and event.keystate == 1: modifiers = set() for mod, state in mods.items(): if state: modifiers.add( getattr(Modifiers, mod)[0]) hotkey = HotKey(key, modifiers) if hotkey in self.hk_callbacks: self.enqueue(self.hk_callbacks[hotkey], hotkey) if self.hotstrings and event.keystate == 0 and char: self.input.append(char) string = ''.join(self.input) for hotstring in self.hotstrings: if (string.endswith(hotstring.string) and not hotstring.triggers): retstring = HotString( hotstring.string, hotstring.triggers) self.enqueue( self.hotstrings[hotstring], retstring) self.input.clear() elif (string[:-1].endswith( hotstring.string) and string[-1] in hotstring.triggers): retstring = HotString( hotstring.string, hotstring.triggers, string[-1]) self.enqueue( self.hotstrings[hotstring], retstring) self.input.clear() def install_keyboard_hook(self, callback, grab=False): if not self.events.is_alive(): self.events.start() self.hook = True self.hook_callback = callback def uninstall_keyboard_hook(self): self.hook = False def init_hotkeys(self): if not self.events.is_alive(): self.events.start() self.hotkeys = True def uninit_hotkeys(self): self.hotkeys = False self.hk_callbacks = {} def register_hotkey(self, key, modifiers, callback): mods = set() for mod in modifiers: for Mod in Modifiers: if mod in Mod: mods.add(Mod[0]) hotkey = HotKey(key, mods) self.hk_callbacks[hotkey] = callback return hotkey def unregister_hotkey(self, hotkey): if hotkey in self.hk_callbacks: del self.hk_callbacks[hotkey] def register_hotstring(self, string, triggers, callback): if self.hook: hotstring = HotString(string, triggers) self.hotstrings[hotstring] = callback return hotstring else: raise RuntimeError('Keyboard hook not installed') def unregister_hotstring(self, hotstring): if hotstring in self.hotstrings: del self.hotstrings[hotstring] def _press_key(self, key): self.device.write(ecodes.EV_KEY, key.ec, 1) def _release_key(self, key): self.device.write(ecodes.EV_KEY, key.ec, 0) def keypress(self, key, state=None): if state is None: self.enqueue(self._press_key, key) self.enqueue(self._release_key, key) elif state == KeyState.PRESSED: self.enqueue(self._press_key, key) elif state == KeyState.RELEASED: self.enqueue(self._release_key, key) else: raise TypeError('Invalid state') self.enqueue(self.device.syn) def _type(self, string): for char in string: keysym = self.translate.lookup_keysym(char) keycode, mods, locks = self.translate.keysym_to_keycode(keysym) key = Key.from_ec(keycode - self.translate.min_keycode) if any(mods): for mod, state in mods.items(): if state: modifier = getattr(Modifiers, mod, None) if modifier: self._press_key(modifier[0]) self._press_key(key) self._release_key(key) if any(mods): for mod, state in mods.items(): if state: modifier = getattr(Modifiers, mod, None) if modifier: self._release_key(modifier[0]) self.device.syn() def type(self, string): self.enqueue(self._type, string)
def executaAcao(tecla): ui = UInput() print tecla ui.write(e.EV_KEY, e.ecodes[tecla], 1) #key down ui.write(e.EV_KEY, e.ecodes[tecla], 0) #key up ui.syn() ui.close()