• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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