diff options
author | Luigi Semenzato <semenzato@chromium.org> | 2016-01-15 13:33:06 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-02-05 06:02:49 -0800 |
commit | 4ec554dd8fbdd47871dcd04374fb04018b24b7b5 (patch) | |
tree | a786237f2c8a04e1a64efee04e42d39c222b4264 | |
parent | c68e5a7c9bc0c1ae131303a41e51b6e13ca25e31 (diff) | |
download | chrome-ec-4ec554dd8fbdd47871dcd04374fb04018b24b7b5.tar.gz |
ectool: add inject-keys.py
A simple wrapper for "ectool kbpress" to do basic automation
when working remotely (for instance, logging in).
Includes a test script.
BUG=b:26349756
TEST=ran on platform in various ways
BRANCH=none
Signed-off-by: Luigi Semenzato <semenzato@chromium.org>
Change-Id: I96fdd99aa228b51cf22f9323facdc4ddb59db9ff
Reviewed-on: https://chromium-review.googlesource.com/322286
Commit-Ready: Luigi Semenzato <semenzato@chromium.org>
Tested-by: Luigi Semenzato <semenzato@chromium.org>
Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rwxr-xr-x | util/inject-keys.py | 127 | ||||
-rwxr-xr-x | util/test-inject-keys.sh | 111 |
2 files changed, 238 insertions, 0 deletions
diff --git a/util/inject-keys.py b/util/inject-keys.py new file mode 100755 index 0000000000..ef87bb14b6 --- /dev/null +++ b/util/inject-keys.py @@ -0,0 +1,127 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import string +import subprocess +import sys + + +KEYMATRIX = {'`': (3, 1), '1': (6, 1), '2': (6, 4), '3': (6, 2), '4': (6, 3), + '5': (3, 3), '6': (3, 6), '7': (6, 6), '8': (6, 5), '9': (6, 9), + '0': (6, 8), '-': (3, 8), '=': (0, 8), 'q': (7, 1), 'w': (7, 4), + 'e': (7, 2), 'r': (7, 3), 't': (2, 3), 'y': (2, 6), 'u': (7, 6), + 'i': (7, 5), 'o': (7, 9), 'p': (7, 8), '[': (2, 8), ']': (2, 5), + '\\': (3, 11), 'a': (4, 1), 's': (4, 4), 'd': (4, 2), 'f': (4, 3), + 'g': (1, 3), 'h': (1, 6), 'j': (4, 6), 'k': (4, 5), 'l': (4, 9), + ';': (4, 8), '\'': (1, 8), 'z': (5, 1), 'x': (5, 4), 'c': (5, 2), + 'v': (5, 3), 'b': (0, 3), 'n': (0, 6), 'm': (5, 6), ',': (5, 5), + '.': (5, 9), '/': (5, 8), ' ': (5, 11), '<right>': (6, 12), + '<alt_r>': (0, 10), '<down>': (6, 11), '<tab>': (2, 1), + '<f10>': (0, 4), '<shift_r>': (7, 7), '<ctrl_r>': (4, 0), + '<esc>': (1, 1), '<backspace>': (1, 11), '<f2>': (3, 2), + '<alt_l>': (6, 10), '<ctrl_l>': (2, 0), '<f1>': (0, 2), + '<search>': (0, 1), '<f3>': (2, 2), '<f4>': (1, 2), '<f5>': (3, 4), + '<f6>': (2, 4), '<f7>': (1, 4), '<f8>': (2, 9), '<f9>': (1, 9), + '<up>': (7, 11), '<shift_l>': (5, 7), '<enter>': (4, 11), + '<left>': (7, 12)} + + +UNSHIFT_TABLE = { '~': '`', '!': '1', '@': '2', '#': '3', '$': '4', + '%': '5', '^': '6', '&': '7', '*': '8', '(': '9', + ')': '0', '_': '-', '+': '=', '{': '[', '}': ']', + '|': '\\', + ':': ';', '"': "'", '<': ',', '>': '.', '?': '/'} + +for c in string.ascii_lowercase: + UNSHIFT_TABLE[c.upper()] = c + + +def inject_event(key, press): + if len(key) >= 2 and key[0] != '<': + key = '<' + key + '>' + if key not in KEYMATRIX: + print "%s: invalid key: %s" % (this_script, key) + sys.exit(1) + (row, col) = KEYMATRIX[key] + subprocess.call(["ectool", "kbpress", str(row), str(col), + "1" if press else "0"]) + + +def inject_key(key): + inject_event(key, True) + inject_event(key, False) + + +def inject_string(string): + for c in string: + if c in KEYMATRIX: + inject_key(c) + elif c in UNSHIFT_TABLE: + inject_event("<shift_l>", True) + inject_key(UNSHIFT_TABLE[c]) + inject_event("<shift_l>", False) + else: + print "unimplemented character:", c + sys.exit(1) + + +def usage(): + print "Usage: %s [-s <string>] [-k <key>]" % this_script, \ + "[-p <pressed-key>] [-r <released-key>] ..." + print "Examples:" + print "%s -s MyPassw0rd -k enter" % this_script + print "%s -p ctrl_l -p alt_l -k f3 -r alt_l -r ctrl_l" % this_script + + +def help(): + usage() + print "Valid keys are:" + i = 0 + for key in KEYMATRIX: + print "%12s" % key, + i += 1 + if i % 4 == 0: + print + print + print "angle brackets may be omitted" + + +def usage_check(asserted_condition, message): + if asserted_condition: + return + print "%s:" % this_script, message + usage() + sys.exit(1) + + +# -- main + +this_script = sys.argv[0] +arg_len = len(sys.argv) + +if arg_len > 1 and sys.argv[1] == "--help": + help() + sys.exit(0) + +usage_check(arg_len > 1, "not enough arguments") +usage_check(arg_len % 2 == 1, "mismatched arguments") + +for i in range(1, arg_len, 2): + usage_check(sys.argv[i] in ("-s", "-k", "-p", "-r"), + "unknown flag: %s" % sys.argv[i]) + +for i in range(1, arg_len, 2): + flag = sys.argv[i] + arg = sys.argv[i+1] + if flag == "-s": + inject_string(arg) + elif flag == "-k": + inject_key(arg) + elif flag == "-p": + inject_event(arg, True) + elif flag == "-r": + inject_event(arg, False) diff --git a/util/test-inject-keys.sh b/util/test-inject-keys.sh new file mode 100755 index 0000000000..031452150e --- /dev/null +++ b/util/test-inject-keys.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# +# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Regression test for inject-keys.py. Works by creating a "fake" ectool +# and comparing expected ectool commands with expected ones. + +TMPX=/tmp/inject-key-test$$_x +TMPY=/tmp/inject-key-test$$_y + +cleanup() { + rm -f ./ectool $TMPX $TMPY +} + +fail() { + echo $* + exit 1 +} + +trap cleanup SIGINT + +PATH=.:$PATH + +if [ -e ectool ]; then + if [ "$(echo $(cat ectool))" != '#! /bin/bash echo $*' ]; then + echo "./ectool exists, please remove it to run this script" + exit 1 + fi +fi + +echo "#! /bin/bash" > ectool +echo 'echo $*' >> ectool +chmod a+x ectool + +# tests that should fail + +# bad args +./inject-keys.py >& /dev/null && fail "undetected zero args" +./inject-keys.py -k >& /dev/null && fail "undetected mismatched args (1)" +./inject-keys.py -k a b >& /dev/null && fail "undetected mismatched args (2)" +./inject-keys.py -z a >& /dev/null && fail "undetected bad flag" + +# bad key +./inject-keys.py -p foobar >& /dev/null && fail "undetected bad key" + +# tests that should succeed with the expected output + +# simple string +./inject-keys.py -s abcd > $TMPX + +cat > $TMPY <<EOF +kbpress 4 1 1 +kbpress 4 1 0 +kbpress 0 3 1 +kbpress 0 3 0 +kbpress 5 2 1 +kbpress 5 2 0 +kbpress 4 2 1 +kbpress 4 2 0 +EOF + +cmp $TMPX $TMPY || fail $TMPX and $TMPY differ + +# string with shifted characters +./inject-keys.py -s A@%Bx > $TMPX + +cat > $TMPY <<EOF +kbpress 5 7 1 +kbpress 4 1 1 +kbpress 4 1 0 +kbpress 5 7 0 +kbpress 5 7 1 +kbpress 6 4 1 +kbpress 6 4 0 +kbpress 5 7 0 +kbpress 5 7 1 +kbpress 3 3 1 +kbpress 3 3 0 +kbpress 5 7 0 +kbpress 5 7 1 +kbpress 0 3 1 +kbpress 0 3 0 +kbpress 5 7 0 +kbpress 5 4 1 +kbpress 5 4 0 +EOF + +cmp $TMPX $TMPY || fail $TMPX and $TMPY differ + +# keystroke injection +./inject-keys.py -k enter > $TMPX + +cat > $TMPY <<EOF +kbpress 4 11 1 +kbpress 4 11 0 +EOF + +cmp $TMPX $TMPY || fail $TMPX and $TMPY differ + +# key event injection +./inject-keys.py -p enter > $TMPX + +cat > $TMPY <<EOF +kbpress 4 11 1 +EOF + +cmp $TMPX $TMPY || fail $TMPX and $TMPY differ + +cleanup |