summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuigi Semenzato <semenzato@chromium.org>2016-01-15 13:33:06 -0800
committerchrome-bot <chrome-bot@chromium.org>2016-02-05 06:02:49 -0800
commit4ec554dd8fbdd47871dcd04374fb04018b24b7b5 (patch)
treea786237f2c8a04e1a64efee04e42d39c222b4264
parentc68e5a7c9bc0c1ae131303a41e51b6e13ca25e31 (diff)
downloadchrome-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-xutil/inject-keys.py127
-rwxr-xr-xutil/test-inject-keys.sh111
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