diff options
author | Victor Lowther <victor.lowther@gmail.com> | 2010-06-12 12:52:36 -0500 |
---|---|---|
committer | Victor Lowther <victor.lowther@gmail.com> | 2010-06-12 12:52:36 -0500 |
commit | cbb1de4dd5c79641169316e232b630662ecbf46f (patch) | |
tree | 36b0a7ae304cd6026aae18dbe1f71f3910e0dc97 | |
parent | eaebe53f016fb1a875a13de225b1d9d4e2db197c (diff) |
Add more specificity to the wireless hook.
Explicity handle Intel wireless cards according to their unique requirements.
If only iwconfig power on/off did The Right Thing on all the cards.
-rw-r--r-- | pm/power.d/wireless | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/pm/power.d/wireless b/pm/power.d/wireless index eb0f02e..0487dc1 100644 --- a/pm/power.d/wireless +++ b/pm/power.d/wireless @@ -1,24 +1,61 @@ #!/bin/sh -[ -x /sbin/iwconfig ] || exit $NA +# See if we have the usual wireless tools. +# Do not just fail because not all cards require these. +which iwpriv >/dev/null 2>&1 && have_iwpriv="true" +which iwconfig >/dev/null 2>&1 && have_iwconfig="true" -# This hook is very generic and only works on wireless hardware that -# iwconfig can actually configure power settings on. Sadly, this misses -# some more popular cards *cough* iwlwifi *cough*. +# If only all the drivers did The Right Thing with iwconfig power. +# Too bad they do not. -# Better heuristics and better control for specific cards -# would be welcome. +get_wireless_params() { + # $1 = interface + # $2 = on or off + unset iwpriv iwconfig iwlevel + + # Don't do anything if we cannot find a driver for this iface. + [ -L "/sys/class/net/$1/device/driver" ] || return 1 + # Skip if not a wireless card. + [ -d "/sys/class/net/$1/wireless" ] || return 1 + # Also don't do anything if the device is disabled + [ "$(cat /sys/class/net/$1/device/enabled)" = "1" ] || return 1 + driver="$(readlink "/sys/class/net/$1/device/driver")" + driver=${driver##*/} + case $driver in + ipw2100) iwpriv_ac="set_power 0" + iwpriv_batt="set_power 5" + iwconfig_ac="power on" + iwconfig_batt="power on";; + ipw3945) + iwpriv_ac="set_power 6" + iwpriv_batt="set_power 7";; + iwl*) if [ -f "/sys/class/net/$1/device/power_level" ]; then + iwlevel_ac=0 + iwlevel_batt=3 + else + iwconfig_ac="power off" + iwconfig_batt="power on" + fi;; + *) iwconfig_ac="power off" + iwconfig_batt="power on";; + esac + case $2 in + off) [ "$iwpriv_ac" ] && iwpriv="$iwpriv_ac" + [ "$iwconfig_ac" ] && iwconfig="$iwconfig_ac" + [ "$iwlevel_ac" ] && iwlevel="$iwlevel_ac";; + on) [ "$iwpriv_batt" ] && iwpriv="$iwpriv_batt" + [ "$iwconfig_batt" ] && iwconfig="$iwconfig_batt" + [ "$iwlevel_batt" ] && iwlevel="$iwlevel_batt";; + esac + return 0 +} wireless_powersave() { - case $1 in - on) iwparams="txpower auto power on" ;; - off) iwparams="txpower auto power off" ;; - *) exit $NA ;; - esac - cd /sys/class/net - for dev in *; do - [ -w "${dev}/wireless" ] || continue - /sbin/iwconfig $dev $iwparams + for dev in /sys/class/net/*; do + get_wireless_params "${dev##*/}" "$1" + [ "$have_iwconfig" = true -a "$iwconfig" ] && iwconfig $iwconfig + [ "$have_iwpriv" = true -a "$iwpriv" ] && iwpriv $iwpriv + [ "$iwlevel" ] && echo "$iwlevel" > "$dev/device/power_level" done } |