NDS WiFi programming with devkitARM
I have a grand plan to make a beowulf cluster dedicated to computing, interfacing and manipulating chaotic systems. I have a protocol devised that would allow multiple applications running on an arbitrary number of computers in a network pool hardware resources for this task. Each application (node) would have it's own capabilities, and could be used to collect sensory data, provide a human interface, or just to crunch numbers. I could easily have a management node that would maintain a list of other nodes and their abilities, and query them as needed. I recently had a great idea to use a NintendoDS as both an interface (via the touchscreen), and a sensory device (collecting audio samples with the buit-in microphone).
So I did a bunch of NDS programming a few years back using the devkitPro toolchain, specifically devkitARM. They were at release r20 then, and dswifi had just made it on the scene. For those who don't know, dswifi is a library written by Stephen Stair that allows NintendoDS homebrew developers using devkitARM to use the wifi features of the NDS. You can connect to wireless access points, and from there you have network access and a standard Berkley sockets interface, so you can pretty much accomplish anything you set your mind to. I just downloaded the latest version of devkitARM, which is now r26. I was quite pleased with the progress the toolchain had made during my absence, and especially pleased to see dswifi so well integrated. Things pretty much went downhill from there.
NOTE: 09.06.16 - The rest of this post is for historical information only. After I isolated the bug in dswifi that was the root of my problems, I notified the maintainers of devkitPro who committed a fix. There are now new releases of libnds, dswifi and default arm 7 available that correctly handle the DS' MAC address. Please see the addendum at the end of this article for more information. Do not downgrade your devkitPro install if you are having problems. Instead get the very latest versions of all libraries, and you should be good.
There were no examples provided with the nds-examples package that showed how to connect to WEP secured Access Point (AP). The only examples provided were for either using the WFC information stored in the NDS firmware, or for connecting to an unsecured AP. They did have code to enumerate APs and to provide a keyboard interface that I happily integrated. Prior to even testing the included examples I poured a couple hours into writing a code base using the most involved methods possible (swapping out all the simple 0 argument init functions with the 8 argument equivalents) to establish a console and collect and display a list of APs. Selecting an AP from this list that was secured would then provide a prompt to specify either 40-bit or 104-bit encryption. The user could then type in the 10 or 26 character string using a tiny little keyboard on the DS touchscreen. This string was then encoded to a byte array and passed to the Wifi_ConnectAP(...) function provided by dswifi.

Wifi AP list and a tiny keyboard
I then spent three times as long troubleshooting. It took a while for me to remember that I have MAC address filtering enabled on my router (*bonk self*). I loaded up a wifi enabled game, pulled the MAC address of my DS from Nintendo's WFC interface, and put it on my router's Access Control List. I rubbed my hands in greedy anticipation, and loaded up my homebrew app once again. No joy ensued. I still could not connect to my AP.
At this point, I decided to try something simple just to verify the functionality of dswifi (yes, I'm backasswards when it comes to programming), so I loaded up one of the basic dswifi examples. Strangely, it did not work either. I knew it wasn't my DS or router anymore, because I would connect with a proper DS game that was wifi enabled. I didn't see anyone else complaining in the devkitPro forums, but r26 was *just* released and the forums over there aren't exactly teeming with DS programmers. I thought maybe the devkitPro toolchain for x64 Linux might have been the culprit, so I tried in Windows XP as well. Still no joy.
Operating under the assumption that dswifi worked at SOME point in devkitPro, I decided it was time to start digging backwards through the releases, and testing the functionality as I went with the most simple example possible... one that loaded the AP information from the WFC info stored in the DS and automatically tried to connect. This simple example did indeed work back in devkitPro r25 (2009.02.20). I then increased my resolution to try and find *exactly* where dswifi broke in devkitPro.
<SNIP>
Several paragraphs removed at the request of the devkitPro maintainers.
This section basically highlighted my procedures to somewhat subvert the available devkitPro library distributions to create a tool chain that pre-dated issues with the DS MAC address handling. As noted above, the bug I isolated has been fixed in the latest devkitPro library distributions, so this information is no longer pertinent. I found out that in my setup, the simple WFC autoconnect example worked fine when built with dswifi 0.3.7, but refused to work in dswifi 0.3.8. So I configured a motley devkitPro toolchain with different versions of specific libraries in order to get dswifi working for me.
</SNIP>

Telnetting into my NintendoDS Echo Server.
I now have code running on my DS that allows me to connect to my WEP secured AP, and from there get a socket connection to my workstation. Its pretty blasted awesome to be able to telnet into your DS and see what you type into your computer appear on the screen. Its several magnitudes more awesome to use the DS touchscreen and keys to remotely manipulate a 3D chaotic system in realtime. Add the ability to pipe recorded audio data from the DS microphone over the network and into that system where the fourier-tranformed signal is then used to modulate said system, and you might as well be dividing by zero.
UPDATE 2009.06.07:
After butting heads with the maintainers of devkitPro on the forum (they deleted a few of my posts because they don't like people telling users to downgrade or linking to obsolete libraries -- support headaches) who said the examples worked fine in r26, I pulled the source code for dswifi 0.3.7 and 0.3.8 than ran diff against the versions, excluding the svn nonsense:
diff -urNp -x '*svn*' dswifi-src-0.3.7 dswifi-src-0.3.8 > dswifi.patch
Thanks to diff and a little persistence reading through the patch file, I found exactly where my problem was originating.
Remember how I said I had MAC address filtering enabled on my router? Well recent changes to dswifi did indeed break the example, for me at least... the MAC address bytes were being read from the firmware but written to a main data structure incorrectly:
for(i=0;i<3;i++) WifiData->MacAddr[i]= ReadFlashByte(0x36+i) + (ReadFlashByte(0x36+i+1)<<8);
This loop doesn't write the data to MacAddr as intended. After the loop, MacAddr is filled with the bytes from the following firmware addresses : 0x36, 0x37, 0x37, 0x38, 0x38, 0x39. The intention is obviously to write the bytes from 0x36, 0x37, 0x38, 0x39, 0x40, 0x41. Simple mistake, simple solution. I notified the maintainers, so when you download devkitPro r27, you can thank me when connecting to APs with MAC address filtering. =)
ADDENDUM 2009.06.16:
A fix for the MAC address bug in dswifi was submitted to the devkitPro svn on June 11th. The maintainers built new distributions of three libraries the same day. So if you get the following versions of libnds, dswifi and default arm7, your DS' MAC will be properly presented to access points:
libnds 1.3.5
dswifi 0.3.9
default arm7 0.5.4
Way to go, devkitPro.
You can see the full discourse on the forums here.
With this issue now past tense, I'll work on posting a PART 2 of this article with some actually useful programming information.
Tags: chaos, devkitpro, dswifi, NintendoDS, programming
I’m writing a telnet client w/ keyboard pretty much like how you have set up. Trying to figure out the WEP stuff. Glad you caught that bug though! Is part 2 going to have examples on how to do this? I’m having trouble finding good documentation for the DSwifi library and all of its functions.
Hey funkadil, thanks for a valid comment amongst all the russian spam bots. Indeed, when I finish the series I will post the NDS client code as well as the PC host code. It should be pretty good. As far as the WEP stuff, there weren’t any good examples out there, so I had to take a stab in the dark with my code and just hope it worked. My knife sank deep in some valid WEP authentication with DSWifi.
The jist of it is that when you call Wifi_ConnectAP(…) the 4th parameter is the WEP key _bytes_, not the string representation of the bytes. Each character in a WEP key is a hex value that spans 4 bits, so you need to take two successive characters, convert each from character to bit representaton, and pack these two into a unsigned byte. Continue this until the terminating null of the string represenation of the WEP key is hit. You can then tell by the number of characters converted what type of WEP key it is. If it is 10 characters, it is a 40-bit key, if it is 26 characters, it is a 104-bit key. Strangely and quite confusingly, DSWifi defines WEPMODE_40BIT and WEPMODE_128BIT. One defined as the length excluding the initialization vector, and one defined as the length including the initialization vector. Very odd. Regardless, 10 char = WEPMODE_40BIT and 26 char = WEPMODE_128BIT. Hope this helps in the interim. I got a bit derailed on the project… you’ll see why.