After attempts at buying a GPS-equipped cellular router for a vehicular communications project fell through, I spent the weekend trying to find an alternative based on a standard Ethernet router. The process uncovered lots of new and poorly documented tasks so I hope my notes will save someone else a whole heap of time and frustration.
My first target was the Asus WL-500GL, after reading of success with oleg's firmware and gpsd. Unfortunately, combing all the local electronic retailers in my city (Newcastle, Australia) for Asus routers turned up only strange looks and zero routers. In desperation I found that the Linksys WRT54GL was a possibility, having good support for OpenWrt and at least one available serial port. However, to my dismay I found hundreds of WRT54G2, which despite the similar name, lack critical features that the unavailable WRT54GL sports.
Of the routers that were actually available, the only remaining glint of hope I found was in the D-Link DIR-615. The OpenWrt docs claim support for the C1 model, but the closest I could find was C2. Options were running dry fast, so I took the plunge on the C2 model.
Setup was straightforward. The router bag was sealed with large sticker and plenty of warnings that the software from the CD must be installed before connecting the router. I ignored them. I don't have a Windows machine handy and the CD only contains a compressed installer image. With the router up and running, it was time to create the build environment.
I'm running Mac OS X 10.6.3 (Snow Leopard) with the Developer Tools installed. I'll indicate commands for the host terminal with the prefix '$' and commands for the router terminal with the prefix '%'.
I used MacPorts to get some dependencies:
$ sudo port install coreutils
$ sudo port install gawk
$ sudo port install wget
$ sudo port install findutils
coreutils installs fileutils and findutils installs the GNU version of find, necessary when creating the build images.
The build system requires a case-sensitive filesystem, so I used Disk Utility to create a 4GB (yes, >3GB to compile sources!) Mac OS Extended (Case-sensitive) disk image, then used terminal to navigate to it.
$ cd /Volumes/OpenWrt/
I checked out the OpenWrt trunk source. I actually spent the first 6 hours working with the 8.09 branch (as suggested by the compatible hardware list) but found many problems, including lack of DIR-615 profiles, file too big problems and linker errors "Nonrepresentable section on output". So I switched to trunk and everything started to work. For what it is worth, I pulled trunk on the 4th April, 2 days after Backfire 10.03-rc3 was posted.
$ svn co svn://svn.openwrt.org/openwrt/trunk
$ cd trunk
$ make prereq
$ make menuconfig
If make prereq succeeds, it may run menuconfig automatically. In any case, once I was in menuconfig I had to be very careful not to press an arrow key! It appears the arrow keys aren't escaped properly, and generally cause menuconfig to quit. Instead, I navigated using the accelerators, enter, esc, plus, minus, 'y', 'n' and spacebar.
I used menuconfig to:
* Change Target System to Atheros AR71xx
* Change Profile to D-Link DIR-615 C1
To save the config I pressed Esc from the main menu and then Enter to select "Yes". Then I built the configuration:
$ make
This took around 30 minutes on a 2.8GHz Intel Core 2 Duo. Once it was complete, my bin/ar71xx directory contained the following (preceded by file size):
3866648 openwrt-ar71xx-dir-615-c1-squashfs-factory.bin
2555908 openwrt-ar71xx-dir-615-c1-squashfs-sysupgrade.bin
2752512 openwrt-ar71xx-root.jffs2-128k
2621440 openwrt-ar71xx-root.jffs2-64k
1703936 openwrt-ar71xx-root.squashfs
1646596 openwrt-ar71xx-root.squashfs-4k
2005637 openwrt-ar71xx-rootfs.tgz
1183055 openwrt-ar71xx-uImage-gzip.bin
852722 openwrt-ar71xx-uImage-lzma.bin
2619896 openwrt-ar71xx-vmlinux.bin
2686288 openwrt-ar71xx-vmlinux.elf
1245184 openwrt-ar71xx-vmlinux.gz
917504 openwrt-ar71xx-vmlinux.lzma
And I was ready for the first flashing. This is where things get nervous. It turns out the DIR-615 has a ~200KB boot space reserved for the boot loader and the flash image takes up the remaining 3.8MB. That should make it pretty hard to brick the router, and I didn't have any problems, but you never know.
After mucking around with the router's "emergency upgrade flash" mode (accessed by holding the reset button for 30 seconds until power light flashes amber) for a couple of hours, trying all manner of hardware IDs, I gave up and used the D-Link web interface instead. Under Tools there should be a "Upgrade Firmware" link. I used this, uploaded "openwrt-ar71xx-dir-615-c1-squashfs-factory.bin" and away it went!
In just 14 hours I had OpenWrt running on the DIR-615!
To restore access to the router I set my network settings to manual IP 192.168.1.100, then logged in:
$ telnet 192.168.1.1
% passwd
% vi /etc/config/network
I changed the lan option ipaddr to 192.168.0.1 so it didn't clash with my existing network.
% reboot
Remember to change manual IP to 192.168.0.100 to suit new subnet.
$ ssh root@192.168.0.1
And we're in! The router automatically picked up a WAN address from my ADSL modem and everything worked as expected. I even tried commenting out "open disabled 1" in /etc/config/wireless and found that wireless worked without a hitch.
With the default OpenWrt kernel installed I was able to run opkg to install gpsd which worked well. In order to test the system however, I really needed some more software. At first I investigated modifying the gpsd package to include gpsfake, but after discovering that it requires python which is a large package itself, I decided to include my own software instead.
I found the easiest way to include my own software was to create a basic package and stick it in trunk/package:
$ cd package
$ mkdir gpssim
$ cd gpssim
$ touch Makefile
$ mkdir src
$ touch src/gpssim.c
$ touch src/Makefile
Most of the packages actually download their source from the Internet, but a neat trick in the package Makefile allows the source to be included locally. My Makefile looks like this:
include $(TOPDIR)/rules.mk
PKG_NAME:=gpssim
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/gpssim
SECTION:=net
CATEGORY:=Network
TITLE:=Simulate a dumb GPS receiver serving on port 2947
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
endef
define Package/gpssim/install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/gpssim $(1)/bin/
endef
$(eval $(call BuildPackage,gpssim))
The src directory then, contains a simple c source file and a very small Makefile. Both can be developed in the native host environment before including in OpenWrt.
While I was adding software to the kernel image, it made sense to add gpsd as well.
$ cd package
$ svn co svn://svn.openwrt.org/openwrt/packages/net/gpsd
$ svn co svn://svn.openwrt.org/openwrt/packages/libs/uclibc++
Adding the uclibc++ dependency now saves a lot of wasted time later!
menuconfig automatically picks up the new packages:
$ cd ..
$ make menuconfig
This time I entered Network and hit 'y' for gpsd and gpssim. I also entered Libraries and noted that uclibc++ had been added as a required build. Esc and Enter to exit and save menuconfig.
make
This time the openwrt-ar71xx-dir-615-c1-squashfs-factory.bin image was created with the extra packages included. Now how to flash the new image, since we've lost the D-Link web interface? At first I tried many permutations of mtd after deciphering /proc/mtd and dmesg, but couldn't get past this:
$ scp bin/ar71xx/openwrt-ar71xx-dir-615-c1-squashfs-factory.bin root@192.168.0.1:/tmp/images/
% mtd -e firmware -r write /tmp/images/openwrt-ar71xx-dir-615-c1-squashfs-factory.bin firmware
[e]Failed to erase block
So I tried tftp instead:
$ cd bin/ar71xx
$ tftp 192.168.0.1
> binary
> rexmt 1
> timeout 60
> trace
At this point I power cycled the router and immediately began issuing this command over and over again:
> put openwrt-ar71xx-dir-615-c1-squashfs-factory.bin
Eventually the "sendto: No route to hose" message doesn't come back, and the following appears instead:
tftp> put openwrt-ar71xx-dir-615-c1-squashfs-factory.bin
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
tftp: sendto: No route to host
tftp> put openwrt-ar71xx-dir-615-c1-squashfs-factory.bin
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
sent WRQ <file=openwrt-ar71xx-dir-615-c1-squashfs-factory.bin, mode=octet>
tftp: sendto: No route to host
The router then automatically reboots and loads the new firmware. It also resets itself to 192.168.1.1, so to get it back I switched my manual IP to 192.168.1.100 and then:
$ telnet 192.168.1.1
% passwd
% exit
$ ssh root@192.168.1.1
% vi /etc/config/network
Change ipaddr back to 192.168.0.1…
% reboot
Change manual IP back to 192.168.0.100…
$ ssh root@192.168.0.1
And we're done! A working OpenWrt install complete with custom software, ready to try to get gpsd to work. The first thing I did was add enable gpsd at boot by creating /etc/init.d/gpsd with the following contents:
% cat /etc/init.d/gpsd
#!/bin/sh /etc/rc.common
START=99
start() {
gpsd -G /dev/ttyS0
}
stop() {
killall gpsd
}
So far I've done some preliminary tests to find and enable the serial port. I've found that the 4 vias near the bottom left of this photo are likely serial suspects.
The top via is ground, the next two are Rx and Tx (I'll check which is which using an oscilloscope tomorrow) and the bottom is 3.3V. I've confirmed I can send and receive data (albeit, unreliably) via this interface by sticking a paper clip between the middle two vias, running "% cat < /dev/ttyS0" in one session and "echo 'Hello, world!' > /dev/ttyS0" in another.
What remains is to dump the information I've found about this router for Google fodder and also in case someone wants to update the wiki!
* Another shot of the internals appears below, but the FCC also have photos from their tests on their website.
* It turns out the C2 hardware version I have actually has a circuit board with C1 stamped on it inside. So I do not know what the difference between C1 and C2 is.
* Filesystem:
root@OpenWrt:~# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 1408 1408 0 100% /rom
tmpfs 14792 36 14756 0% /tmp
tmpfs 512 0 512 0% /dev
/dev/mtdblock4 1472 204 1268 14% /overlay
mini_fo:/overlay 1408 1408 0 100% /
* cpuinfo:
# less /proc/cpuinfo
system type : Atheros AR9130 rev 2
machine : D-Link DIR-615 rev. C1
processor : 0
cpu model : MIPS 24Kc V7.4
BogoMIPS : 266.24
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ff8]
ASEs implemented : mips16
shadow register sets : 1
core : 0
VCED exceptions : not available
VCEI exceptions : not available
* Chips on board:
** AR9130-BC1E
** W9425G6EH-5: 4M, 16 BITS DDR SDRAM (there seems to be confusion about 4MB/8MB - it only has 4MB but each location is 16 bits)
** AR8216: Ethernet switch
** MX25l3205: 32Mbit CMOS Flash (RAM and FLASH sizes are reported backwards in some docs)
** RT9183H: Linear Regulator
* The router comes with DIR-615_3.01-tomizone-1.0.2 firmware. This version does not appear to be on ftp.dlink.com, but is available from http://www.tomizone.com/downloads/firmware. It looks like tomizone support is the difference between C1 and C2. Given the trouble I had getting the emergency flash upgrade page to accept any images, it may be difficult to return to router to D-Link firmware.
More to come as I work on interfacing a Garmin GPS 18x OEM LVC to the serial port.