blob: e6f196417fa500c5ec5ee80ae1da3bd7a5e02761 [file] [log] [blame]
Dennis Kempinbf129f82014-03-06 23:50:581#!/bin/sh
2# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6XINPUT=/usr/bin/xinput
7
8export DISPLAY=:0
9export XAUTHORITY=/home/chronos/.Xauthority
10
11pref_folder="/home/chronos/user/cmt"
12if ! [ -d $pref_folder ]; then
13 mkdir $pref_folder
14fi
Dennis Kempin116473b2014-03-31 21:43:4515chown chronos:chronos $pref_folder
Dennis Kempinbf129f82014-03-06 23:50:5816
17# Functions for storing preferences
18# A preference requires the following global variables:
19# pref_${pref}_type: device type this preference is appllied on
20# pref_${pref}_validator: a batch match to validate the preference value
21# pref_${pref}_default: default value
22# apply_${pref}: function to apply the preference to a device
23# Also a list of all preference names is stored in the variable: preferences
24
25apply_preference() {
26 local pref="$1"
27 local type="$(eval echo \"\${pref_${pref}_type}\")"
28 local value="$3"
29 for device in $2; do
30 if device_is_${type} $device; then
31 log "Applying $pref=$value to device $device"
32 apply_${pref} "$device" "$value"
33 fi
34 done
35}
36
37apply_all_preferences() {
38 local devices="$1"
39 for pref in $preferences; do
40 local value=$(load_preference $pref)
41 for device in $devices; do
42 apply_preference $pref $device $value
43 done
44 done
45}
46
47validate_preference() {
48 local pref="$1"
49 local value="$2"
50 local validator="$(eval echo \"\${pref_${pref}_validator}\")"
51 case $value in
52 $validator) true ;;
53 *)
54 echo "invalid value '${value}' for preference ${pref}" >&2
55 false
56 ;;
57 esac
58}
59
60transition_legacy_pref_file() {
61 local pref=$1
62 local new_file="$pref_folder/$pref"
63
64 case $pref in
65 "mouse_sensitivity") filename="mouse_sensitivity" ;;
66 "touchpad_sensitivity") filename="touchpad_sensitivity" ;;
67 "mouse_swap_lr") filename="mouse_swap_lr_buttons" ;;
68 "tapclick") filename="touchpad_tap_enable" ;;
69 "tapdrag") filename="touchpad_tap_drag_enable" ;;
70 "t5r2_three_finger_click") filename="touchpad_t5r2_3f_click_enable" ;;
71 *) return ;;
72 esac
73
74 legacy_file="/home/chronos/user/$filename"
75 if [ -f $legacy_file ]; then
76 log "mv $legacy_file $new_file"
77 mv $legacy_file $new_file
Dennis Kempin116473b2014-03-31 21:43:4578 chown chronos:chronos $new_file
Dennis Kempinbf129f82014-03-06 23:50:5879 fi
80}
81
82load_preference() {
83 assert_eq $# 1
84 local pref="$1"
85 local default="$(eval echo \"\${pref_${pref}_default}\")"
86 local file="$pref_folder/$pref"
87
88 # The new inputcontrol script uses a different file path to store preferences
89 # Make sure to copy the old setting over when the new file does not yet exist.
90 if [ ! -f $file ]; then
91 transition_legacy_pref_file $pref
92 fi
93
94 if [ ! -f $file ]; then
95 echo $default
96 return
97 fi
98
99 local file_size="$(stat -c %s $file)"
100 if [ "$file_size" != "2" ]; then
101 # invalid file size
102 echo $default
103 return
104 fi
105
106 local value=$(cat ${file})
107 if validate_preference $pref $value; then
108 echo $value
109 else
110 echo $default
111 fi
112}
113
114save_preference() {
115 assert_eq $# 2
116 local pref="$1"
117 local value="$2"
118 local pref_file="$pref_folder/$pref"
119
120 if validate_preference "$pref" "$value"; then
121 log "echo $value > $pref_file"
122 echo "$value" > $pref_file
123 fi
124}
125
126# Functions to access information about a device
127
128device_get_name() {
129 assert_eq $# 1
130 xinput --list --name-only $1
131}
132
133device_get_canonical_name() {
134 assert_eq $# 1
135 device_get_name $device | sed 's/[^a-zA-Z0-9]/_/g'
136}
137
138device_set_prop() {
139 assert_eq $# 3
140 log "$XINPUT set-prop \"$1\" \"$2\" \"$3\""
141 $XINPUT set-prop "$1" "$2" "$3"
142}
143
144device_get_prop() {
145 assert_eq $# 2
146 $XINPUT list-props $1 | awk "/$2/ { print \$4 }"
147}
148
149device_get_bool_prop() {
150 assert_eq $# 2
151 prop=$(device_get_prop $1 "$2")
152 [ "$prop" = "1" ]
153}
154
155device_is_mouse() {
156 assert_eq $# 1
157 device_get_bool_prop $1 "Device Mouse"
158}
159
160device_is_multitouch() {
161 assert_eq $# 1
162 device_get_bool_prop $1 "Device Touchpad"
163}
164
165device_is_touchpad() {
166 assert_eq $# 1
167 ! device_is_mouse $1 && device_is_multitouch $1
168}
169
170device_is_multitouch_mouse() {
171 assert_eq $# 1
172 device_is_mouse $1 && device_is_multitouch $1
173}
174
175device_is_touchscreen() {
176 assert_eq $# 1
177 device_get_name $1 | grep -q '[tT]ouch[sS]creen'
178}
179
180device_is_valid() {
181 assert_eq $# 1
182 device_is_mouse $1 || device_is_multitouch $1 || device_is_touchscreen $1
183}
184
185device_status() {
186 assert_eq $# 1
187 if device_is_valid $1; then
188 echo
189 echo "ID $1:"
190 $XINPUT list-props $1
191 fi;
192}
193
194# Functions to list devices
195
196list_devices() {
197 # optional first argument is filter method
198 local filter=device_is_valid
199 if ! [ -z $1 ]; then
200 filter=$1
201 fi
202
203 # Search for an xinput entry that contains the "slave pointer"
204 # Then, find a field that matches "id=".
205 # Lastly, return the part of the field after the '='.
206 local devices="$($XINPUT list | \
207 awk '/.*slave.*/ { for (i=1; i<NF; i++) \
208 if ($i ~/id=/) print substr($i, 4) }')"
209
210 for device in $devices ; do
211 if $filter $device; then
212 echo -n " ${device}"
213 fi
214 done
215}
216
217list_mice() {
218 list_devices device_is_mouse
219}
220
221list_touchpads() {
222 list_devices device_is_touchpad
223}
224
225list_touchscreens() {
226 list_devices device_is_touchscreen
227}
228
229list_multitouch() {
230 list_devices device_is_multitouch
231}
232
233list_multitouch_mice() {
234 list_devices device_is_multitouch_mouse
235}
236
237# Returns the xinput ID of the newly attached mouse. If X hasn't loaded a driver
238# for the new mouse, yet, this will not print anything. If found, it prints the
239# xinput ID.
240get_device_by_devname() {
241 # Get the list of xinput IDs:
242 local ids="$(list_devices)"
243 if [ -z "$ids" ]; then
244 return
245 fi
246 for id in $ids; do
247 local test_node=$(device_get_prop $id "Device Node")
248 if [ "$test_node" = "\"$1\"" ]; then
249 echo $id
250 return
251 fi
252 done
253}
254
255wait_and_get_added_device() {
256 tries=10
257 while [ "$tries" -ne "0" ]; do
258 tries=$((tries - 1))
259 newid=$(get_device_by_devname $1)
260 if [ -n "$newid" ]; then
261 echo $newid
262 return
263 fi
264 sleep 1
265 done
266}
267
268
269canonical_ids() {
270 # In case minus number is passed, truncate it to the last 4 hexdigits.
271 # e.g., -16360 -> ffffffffffffc018 -> c018
272 local id_strings id_str first
273 read id_strings
274 for id_str in $id_strings; do
275 if [ -n "$first" ]; then
276 printf ":"
277 fi
278 printf "%04x" "$id_str" | sed 's/.*\(.\{4\}\)$/\1/'
279 first="not"
280 done
281}
282
283device_get_vendor_product() {
284 local xinput_id="$1"
285
286 local vp="$(xinput list-props $xinput_id 2>/dev/null \
287 | fgrep "Device Product ID" | \
288 cut -d : -f 2 | sed 's/,//' | canonical_ids)"
289 if ! echo "${vp}" | grep -q ':'; then
290 vp="$(xinput list-props $xinput_id 2>/dev/null \
291 | fgrep "Device Vendor ID" | \
292 cut -d : -f 2 | canonical_ids)"
293 vp="${vp}:$(xinput list-props $xinput_id 2>/dev/null \
294 | fgrep "Device Product ID" | \
295 cut -d : -f 2 | canonical_ids)"
296 fi
297 echo "$vp"
298}
299
300
301# Helper for debugging in bash
302
303log() {
304 if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ] ; then
305 echo "$@" >&2
306 fi
307}
308
309assert_eq() {
310 if [ "$1" -ne "$2" ]; then
311 echo "${FUNCNAME[1]}: Assertion '$1' == '$2' failed" >&2
312 exit -1
313 fi
314}
315
316# FUNCNAME is only available in BASH. Disable assert_eq on all other shells.
317if [ -z "$BASH_VERSION" ]; then
318 assert_eq() { true; }
319fi