The Rio Receiver is a piece of home stereo equipment for playing
MP3 or WMA files over either ethernet or an HPNA phone line
network. The Rio Receiver is also sold as the Dell Digital Audio
Receiver. The two products have different front bezels and
splash screens, but they are the same product otherwise.
Currently the Dell product is sold for $299 including speakers
and the Rio product is sold for $349 without speakers. I'll
refer to both devices as the Rio Receiver.

The device was developed by Empeg in England and they licensed the
design to Rio/S3/Diamond/SonicBlue who later acquired Empeg. Empeg is
the company that developed a well known Linux based automotive MP3 player.

The device is designed to work with a Windows host that serves
audio files to the device. It's a nice idea, I bought one
hoping to use a Linux machine as the server. I read
that the Empeg automotive product was Linux based and fairly
open, so I purchased a receiver optimistic that the home stereo product
is a similar design and that I could coerce it to work with a
Linux server.

With the enclosed Perl scripts it's easy
to setup a Linux machine running Apache to serve MP3's to any
number of these receivers. With a Linux server the device operates
nearly identical to a box using a Windows machine as a server
although there are still a few features missing from the Linux
server. This code currently does not support saved playlists
or saving favorites. I have not attempted to
support the HPNA networking interface, I also have not attempted to
support WMA files. All of my content is in MP3 format, but I
suspect that adding WMA support to the server is trivial.

The linux server has a few features not provided in the windows
implementation. It's open source and easy to change to suit your
needs. The database of songs (stored in DBM files) can be modified
while music is playing, the Windows implmentation requires that
music play stop during a database update. When an album is
selected this implementation plays songs in the original order of the
album.

This document is still a bit rough. It is not a clean howto, it's
more of a description about how the receiver works, but it should
be easy to setup a server. I'm assuming that the reader
is pretty technical and comfortable configuring Apache, setting
up a DHCP server, and configuring NFS on a linux box.

I have not modified the device software so there's no worry about
trashing the firmware stored in flash in the receiver. It's not
necessary to open the case of the receiver so there's no worry
about voiding the warranty.

Hardware

The Rio Receiver contains a 74MHz ARM7 Cirrus processor, 512KB of
flash memory for booting, 4MB of DRAM, a CS8900 based 10baseT ethernet
interface, and a Broadcom HPNA interface. HPNA is a 10mbit/s network
that shares the telephone wires in your house. No doubt a remarkable
technical achievement, but in a world where 100baseT switched hubs
are $99 I don't have any interest in sorting out HPNA.

The receiver also contains a 16-bit DAC, headphone amplifier, 10W
power amp for speakers, an LCD, an IR receiver for a consumer remote
control, and buttons for a user interface.

The box contains no storage for music, all of the content must come
over the network. With 4MB of DRAM it has enough memory for many
seconds of music buffering.

The box is currently priced at $299 (Dell) and $349 (SonicBlue).
This price is similar to the introductory price for other MP3 devices,
but I think the product is terribly over-priced as measured by
parts cost. Portable MP3 players typically have 64MB of flash
memory that is the main cost of the unit. At today's prices 64MB
of flash is about $50 of parts cost. The Rio Receiver only contains
0.5 MB of flash for booting, this is inexpensive and the other
components on the board are inexpensive as well. I estimate
the parts cost of the receiver to be about $80. Using rule of
thumb margins this device could sell online for well under $200.
I hope the vendors will price the device more agressively after
collecting money from the early adopters like me.

Network Snooping

To develop the Linux code I installed the host software on a Windows
machine and used ethereal, a fabulous network snopping tool, to
watch packets from my Linux machine. My strategy was to observe
the behavior of the device with a windows box and then write code
to duplicate the behavior on Linux.

The first thing the box does on power-up is to send out a DHCP request
to get an IP address. Rio's windows software has a limited DHCP server
that evidently only repsonds to requests from audio receivers. It's
easy enough to add a DHCP entry on the Linux box to provide an IP
address to the reciever. I don't think there is a method to assign a
static IP.

The second thing the box does is broadcast an SSDP request on a specific
UDP port (21075) looking for a server. The server responds to the box on
the same UDP port with a packet that contains a URL and port number.

The port number contained in the SSDP response is used by the server for all
future communication between receiver and server. This is a little
problematic in that this port is used for portmapper requests
(instead of port 111) for NFS mounts.

My linux solution for the SSDP requests is a very simple UDP server
written in Perl that listens on UDP port 21075 for requests from
a receiver box and replies with an IP address for the server, but
omits the port number. When the port number is ommitted in the
SSDP reply the receiver uses standard ports for various requests
making linux configuration easier.

I start the SSDP server ssdp.pl from
/etc/rc.d/rc.local. It sits
quietly and responds to a couple of SSDP requests when the receiver
is booted.

NFS

After receiving the SSDP response the box attempts to do a read-only, no_root_squash
NFS mount of "/tftpboot" and looks for the path
/tftpboot/ipaddr/
on the server. If you have ssdp.pl running you should be able
to boot the box and see syslog messages for the NFS mount. Add
an entry in /etc/exports to provide an insecure read-only mount for
/tftpboot. Please review your network security and make sure
you're not doing anything to expose your machine to Internet attack. This
warning applies to all these configuration issues, none of this
should be considered secure.

After the NFS mount, the box proceeds to access
/zImage on the mounted
partition. On reset the box first boots Linux from the onboard flash, NFS
mounts the root partition, reads
/zImage from the mounted partition,
and boots linux a second time from the zImage file. The double boot stategy
is very clever, the kernel stored in flash does not need to change when
software is upgraded, kernel enhancements can be added to
/zImage on the NFS
partition and take effect on the second boot.

The /tftpboot/ path prefix for the root partition is a bit of a
misnomer. TFTP is a different UDP protocol for booting, we are NFS
mounting a directory called /tftpboot, there is no TFTP server required. This is a quirk of the default paths for NFS root partitions
in the Linux kernel.

Root filesystem

The root filesystem for the receiver is stored in the Windows software
distrubution in a file called mercury.arf. This is a standard GNU tar
archive file. Untar the file into /tftpboot/ipaddr and you'll find
a minimal but familiar looking linux root filesystem.

I have not included mercury.arf in this distribution because I don't
believe that I can. In addition to the Linux kernel this tar file
contains the closed source player application for the receiver that I
do not have permission to distribute.

Once the root filesystem is in place you should be able to reboot the
reciever and follow the action in the server's syslog. First DHCP, a SSDP
request gets logged, NFS mount of "/", and if all goes well the box
will read zImage and boot a second time. On the second boot networking
information is passed in the command line to the kernel so it will
not make a second DHCP or SSDP request but it will mount the NFS
root filesystem a second time. If you snoop the NFS traffic (did I
mention how great ethereal is) you'll see the client box read quite a
few files including running the application in
/empeg/bin/player.
When the player starts in the client it will make a different SSDP
request you'll see in the syslog. Previous SSDP requrests are labeled
"linux" requests, this one will be labeled a "player" request. When
you get this far this is quite a milestone. You'll be playing music
soon after a little Apache configuration. The second SSDP reply
provides the server IP address, but also provides a port number this
time. This port is used for HTTP requests to access music content.
By default ssdp.pl tells the reciever to use port 81 for HTTP
requests but you can easily change this is if you would like to use
a different port. I use a non-standard port number and associated
Apache virual host configuration to keep my music playing separate from
my normal web server activities.

Music Serving

The player application in the receiver uses HTTP for accessing the
music database and music content. When I started snooping the
network packets and analyzing the requests I figured that I would
write a Perl HTTP server to provide all of the receiver's needs.
As it turned out, it was much easier to configure Apache and add a
few CGI scripts to do the same thing.

An interesting aspect of the receiver's user interface is that most of
the onscreen navigation is a front end to web server requests that
provide song information. This is an interesting way to build a
user interface for a piece of consumer electronics, but sadly the
Rio Receiver only takes this concept to the point where the web server
provides data. Navigation and UI appearance are hard coded into the
client app.

DHCP Configuration

If you already have a DHCP server, configure it to give the Rio the same IP address every time either by specifying its MAC address, or by giving it infinite timeout. If you cannot give it a static IP address, then you'll have to create symbolic links in the /tftpboot directory for each IP address that it might have. (Don't worry -- they won't interfere with any other non-RIO computers on your network.)

If you use a differnt directory other than /share/rio you'll also have to edit /share/rio/mserve/config.pl .

And restart httpd:

# service httpd restart

You can change this to suit your needs. The only funny business is
the AliasMatch directive. Some of the HTTP requests come in a
form that is a little awkward for running a CGI script so I use
the alias feature of Apache to coerce the URL into a suitable
form. For example, the box will make a request like
GET /tags/4000
to read the mp3 tag information from track 4000. The alias
causes the request to run the CGI script
/share/rio/mserver/tags.cgi
which is passed the orignal URL to sort out and return
the correct data. It's not as complicated as I just made it
sound.

Untar this distrubution into the newly configured virtual web server,
/share/rio/mserver
in my case. Change the ownership
of all of the files in the directory to apache to avoid any permission
problems:

Building the music database

The next order of business is to build a music database containing information
about all of your MP3 files. The scripts are setup assuming that your
MP3s are stored in
/share/rio/music.
If you wish to store them elsewhere
then change the .CGI files to reflect the new path.

One of the things that happens when the music database is built is that
the content sub-directory is filled with a bunch of symbolic links to the actual
MP3 files. I was having trouble getting Apache to follow symbolic links
outside of
/share/rio
and I wound up putting a symbolic link to music files from within the
Apache directory tree with ln -s /share/music /share/rio/music,
but that might just be my
own ignorance about configuring Apache.

Once you have the paths configured in the scripts and your music files
ready. From a web browser click on the "rebuild entire database" link
located in the index.html page at the root of the music server.
This should spew ugly text output about each MP3 file along with a 4 digit
hex identifier used by the receiver. You might look in the content
subdirectory and find a large number of symbolic links with names like
"4000" that point to actual MP3 files. You should also look in the dbm
directory and see a number of DBM files.

Testing the database

Here are a few things you can do to test the database. The "dump" link
from the main page prints out the DBM files used for the database in a
pretty raw format useful for debugging. The "music" link shows the
database in a nicely ordered way. The two main problems you might have
building the database are setting the protection bits on the directories
such that the CGI scripts cannot write the DBM files, or possibly an
Apache configuration problem with symbolic links.

Finally, we can use a browser to make a request the same way the receiver
does to verify operation. Try the following cryptic URL from a web
browser:

http://192.168.0.2:81/query?artist=

If the databse has been built should see output something like this although
your musical tastes may vary:

If there are problems the scripts are setup to dump errors to
the file error-log in the same directory. If this is working you
are pretty much ready to go. Reboot the receiver and you should be
rewarded with the MP3 tag information of one of your songs in the
display. If we're very lucky you can hit the play button and listen
to music.

Once you get this far you should play with the user interface of
the box. The only missing features are the "list" button on the
remote control and selecting songs by playlist. You can select
songs by artist, album, etc. You can use the slightly awkward
user interface feature to spell out a portion of a title using the
telephone pad on the remote control.

There is another link on the page to incrementally add songs to
the database. If the database is completely rebuilt the receiver
needs to be rebooted but songs can be added incrementally. The
script scans the music directory and only adds songs that aren't
already in the database.

I've been using the reveiver to listen to music hosted by my linux
machine for several weeks now. I've had a couple of odd occassions
where I need to reboot the receiver, but it's been quite reliable
for the most part.

I no longer have a CD player in my livingroom. I still buy quite
a few CDs, but they arrive from Amazon, get ripped on the CD drive of
my PC, and then stored away in a closet and never make it to
the livingroom.

The receiver has a generally annoying user interface, the screen is
too small, and the UI presents information too small for navigation
from across the room. The box has a couple of annoying qualities,
the volume control only operates on the headphone and speaker outputs.
Based on a suggestion from Hugo Fennes here is a kernel
patch for the device
to cause the volume control
to operate on the line level outputs of the box as well. If you
don't fell like getting setup for building an Arm Linux kernel there
is a pre-built kernel linked on the page.

It's unfortunate that you can't control the receiver from the network
interface. There is a UDP protocol in the receiver for getting status
information and doing a few operations like rebooting or reloading
database information,
but it's not possible to control play from the network interface (as
far as I can tell). I keep wanting to use the receiver as an alarm
clock controlled by my linux box.

I don't think the HPNA interface was a great idea. I'm probably not
a typical consumer, but if a consumer is interested in digital music
in their livingroom, they probably use a program like Napster. If
they run Napster they probably have a DSL line or a cable modem. If
they have a high bandwidth connection then ethernet is already a
part of their lives.

Having said that, the device is really nice and I enjoy having
it my livingroom quite a lot. I trust the Empeg people are working
on a new software release and will work out many of the kinks in
the first release.

Console

It is possible to access the linux console of the receiver. If
you're just setting up another linux machine as a server it's not
necessary and probably voids your warranty to open the box to
access the console, but it is kind of fun.

If you open the case there is a 4-pin header labelled JP5. This
header provides 3.3v power, ground, Tx, and Rx pins for the
serial port built into the Cirrus Arm processor. The pinout
of the header is shown below. The Tx and Rx pins are 3.3v logic
levels, so you have to build a small piece of hardware to convert
the 3.3v logic levels to RS-232 levels. I built a small board
with a Linear Tech LTC1348 from Digikey to get serial port out.
The console header is show in the image above, the pinout as
follows:

Triangle mark on PCB, 3.3v power

Tx data from box (3.3v logic level)

Rx data to box (3.3v logic level)

Ground

If you build a level converter and hook it to the header you'll
see familiar Linux boot messages at 115k baud, you'll also see
the two stage boot process when it loads the second kernel over
NFS.

When the receiver boots it looks for /bin/bash and allows you
to drop into a shell from the console by typing
"q&ltcr&gt"
on the console.
The mercury.arf file distributed with the recevier does not contain
bash, but it's easy enough to build an ARM cross-compiler and then build
bash, but there's not much you can do with a shell right now.

Wish list

It's difficult to hack the application running on the receiver.
If you look at the filesystem for the receiver you'll find that
the player application is a single monolithic statically linked
app. The best thing would be to make this app open source.
Short of that I would suggest breaking the application into
three pieces: the audio player engine, streaming file access, and user
interface. This way someone could write a new UI for the player
or perhaps a new access mechanism or a new codec without
rewriting everything else.

To do

Need to add playlist support and favorites support. I would really
like to replace the player app and rewrite the UI, but this is a
pretty big project. Hopefully some other people will get involved
with hacking the receiver. If you use this package send
me some email and let me know how it goes.