1#!/usr/bin/env python3 2# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6# Description: 7# 8# Class for injecting input events to linux 'evdev' input devices. 9# 10# Provides evemu-play-like functionality if run from the command line: 11# $ input_event_player.py -d /dev/input/event6 12 13""" Playback input events on a linux input device. """ 14 15from __future__ import division 16from __future__ import print_function 17 18import glob 19import os.path 20import re 21import time 22 23from optparse import OptionParser 24# Try to import from the autotest_lib structure. If it fails try the default. 25# If this script was run outside of autotest the "except" would be the flow. 26# If run within, the "try" is the flow. 27try: 28 from autotest_lib.client.bin.input.input_device import InputDevice, InputEvent 29except ImportError: 30 from input_device import InputDevice, InputEvent 31 32 33class InputEventPlayer: 34 """ Linux evdev input event player. 35 36 An "evdev" input event player injects a stream of "input events" to kernel 37 evdev driver. With this player, we could easily playback an input event file 38 which was recorded with the tool evemu-record previously. 39 40 """ 41 42 def __init__(self): 43 self.tv_sec = None 44 self.tv_usec = None 45 46 def playback(self, device, gesture_file): 47 """ Play the events in gesture_file on device. 48 49 Keyword arguments: 50 device -- the InputDevice device object 51 gesture_file -- the name of the event file recorded previously 52 """ 53 if not device: 54 raise 55 event_str = 'E: (\d+)\.(\d+) ([0-9a-f]{4}) ([0-9a-f]{4}) ([-]?\d+)' 56 event_pattern = re.compile(event_str) 57 for line in open(gesture_file, 'rt'): 58 m = event_pattern.match(line) 59 if not m: 60 raise 61 event = InputEvent(int(m.group(1)), 62 int(m.group(2)), 63 int(m.group(3), 16), 64 int(m.group(4), 16), 65 int(m.group(5))) 66 if not self.tv_sec: 67 self.tv_sec = event.tv_sec 68 self.tv_usec = event.tv_usec 69 delta = event.tv_sec - self.tv_sec 70 delta += ((event.tv_usec - self.tv_usec) / 1000000.0) 71 # Sleep only if the event is 0.05 ms later than the previous one 72 if delta > 0.0000500: 73 time.sleep(delta) 74 self.tv_sec = event.tv_sec 75 self.tv_usec = event.tv_usec 76 event.write(device.f) 77 78 79if __name__ == '__main__': 80 parser = OptionParser() 81 82 parser.add_option('-d', '--devpath', dest='devpath', default='', 83 help='device path (/dev/input/event0)') 84 parser.add_option('-t', '--touchpad', action='store_true', dest='touchpad', 85 default=False, help='Find and use first touchpad device') 86 parser.add_option('-f', '--file', action='store', dest='gesture_file', 87 help='Event file to playback') 88 (options, args) = parser.parse_args() 89 90 if options.touchpad: 91 for evdev in glob.glob('/dev/input/event*'): 92 device = InputDevice(evdev) 93 if device.is_touchpad(): 94 break 95 else: 96 print('Can not find a touchpad device') 97 exit() 98 elif not os.path.exists(options.devpath): 99 print('Can not find the input device "%s".' % options.devpath) 100 exit() 101 else: 102 device = InputDevice(options.devpath) 103 if not options.gesture_file: 104 print('Gesture file is not specified.') 105 exit() 106 if not os.path.exists(options.gesture_file): 107 print('Can not find the gesture file %s.' % options.gesture_file) 108 exit() 109 110 InputEventPlayer().playback(device, options.gesture_file) 111 print('Gesture file %s has been played.' % options.gesture_file) 112