Platform/MTReplay: Add automatic platform creation
The new command mtreplay --add-platform $IP will connect to a remote
device and guide the user through the creation of a new platform for
mtreplay and touchpad-tests.
It will automatically pull hw properties and ask the user to pick
the right xorg config files and identifiers.
The new platform info will then be stored in mttools/platforms/
BUG=chromium:353779
TEST=run mtreplay -a $IP
Change-Id: I33f077a3897508c0d2a9d2c1838a8ce81f768db4
Reviewed-on: https://chromium-review.googlesource.com/194976
Reviewed-by: Dennis Kempin <denniskempin@chromium.org>
Tested-by: Dennis Kempin <denniskempin@chromium.org>
Commit-Queue: Dennis Kempin <denniskempin@chromium.org>
diff --git a/mtlib/platform.py b/mtlib/platform.py
index b945ee7..e505c6e 100755
--- a/mtlib/platform.py
+++ b/mtlib/platform.py
@@ -8,6 +8,7 @@
import re
import sys
from xorg_conf import XorgInputClassParser
+from cros_remote import CrOSRemote
# path to current script directory
script_dir = os.path.dirname(os.path.realpath(__file__))
@@ -15,6 +16,18 @@
xorg_conf_path = os.path.realpath(os.path.join(script_dir, '..',
'..', 'xorg-conf'))
+props_template = """\
+{
+ "gestures": {
+ },
+ "xorg": {
+ "file": "%s",
+ "identifiers": %s
+ },
+ "ignore": [
+ ]
+}"""
+
class PlatformProperties(object):
""" A class containing hardware and xorg properties for a platform.
@@ -257,3 +270,133 @@
print 'cannot find matching platform'
return None
return result
+
+ @staticmethod
+ def RegisterPlatformFromDevice(ip):
+ # get list of multitouch devices
+ remote = CrOSRemote(ip)
+ devices = remote.ReadCommand(
+ "/opt/google/input/inputcontrol -t multitouch --names",
+ verbose=True)
+ if devices is False:
+ return None
+
+ # Each line has the format:
+ # id: Device Name
+ # devices[*][0] will have the id
+ # devices[*][1] will have the name
+ devices = devices.splitlines()
+ devices = [l.split(":", 1) for l in devices]
+
+ # select one device from list
+ idx = UserSelection([d[1] for d in devices],
+ "Which device would you like to register?")
+ device_id = devices[idx][0]
+
+ # read hardware properties
+ hwprops = remote.ReadCommand(
+ "/opt/google/input/inputcontrol --id %s --hwprops" % device_id,
+ verbose=True)
+ if not hwprops:
+ print "Please update your device to latest canary or:"
+ print " emerge-${BOARD} inputcontrol"
+ print " cros deploy $DEVICE_IP inputcontrol"
+ return None
+
+ # Asks user to select xorg identifiers from a file
+ def SelectXorgIDs(xorg_file):
+ print "Selecting Xorg identifiers from", xorg_file
+ conf = remote.Read(xorg_file)
+ ids = []
+ for match in re.finditer("Identifier\s+\"([a-zA-Z0-9 ]+)\"", conf):
+ ids.append(match.group(1))
+
+ idxs = UserSelection(ids, "Which xorg identifiers apply to this device?",
+ allow_multi=True, allow_zero=True)
+ return [ids[i] for i in idxs]
+
+ # first ask user for xorg identifiers from platform specific file,
+ # then for identifiers from generic config file.
+ xorg_file = remote.ReadCommand(
+ "ls /etc/X11/xorg.conf.d/50-touchpad-cmt-*",
+ verbose=True).strip()
+ ids = SelectXorgIDs(xorg_file)
+ if not ids:
+ xorg_file = "/etc/X11/xorg.conf.d/40-touchpad-cmt.conf"
+ ids = SelectXorgIDs(xorg_file)
+ if not ids:
+ print "Please configure the platform properties manually"
+ xorg_file = "todo: add correct xorg conf file"
+ ids = ["todo: add correct xorg identifier"]
+
+ ids_string = "[" + ", ".join(["\"%s\"" % id for id in ids]) + "]"
+ xorg_file = os.path.basename(xorg_file)
+
+ sys.stdout.write("Please name this platform: ")
+ sys.stdout.flush()
+ platform_name = sys.stdin.readline().strip()
+
+ # write platform info to files
+ hwprops_file = os.path.join(platforms_dir, platform_name + ".hwprops")
+ props_file = os.path.join(platforms_dir, platform_name + ".props")
+
+ open(hwprops_file, "w").write(hwprops)
+ open(props_file, "w").write(props_template % (xorg_file, ids_string))
+
+ print "Created files: "
+ print " ", hwprops_file
+ print " ", props_file
+
+ return platform_name
+
+
+def UserSelection(list, msg, allow_multi=False, allow_zero=False):
+ idx = [0]
+ if len(list) == 1:
+ return [0] if allow_multi else 0
+
+ # repeat until user made a valid selection
+ while True:
+
+ # get user input
+ print msg
+ if allow_zero:
+ print " 0: None"
+ for i, item in enumerate(list):
+ print " ", str(i + 1) + ":", item
+ if allow_multi:
+ print "(Separate multiple selections with spaces)"
+ sys.stdout.write('> ')
+ sys.stdout.flush()
+ selection = sys.stdin.readline()
+
+ # validates single input value
+ def CheckSelection(selection):
+ try:
+ idx = int(selection) - 1
+ if allow_zero and idx == -1:
+ return True
+ if idx < 0 or idx >= len(list):
+ print 'Number out of range'
+ return False
+ except:
+ print 'Not a number'
+ return False
+ return True
+
+ if allow_multi:
+ # validate list of values
+ valid = True
+ selections = selection.split(" ")
+ for selection in selections:
+ if not CheckSelection(selection):
+ valid = False
+ break
+ if valid:
+ selections = [int(s) - 1 for s in selections]
+ if -1 in selections:
+ return []
+ return selections
+ else:
+ if CheckSelection(selection):
+ return int(selection) - 1