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