[update] As Sean Lincolne pointed out, squishguava, the boot image this thing loads over the network when it boots, is just a simple cramfs image. The "COMPRESSED ROMFS" in my earlier 'strings' is a dead give-away on this. I finally got some time to have a peek at it. It has the following in it:
libc-2.1.3.so* | libm-2.1.3.so* | librms.so* | rio* |
libdl-2.1.3.so* | libmp3msp.so* | libthreadutil.so* | scripts/ |
libhttpmsp.so* | libmrdi.so* | libwmamsp.so* | version.txt |
libiupnp.so* | liboalmsp.so* | mrd* | web/ |
libixml.so* | libpil.so* | mrdDevice* | |
libllmsp.so* | libpthread-0.8.so* | pilreg.dat* |
It is obviously not a full Linux filesystem, as can be seen by looking
at files in the scripts directory, this filesystem gets mounted on
/guava
. I compiled a small statically linked busybox and stuck it in
bb/
which among other things had bb/sbin/telnetd
in it. Then I
hacked up scripts/rio-script
and had it launch the telnetd
right
before it launches the rio
. Built a new cramfs squishguava image and
booted with it. It actually booted just fine. I was worried they might
have some sort of checksum check, or my added 600k would overflow
something, but it was fine. The bad news is that I couldn't get in via
telnet. So, either, my telnetd didn't start properly, or the port is
blocked.
I did notice that the default shell is /bin/ash
which also happens to
be the default shell in BusyBox and Linksys has used Busybox on other
devices in the past. I bet the rom firmware which has the root
filesystem for this thing is just a busybox image. So a bit more hacking
on that rio-script should let me either somehow get a message out to me
by trying various standard busybox commands, or I can run some stuff to
try to deblock the port. Any suggestions on what is likely to work right
away?
More info. I replaced the rio binary with my arm cross-compiled telnetd
binary and it then doesn't get beyond the "Launching remote-IO" message
during boot. At least it tells me that what I am doing has some effect.
But I still can't get in via telnet. I also tried replacing it with a
script that tried to ping out, cat stuff to /dev/dsp and echo stuff to
various devices and none of that did anything I could
see/hear.
[/update]
This looks like a nifty little box that will make it easy to access mp3's and photos directly from a remote-control TV-displayed interface. Much nicer than needing to stick a PC next to the TV/Stereo in the living room.
This little device showed up today. Had no trouble configuring it and hooking it up once I shuffled the various cables around a bit on the back of the TV and stereo. The music navigator is really nice on it and I like that you can play mp3's while a photo album is cycling through. Will have to try this thing against some Samba shares later on.
No luck on the Samba shares, or any sort of shares at all actually. I did a bit of sniffing of the datastream between the WMA and XP. When it starts up the first thing it does after getting an IP via DHCP is to grab its OS image from the XP box. That image is clearly a Linux 2.4.17 kernel and all communications appear to be via a UPnP A/V Media Renderer SOAP thing. As far as I can tell, when you designate a directory via the Media tool on the XP box, it creates a regular .m3u playlist out of that and serves it up to the WMA when requested. There doesn't appear to be any encryption involved, so getting this thing to work with a Linux box as the server would involve creating a UPnP SOAP server that understood the requests from the WMA. Not that this is a trivial effort, but certainly not impossible and once done this thing would be able to serve files up from anywhere a Linux box could access files from. Frankly I don't see why the heck the SOAP server they provide for XP can't serve up its playlists from a network share. There doesn't appear to be any technical reason for this restriction. I bet that with a bit of hacking and with the help of libupnp this is quite feasible.
Or, alternatively, create a custom image from the sources Linksys is supposed to provide. They have their GPL Page but it doesn't list the WMA11B (yet?). As George notes, SOAP isn't exactly ideal for something as simple as moving mp3s and image files around. An alternate image that was able to mount shares directly, would be cool. It might require sticking a .m3u playlist file in each directory so you wouldn't need to do that on the WMA, but that wouldn't bug me either.
For more info on the technology in this device, have a read through
Intel's Digital Home
Site or see the
extended entry for some nitty-gritty protocol details.
Don't ask me why the boot image is called squishguava, but it is. Can't
gleam too much out of it other than the fact that it is very likely to
be a Linux image.
% strings squishguava
Compressed ROMFS
6i8V
Compressed
version.txt
libhttpmsp.so
libiupnp.so
libixml.so
libllmsp.so
libmp3msp.so
libmrdi.so
liboalmsp.so
libpil.so
librms.so
libthreadutil.so
libwmamsp.so
mrdDevice
pilreg.dat
libc-2.1.3.so
libdl-2.1.3.so
libm-2.1.3.so
libpthread-0.8.so
scripts
channelmgrscpd.xml
remoteinputscpd.xml
riodevicedesc.xml
rioscpd.xml
ConnectionManager.xml
MediaRendererDevDesc.xml
RendererControl.xml
TCxml.xml
Transport.xml
rio-script
mrd-script
The data stream when you fire this thing up is much more telling. Near the start we see a, "Hey I am Awake" message. 172.16.10.100 is the WinXP box and 172.16.10.105 is the WMA.
NOTIFY /AdapterInfoService/event HTTP/1.1
HOST: 172.16.10.100:8037
Content-Type: text/xml
NT: upnp:event
NTS: upnp:propchange
SID: uuid:1
SEQ: 0
Content-Length: 324
<?xml version="1.0" encoding="utf-8"?><e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0"><e:property><BootImageVersion><firmware>
<version>Ver. 11 R06</version>
<time>09:50:28 AM</time>
<date>08/01/03</date>
</firmware>
</BootImageVersion></e:property></e:propertyset>
It also sends a NOT_STARTED message:
NOTIFY /ApplicationTransferService/event HTTP/1.1
HOST: 172.16.10.100:8037
Content-Type: text/xml
NT: upnp:event
NTS: upnp:propchange
SID: uuid:2
SEQ: 0
Content-Length: 177
<?xml version="1.0" encoding="utf-8"?><e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0"><e:property>
<TransferState>NOT_STARTED</TransferState>
</e:property></e:propertyset>
And the response back from the WinXP box is:
POST /AdapterInfoService/control HTTP/1.1
HOST: 172.16.10.105:62063
SOAPACTION: "urn:schemas-upnp-org:service:AdapterInfoService:1#GetExtDeviceDescription"
CONTENT-TYPE: text/xml ; charset="utf-8"
Content-Length: 303
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"^gt;
<s:Body>
<u: xmlns:u="urn:schemas-upnp-org:service:AdapterInfoService:1" />
</s:Body>
</s:Envelope>
These go back and forth a few times with the same questions and answers just to get synched up, I guess. Then after a bunch of other exchanges where the WinXP box is asking the WMA what sort of box it is, it finally tells the WMA where to go and fetch its brain:
POST /ApplicationTransferService/control HTTP/1.1
HOST: 172.16.10.105:62063
SOAPACTION: "urn:schemas-upnp-org:service:ApplicationTransferService:1#SetApplicationPackageURI"
CONTENT-TYPE: text/xml ; charset="utf-8"
Content-Length: 473
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:SetApplicationPackageURI xmlns:u="urn:schemas-upnp-org:service:ApplicationTransferService:1">
<ApplicationURI>uri://172.16.10.100:49156/squishguava</ApplicationURI>
<ImageLength>2260992</ImageLength>
</u:SetApplicationPackageURI>
</s:Body>
</s:Envelope>
SquishGuava!! The WMA sends back a SERVER_WAIT while it adjusts to its new brain, and then a STARTED followed by a COMPLETED when it is ready. I also see some errors popping up in the stream:
SERVER: Linux/2.4.17-rmk3-cot1, UPnP/1.0, Intel SDK for UPnP devices /1.2
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring>UPnPError</faultstring>
<detail>
<UPnPError xmlns="urn:schemas-upnp-org:control-1-0">
<errorCode>-1</errorCode>
<errorDescription>Invalid Action</errorDescription>
</UPnPError>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
Nice to see that they aren't filling up my wireless bandwidth with any useless traffic! But eventually the WMA tells the server all about itself:
<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<URLBase>http://172.16.10.105:49152/</URLBase>
<device>
<deviceType>urn:schemas-upnp-org:device:RemoteIO:1</deviceType>
<friendlyName>Linksys Wireless-B Media Adapter</friendlyName>
<manufacturer>Linksys Corporation</manufacturer>
<manufacturerURL>http://www.linksys.com</manufacturerURL>
<modelDescription>UPnP Remote I/O Device 2.0</modelDescription>
<modelName>UPnP Remote I/O Device</modelName>
<modelNumber>1.0</modelNumber>
<modelURL>http://www.linksys.com</modelURL>
<serialNumber>1234567890012</serialNumber>
<UDN>uuid:0006250DBAA7RemoteIO</UDN>
<UPC>1234567891</UPC>
<serviceList>
<service>
<serviceType>urn:schemas-upnp-org:service:RemoteIO:1</serviceType>
<serviceId>urn:upnp-org:serviceId:RemoteIO1</serviceId>
<controlURL>/upnp/control/RemoteIO1</controlURL>
<eventSubURL>/upnp/event/RemoteIO1</eventSubURL>
<SCPDURL>/rioscpd.xml</SCPDURL>
</service>
<service>
<serviceType>urn:schemas-upnp-org:service:RemoteInput:1</serviceType>
<serviceId>urn:upnp-org:serviceId:RemoteInput1</serviceId>
<controlURL>/upnp/control/RemoteInput1</controlURL>
<eventSubURL>/upnp/event/RemoteInput1</eventSubURL>
<SCPDURL>/remoteinputscpd.xml</SCPDURL>
</service>
</serviceList>
<presentationURL></presentationURL>
</device>
</root>
I haven't touched the serial number in that, by the way. Looks like they aren't using it. Again, nice to see them going out of their way to save bandwidth. After this comes a bunch more crap describing the services. Stuff like this sort of makes me wonder:
<PeerConnection>xrt2://172.16.10.100:52135/jdfkdjfkjdkfjdkjfkdjfkdjfkjdfkjdkfjdkfjiwi18
</PeerConnection>
And a clue as to what file types the WMA can handle:
<Sink>http-get:*:audio/mpeg:*,http-get:*:audio/x-mpeg:*,
http-get:*:audio/mp3:*,http-get:*:audio/x-ms-wma:*,
http-get:*:audio/mpegurl:*,http-get:*:audio/x-mpegurl:*,
http-get:*:audio/m3u:*</Sink>
And some more interesting bits:
<Event xmlns="urn:schemas-upnp-org:metadata-1-0/AVT/">
<InstanceID val="1">
<TransportState val="NO_MEDIA_PRESENT"></TransportState>
<TransportStatus val="OK"></TransportStatus>
<TransportPlaySpeed val="1"></TransportPlaySpeed>
<CurrentPlayMode val="NORMAL"></CurrentPlayMode>
<CurrentRecordQualityMode val="NOT_IMPLEMENTED"></CurrentRecordQualityMode>
<PossiblePlaybackStorageMedia val="NETWORK"></PossiblePlaybackStorageMedia>
<PossibleRecordStorageMedia val="NOT_IMPLEMENTED"></PossibleRecordStorageMedia>
<PossibleRecordQualityModes val="NOT_IMPLEMENTED"></PossibleRecordQualityModes>
<NumberOfTracks val="0"></NumberOfTracks>
<CurrentMediaDuration val="0:00:00"></CurrentMediaDuration>
<AVTransportURI></AVTransportURI>
<AVTransportURIMetaData></AVTransportURIMetaData>
<NextAVTransportURI></NextAVTransportURI>
<NextAVTransportURIMetaData></NextAVTransportURIMetaData>
<PlaybackStorageMedium val="NETWORK"></PlaybackStorageMedium>
<RecordStorageMedium val="NOT_IMPLEMENTED"></RecordStorageMedium>
<RecordMediumWri
teStatus val="NOT_IMPLEMENTED"></RecordMediumWriteStatus>
<CurrentTrack val="0"></CurrentTrack>
<CurrentTrackDuration val="0:00:00"></CurrentTrackDuration>
<CurrentTrackMetaData val="NOT_IMPLEMENTED"></CurrentTrackMetaData>
<CurrentTrackURI></CurrentTrackURI>
<CurrentTransportActions val="Play,Stop,Pause,Seek,Next,Previous"></CurrentTransportActions>
</InstanceID>
</Event>
Fast-forwarding through oodles of more SOAP stuff and we finally get to the server sending a playlist:
HTTP/1.1 206 Partial Content
CONTENT-RANGE: bytes 0-2559/245115
CONTENT-TYPE: audio/mpegurl
Content-Length: 2560
#EXTM3U
#EXTINF:154,Stone Temple Pilots - "Unglued"
http://172.16.10.100:54455/-1562803410/Stone%20Temple%20Pilots%20%20-%20%20%22Unglued%22.mp3
#EXTINF:171,Enya - (1)The Celtz.MP3 Track 1 of 15
http://172.16.10.100:54455/1695573734/Enya%20%20-%20%20%281%29The%20Celtz.MP3%20Track%201%20of%2015.mp3
This is in standard M3U format. And finally to actually play a song, the WMA issues this request:
GET /1695573734/Enya%20%20-%20%20%281%29The%20Celtz.MP3%20Track%201%20of%2015.mp3 HTTP/1.0
Host: 172.16.10.100
1
and gets back:
HTTP/1.0 200 OK
Content-Type: audio/mpeg
Server: Intel CEL / CLR MiniWebServer
[mp3 data]
So, that's the WMA. When I get back from Comdex/Apachecon I'll try messing with libupnp. For now this toy works pretty well and Carl likes it: