Attach functions to a push button
There several ways for controlling buttons in OpenWrt.
-
Hotplug buttons, using the hotplug daemon or procd in compatibility mode (hotplug itself was phased out with r36003).
-
HID buttons, using /dev/input/event with an application like triggerhappy.
Kernel configuration If a target platform is known to support buttons, appropriate kernel modules are selected by default. If a platform is not known to support buttons, you are required to install various kernel modules yourself such as diag ,input-gpio-buttons , gpio-button-hotplug , and others.However, installing various modules will not necessarily yield a successful result. |
procd buttons
native button handling in procd is handled by scripts in '/etc/rc.button/*
'
These scripts receive the same environment as older style hotplug buttons received. However, the script files have to be named after the button. I am unaware of a way of getting the button name. (Other than using hotplug compatible scripts with procd ;)
Button Action | Script Environment | Script return value |
---|---|---|
Press | ACTION="pressed" | Seconds before "timeout" |
Held "timeout" seconds | ACTION="timeout" SEEN="<timeout secs>" | n/a |
Release1 | ACTION="released" SEEN="<seconds held>" | n/a |
1 - "released" action is sent on release even if "timeout" has been sent.
Hotplug Buttons
Note that after the introduction of procd into OpenWrt in r37132 the package hotplug2 has been removed from the default packages. However at the time of writing, r37336: procd: make old button hotplug rules work until all packages are migrated is still in effect. See also procd.buttons | |
Please read the articles wifitoggle, buttons and nslu2.hardware.button and eventually merge them into this one article |
Preliminary steps
The cat /sys/kernel/debug/gpio command queries the current pin state. Lo, low level, hi is high level
The first step is to find out the internal name of the button you want to use: some images use generic names such as BTN_1
, BTN_2
, others have more specific ones like reset
,wps
, etc. Run the following:
# mkdir -p /etc/hotplug.d/button
Create the file /etc/hotplug.d/button/buttons
with your favorite text editor, paste the following:
#!/bin/shlogger the button was $BUTTON and the action was $ACTION
Save and exit. Now press the button you want to use, then run logread
.
Jan 1 00:01:15 OpenWrt user.notice root: BTN_1 Jan 1 00:01:15 OpenWrt user.notice root: pressed Jan 1 00:01:16 OpenWrt user.notice root: BTN_1 Jan 1 00:01:16 OpenWrt user.notice root: released
BTN_1
is the name of the button you want to use. If you want or need to use another button, replace every instance of BTN_1
in the rest of this document with the correct text. From now on, there are several possible approaches: the first uses the 00-button
script from the atheros
target, the other a simpler shell script.
notice
If you want to run programs from hotplug's scripts you need to be sure PATH
and the like are initialized properly, scripts invoked by hotplug only have a default env. Especially if you install stuff into nonstandard locations like /opt/usr/bin. It's possible by adding . /etc/profile
after #!/bin/sh
#!/bin/sh. /etc/profile
Using Atheros' 00-button + UCI
If you've installed the full version of wget
, run the following:
# wget -O /etc/hotplug.d/button/00-button https://dev.openwrt.org/export/36332/trunk/target/linux/atheros/base-files/etc/hotplug.d/button/00-button
If you only have wget-nossl
and don't want to or can't upgrade, create /etc/hotplug.d/button/00-button
with your favorite editor, then paste the following:
#!/bin/sh. /lib/functions.sh do_button () { local button local action local handler local min local max config_get button $1 button config_get action $1 action config_get handler $1 handler config_get min $1 min config_get max $1 max [ "$ACTION" = "$action" -a "$BUTTON" = "$button" -a -n "$handler" ] && { [ -z "$min" -o -z "$max" ] && eval $handler [ -n "$min" -a -n "$max" ] && { [ $min -le $SEEN -a $max -ge $SEEN ] && eval $handler } }} config_load system config_foreach do_button button
Please note that after r34793 /etc/functions.sh → /lib/functions.sh so if you are using an old version change it!
Save and exit, then issue these commands:
uci add system button uci set system.@button[-1].button=BTN_1 uci set system.@button[-1].action=pressed uci set system.@button[-1].handler='logger BTN_1 pressed'uci commit system
button
is the name as the button, action
is the event (two values: pressed
and released
), handler contains the command line to be run when the event is detected (can be a script as well).
You may need to reboot the router the make the change effective (mine would work with the simple shell script just fine but wouldn't budge when using the 00-button script — Frex 2011/03/25 22:29). If this works, you can change the handler to something more useful, and add more button handlers.
Examples
Example 1: Toggle Wi-Fi radio with a button press
uci add system button uci set system.@button[-1].button=wps uci set system.@button[-1].action=pressed uci set system.@button[-1].handler='uci set wireless.@wifi-device[0].disabled=1 && wifi'uci commit system
Example 2: Assign two different functions to the same button: short press VS long press. This relies on tracking the released event rather than the pressed event.
uci add system buttonuci set system.@button[-1].button=BTN_1 uci set system.@button[-1].action=released uci set system.@button[-1].handler='logger timed pressed: 0-3s'uci set system.@button[-1].min=0uci set system.@button[-1].max=3uci add system buttonuci set system.@button[-1].button=BTN_1 uci set system.@button[-1].action=released uci set system.@button[-1].handler='logger timed pressed: 8-10s'uci set system.@button[-1].min=8uci set system.@button[-1].max=10uci commit system
Example 3: Unmount USB storage using a long-ish press
uci add system buttonuci set system.@button[-1].button=BTN_1 uci set system.@button[-1].action=released uci set system.@button[-1].handler="for i in \$(mount | awk '/dev\/sd[b-z]/ { print \$1}'); do umount \$i; done"uci set system.@button[-1].min=5uci set system.@button[-1].max=10uci commit system
Example 4: Restore defaults
config button option button reset option action released option handler "firstboot && reboot" option min 5 option max 30
Example 5: Toggle Wi-Fi using a script
config button option button wps option action released option handler "/usr/bin/wifionoff" option min 0 option max 3
You'll have to create the file /usr/bin/wifionoff
and paste this:
#!/bin/shSW=$(uci -q get wireless.@wifi-device[0].disabled)[ "$SW" == "1" ] && uci set wireless.@wifi-device[0].disabled=0[ "$SW" == "1" ] || uci set wireless.@wifi-device[0].disabled=1wifi
Another option for wifionoff is this script (doesn't store the state in uci, so it remains what is set in the configuration) You can also call this script eg. from cron, to switch off your wifi at night.
#!/bin/shSTATEFILE="/tmp/wifionoff.state" if [ $# -eq 1 ]; then case $1 in "up"|"on") STATE=off ;; "down"|"off") STATE=on ;; esacelse if [ ! -e ${STATEFILE} ]; then STATE=on else . ${STATEFILE} fifiif [ -z ${STATE} ]; then STATE=onfi if [ ${STATE} == "on" ]; then /sbin/wifi down STATE=offelse /sbin/wifi up STATE=onfi echo "STATE=${STATE}" > ${STATEFILE}
Example 6: Set transmission-daemon alt-speed, enable or disable.Short press will activate alt-speed or longer press will deactivate alt-speed and also turns on qss led about speed status on tl-wr1043nd
Edit your alt-speed limits from transmission-daemon , settings.json file.To execute script, you need to install transmission-remote package from opkg.
uci add system button uci set system.@button[-1].button=BTN_1 uci set system.@button[-1].action=pressed uci set system.@button[-1].handler='transmission-remote -as'uci add system button uci set system.@button[-1].button=BTN_1 uci set system.@button[-1].action=pressed uci set system.@button[-1].handler='echo 1 > /sys/class/leds/tl-wr1043nd:green:qss/brightness'uci add system buttonuci set system.@button[-1].button=BTN_1 uci set system.@button[-1].action=released uci set system.@button[-1].handler='transmission-remote -AS'uci set system.@button[-1].min=1uci set system.@button[-1].max=4uci add system buttonuci set system.@button[-1].button=BTN_1 uci set system.@button[-1].action=released uci set system.@button[-1].handler='echo 0 > /sys/class/leds/tl-wr1043nd:green:qss/brightness'uci set system.@button[-1].min=1uci set system.@button[-1].max=4uci commit system
Leftovers from a previous version
mkdir -p /etc/hotplug.d/buttontouch /etc/hotplug.d/button/00-button
if [ "$ACTION" = "pressed" ]; then if [ "$BUTTON" = "BTN_0" ]; then BTN_0 elif [ "$BUTTON" = "BTN_1" ]; then BTN_1 fi fi
mkdir -p /etc/hotplug.d/buttonwget -O /etc/hotplug.d/button/00-button http://dev.openwrt.org/export/21216/trunk/target/linux/atheros/base-files/etc/hotplug.d/button/00-button wget -O http://dev.openwrt.org/export/21216/trunk/target/linux/atheros/base-files/etc/hotplug.d/button/00-button
#!/bin/sh[ "$BUTTON" = "BTN_1" ] && [ "$ACTION" = "pressed" ] && {SW=$(uci get wireless.@wifi-device[0].disabled)[ $SW == '0' ] && uci set wireless.@wifi-device[0].disabled=1[ $SW == '0' ] || uci set wireless.@wifi-device[0].disabled=0wifi}
WR1043ND
If you decide to use the wifitoggle
package, you will need to change a few things on the default configuration. The following will work and make the QSS led blink "slowly" when wifi is on:
uci show wifitoggle uci set wifitoggle.@wifitoggle[0]=wifitoggle uci set wifitoggle.@wifitoggle[0].led_enable_trigger=timer uci set wifitoggle.@wifitoggle[0].persistent=1uci set wifitoggle.@wifitoggle[0].button=BTN_1 uci set wifitoggle.@wifitoggle[0].led_sysfs=tl-wr1043nd:green:qss uci set wifitoggle.@wifitoggle[0].led_enable_delayon=2000uci set wifitoggle.@wifitoggle[0].led_disable_default=1uci set wifitoggle.@wifitoggle[0].led_enable_delayoff=3000uci set wifitoggle.@wifitoggle[0].timer=0
You can probably get similar behaviour with phy0tpt trigger.
HID buttons
triggerhappy
To manage the router buttons and also other HID buttons (i.e pad buttons or keys of an usb device) we can use an application like triggerhappy.
Installation
-
Install the triggerhappy package and the kmod-hid kernel module
-
list your available buttons: execute
thd --dump /dev/input/event*
press your buttons
EV_KEY KEY_WPS_BUTTON 1 /dev/input/event0 # KEY_WPS_BUTTON 1 command EV_KEY KEY_WPS_BUTTON 0 /dev/input/event0 # KEY_WPS_BUTTON 0 command EV_KEY KEY_VOLUMEDOWN 1 /dev/input/event1 # KEY_VOLUMEDOWN 1 command EV_KEY KEY_VOLUMEDOWN 0 /dev/input/event1 # KEY_VOLUMEDOWN 0 command
-
Now associate your buttons to commands or scripts
path /etc/triggerhappy/triggers.d/example.confKEY_WPS_BUTTON 1 /etc/mywifiscript.sh KEY_VOLUMEUP 1 amixer -q set Speaker 3%+ KEY_VOLUMEDOWN 1 amixer -q set Speaker 3%-
-
run triggerhappy
/etc/init.d/triggerhappy start
-
enable triggerhappy permanently
/etc/init.d/triggerhappy enable
Notes
-
triggerhappy repeats commands twice: see bug https://dev.openwrt.org/ticket/14995
-
kernel modules: kmod-hid and kmod-hid-generic both should be installed
The kmod-hid-generic kernel module must be installed for buttons on USB devices such as USB sound cards to work in OpenWrt trunk. Only then the /dev/input/event0 node for the buttons was created on the DIR-505 router with attached USB sound card.[ 31.720000] input: C-Media USB Headphone Set as /devices/platform/ehci-platform/usb1/1-1/1-1:1.3/input/input0 [ 31.760000] hid-generic 0003:0D8C:000C.0001: input,hidraw0: USB HID v1.00 Device [C-Media USB Headphone Set ] on usb-ehci-platform-1/input3 [ 31.800000] usbcore: registered new interface driver usbhid [ 31.800000] usbhid: USB HID core driver
This is also noted in https://dev.openwrt.org/ticket/12631
cmdpad
Another simpler application to manage buttons.
original text:http://bi.du.haochici.xyz/browse.php?u=9edoPwh0ar%2FhtXlJ%2Fi1D0z42oVUjVm61%2FTsWdC26vfy8cmeN3%2B62Dl4TDp6Mew%3D%3D&b=13
本文转自 Linux_woniu 51CTO博客,原文链接:http://blog.51cto.com/linuxcgi/2047945