Looking under the skin of SoundMate M1 (Airmusic NW11)
In this article I'll do a bit of digging under the skin and do some reverse engineering of SoundMate M1 audio streaming device.
OpenWrt is a not your average embedded OS, it is fully featured Linux with hundreds of packages which you can install with ease. Actually I'm puzzled how come we have just started to see consumer products use OpenWrt.
telnet to device, and use "root" for username and "ifconfig" for password.
# free -m
total used free shared buffers
Mem: 62192 27584 34608 0 1376
-/+ buffers: 26208 35984
Swap: 0 0 0
So this device had 64Mb of ram, and more than half of it is free.
# df -h
Filesystem Size Used Available Use% Mounted on
rootfs 1.0M 64.0K 976.0K 6% /
/dev/root 5.9M 5.9M 0 100% /rom
tmpfs 30.4M 288.0K 30.1M 1% /tmp
tmpfs 512.0K 0 512.0K 0% /dev
/dev/mtdblock3 1.0M 64.0K 976.0K 6% /overlay
overlayfs:/overlay 1.0M 64.0K 976.0K 6% /
By looking at free drive space we see that there is 976K of free space for any additional tools or scripts.
# ls -1 /etc/rc.d/
K90network
K98boot
K99umount
S05defconfig
S10boot
S20fstab
S39usb
S40network
S42wanlan
S45dnsmasq
S50cron
S50lighttpd
S50telnet
S50wifi_save
S60dbus
S61avahi-daemon
S69shairport
S90firewall
S95done
S97watchdog
S98sysntpd
S99sysctl
Listing of services shows that this device is using all Open source tools, main tool that enables music streaming is shairport
which emulates Apple Airplay service.
# cat /etc/config/network
config 'interface' 'loopback'
option 'ifname' 'lo'
option 'proto' 'static'
option 'ipaddr' '127.0.0.1'
option 'netmask' '255.0.0.0'
config 'interface' 'lan'
option 'type' 'bridge'
option 'proto' 'static'
option 'ipaddr' '192.168.222.254'
option 'netmask' '255.255.255.0'
config 'interface' 'wan'
option 'ifname' 'eth0'
option 'proto' 'dhcp'
option 'hostname' 'SoundMate'
option 'workmode' '1'
config 'interface' 'wwan'
option 'ifname' 'wlan1'
option 'proto' 'dhcp'
option 'hostname' 'SoundMate'
It is strange to see eth0
port configured when this device is missing RJ45 connector.
# cat /etc/config/wireless
config 'wifi-device' 'radio0'
option 'type' 'mac80211'
option 'hwmode' '11ng'
option 'noscan' '1'
list 'ht_capab' 'SHORT-GI-20'
list 'ht_capab' 'SHORT-GI-40'
list 'ht_capab' 'RX-STBC1'
list 'ht_capab' 'DSSS_CCK-40'
option 'macaddr' '88:a0:cc:87:0a:35'
option 'channel' '11'
option 'htmode' 'HT40-'
config 'wifi-iface'
option 'device' 'radio0'
option 'network' 'lan'
option 'mode' 'ap'
option 'wpa_group_rekey' '0'
option 'wpa_pair_rekey' '0'
option 'wpa_master_rekey' '0'
option 'wds' '1'
option 'encryption' 'mixed-psk+ccmp'
option 'ssid' 'SoundMate'
option 'key' 'password'
config 'wifi-iface'
option 'device' 'radio0'
option 'network' 'wwan'
option 'mode' 'sta'
option 'wds' '0'
option 'disabled' '0'
option 'ssid' 'Home Wifi'
option 'encryption' 'psk2+ccmp'
option 'key' 'Password'
Wifi options need a bit more investigating.
# ps
PID USER VSZ STAT COMMAND
1 root 1520 S init
2 root 0 SW [kthreadd]
3 root 0 SW [ksoftirqd/0]
4 root 0 SW [kworker/0:0]
5 root 0 RW [kworker/u:0]
6 root 0 SW [rcu_kthread]
7 root 0 SW< [khelper]
8 root 0 RW [kworker/u:1]
55 root 0 SW [sync_supers]
57 root 0 SW [bdi-default]
59 root 0 SW< [kblockd]
87 root 0 SW [kswapd0]
137 root 0 SW [fsnotify_mark]
151 root 0 SW< [ar71xx-spi]
164 root 0 SW [mtdblock0]
169 root 0 SW [mtdblock1]
174 root 0 DW [mtdblock2]
179 root 0 SW [mtdblock3]
184 root 0 SW [mtdblock4]
189 root 0 SW [mtdblock5]
233 root 0 SW [kworker/0:1]
387 root 0 SW< [ipolldevd]
415 root 0 SWN [jffs2_gcd_mtd3]
417 root 0 SW [flush-mtd-unmap]
432 root 1552 S {rcS} /bin/sh /etc/init.d/rcS S boot
433 root 1520 S /sbin/getty 115200 ttyATH0
434 root 1552 S {rcS} /bin/sh /etc/init.d/rcS S boot
435 root 1520 S logger -s -p 6 -t sysinit
465 root 0 SW< [cfg80211]
483 root 0 SW [khubd]
500 root 0 SW< [rpciod]
515 root 0 SW< [nfsiod]
567 root 736 S /sbin/hotplug2 --override --persistent --set-worker /lib/hotplug2/worker_fork.so --set-rules-file /etc/hotplug2.rules --max-children 1
783 root 0 RW [kworker/0:2]
846 root 1408 S hostapd -P /var/run/wifi-phy0.pid -B /var/run/hostapd-phy0.conf
1029 root 1424 S wpa_supplicant -B -P /var/run/wifi-wlan1.pid -D nl80211 -i wlan1 -c /var/run/wpa_supplicant-wlan1.conf -H /var/run/hostapd-phy0/wlan0
1086 root 912 S wanlan
1146 nobody 864 S /usr/sbin/dnsmasq -K -D -y -Z -b -E -s lan -S /lan/ -l /tmp/dhcp.leases -r /tmp/resolv.conf.auto --rebind-localhost-ok --dhcp-range=lan,192.168.222.1,192.168.222.24,255
1227 root 1520 S udhcpc -t 0 -i eth0 -H SoundMate -b -p /var/run/dhcp-eth0.pid -O rootpath -R
1415 root 1536 S udhcpc -t 0 -i wlan1 -H SoundMate -b -p /var/run/dhcp-wlan1.pid -O rootpath -R
1478 root 3904 S lighttpd -f /etc/lighttpd/lighttpd.conf
1481 root 1520 S telnetd -l /bin/login
1483 root 1120 S wifi_save
1500 root 1632 S /usr/sbin/dbus-daemon --system
1508 root 1536 S -ash
1515 nobody 2144 S avahi-daemon: running [SoundMate.local]
1557 root 3856 S /bin/newshair -a MusicBox -m external-avahi -d
1560 root 1552 S avahi-publish-service E3A17DD59D85@MusicBox _raop._tcp 5002 tp=UDP sm=false ek=1 et=0,1 cn=0,1 ch=2 ss=16 sr=44100 vn=3 txtvers=1 da=true md=0,1,2 pw=false
1579 root 1568 S {S95done} /bin/sh /etc/rc.common /etc/rc.d/S95done boot
1584 root 896 S /usr/sbin/updatefw
1645 root 800 D nrender --friendly-name MusicBox --ip-address 192.168.1.XXX --uuid SM-mac=88a0cc87XXXX
1647 root 912 S checknren
1650 root 1568 S {S95done} /bin/sh /etc/rc.common /etc/rc.d/S95done boot
1651 root 1504 D awk BEGIN{FS="[ \t]+:[ \t]"} /machine/ {print $2} /proc/cpuinfo
1658 root 1520 S /bin/sh -c uci commit
1659 root 928 D uci commit
1660 root 1520 D sh -c ps -w |grep friendly-name | grep -v grep|wc -l
1661 root 1520 R ps -w
1662 root 1520 S [grep]
1663 root 0 Z [grep]
1664 root 1520 R ps
I'm not sure what nsrender
does, does it complement shairtunes
or is it a separate tool.
# cat /etc/rc.local
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.
date -s "2013-01-01 08:00:00"
[ -d /tmp/root ] && {
ismount=$(mount | grep -c disk)
if [ "$ismount" -ne "1" ]; then
for device in $(ls /dev | grep sd); do
n=$(echo $device | sed -e "s/sd//")
m=$n
q=$(echo $n | sed -e "s/[a-z]//")
if [ -z "$q" ]; then
q=${m}0
m=$q
fi
n=$(expr substr "$n" 1 1)
mkdir -p /tmp/mnt/disk-$m
ntfs-3g -o nls=utf8 /dev/$device /tmp/mnt/disk-$m
ismount=$(mount | grep -c disk-$m)
if [ "$ismount" -ne "1" ]; then
mount -o fmask=000,dmask=000,iocharset=utf8 /dev/$device /tmp/mnt/disk-$m
ismount=$(mount | grep -c disk-$m)
if [ "$ismount" -ne "1" ]; then
mount -t exfat -o fmask=000,dmask=000,iocharset=utf8 /dev/$device /tmp/mnt/disk-$m
ismount=$(mount | grep -c disk-$m)
if [ "$ismount" -ne "1" ]; then
rm -r /tmp/mnt/disk-${m}
fi
fi
fi
done
fi
}
/usr/sbin/updatefw &
brctl addif br-lan eth2
insmod /lib/modules/2.6.39.4/ar7240_i2s.ko
mknod /dev/i2s c 253 0
nrestart
checknren &
exit 0
rc.local
script has few interesting thing, first part with if statement is to mount external usb devices. updatefw
is obviously firmware upgrade tool which look if new firmware is put on usb and then it updates current firmware. ar7240_i2s
kernel driver provides support for audio DAC that is connected over i2s
bus to AR9331
SoC.