blob: a6c840cb6fd36705547c5b8d439fe76ccfa43cdd [file] [log] [blame]
Dennis Kempin037675e2013-06-14 14:12:39 -07001# Copyright (c) 2012 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#
5# This module manages the platform properties in mttools/platforms
6import os
7import re
8import json
9from xorg_conf import XorgInputClassParser
10
11# path to current script directory
12script_dir = os.path.dirname(os.path.realpath(__file__))
13platforms_dir = os.path.realpath(os.path.join(script_dir, "..", "platforms"))
14xorg_conf_path = os.path.realpath(os.path.join(script_dir, "..",
15 "..", "xorg-conf"))
16
17class PlatformProperties(object):
18 """
19 A class containing hardware and xorg properties for a platform.
20 The class can be created from an activity log or by providing
21 the name of the platform. Information will then be read from the
22 'platforms_dir' directory.
23 """
24 def __init__(self, platform=None, activity_data=None):
25 if platform:
26 basename = os.path.join(platforms_dir, platform)
27 self.name = platform
28 self.hwprops_file = basename + ".hwprops"
29 self.props_file = basename + ".props"
30 self.xorg_parser = XorgInputClassParser()
31 self._ParseHWProperties(open(self.hwprops_file).read())
32 self._ParseProperties(open(self.props_file).read())
33 self._UpdateDimensions()
34 elif activity_data:
35 self.name = ""
36 self._ParseActivityLog(activity_data)
37
38 def _ParseActivityLog(self, activity_data):
39 """
40 Parse property information from an activity log
41 """
42 activity = json.loads(activity_data)
43 self.properties = activity["properties"]
44
45 hwprops = activity["hardwareProperties"]
46 self.x_min = int(hwprops["left"])
47 self.x_max = int(hwprops["right"])
48 self.x_res = int(hwprops["xResolution"])
49 self.y_min = int(hwprops["top"])
50 self.y_max = int(hwprops["bottom"])
51 self.y_res = int(hwprops["yResolution"])
52
53 def _ParseHWProperties(self, data):
54 """
55 parse x and y dimensions and resolution from hwprops file
56 """
57 xregex = re.compile("A: 35 ([0-9\-]+) ([0-9\-]+) ([0-9\-]+) " +
58 "([0-9\-]+) ([0-9\-]+)")
59 xmatch = xregex.search(data);
60 self.x_min = int(xmatch.group(1))
61 self.x_max = int(xmatch.group(2))
62 self.x_res = int(xmatch.group(5))
63
64 yregex = re.compile("A: 36 ([0-9\-]+) ([0-9\-]+) ([0-9\-]+) " +
65 "([0-9\-]+) ([0-9\-]+)")
66 ymatch = yregex.search(data);
67 self.y_min = int(ymatch.group(1))
68 self.y_max = int(ymatch.group(2))
69 self.y_res = int(ymatch.group(5))
70
71 def _ParseProperties(self, data):
72 """
73 parse properties from file and inject xorg properties.
74 """
75 self.properties = {}
76 data = json.loads(data)
77
78 if "gestures" in data:
79 self.properties.update(data["gestures"])
80
81 if "device_class" in data:
82 self.device_class = data["device_class"]
83
84 if xorg_conf_path and "xorg" in data and "file" in data["xorg"]:
85 filename = os.path.join(xorg_conf_path, data["xorg"]["file"])
86 input_classes = self.xorg_parser.Parse(file=filename)
87 if "identifier" in data["xorg"]:
88 properties = input_classes[data["xorg"]["identifier"]]
89 self.properties.update(properties)
90 if "identifiers" in data["xorg"]:
91 for identifier in data["xorg"]["identifiers"]:
92 properties = input_classes[identifier]
93 self.properties.update(properties)
94
95 def _UpdateDimensions(self):
96 """
97 CMT allows hardware properties to be overwritten by xorg properties.
98 Do the same in this class.
99 """
100 if "Active Area Left" in self.properties:
101 self.x_min = int(self.properties["Active Area Left"])
102 if "Active Area Right" in self.properties:
103 self.x_max = int(self.properties["Active Area Right"])
104 if "Horizontal Resolution" in self.properties:
105 self.x_res = int(self.properties["Horizontal Resolution"])
106 if "Active Area Top" in self.properties:
107 self.y_min = int(self.properties["Active Area Top"])
108 if "Active Area Bottom" in self.properties:
109 self.y_max = int(self.properties["Active Area Bottom"])
110 if "Vertical Resolution" in self.properties:
111 self.y_res = int(self.properties["Vertical Resolution"])
112
113 def Match(self, other):
114 """
115 Compare these properties to another PlatformProperties instance.
116 The return value is a score between 1. 0 meaning there is a big mismatch
117 and 1 meaning the properties match completely.
118 Only a selected range of properties are compared in order to
119 prevent property adjustments to cause platforms to be mismatched.
120 """
121 scores = []
122 def compare(a, b, what):
123 value = abs(float(a) - float(b))
124 if value > 0:
125 value = min(1, value / abs(float(a)), abs(float(b)))
126 scores.append(1-value)
127 def compare_attr(what):
128 compare(getattr(self, what), getattr(other, what), what)
129 def compare_prop(what):
130 if what not in self.properties or what not in other.properties:
131 return 0
132 compare(self.properties[what], other.properties[what], what)
133 compare_attr("x_min")
134 compare_attr("x_max")
135 compare_attr("x_res")
136 compare_prop("Pressure Calibration Offset")
137 return reduce(lambda x,y: (x * y), scores)
138
139class PlatformDatabase(object):
140 """
141 This class reads all available platforms from the platforms_dir and allows
142 to search for matching platforms to an activity log file.
143 """
144 def __init__(self):
145 platform_files = [ f for f in os.listdir(platforms_dir)
146 if f.endswith(".hwprops") ]
147 self.platforms = {}
148 for file in platform_files:
149 name = file.replace(".hwprops", "")
150 self.platforms[name] = PlatformProperties(platform=name)
151
152 def FindMatching(self, activity_data):
153 """
154 Returns the PlatformProperties instance of the platform matching
155 the activity log data.
156 """
157 result = None
158 properties = PlatformProperties(activity_data=activity_data)
159 for name, platform in self.platforms.items():
160 score = platform.Match(properties)
161 if score > 0.9:
162 if result:
163 print ("multiple matching platforms:", result.name,
164 "and", platform.name)
165 sys.exit(-1)
166 result = platform
167 if not result:
168 print "cannot find matching platform"
169 return result