My father has a laptop which is used as fixed computer. This is a very common usage: he has bought an external mouse, keyboard and monitor which are always connected to the laptop.
This set-up has the advantage of the comfort of a fixed station, and the portability of a laptop when needed.
However there are some disadvantages, the most annoying thing is the fact that the switch-on button is in a very uncomfortable position. From long time the manufactures moved the button from the side of the laptop to below the monitor. So the user should open the laptop before doing the switch-on.
In the case of my father, he put the laptop below the external monitor; so it is not easy for him to open the monitor and switch-on the computer.
I am still guessing the reason why the manufacturer moved the button from the side to below the monitor..
To avoid to open the laptop, a possible solution is to buy a docking station. But this is a very expensive solution. Also not all the laptop (noticeably the cheapest ones) have a docking station.
Finally the light
At work, my colleagues bought a support for a laptop for some exposition. This is a very expensive solution (around 1-2000 euros), but it has some very interesting solution (the desk is moveable, there are some drawers electronically blocked; a pin is required for the unlock...). But the one which caught my attention was how the laptop can be switched-on. It uses the WAKE ON LAN facility to power-on the laptop. Because the laptop could be inside this support, an external button is connected to a "magic black box"(tm), which is able to emit the WOL packet. Of course the laptop should be connected via lan to this "magic black box".
WAKE ON LAN
The WAKE ON LAN is a facility that every modern PC has. From wikipedia [1]
Wake-on-LAN (WOL) is an Ethernet computer networking standard that allows a computer to be turned on or woken up by a network message.
The message is usually sent by a program executed on another computer on the same local area network. It is also possible to initiate the message from another network by using Subnet directed broadcasts or a WOL gateway service. Equivalent terms include wake on WAN, remote wake-up, power on by LAN, power up by LAN, resume by LAN, resume on LAN, and wake up on LAN. In case the computer being woken is communicating via Wi-Fi, a supplementary standard called Wake on Wireless LAN (WoWLAN) must be employed.
After seeing this solution, I started to think how implement this for my father. I never mind to buy this "laptop support" due to its cost. I even searched on ebay, looking for something capable to act as WON "generator". I also evaluated if some embedded computer (like arduino, or raspberry_pi) could solve this problem. At the end I found that a router equipped with a custom firmware like DD-WRT [2] (or an equivalent one) could be a viable solution.
The router
I bought an used router DLink DIR-615, already equipped with DD-WRT. The router was quite cheap; but was without its power supply; at the end the cost of the power supply was greater than the cost of the (used) router :).
The DD-WRT distribution, is already equipped with some WOL facilities; via the administration web interface it is possible to send the WOL packet. Unfortunately this is impossible if the pc is switched-off. It is a typical chicken-egg problem :)
This kinds of routers are normally equipped with a button called SES-Button. This button is used to help the key exchange for wireless connection. But with the DD-WRT it is possible to associate other actions to the button.
When I received the router I faced with two problems:
1) The official way to handle the button event didn't work
2) It was not so simple to store the configuration changes
Using the SES-Button to generate the WOL packet
DD-WRT allows the user to handle the SES-Button event. If a script called <something>.sesbutton exists [3], it is called when the button is pressed. Unfortunately some tests quickly pointed out that on my router this didn't happen (see also this post [4])
I think that the real GPIO assignment is different from the one implemented in my firmware. With some testing I discovered that the SES Button is linked to the GPIO pin #0.
All my tests were performed with the stock gpio utility provided by the DD-WRT firmware. This utility has also the poll mode. So I tried to use it in a shell script to handle the SES Button event (GPIO #0). Quickly I discovered two problem of this program, which was not created to be used in a shell script:
1) the polling is continuously, this means that 100% CPU is used
2) this tool doesn't flush the buffer, so when it is used in a pipe the pipeline stalled.
The solution was to pick the source (which was gpl) and modify it. I downloaded the toolchains [5], then the program source [6]. The change was quite easy: removed all the unused code (I leaved only the code related to my hardware and the polling routines), add the missing fflush(2) call, add a call to usleep(3) in order to performs only 10 polls for second.
With these changes it was trivial to make a script which polls the button status, and when the button is pressed emit a WOL packet. Of course I added some led effects, when the button is pressed, as feedback.
Here [7] you can find all the source.
Storing the change
What was more difficult was to store these change. After a bit of test I discovered that not all routers have a writeable file-system. The only way to store something is to use the nvram (Non Volatile RAM). Fortunately the DD-WRT firmware during the boot looks at the nvram variable rc_startup, and it executes its value via the shell interpreter (ash - busybox). To make more complex the things, I have also a binary executable to run.
The solution was to build a script which deploys and runs all the other scripts/executable. A common technique is to append the files ( as uu-encoded tar archive) at the end of the script and to untar it in the filesystem.
The DD-WRT firmware didn't provide a "uudecode" utility. With a quick search on Internet I found a bash code capable to uu-decode [6]. I made a bit of hacking to support the syntax of ash.
Then I wrote a script (called build.sh) which joins this uu-decoder with the tar archive. The results is a script (called prg.sh) able to extract the self-contained archive; after the deploy, this script try also to execute the setup.sh command if present in the archive.
Below an excerpt of the resulted script, where I omitted the uudecode function, and the final blob:
#!/bin/ash
DEST=/tmp/
# this function is based on the one found on the following pages
# http://www.weeklywhinge.com/?p=108&cpage=1
# wringler should be the author
uudecode(){
[.....]
}
main(){
cat "$0" | (
skip=1
while read line; do
if [ "$line" = "# PUT THE UUENCODE TAR BELOW" ]; then
skip=0
break
fi
done
cat
) | uudecode | tar xz -C "$DEST"
[ -x $DEST/setup.sh ] && $DEST/setup.sh
}
main
exit
# PUT THE UUENCODE TAR BELOW
begin 644 file.tar.gz
M'XL(`)"T-T\``^U:76P;QQ$>_DB6J5BB_Q+&5IJEPM@R&I](_3JVU5)_D97*
MDJ`H3=(Z.%'D26)`D0<>Y3A%BA*.4_O!,`44!9P@0)7`3E-`J-WDI0].:Z`O
[....]
Summarizing:
- During the boot the DD-WRT firmware reads the value of the rc_startup from the nvram and executes this.
- this script extracts a self contained tar archive which contains:
1) the gpio_read executable, which is able to poll (10 times per seconds in order to avoid to use 100% CPU) a GPIO pin
2) the button_daemon shell script which emits the WOL packet when the SES Button is pressed
3) the setup.sh script aimed to make some further setup.
- After the unpacking the daemon is started by setup.sh
The main settings are stored in nvram. The following variable is used to configure the daemon:
- button_daemon_mac is the mac address of the host to power-on
Install
Below is show how install this software. As usual the following disclaimer is valid:
- it is assumed that the user is enough skilled for this kind of operations
- pay attention: there is always the risk to brick your router: I am not responsible if you brick your router, nor if you dog drink your beer
- this post is related to the DLINK DIR-615 equipped with the DD-WRT firmware (DD-WRT v24-sp2). It is very unlikely that you can use this script as is for other routers.
First you have to download the program:
root@DD-WRT:~# cd /tmp/
root@DD-WRT:/tmp# scp ghigo@192.168.7.27:/home/ghigo/ddwrt/gpio/tmp/prg.sh .
prg.sh is the deploy-er script, which can be found in [7].
Check the md5sum; it is not important that the your value is equal to the one of this post.
root@DD-WRT:/tmp# md5sum prg.sh
6f11f31d2e469e87ece1872efdedba6f prg.sh
Install the software and check the checksum:
root@DD-WRT:/tmp# nvram set rc_startup="$( cat prg.sh )"
root@DD-WRT:/tmp# nvram get rc_startup | md5sum
6f11f31d2e469e87ece1872efdedba6f -
You must check that the two md5sum match. The values could be different from the one showed in this post, but the two ones calculated by you have to match.
Configure the mac address:
root@DD-WRT:/tmp# nvram set button_daemon_mac=00:08:74:08:cc:ce
00:08:74:08:cc:ce is the mac address of the target computer.
Finally perform a commit
root@DD-WRT:/tmp# nvram commit
Now you can reboot the router and test the system pressing the SES Button.
Conclusion
At the end I got an small object capable to start a laptop without opening it. In any case my father needed a router, so I didn't add other object on its desk.
Dir-615 GPIO connections
The table below show how some GPIO pins are connected:
GPIO Pin | Function |
#0 | SES Button (0 pressed, 1 released) |
#8 | Orange main led (0 on, 1 off) |
#9 | Green main led (0 on, 1 off) |
#11 | Blue button led (0 on, 1 off) |
#13 | Red button led (0 on, 1 off) |
References
[1] Wikipedia: WAKE ON LAN
[2] DD-WRT
[4] Forum on D-Link DIR-615 D3
[5] Development info - DD-WRT - Toolchain download
[6] gpio source
[6] uuencode implemented entirely in bash
[7] The archive with the scripts