Pimp your TL-MR3020 mobile router

Buttons and LEDs

By way of the web interface or SSH, you can completely control the TL-MR3020 as a mini-server. However, it is easier to use the existing buttons. The original WPS button is suitable for triggering individual actions, and the slide switch on the side (with its three positions) does the switching between different operating conditions (more about this later).

The LEDs serve as a kind of output device. Three different states are possible: on, off, or flashing. In combination with the buttons, you can build some nice features. From a technical point of view, you need to control the LEDs on files below /sys/class/leds (e.g., for the WPS LED, this is the /sys/class/leds/tp-link:green:wps directory). The makers of OpenWrt hide the complexity, and you normally only need to edit the configuration in the /etc/config/system file (Listing 5, lines 13-35).

Listing 5

Editing /etc/config/system

01 # Configuring LEDs and buttons
02 config system
03    option hostname 'jupiter.bablokb-local.de'
04    option timezone 'CET-1CEST,M3.5.0,M10.5.0/3'
06 config timeserver 'ntp'
07    list server '0.openwrt.pool.ntp.org'
08    list server '1.openwrt.pool.ntp.org'
09    list server '2.openwrt.pool.ntp.org'
10    list server '3.openwrt.pool.ntp.org'
11    option enable_server '0'
13 config led 'led_usb'
14    option name 'USB'
15    option sysfs 'tp-link:green:3g'
16    option trigger 'usbdev'
17    option dev '1-1'
18    option interval '50'
20 config led 'led_wlan'
21    option name 'WLAN'
22    option sysfs 'tp-link:green:wlan'
23    option trigger 'phy0tpt'
25 config led 'led_lan'
26    option name 'LAN'
27    option sysfs 'tp-link:green:lan'
28    option trigger 'netdev'
29    option dev 'eth0'
30    option mode 'link tx rx'
32 config led 'led_wps'
33         option name 'wps'
34         option sysfs 'tp-link:green:wps'
35         option trigger 'default-on'
37 config button
38         option button 'wps'
39         option action 'released'
40         option min '3'
41         option max '6'
42         option handler 'halt'
44 config button
45         option button 'wps'
46         option action 'released'
47         option min '0'
48         option max '2'
49         option handler 'logger wps pressed 0-2s'
51 config slider 'slider'
52         option handler '/usr/sbin/handle_slider'

Typically, OpenWrt couples LED activity with the operating states of individual components, such as the network or USB interface. However, you can adjust the defaults to suit your needs.

Configuring the switch is also easy. You need to configure the event system kernel so that it triggers on the appropriate button events. To do this, edit the /etc/hotplug2.rules file and remove the caret before the ^Buttons string. Because this is an exception list, you enable events for buttons by removing the comment sign. From now on, the system runs all the scripts in the directory /etc/hotplug/button for each button event. The variables BUTTON and ACTION are set.

An example that demonstrates the interaction with the LEDs is shown in Listing 6. This script is only for the WPS button (line 22), and it causes the WPS LED to flash for three seconds (lines 6-8 and 10) then go off for another three seconds. When you release the button, the script turns on the LED again (line 19).

Listing 6

LED Interaction

01 #!/bin/sh
02 # Handle button events
04 set_led_blink() {
05 # Switch flashing on (1s on / 0.2 sec off)
06   echo timer > /sys/class/leds/tp-link\:green\:wps/trigger
07   echo 1000 > /sys/class/leds/tp-link\:green\:wps/delay_on
08   echo  200 > /sys/class/leds/tp-link\:green\:wps/delay_off
09 # Turn off after three seconds
10   sleep 3
11   echo none > /sys/class/leds/tp-link\:green\:wps/trigger
12 # Turn on after three seconds
13   sleep 3
14   set_led_on
15 }
17 set_led_on() {
18 # Turn on LED
19   echo default-on > /sys/class/leds/tp-link\:green\:wps/trigger
20 }
22 if [ "$BUTTON" = "wps" ]; then
23   if [ "$ACTION" = "pressed" ]; then
24     set_led_blink &
25   else
26     set_led_on
27   fi
28 else
29   exit 0
30 fi

Instead of storing each script individually in the Button directory and querying the status of the switch there, as in Listing 5, it makes sense to download a generic button script from the OpenWrt treasure trove [4]. Then, you can configure the switch similar to the LEDs in /etc/config/system.

The WPS button is configured as an off switch here: If you hold down the button for at least three, and a maximum of six, seconds and then let go, the system shuts down (lines 37-42 in Listing 5).

This step also reveals the meaning of the program in Listing 6; the button LED flashes for three seconds and then switches off for three seconds – so you do not have to count to shut down the system. Likewise, you could also use the WPS button to start another operation with short clicks. Listing 5 (lines 44-49) configures a log entry for demonstration purposes.

The Slide Switch

The slide switch on the TL-MR3020 is slightly trickier for two reasons. First, the kernel does not see the slide switch as one button but as two; mapping the three possible states takes 2 bits. Each change of the switch thus triggers two events, which reach the processing script sequentially but must be evaluated together. Second, the event system only sees the changes.

Now you can try a little script that checks the status of the slide switch while booting, for example, to configure the network environment. This aspect, however, is only hinted at in the OpenWrt wiki documentation. Listing 7 shows you how: The script stores the status of the two buttons BTN_0 and BTN_1 in appropriately named files under /var/run. The script runs once at startup, starting from /etc/rc.local.

Listing 7

Checking Status of the Slide Switch

01 #!/bin/sh
02 # Read the slider (aka BTN_0/BTN_1)
03 # rmmod uses underscores, insmod uses strokes!
04 rmmod gpio_button_hotplug                           # Remove kernel module
05 echo 18 > /sys/class/gpio/export                    # export BTN_0
06 echo 20 > /sys/class/gpio/export                    # export BTN_1
07 cat /sys/class/gpio/gpio18/value > /var/run/BTN_0   # Status BTN_0
08 cat /sys/class/gpio/gpio20/value > /var/run/BTN_1   # Status BTN_1
09 echo 18 > /sys/class/gpio/unexport                  # unexport BTN_0
10 echo 20 > /sys/class/gpio/unexport                  # unexport BTN_1
11 insmod gpio-button-hotplug                          # Load kernel module

In contrast, the script in Listing 8 runs for every button event. It updates the Status button in /var/run. Additionally, it starts a processing script. The extra magic in lines 10-12 ensures that only one processing script starts. The wait time before processing (line 21) ensures that all relevant button events are also received and processed. Lines 16 and 17 retrieve the processing script from the configuration file in /etc/config/system. The processing script then starts at line 22.

Listing 8

Updating the Status Button

01 #!/bin/sh
02 # Handle slider events
03 . /lib/functions.sh
04 DELAY=5
05 LOCK=/var/run/slider.lock
07 # --- Run Update (asynchronous) ---
08 run_handler() {
09   # Only start if not already active
10   if ! mkdir "$LOCK" 2>/dev/null; then
11     logger "update-script already running"
12     exit 0
13   fi
15   # Read processing script from /etc/config/system
16   config_load system
17   config_get handler slider handler
18   logger "handler-script: $handler"
20   logger "wait $DELAY seconds for all events"
21   sleep $DELAY
22   eval $handler                   # Execute handler
23   rm -fr "$LOCK"
24 }
26 # --- Main Program ------------------
27 logger "Process event '$ACTION' for $BUTTON"
29 # Ignore WPS button
30 if [ "$BUTTON" = "wps" ]; then
31   exit 0
32 fi
34 # Update button file to match event
35 if [ "$ACTION" = "pressed" ]; then
36   echo "1" > "/var/run/$BUTTON"
37 else
38   echo "0" > "/var/run/$BUTTON"
39 fi
40                     # Run asynchronously
41 run_handler &       # (do not block event handling)

An example of such a script is shown in Listing 9. It reads the status of the slide switch and reconfigures the network. The actual network files are only symbolic links; thus, the reconfiguration consists of pointing the symlinks at the new configuration files. For example, /etc/config/network.AP contains the network configuration when the slider is in the AP position. It makes sense to start the processing script once at startup time (in /etc/rc.local) after reading the slider status.

Listing 9

Processing Script

01 #!/bin/sh
02 # Processing script for the slider
03 logger "Execute $0"
05 # Read status of slider
06 if [ `cat /var/run/BTN_0` = "0" ]; then
07   slider="WISP"
08 elif [ `cat /var/run/BTN_1` = "0" ]; then
09   slider="3G"
10 else
11   slider="AP"
12 fi
13 logger "Status of slider: $slider"
15 # Remove old symlinks
16 rm /etc/config/dhcp
17 rm /etc/config/network
18 rm /etc/config/wireless
20 # Set new symlinks
21 ln -s dhcp.$slider     /etc/config/dhcp
22 ln -s network.$slider  /etc/config/network
23 ln -s wireless.$slider /etc/config/wireless
25 # Restart network and DHCP
26 /etc/init.d/network restart
27 /etc/init.d/dnsmasq restart


In this article, I've explained the hardware, so you "only" need to combine the individual components. For more detailed information about getting a UMTS stick to run, for example, or implementing specific network scenarios, please see the OpenWrt wiki.

The little TL-MR3020 router cannot cover every application (see the "More Application Examples" box). However, the mechanisms described here are at least similar for other devices, including those by other manufacturers. At the upper end of the power spectrum are the QNAP NAS devices that are supplied with OpenWrt in place. However, the range of preconfigured services makes customization more difficult.

More Application Examples

The usefulness of the TL-MR3020 is a result of its low power consumption and mobility. I use it as a synchronization server using the "Rsync for Android" app, and it synchronizes data between my mobile devices, the server, and other computers. On the road, the server acts as a router and emulates my home network, with no need to reconfigure my mobile zoo.

Further application scenarios for the TL-MR3020 can be found online through a simple web search. These range from web servers and VPN gateways to a simple social networking platform. To explore the computer's limits, I also installed ownCloud on the TL-MR3020. The application needs a web server and a complete PHP stack.

Basic functions, such as viewing and maintaining the calendar, do work, but slowly. Also, the TL-MR3020 crashed reproducibly while attempting to upload multiple images simultaneously. Perhaps a little tuning could tweak a bit more out of the box, but to run ownCloud seriously, you need something more powerful on the hardware side.

The Author

Bernhard Bablok works at Allianz Managed Operations & Services SE as a SAP HR developer. When he's not listening to music, riding his bike, or walking, he focuses on topics relating to Linux and object orientation. You can contact him at mailto:mail@bablokb.de.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus

Direct Download

Read full article as PDF:

Price $2.95