blob: 6b830dc9e9e37b277360aa8599bdf1149c15d79d [file] [log] [blame]
Nicolas Boichat8b3c51b2017-04-25 09:43:58 +08001# Copyright 2015 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import argparse
6# Get all evdev/uinput events in our namespace.
7# pylint: disable=wildcard-import, unused-wildcard-import
8from uinput.ev import *
9import subprocess
10import time
11import uinput
12
13# Default delay between key presses in seconds. 12ms is the xdotool default.
14default_delay = 0.012
15uinput_device_keyboard = None
16
17
18# This dictionary contains most 7 bit ASCII characters. Add more if needed.
19# TODO(ihf): Create this table using xkbcommon to support arbirtrary
20# character sets and keyboard layouts.
21_CROS_CHAR_MAP = {
22 "\b": [KEY_BACKSPACE],
23 "\t": [KEY_TAB],
24 "\n": [KEY_ENTER],
25
26 " ": [KEY_SPACE],
27 "!": [KEY_LEFTSHIFT, KEY_1],
28 '"': [KEY_LEFTSHIFT, KEY_APOSTROPHE],
29 "#": [KEY_LEFTSHIFT, KEY_3],
30 "$": [KEY_LEFTSHIFT, KEY_4],
31 "%": [KEY_LEFTSHIFT, KEY_5],
32 "&": [KEY_LEFTSHIFT, KEY_7],
33 "'": [KEY_APOSTROPHE],
34 "(": [KEY_LEFTSHIFT, KEY_9],
35 ")": [KEY_LEFTSHIFT, KEY_0],
36 "*": [KEY_KPASTERISK],
37 "+": [KEY_LEFTSHIFT, KEY_EQUAL],
38 ",": [KEY_COMMA],
39 "-": [KEY_MINUS],
40 ".": [KEY_DOT],
41 "/": [KEY_SLASH],
42
43 "0": [KEY_0],
44 "1": [KEY_1],
45 "2": [KEY_2],
46 "3": [KEY_3],
47 "4": [KEY_4],
48 "5": [KEY_5],
49 "6": [KEY_6],
50 "7": [KEY_7],
51 "8": [KEY_8],
52 "9": [KEY_9],
53
54 ":": [KEY_LEFTSHIFT, KEY_SEMICOLON],
55 ";": [KEY_SEMICOLON],
56 "<": [KEY_LEFTSHIFT, KEY_COMMA],
57 "=": [KEY_EQUAL],
58 ">": [KEY_LEFTSHIFT, KEY_DOT],
59 "?": [KEY_LEFTSHIFT, KEY_SLASH],
60 "@": [KEY_LEFTSHIFT, KEY_2],
61
62 "A": [KEY_LEFTSHIFT, KEY_A],
63 "B": [KEY_LEFTSHIFT, KEY_B],
64 "C": [KEY_LEFTSHIFT, KEY_C],
65 "D": [KEY_LEFTSHIFT, KEY_D],
66 "E": [KEY_LEFTSHIFT, KEY_E],
67 "F": [KEY_LEFTSHIFT, KEY_F],
68 "G": [KEY_LEFTSHIFT, KEY_G],
69 "H": [KEY_LEFTSHIFT, KEY_H],
70 "I": [KEY_LEFTSHIFT, KEY_I],
71 "J": [KEY_LEFTSHIFT, KEY_J],
72 "K": [KEY_LEFTSHIFT, KEY_K],
73 "L": [KEY_LEFTSHIFT, KEY_L],
74 "M": [KEY_LEFTSHIFT, KEY_M],
75 "N": [KEY_LEFTSHIFT, KEY_N],
76 "O": [KEY_LEFTSHIFT, KEY_O],
77 "P": [KEY_LEFTSHIFT, KEY_P],
78 "Q": [KEY_LEFTSHIFT, KEY_Q],
79 "R": [KEY_LEFTSHIFT, KEY_R],
80 "S": [KEY_LEFTSHIFT, KEY_S],
81 "T": [KEY_LEFTSHIFT, KEY_T],
82 "U": [KEY_LEFTSHIFT, KEY_U],
83 "V": [KEY_LEFTSHIFT, KEY_V],
84 "W": [KEY_LEFTSHIFT, KEY_W],
85 "X": [KEY_LEFTSHIFT, KEY_X],
86 "Y": [KEY_LEFTSHIFT, KEY_Y],
87 "Z": [KEY_LEFTSHIFT, KEY_Z],
88
89 "[": [KEY_LEFTBRACE],
90 "\\": [KEY_BACKSLASH],
91 "]": [KEY_RIGHTBRACE],
92 "^": [KEY_LEFTSHIFT, KEY_6],
93 "_": [KEY_LEFTSHIFT, KEY_MINUS],
94 "`": [KEY_GRAVE],
95
96 "a": [KEY_A],
97 "b": [KEY_B],
98 "c": [KEY_C],
99 "d": [KEY_D],
100 "e": [KEY_E],
101 "f": [KEY_F],
102 "g": [KEY_G],
103 "h": [KEY_H],
104 "i": [KEY_I],
105 "j": [KEY_J],
106 "k": [KEY_K],
107 "l": [KEY_L],
108 "m": [KEY_M],
109 "n": [KEY_N],
110 "o": [KEY_O],
111 "p": [KEY_P],
112 "q": [KEY_Q],
113 "r": [KEY_R],
114 "s": [KEY_S],
115 "t": [KEY_T],
116 "u": [KEY_U],
117 "v": [KEY_V],
118 "w": [KEY_W],
119 "x": [KEY_X],
120 "y": [KEY_Y],
121 "z": [KEY_Z],
122
123 "{": [KEY_LEFTSHIFT, KEY_LEFTBRACE],
124 "|": [KEY_LEFTSHIFT, KEY_BACKSLASH],
125 "}": [KEY_LEFTSHIFT, KEY_RIGHTBRACE],
126 "~": [KEY_LEFTSHIFT, KEY_GRAVE],
127}
128
129
130# A list of American English ChromeOS keys to define a keyboard device.
131_CROS_KEYS_ALL = [
132 # Function row.
133 KEY_ESC,
134 KEY_F1,
135 KEY_F2,
136 KEY_F3,
137 KEY_F4,
138 KEY_F5,
139 KEY_F6,
140 KEY_F7,
141 KEY_F8,
142 KEY_F9,
143 KEY_F10,
144 KEY_F11,
145 KEY_F12,
146 KEY_HOME,
147 KEY_END,
148 KEY_INSERT,
149 KEY_DELETE,
150 # First row.
151 KEY_GRAVE,
152 KEY_1,
153 KEY_2,
154 KEY_3,
155 KEY_4,
156 KEY_5,
157 KEY_6,
158 KEY_7,
159 KEY_8,
160 KEY_9,
161 KEY_0,
162 KEY_MINUS,
163 KEY_EQUAL,
164 KEY_BACKSPACE,
165 # Second row.
166 KEY_TAB,
167 KEY_Q,
168 KEY_W,
169 KEY_E,
170 KEY_R,
171 KEY_T,
172 KEY_Y,
173 KEY_U,
174 KEY_I,
175 KEY_O,
176 KEY_P,
177 KEY_LEFTBRACE,
178 KEY_RIGHTBRACE,
179 KEY_BACKSLASH,
180 # Third row
181 KEY_CAPSLOCK,
182 KEY_A,
183 KEY_S,
184 KEY_D,
185 KEY_F,
186 KEY_G,
187 KEY_H,
188 KEY_J,
189 KEY_K,
190 KEY_L,
191 KEY_SEMICOLON,
192 KEY_APOSTROPHE,
193 KEY_ENTER,
194 # Forth row.
195 KEY_LEFTSHIFT,
196 KEY_Z,
197 KEY_X,
198 KEY_C,
199 KEY_V,
200 KEY_B,
201 KEY_N,
202 KEY_M,
203 KEY_COMMA,
204 KEY_DOT,
205 KEY_SLASH,
206 KEY_RIGHTSHIFT,
207 # Fifth row.
208 KEY_LEFTCTRL,
209 KEY_FN,
210 KEY_SEARCH,
211 KEY_LEFTALT,
212 KEY_SPACE,
213 KEY_NUMLOCK,
214 KEY_SCROLLLOCK,
215 KEY_RIGHTALT,
216 KEY_RIGHTCTRL,
217 # Directional keys.
218 KEY_UP,
219 KEY_PAGEUP,
220 KEY_LEFT,
221 KEY_RIGHT,
222 KEY_DOWN,
223 KEY_PAGEDOWN,
224]
225
226
227def _chars_to_events(chars):
228 """
229 Translates string to key events.
230
231 @param chars: characters to translate to events.
232 @returns: list of lists of events representing characters.
233 """
234 events = []
235 for char in chars:
236 events.append(_CROS_CHAR_MAP[char])
237 return events
238
239
240def _get_uinput_device_keyboard():
241 """
242 Lazy initialize device and return it. We don't want to create a device
243 during build_packages or for tests that don't need it, hence init with None.
244 """
245 global uinput_device_keyboard
246 if uinput_device_keyboard is None:
247 # For DUTs without keyboard attached force load uinput.
248 subprocess.Popen(['modprobe', 'uinput']).wait()
249 uinput_device_keyboard = uinput.Device(_CROS_KEYS_ALL)
250 return uinput_device_keyboard
251
252
253def _uinput_translate_name(event_name):
254 """
255 Translates string |event_name| to uinput event.
256 """
257 return getattr(uinput, event_name)
258
259
260def _uinput_emit_keycombo(device, events, syn=True):
261 """
262 Wrapper for uinput.emit_combo. Emits sequence of events.
263 Example: [KEY_LEFTCTRL, KEY_LEFTALT, KEY_F5]
264 """
265 time.sleep(default_delay)
266 device.emit_combo(events, syn)
267
268
269def press_keys(keys):
270 """Presses the given keys as one combination.
271
272 Please do not leak uinput dependencies outside of the file.
273
274 @param key: A simple list of key strings, e.g. ['LEFTCTRL', 'F4']
275 """
276 events = [_uinput_translate_name(en) for en in keys]
277 _uinput_emit_keycombo(_get_uinput_device_keyboard(), events)
278
279
280def type_chars(text):
281 """Translates ASCII text to keystrokes and sends them as events.
282
283 @param text: string to send as events to keyboard.
284 """
285 events = _chars_to_events(text)
286 device = _get_uinput_device_keyboard()
287 for keys in events:
288 _uinput_emit_keycombo(device, keys)