summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Lowther <victor.lowther@gmail.com>2010-06-12 12:52:36 -0500
committerVictor Lowther <victor.lowther@gmail.com>2010-06-12 12:52:36 -0500
commitcbb1de4dd5c79641169316e232b630662ecbf46f (patch)
tree36b0a7ae304cd6026aae18dbe1f71f3910e0dc97
parenteaebe53f016fb1a875a13de225b1d9d4e2db197c (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/wireless67
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
}