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