blob: 4379f3f2b21d33383c1725d826c1ea81ae31445e [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
Dennis Kempin44b9c742014-04-02 21:44:53140 log "$XINPUT set-prop \"$1\" \"$2\" $3"
141 $XINPUT set-prop "$1" "$2" $3
Dennis Kempinbf129f82014-03-06 23:50:58142}
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
Dennis Kempin52f479b2014-04-15 16:23:46155device_get_string_prop() {
156 assert_eq $# 2
157 prop=$(device_get_prop $1 "$2")
158 # get rid of " around value via eval
159 eval echo $prop
160}
161
Dennis Kempinbf129f82014-03-06 23:50:58162device_is_mouse() {
163 assert_eq $# 1
164 device_get_bool_prop $1 "Device Mouse"
165}
166
167device_is_multitouch() {
168 assert_eq $# 1
169 device_get_bool_prop $1 "Device Touchpad"
170}
171
172device_is_touchpad() {
173 assert_eq $# 1
174 ! device_is_mouse $1 && device_is_multitouch $1
175}
176
177device_is_multitouch_mouse() {
178 assert_eq $# 1
179 device_is_mouse $1 && device_is_multitouch $1
180}
181
Dennis Kempin3d52d792014-03-28 21:03:17182device_is_nontouch_mouse() {
183 assert_eq $# 1
184 device_is_mouse $1 && ! device_is_multitouch $1
185}
186
Dennis Kempinbf129f82014-03-06 23:50:58187device_is_touchscreen() {
188 assert_eq $# 1
189 device_get_name $1 | grep -q '[tT]ouch[sS]creen'
190}
191
192device_is_valid() {
193 assert_eq $# 1
194 device_is_mouse $1 || device_is_multitouch $1 || device_is_touchscreen $1
195}
196
197device_status() {
198 assert_eq $# 1
199 if device_is_valid $1; then
200 echo
201 echo "ID $1:"
202 $XINPUT list-props $1
203 fi;
204}
205
206# Functions to list devices
207
208list_devices() {
209 # optional first argument is filter method
210 local filter=device_is_valid
211 if ! [ -z $1 ]; then
212 filter=$1
213 fi
214
215 # Search for an xinput entry that contains the "slave pointer"
216 # Then, find a field that matches "id=".
217 # Lastly, return the part of the field after the '='.
218 local devices="$($XINPUT list | \
219 awk '/.*slave.*/ { for (i=1; i<NF; i++) \
220 if ($i ~/id=/) print substr($i, 4) }')"
221
222 for device in $devices ; do
223 if $filter $device; then
224 echo -n " ${device}"
225 fi
226 done
227}
228
229list_mice() {
230 list_devices device_is_mouse
231}
232
233list_touchpads() {
234 list_devices device_is_touchpad
235}
236
237list_touchscreens() {
238 list_devices device_is_touchscreen
239}
240
241list_multitouch() {
242 list_devices device_is_multitouch
243}
244
245list_multitouch_mice() {
246 list_devices device_is_multitouch_mouse
247}
248
249# Returns the xinput ID of the newly attached mouse. If X hasn't loaded a driver
250# for the new mouse, yet, this will not print anything. If found, it prints the
251# xinput ID.
252get_device_by_devname() {
253 # Get the list of xinput IDs:
254 local ids="$(list_devices)"
255 if [ -z "$ids" ]; then
256 return
257 fi
258 for id in $ids; do
259 local test_node=$(device_get_prop $id "Device Node")
260 if [ "$test_node" = "\"$1\"" ]; then
261 echo $id
262 return
263 fi
264 done
265}
266
267wait_and_get_added_device() {
268 tries=10
269 while [ "$tries" -ne "0" ]; do
270 tries=$((tries - 1))
271 newid=$(get_device_by_devname $1)
272 if [ -n "$newid" ]; then
273 echo $newid
274 return
275 fi
276 sleep 1
277 done
278}
279
280
281canonical_ids() {
282 # In case minus number is passed, truncate it to the last 4 hexdigits.
283 # e.g., -16360 -> ffffffffffffc018 -> c018
284 local id_strings id_str first
285 read id_strings
286 for id_str in $id_strings; do
287 if [ -n "$first" ]; then
288 printf ":"
289 fi
290 printf "%04x" "$id_str" | sed 's/.*\(.\{4\}\)$/\1/'
291 first="not"
292 done
293}
294
295device_get_vendor_product() {
296 local xinput_id="$1"
297
298 local vp="$(xinput list-props $xinput_id 2>/dev/null \
299 | fgrep "Device Product ID" | \
300 cut -d : -f 2 | sed 's/,//' | canonical_ids)"
301 if ! echo "${vp}" | grep -q ':'; then
302 vp="$(xinput list-props $xinput_id 2>/dev/null \
303 | fgrep "Device Vendor ID" | \
304 cut -d : -f 2 | canonical_ids)"
305 vp="${vp}:$(xinput list-props $xinput_id 2>/dev/null \
306 | fgrep "Device Product ID" | \
307 cut -d : -f 2 | canonical_ids)"
308 fi
309 echo "$vp"
310}
311
312
313# Helper for debugging in bash
314
315log() {
316 if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ] ; then
317 echo "$@" >&2
318 fi
319}
320
321assert_eq() {
322 if [ "$1" -ne "$2" ]; then
323 echo "${FUNCNAME[1]}: Assertion '$1' == '$2' failed" >&2
324 exit -1
325 fi
326}
327
328# FUNCNAME is only available in BASH. Disable assert_eq on all other shells.
329if [ -z "$BASH_VERSION" ]; then
330 assert_eq() { true; }
Dennis Kempin3d52d792014-03-28 21:03:17331fi