blob: 24f73dcfbe43daa4aace27848c008240ed0cc439 [file] [log] [blame]
#!/bin/sh
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Log all calls, with arguments, to /var/log/messages
logger "$0" "$@"
XINPUT=/usr/bin/xinput
PROG=`basename $0`
COMMAND=$1
SCREEN_DPI=125
. $(dirname "$0")/common
export DISPLAY=:0
export XAUTHORITY=/home/chronos/.Xauthority
# On disk preferences
PREF_SENS_FILE=/home/chronos/user/mouse_sensitivity
PREF_SENS_VALID="[12345]"
PREF_SENS_DEFAULT=3
PREF_SWAP_LR_FILE=/home/chronos/user/mouse_swap_lr_buttons
PREF_SWAP_LR_VALID="[01]"
PREF_SWAP_LR_DEFAULT=0
# We are supposed to set an xinput setting as screen DPI * a multiplier that
# describes how fast the mouse should be (user preference). This function
# returns that product.
# We use multipliers of: 1, 1.4, 1.8, 2, 2.2. The low three have a slope that
# stops rising after speeds of 5 in/sec (hence 500 hundredths of an inch/sec
# param). See xorg-server's dix/ptrveloc.c for more info on the acceleration
# algorithm.
thresh_and_dpi_times_sensitivity_multiplier() {
local sens=$1 # 1..5
case $sens in
1) echo 500 $SCREEN_DPI;;
2) echo 500 $(((SCREEN_DPI * 7) / 5));;
3) echo 500 $(((SCREEN_DPI * 9) / 5));;
4) echo 0 $((SCREEN_DPI * 2));;
5) echo 0 $(((SCREEN_DPI * 11) / 5));;
esac
}
# Applies the given sensitivity preference (1..5) to all mice attached to the
# system. If this is called when a new device is being connected, that new
# device probably won't show up yet, so this won't apply to it.
apply_sensitivity() {
local sens="$1"
local mice="$2"
local thresh_and_acc="$(thresh_and_dpi_times_sensitivity_multiplier "$sens")"
if [ -z "$thresh_and_acc" ]; then
return
fi
for mouse in $mice ; do
if is_multitouch_mouse ${mouse}; then
$XINPUT set-prop ${mouse} "Pointer Sensitivity" "${sens}"
else
$XINPUT set-ptr-feedback $mouse $thresh_and_acc 1
fi
done
}
# Applies the preference for whether or not to swap the left and right mouse
# buttons on all existing mice attached to the system. If this is called when a
# new device is being connected, that new device probably won't show up yet, so
# this won't apply to it.
apply_swap_lr() {
local value="$1"
local mice="$2"
local map="1 2 3"
if [ "$value" -eq 1 ]; then
map="3 2 1"
fi
for mouse in $mice ; do
$XINPUT get-button-map $mouse | sed "s/^[0-9]* [0-9]* [0-9]*/$map/" | \
xargs $XINPUT set-button-map $mouse
done
}
# Remaps buttons for a device
apply_button_remap() {
local xinput_ids="$1"
for xinput_id in $xinput_ids ; do
local vp="$(vendor_product_for_xinput_id $xinput_id)"
# 0304: USB Mighty Mouse, 030c: BT Mighty Mouse
if [ "$vp" = "05ac:0304" -o "$vp" = "05ac:030c" ]; then
$XINPUT get-button-map $xinput_id | awk \
'{ for (i=1; i <= NF; i++) { \
if (i == 8) { printf 0 } else { printf $(i) }; printf " " \
} } END{ print "" }' | \
xargs $XINPUT set-button-map $xinput_id
fi
done
}
apply_cpi_for_mouse() {
local mouse="$1"
if is_multitouch_mouse $1; then
$XINPUT set-prop $mouse "Mouse CPI" $(get_cpi $mouse)
$XINPUT set-prop $mouse "Device Accel Profile" -1
$XINPUT set-prop $mouse "Device Accel Constant Deceleration" 1
$XINPUT set-prop $mouse "Device Accel Velocity Scaling" 1
else
$XINPUT set-prop $mouse "Device Accel Constant Deceleration" \
$(get_cpi $mouse)
$XINPUT set-prop $mouse "Device Accel Velocity Scaling" 1
fi
}
# Applies the correct CPI to the given mice
apply_cpi() {
local mice="$1"
for mouse in $mice ; do
apply_cpi_for_mouse $mouse
done
}
# Prints out all xinput IDs for all existing attached mice. If this is called
# when a new device is being connected, that new device probably won't show up
# yet, so this won't apply to it.
find_mice() {
# Search for an xinput entry that contains the "slave pointer"
# Then, find a field that matches "id=".
# Lastly, return the part of the field after the '='.
local slave_pointers="$($XINPUT list | \
awk '/slave *pointer/ { for (i=1; i<NF; i++) \
if ($i ~/id=/) print substr($i, 4) }')"
# Next, return only those slave pointers that are using the Evdev driver
for pointer in $slave_pointers ; do
local match=$($XINPUT list-props $pointer | grep "Evdev" | wc -l)
if [ "$match" != "0" ]; then
echo -n " $pointer"
elif is_multitouch_mouse ${pointer}; then
echo -n " ${pointer}"
fi
done
}
# WARNING: This table is now deprecated. If you want to add new entries to it,
# please instead add a new section in the 20-mouse.conf file in the xorg-conf
# package.
#
# Returns the CPI (counts per inch) of the newly attached mouse. Since mice
# generally don't report CPI, we use the following approach: By default, we
# assume a CPI of 1000, as this is quite close to most mice on the market today
# (2012 time frame). For mice that we know aren't near 1000, we have a database
# of CPI values.
get_cpi() {
local xinput_id="$1"
local vp="$(vendor_product_for_xinput_id $xinput_id)"
# Database of mice that have CPI (DPI) significantly off from 1000.
local cpi=1000; # Default CPI
local trackpoint_cpi=400; # Approximate, since CPI doesn't exactly apply
case $vp in
"0002:000a") cpi=$trackpoint_cpi;; # PS/2 IBM Trackpoint
"045e:0024") cpi=400;; # Microsoft Corp. Trackball Explorer*
"045e:0040") cpi=416;; # Microsoft Corp. Wheel Mouse Optical
"0461:4d22") cpi=474;; # Standard Dell
"046d:1028") cpi=600;; # M570 trackball[u]
"046d:400e") cpi=400;; # K400 touchpad[u]
"046d:4024") cpi=400;; # K400r touchpad[u]
"046d:c00f") cpi=385;; # Logitech MouseMan Traveler/Mobile
"046d:c00"*) cpi=385;; # Old Logitech Mice (copying 0xc00f setting)
"046d:c014") cpi=425;; # HP branded "Logitech Optical USB Mouse"
"046d:c016") cpi=377;; # HP branded "Logitech, Inc. Optical Wheel Mouse"
"046d:c018") cpi=530;; # "Logitech, Inc. Optical Wheel Mouse" model M-UAE96
"046d:c03d") cpi=434;; # Logitech M-BT96a Pilot Optical Mouse
"046d:c03e") cpi=464;; # Logitech Premium Optical Wheel Mouse (M-BT58)
"046d:c077") cpi=580;; # HP branded "Logitech USB Optical Mouse"
# According to http://www.linux-usb.org/usb.ids , these are 4 trackballs:
"046d:c40"*) cpi=300;; # Logitech Trackballs*
"046d:c508") cpi=300;; # Cordless Trackball
"047d:1002") cpi=300;; # Kensington Turbo Mouse Pro (trackball)*
"047d:1003") cpi=300;; # Kensington Orbit TrackBall (trackball)*
"047d:1005") cpi=300;; # Kensington TurboBall (trackball)*
"047d:1006") cpi=300;; # Kensington TurboRing (trackball)*
"047d:1009") cpi=300;; # Kensington Orbit TrackBall for Mac (trackball)*
"047d:1020") cpi=300;; # Kensington Expert Mouse (trackball)*
"047d:2041") cpi=300;; # Kensington SlimBlade Trackball (trackball)*
"04d9:2519") cpi=400;; # FAVI Wireless Keyboard (TouchPad)*
"05ac:0304") cpi=400;; # Apple USB Optical Mouse (Mighty Mouse)
"05ac:030c") cpi=400;; # Apple BT Optical Mouse (Mighty Mouse)
"05ac:030d") cpi=1780;; # Apple magicmouse (BT)
"05ac:"*) cpi=373;; # Apple mice (other)
"06cb:0009") cpi=$trackpoint_cpi;; # USB IBM Trackpoint
"0a5c:8502") cpi=400;; # FAVI Wireless Keyboard (TouchPad), Bluetooth*
"0c45:7000") cpi=400;; # FAVI Entertainment Wireless Keyboard (TouchPad)*
"1532:0016") cpi=1714;; # Razer USA, Ltd DeathAdder RZ01-0015
"17ef:6009") cpi=$trackpoint_cpi;; # Lenovo ThinkPad Keyboard w/ TrackPoint
"17ef:6014") cpi=400;; # Lenovo N5901 multimedia keyboard/trackball*
"17ef:602b") cpi=400;; # Lenovo N5902 multimedia keyboard/OFN*
"1997:0409") cpi=400;; # Riitek Rii Mote i6 (TouchPad)*
"413c:3012") cpi=502;; # Dell Computer Corp. Optical Wheel Mouse
esac
# * Trackball/touchpad measurements are approximate
# [u] This device uses the unifying receiver
echo $cpi
}
# Kernel's Apple magicmouse driver by default will interpret mouse events, and
# we would like to turn off this interpretation.
fixup_apple_magicmouse_driver_parameters() {
if [ "$(vendor_product_for_xinput_id $1)" != "05ac:030d" ]; then
return
fi
echo 0 > /sys/module/hid_magicmouse/parameters/emulate_3button
echo 0 > /sys/module/hid_magicmouse/parameters/emulate_scroll_wheel
}
# Add is a special command that's run possibly before xinput detects the mice.
# It's run from udev. We handle this here, rather than below, since a newly
# plugged device may not show up in xinput yet.
if [ "$COMMAND" = "add" ]; then
newid=$(wait_and_get_added_xinput_id)
if [ -z "$newid" ]; then
return
fi
apply_cpi_for_mouse $newid
sens=$(load_pref SENS)
apply_sensitivity $sens "$newid"
swap_lr=$(load_pref SWAP_LR)
apply_swap_lr $swap_lr "$newid"
apply_button_remap "$newid"
fixup_apple_magicmouse_driver_parameters "$newid"
exit 0
fi
usage() {
echo "Usage:" \
"$PROG {listdev|add|status|sensitivity [1-5]|swap_left_right" \
"[01]|set property value}"
}
MICE=$(find_mice)
if [ -z "$MICE" ]; then
exit 0
fi
VALID=0
# If no args passed, print usage
if [ $# = 0 ] ; then
usage
exit 1
fi
while true ; do
COMMAND=$1
VALID=0
if [ $# = 0 ] ; then
# If no commands remain, we're done
exit 0
elif [ "$COMMAND" = "listdev" ] ; then
for mouse in $MICE ; do
echo "${mouse}"
done
VALID=1
shift
elif [ "$COMMAND" = "status" ] ; then
for mouse in $MICE ; do
echo "Details for mouse ${mouse}:"
$XINPUT list-props $mouse
$XINPUT get-feedbacks $mouse
done
VALID=1
shift
elif [ "$COMMAND" = "sensitivity" -a -n "$2" ] ; then
sens="$2"
store_pref SENS "$sens"
apply_sensitivity "$sens" "$MICE"
VALID=1
shift 2
elif [ "$COMMAND" = "swap_left_right" -a -n "$2" ] ; then
value="$2"
store_pref SWAP_LR "$value"
apply_swap_lr "$value" "$MICE"
VALID=1
shift 2
elif [ "$COMMAND" = "refresh" ] ; then
apply_cpi "$MICE"
apply_button_remap "$MICE"
apply_sensitivity $(load_pref SENS) "$MICE"
apply_swap_lr $(load_pref SWAP_LR) "$MICE"
VALID=1
shift
elif [ "$COMMAND" = "set" -a -n "$2" -a -n "$3" ] ; then
prop=$2
value=$3
for mouse in $MICE ; do
$XINPUT set-prop $mouse "$prop" "$value"
done
VALID=1
shift 3
fi
if [ $VALID = 0 ] ; then
usage
exit 1
fi
done