DSi Wifi rev-engineering

Discussion of development of software for any "obsolete" computer or video game system. See the WSdev wiki and ObscureDev wiki for more information on certain platforms.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

DSi Wifi rev-engineering

Post by nocash »

I have just started rev-engineering DSi Wifi.

Some first findings: The SDIO code in browser is about 1200 lines, only ARM code (no THUMB code used). And even better: There seems to be only one function writing to SDIO_CMD, so it should be very easy to capture all SDIO traffic.

Placing a [4004800..4004aff]!!? breakpoint revealed that... the browser doesn't do any wifi traffic (not even wifi initialization) during the lengthy "Please wait" nag screen.

Anyways, for writing the SDIO data to a log file...

Does somebody know how to do file I/O on ARM7 side? I will need using Nintendo's file I/O functions for that (directly writing to SD/MMC ports would probably conflict with other browser functions). I am more or less familar with ARM9 file functions used in Launcher (and Browser may have same/similar functions), but it would be sub-optimal & uncomfortable to pass SDIO data from ARM7 to ARM9 only to have the file functions passing the data back from ARM9 to ARM7 for the actual SD/MMC writes.

PS.
If somebody never heard of DSi Wifi: The Nintendo DSi handheld has two Wifi interfaces: The old NDS interface for older games supports max 2Mbit/s with WEP encryption. The new DSi interface is accessed via SDIO bus and supports WPA2 and max 54Mbit/s. That new interface is yet another of those open source cases where nobody knows how to use it - hence the reverse-engineering.
The plan is to log all SDIO traffic to a log file while running DSi browser, and compare the log file against the SDIO/Wifi stuff that is already documented in gbatek.htm (the wifi hardware is mostly documented, it's just unknown how to use it via software).

EDIT:
I've also started some more general wifi-related side-threads here:
viewtopic.php?f=5&t=18427 - Wifi TKIP on WEP/RC4 hardware - is it really possible?
viewtopic.php?f=5&t=18372 - NTP - Network Time Protocol
viewtopic.php?f=5&t=18306 - Wifi and DHCP benchmarks?

And, I've meanwhile got WPA/WPA2 implemented and working on DSi:
http://problemkaputt.de/wifiboot.htm (binary and source code)
Last edited by nocash on Sun Mar 31, 2019 3:12 am, edited 1 time in total.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

Btw. the DSi wifi hardware was discovered to exist (and to have open source code available) about 2-3 years ago.
The source code should consist of "driver" and "firmware" code.
So far, I've examined only the low-level "firmware" part, and hoped that some HLL coders would figure out the "driver" part. Though I am meanwhile pessimistic that anybody would do that. But...

If somebody would want to help on examining the "driver" source code:
That would be wonderful! And if you like messing with open source - now is your last chance to do so!

What you need to know to get started: The DSi uses Atheros AR6002 wifi chips (aka "hw2") (or some later revisions, which must be backwards compatible with AR6002, else earlier DSi games couldn't use it, because they have the "driver" stored in the ROM image).

Atheros has released many different source code versions (without trying to maintain backwards compatibility; they were supposedly assuming that people would update both driver and firmware; but, as said above, the DSi can't update drivers).

The source code closest to DSi wifi "firmware" that I've found is called "AR6kSDK.build_sw.18" - so you would need the corresponding "driver" source code for that version.

Theoretically, there would be no further reverse-engineering needed if only somebody could find & compile that source code. Or if you need help implementing the DSi-specific SDIO interface, let me know!

The DSi's SDIO registers at 4004A00h-4004BFFh are already well known. The WMI commands/events used by the Atheros firmware are also well known. The problem is that these commands/events seem to cover only wifi initialization - that means there's only one small detail missing: It's unknown how to do any actual wifi data transfers.
And, it looks as if there's also some extra handshaking on SDIO bus (apart from the command/event stuff) (so the whole interface would consist of commands/events + handshakes + data packets) (supposedly distinguished by some small header in the SDIO transfer blocks).

---

Apart from source code... One interesting detail found in the browser is that it's containing code for both DATA16 and DATA32 FIFO's (of which, I had thought that DATA32 wouldn't work properly with the DSi's SDIO hardware).
The DATA32 stuff is part of the SDIO_CMD function. Whilst DATA16 is used in the SDIO IRQ handler. Not sure if/how that can co-exist, maybe it's using only DATA16 or only DATA32 (or has some method to switch between both modes).
Hmmm, DATA16 is used for byte-wise RAM access with manual 16bit I/O. And DATA32 uses NDMA. So the latter is probably used for fast transfer of larger blocks (and, as it's using NDMA, requires multiple of 4 bytes).
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: DSi Wifi rev-engineering

Post by calima »

The old staging ath6kl Linux driver had support for AR6002. You can download the code here:
http://ftp.dei.uc.pt/pub/linux/kernel/p ... h6kl.patch
User avatar
PypeBros
Posts: 34
Joined: Sat Nov 10, 2018 7:35 am

Re: DSi Wifi rev-engineering

Post by PypeBros »

nocash wrote: The source code closest to DSi wifi "firmware" that I've found is called "AR6kSDK.build_sw.18" - so you would need the corresponding "driver" source code for that version.
like http://svn.openmoko.org/trunk/src/targe ... w.18/host/ ?

Btw, I'm not very familiar with the DSi specific hardware ... Am I right guessing that SDIO is a bus towards the SD/MMC card interface that happens to be be connected to a WiFi chip as well ? (possibly using an alternate device identifier ?)
Image - may the source be with you.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

calima wrote:The old staging ath6kl Linux driver had support for AR6002. You can download the code here:
http://ftp.dei.uc.pt/pub/linux/kernel/p ... h6kl.patch
That looks more like a change log than actual code. But yeah, something like that should be right.
Yes, that looks good. And, that seems to be the "driver" side that would run on the ARM CPU, so that's right, too.

There are several AR6002 firmware/driver versions, it would be best to use a matching "driver" for the DSi.
The "build_sw.18" is close, but not perfect. As far as I remember it does use 0047h as WMI command number for WMI_SET_MAC_ADDRESS_CMD, whilst DSi is using F003h instead (one of the many cases where they've screwed up the enumeration for the WMI command numbers).
On the other hand, "build_sw.18" does match up with the response structure for WMI_REPORT_STATISTICS_EVENT, so it's pretty close.

Well, maybe it isn't so important to find perfectly matching source code, one could fix minor details like enum's manually. More important would be the bigger picture: What kind of stuff is transferred, and how does it distinguish between command and data blocks? And how does it connect to an access point at all (I don't even know if the firmware can do that automatically, or if one has to manually send/receive wifi packets to the access point).
PypeBros wrote:Btw, I'm not very familiar with the DSi specific hardware ... Am I right guessing that SDIO is a bus towards the SD/MMC card interface that happens to be be connected to a WiFi chip as well ? (possibly using an alternate device identifier ?)
Yes, very similar. The SD/MMC controller is at ARM7:4004800h-400490Fh (used for eMMC and SD/MMC-slot), and the SDIO controller is using an identical set of registers at ARM7:4004A00h-4004B0Fh (used for Wifi only). The main difference is that the two controllers are wired to different hardware, apart from that they are nearly identical.

SDIO is mainly using CMD52 and CMD53 (instead of the CMD's used for reading/writing sectors on SD/MMC). Plus a few more CMD's like CMD3,CMD5,CMD7 - but that are needed only during initialization.

The Wifi hardware has BMI (initialization) and WMI (actual use) commands. The BMI stuff is done by the Launcher (and also supported by unlaunch), so the only missing part is to figure out how to do the WMI stuff.
I suspect that most of it is sent via the MBOXes (or maybe everything via MBOX0 only). Plus polling some SDIO registers to detect whether there's any incoming MBOX data available.

In the source code, there's "hif" and "htc2".
Looks as if "hif" is SDIO, which would need to be slightly customized for DSi.
And "htc2" might be what's still missing - ie. it might contain header bytes that distinguish between things like command and data?
User avatar
PypeBros
Posts: 34
Joined: Sat Nov 10, 2018 7:35 am

Re: DSi Wifi rev-engineering

Post by PypeBros »

Yes, very similar. The SD/MMC controller is at ARM7:4004800h-400490Fh (used for eMMC and SD/MMC-slot), and the SDIO controller is using an identical set of registers at ARM7:4004A00h-4004B0Fh (used for Wifi only). The main difference is that the two controllers are wired to different hardware, apart from that they are nearly identical.

SDIO is mainly using CMD52 and CMD53 (instead of the CMD's used for reading/writing sectors on SD/MMC). Plus a few more CMD's like CMD3,CMD5,CMD7 - but that are needed only during initialization.
oh yeah! I remember these. There was an extension to the SD/MMC standard that described how to interact with other hardware, and some of Y2K personal digital assistants were using either SD or compact flash cards to augment their features with WiFi.
Image

edit: have you had a look at the SDIO specifications already ? in the wireless LAN addendum, I've been surprised to see references to "HTTP transfer" commands. So apparently, the SDIO card may have a full network stack aboard and some RAM from which it pulls and pushes content from the Internet, pretending that these are mere file on a virtual storage device. (or it might not have been done that way on the DSi)
sdio-cmd52.png
edit again: in the same document, we see that the Fxxx commands are "vendor-specific" extensions to the SDIO commands set. Unknown whether 'vendor' is AR6002 manufacturer or Nintendo themselves ...
Image - may the source be with you.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

Yes, the DSi wifi hardware is alike wifi SDIO card (in the middle of the photo), except it's in daughterboard form, not card-shaped.

SDIO itself is all around CMD52/CMD53, and the standarized CCCR/FBR/CIS registers in "Function 0" space (that are for detecting the hardware and for some basic configuration like SDIO bus width).
I've described that general stuff in the "SDIO Protocol" section in this chapter: http://problemkaputt.de/gbatek.htm#dsis ... andioports

Apart from the SDIO bus standard, the SDIO makers seem to have tried to establish standards for specific SDIO devices like UART, GPS, Camera, and WLAN (as listed in FBR chapter). But I think you can completely forget about that. The DSi's Atheros hardware is marked as "No SDIO standard interface" in the FBR's "Interface Type" register, so I guess it isn't even remotely resembling the "SDIO WLAN interface" standard.
EDIT: Or is it similar? Atheros is referring to WMI commands F000h and up as "Developer commands", that sounds remotely like what you had said about Fxxxh being vendor specific commands. Ie. does the official SDIO WLAN standard have commands 0001h and up resembling Atheros commands like WMI_CONNECT_CMD etc.?

Instead, it's using the Atheros-specific WMI (and BMI) commands described here: http://problemkaputt.de/gbatek.htm#dsia ... ointerface (these are send via MBOX in SDIO "Function 1" space).

Well, and I've also documented most of the internal hardware, http://problemkaputt.de/gbatek.htm#dsia ... alhardware but that's only relevant if you wanted to disassemble the "firmware" part (and for a few cases where the "driver" part is peeking at those registers, eg. for checking the CHIP_ID at 0040ECh (when doing so, it's addressing that internal memory indirectly via WINDOW_READ_ADDR aka "Function 1:0047Ch")).

From what I've seen, the AR6002 is 100% made by Atheros - without any Nintendo-specific customizations in the hardware, nor in the ROM firmware, nor in the RAM firmware.
The later AR6013/AR6014 chips have some small Nintendo-specific customizations, but that's all happening behind your back (ie. DSi games can use those newer chips as if they were AR6002 chips).

---

On the hacking project: I've patched the browser's ARM9 code to write "Hello Test 123" into a "wifi-log.txt" file on SD card. So that's one milestone working. For doing similar writes while ARM7 is doing its SDIO stuff, I think I'll try to create a separate ARM9 thread for it via these browser functions:

Code: Select all

                 arm9_create_thread    equ 0205D478h+1  ;struct,proc,0,stack,C8h,1Fh
                 arm9_sleep_thread     equ 0205D6B0h+1  ;zero
The other options would be hooking the ARM9 main program (but I am not sure which main function(s) it's executiong during wifi connection/transfers), or doing it from inside an IRQ handler (but I guess one can't call the File functions from inside IRQ as they should rely on IRQs themselves).
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

The sleep_thread function wasn't quite right. And enable_thread worked, but did additionally require enable_thread. So I ended up with using this function set (for DSi Browser EUR version 00000001.app):

Code: Select all

arm9_file_open        equ 02056F64h  ;handle,filename,mode?
arm9_file_close       equ 02056FB0h  ;handle
arm9_file_read        equ 02057054h  ;handle,dst,len
arm9_file_write       equ 02057088h  ;handle,src,len
arm9_get_filesize     equ 02056FD4h  ;handle
arm9_file_seek        equ 0205703Ch  ;handle,offset,00h
arm9_file_create      equ 02056BD0h  ;filename,03h
arm9_file_delete      equ 02056C10h  ;filename
arm9_create_thread    equ 0205D478h  ;struct,proc,param_for_proc,stack,stacksize(C8h)?,type/prio(03h/1Fh)?
arm9_enable_thread    equ 0205D72Ch  ;struct
arm9_sleep_millisecs  equ 0205D84Ch  ;milliseconds
The sleep(milliseconds) seems to work just fine. Next steps are hooking ARM7... and writing CMD, PARAM, REPLY to memory... works, too... and writing data NumBlk's and BlkLen and actual data bytes (after waiting for DMA or IRQ transfer to complete)... works, too... whew, now all code fragments are complete : )

And putting it together... storing logged ARM7 data in a 64Kbyte ring buffer (or waiting if the buffer is full)... okay... moving the file functions into the ARM9 thread... writing 16Kbyte chunks to file once when the ring buffer contains enough data (or sleeping otherwise)... and writing the remaining fraction when pressing Button B... works, that's getting cool... and converting the binary data to ASCII strings right on ARM7 side; so one won't need post-processing tools for viewing the log file on PC... and, finally, show delays in number of frames (if it's been more than 1 frame since last command)...

Okay, it's all tested & working in no$gba! Here's the output from the SD card wifi-log.txt file from no$gba, starting with SDIO function 0 stuff with 1-byte transfers, and then followed by actual SDIO function 1 stuff with more data bytes in the last dozens of lines:

Code: Select all

No$2000 SDIO log (done without paying $2000 for a SD/SDIO hardware logging tool)

Cmd  Param    Reply    NumBlk x BlkLen Data bytes
----------------------------------------------------------
Delay 01D8
0434 04000900 00001000
0434 04000100 00001011
0434 04001300 00001000
0434 04001500 00001010
0434 04001700 00001000
0434 04200100 00001001
0434 04200300 00001003
0434 04200B00 00001020
0434 04200D00 00001004
0434 04200F00 00001071
0434 04201100 00001002
0434 04201300 00001000
0434 04201500 00001002
0434 04002500 00001003
0434 84002502 00001002
0434 04001100 00001017
0434 04200100 00001001
0434 04200300 00001003
0434 04200B00 00001020
0434 04200D00 00001004
0434 04201700 00001021
0434 04201900 00001002
0434 04201F00 00001022
0434 04202100 00001004
0434 04202300 00001000
0434 04202500 00001000
0434 04202700 00001008
0434 04202900 00001032
0434 84000F82 00001082
0434 84001117 00001017
0434 04020100 00001000
0434 04021300 00001000
0434 04021500 00001011
0434 04021700 00001000
0434 04220100 00001020
0434 04220300 00001004
0434 04220D00 00001021
0434 04220F00 00001002
0434 04221500 00001022
0434 04221700 0000102A
0434 04221900 00001001
0434 04221B00 00001001
0434 04221D00 00001011
0434 04221F00 00001000
0434 04222100 00001000
0434 04222300 00001000
0434 04222500 00001000
0434 04222700 00001000
0434 04222900 00001000
0434 04222B00 00001000
0434 04222D00 00001000
0434 04222F00 00001000
0434 04223100 00001000
0434 04223300 00001008
0434 04223500 00001000
0434 04223700 00001000
0434 04223900 000010FF
0434 04223B00 00001080
0434 04223D00 00001000
0434 04223F00 00001000
0434 04224100 00001000
0434 04224300 00001000
0434 04224500 00001001
0434 04224700 0000100A
0434 04224900 00001000
0434 04224B00 00001000
0434 04224D00 00001000
0434 04224F00 00001000
0434 04225100 00001000
0434 04225300 00001000
0434 04225500 00001000
0434 04225700 00001000
0434 04225900 00001000
0434 04225B00 00001000
0434 04225D00 00001000
0434 04225F00 00001001
0434 04226100 00001000
0434 04226300 00001001
0434 04226500 00001000
0434 04226700 00001001
0434 04226900 00001000
0434 04226B00 00001001
0434 04220100 00001020
0434 04220300 00001004
0434 04220500 00001071
0434 04220700 00001002
0434 04220900 00001000
0434 04220B00 00001002
0434 84022180 00001080
0434 84022300 00001000
0434 04220100 00001020
0434 04220300 00001004
0434 04220D00 00001021
0434 04220F00 00001002
0434 04221500 00001022
0434 04221700 0000102A
0434 04221900 00001001
0434 04221B00 00001001
0434 04221D00 00001011
0434 04221F00 00001000
0434 04222100 00001000
0434 04222300 00001000
0434 04222500 00001000
0434 04222700 00001000
0434 04222900 00001000
0434 04222B00 00001000
0434 04222D00 00001000
0434 04222F00 00001000
0434 04223100 00001000
0434 04223300 00001008
0434 04223500 00001000
0434 04223700 00001000
0434 04223900 000010FF
0434 04223B00 00001080
0434 04223D00 00001000
0434 04223F00 00001000
0434 04224100 00001000
0434 04224300 00001000
0434 04224500 00001001
0434 04224700 0000100A
0434 04224900 00001000
0434 04224B00 00001000
0434 04224D00 00001000
0434 04224F00 00001000
0434 04225100 00001000
0434 04225300 00001000
0434 04225500 00001000
0434 04225700 00001000
0434 04225900 00001000
0434 04225B00 00001000
0434 04225D00 00001000
0434 04225F00 00001001
0434 04226100 00001000
0434 04226300 00001001
0434 04226500 00001000
0434 04226700 00001001
0434 04226900 00001000
0434 04226B00 00001001
0434 04000500 00001002
0434 84000502 00001002
0434 04000700 00001002
4C35 94083004 00001000 0001x0004 00 00 00 00
4C35 9408FA03 00001000 0001x0003 40 00 00
4C35 9408F801 00001000 0001x0001 EC
5C35 1408E804 00001000 0001x0004 20 00 00 00
4C35 9408FA03 00001000 0001x0003 04 50 00
4C35 9408F801 00001000 0001x0001 58
5C35 1408E804 00001000 0001x0004 00 00 00 00
5C35 1408A004 00001000 0001x0004 00 00 00 00
4C35 941FF804 00001000 0001x0004 08 00 00 00
5C35 141FF804 00001000 0001x0004 00 00 00 00
5C35 141FF804 00001000 0001x0004 F7 47 7C 03
5C35 141FF008 00001000 0001x0008 FF FF FF FF 94 B0 FD 02
5C35 1408A004 00001000 0001x0004 00 00 00 00
4C35 941FE010 00001000 0001x0010 03 00 00 00 00 04 50 00 04 00 00 00 02 00 00 00
5C35 1408A004 00001000 0001x0004 00 00 00 00
4C35 941FF008 00001000 0001x0008 06 00 00 00 C0 80 01 00
5C35 141FF804 00001000 0001x0004 06 00 00 00
5C35 1408A004 00001000 0001x0004 00 00 00 00
4C35 941FE80C 00001000 0001x000C 07 00 00 00 C0 80 01 00 08 00 00 00
5C35 1408A004 00001000 0001x0004 00 00 00 00
4C35 941FF008 00001000 0001x0008 06 00 00 00 C4 40 00 00
5C35 141FF804 00001000 0001x0004 06 00 00 00
5C35 1408A004 00001000 0001x0004 00 00 00 00
4C35 941FE80C 00001000 0001x000C 07 00 00 00 C4 40 00 00 09 00 00 00
5C35 1408A004 00001000 0001x0004 00 00 00 00
4C35 941FE80C 00001000 0001x000C 07 00 00 00 28 40 00 00 05 00 00 00
5C35 1408A004 00001000 0001x0004 00 00 00 00
4C35 941FE80C 00001000 0001x000C 07 00 00 00 20 40 00 00 00 00 00 00
Delay 0072
4C35 94083004 00001000 0001x0004 00 00 00 00
5C35 14080010 00001000 0001x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4C35 94080004 00001000 0001x0004 00 00 00 00
5C35 14080010 00001000 0001x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0434 84000900 00001000
Wow, that's working super cool : ) If there are no unexpected timing problems, then it should work the same way on real hardware.

The above log is showing the browser dealing with the basic SDIO emulation in no$gba (ie. nothing really new as I had already figured out to emulate all that stuff; and no$gba could even already generate a similar log when activating "SD/MMC" logging in the TTY Debug window).
The two new findings are the two delays: The first one is the surreal boot delay (during which the browser refuses to do any browsing or anything useful at all). And the smaller two second delay at the end appears to be some timeout (where the browser dislikes my emulation and/or can't find an access point).

Before testing on hardware, I guess I'll first add some important cosmetic stuff:
Parsing the Parameter word to display Read/Write direction, and SDIO function number and address as "Read/Write Function[N:NNNNN]=Data", with Data extracted from param/reply in case of CMD52.
And especially, parsing the WINDOW_WRITE_ADDR and WINDOW_READ_ADDR stuff to something like "Read/Write AtherosMem[NNNNNNNN]=Data" in a single line (instead of displaying it as separate SDIO commands scattered across three lines).

EDIT: The CMD53 data reading is still bugged in above log. I've had screwed up waiting for IRQ-based transfer completion, so it showed bogus data. Fixing that, it turns out that I had hooked ARM7 code before IRQs got enabled in SDIO_IRQ_MASK. Doing the hook later on, there seem to be cases where IRQs are disabled in CPSR at time sending the SDIO command.
Hmmmm, I could try to force CPSR to enable IRQs for a moment (maybe without crashing everything), or I could try to call the transfer read/write handler manually without IRQs from inside of the hook function when needed. Well, that's for tomorrow.
But, the two cosmetic features mentioned above are already working : ) and it's much easier to read now (and to spot bugs like the above data read issue).
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

CPSR.IRQs are normally enabled, except in the last some commands after the timeout delay. I've tried to forcefully enable CPSR.IRQ for that cases, and it seems to work okay without crashing. Here's the new log output with cosmetic improvements:

Code: Select all

No$2000 SDIO log (done without paying $2000 for a SD/SDIO hardware logging tool)
Delay 01D7
Read  Func[0:00004] = 00
Read  Func[0:00000] = 11
Read  Func[0:00009] = 00
...(snip)...
Read  Func[0:01135] = 01
Read  Func[0:00002] = 02
Write Func[0:00002] = 02
Read  Func[0:00003] = 02
Write Func[1:00418] = Len:0001x0004 00 00 00 00
Read  Mem[000040EC] = 02000001
Read  Mem[00500458] = 00000000
Read  Func[1:00450] = Len:0001x0004 01 00 00 00
Write Func[1:00FFC] = Len:0001x0004 08 00 00 00
Read  Func[1:00FFC] = Len:0001x0004 FF FF FF FF
Read  Func[1:00FFC] = Len:0001x0004 0C 00 00 00
Read  Func[1:00FF8] = Len:0001x0008 88 01 00 20 02 00 00 00
Read  Func[1:00450] = Len:0001x0004 01 00 00 00
Write Func[1:00FF0] = Len:0001x0010 03 00 00 00 00 04 50 00 04 00 00 00 02 00 00 00
Read  Func[1:00450] = Len:0001x0004 01 00 00 00
Write Func[1:00FF8] = Len:0001x0008 06 00 00 00 C0 80 01 00
Read  Func[1:00FFC] = Len:0001x0004 00 00 00 00
Read  Func[1:00450] = Len:0001x0004 01 00 00 00
Write Func[1:00FF4] = Len:0001x000C 07 00 00 00 C0 80 01 00 08 00 00 00
Read  Func[1:00450] = Len:0001x0004 01 00 00 00
Write Func[1:00FF8] = Len:0001x0008 06 00 00 00 C4 40 00 00
Read  Func[1:00FFC] = Len:0001x0004 08 00 00 00
Read  Func[1:00450] = Len:0001x0004 01 00 00 00
Write Func[1:00FF4] = Len:0001x000C 07 00 00 00 C4 40 00 00 09 00 00 00
Read  Func[1:00450] = Len:0001x0004 01 00 00 00
Write Func[1:00FF4] = Len:0001x000C 07 00 00 00 28 40 00 00 05 00 00 00
Read  Func[1:00450] = Len:0001x0004 01 00 00 00
Write Func[1:00FF4] = Len:0001x000C 07 00 00 00 20 40 00 00 00 00 00 00
Delay 0072
Write Func[1:00418] = Len:0001x0004 00 00 00 00
Read  Func[1:00400] = Len:0001x0010 00 00 00 00 0F 00 0F 00 00 00 00 00 00 00 00 00
Write Func[1:00400] = Len:0001x0004 00 00 00 00
Read  Func[1:00400] = Len:0001x0010 00 00 00 00 0F 00 0F 00 00 00 00 00 00 00 00 00
Write Func[0:00004] = 00
The old CMD+PARAM+REPLY are completely removed (unless the browser would happen to send anything other than CMD52/CMD53).
The two "Read Mem[NNNNNNNN]" lines are reading CHIP_ID and a RAM word from atheros memory space.
The "Write Func[1:00Fxx]" lines are writing BMI commands through MBOX0, that are only a few BMI commands; for firmware detect/start (the actual BMI firmware upload was already done earlier, by the launcher).
And at the "Delay 0072" location, the wifi unit should supposedly start to respond something, and the browser should then start to send WMI commands & try to connect to the access point - now it's time to test this on real hardware...
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

Here's the first DSi wifi hardware log:
wifi-log.txt
(364.36 KiB) Downloaded 897 times
The DSi browser is doing a WEP connection to access point with SSID "ead" with password "dslink-dslink" and, because of security concerns, the console's MAC address is shown by using "mm" bytes as placeholder (and "aa" and "bb" for access point and bssid). After completing the connection, I've entered "problemkaputt.de" as WWW address, waited for the page to be displayed, and then quit logging. The DSi wifi board contains a AR6013G chip. Oh, and the logging tool is now also showing data as ASCII characters, additionally to the HEX bytes.

I think that's everything needed to reverse-engineer how to use the wifi hardware, if some idiot takes the time take the log file apart, then all details should unfold in next some weeks (the idiot is me, probably, but everybody else is very welcome to join in).

Some quick observations: I had expected a large "delay" without traffic while typing "problemkaputt.de", but there's no such delay showing up. Reason is probably that the browser is permanently sending whatever data to "nintendowifi.net", now I wonder if Opera on PC is doing such things, too. Well, I guess all modern software is doing that.

One oddity is that I can't find the html text from the http://problemkaputt.de/index.htm page in the log (eg. no link to "gba.htm" found in the log). On the other hand, the .gif files from my homepage are showing up in the log (with the "GIF87a" header, followed by 'monochrome' 24bit palette entries). Oh, and yeah, the server for my homepage seems to be currently having 50% downtime, but it was working when doing the wifi log.

So the overall file-transfer logging seems to work, it's only the index.htm page not appearing in the log... hmmm, that could be some problem with DMA-completion timing for larger packets (although that should be handled by the logging tool), or maybe the browser had cached the index.htm page somewhere from a previous connection, or the htm got compressed somehow?
Last edited by nocash on Thu Nov 29, 2018 1:37 pm, edited 2 times in total.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: DSi Wifi rev-engineering

Post by tepples »

Does the Gzip header (1F 8B 08) appear in the logs? Does "Content-Encoding: gzip" appear in the logs? Does the browser have a "clear cache" or "reload" option?
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

Thanks, yes, "1F 8B 08" is in one of the large packets, right after the first "GET" from problemkaputt.de.
That explains why the html text isn't visible.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

I've made a new log, difference is that it's logging only SDIO Writes this time, that's making things a bit more compact.
Well, and then I've spent some necrophile amount of time on hand-editing the log:
- inserted WMI command names
- removed padding bytes (to 80h-byte boundaries)
- merged HEX bytes with "ASCII" strings

One obvious thing is that there are three types writes, with meaning depending on first byte:
- 00h = unknown (occurs only in first six writes after the BMI commands)
- 01h = WMI command
- 02h = Data packet
Then the second byte is unknown, sometimes this or that.
The next two bytes are length.
The next two bytes are unknown, often zero, and sometimes related to command 002Eh:2008h or other stuff?
That six-byte header is then followed by "length" bytes (eg. containing the WMI command number and parameters).

Note: Below might look better without line-wrapping (eg. copy/paste and view in a text editor without wrapping to see a "summary", or view with wrapping to see all details with parameters).

Code: Select all

No$2000 SDIO log (done without paying $2000 for a SD/SDIO hardware logging tool)
 Showing WRITES (after leading BMI commands) from DSi browser with AR6013G chip
 aa aa aa aa aa aa = Access Point
 bb bb bb bb bb bb = Router
 mm mm mm mm mm mm = DSi Console
 "ead"               SSID
 "dslink-dslink"     WEP password
Write Func[1:00F80] = Len:0001x0080 00 00 08 00 00 00 0002   (unknown init?)                    00 01 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 00 00 08 00 00 00 0002   (unknown init?)                    01 01 05 00 00 00
Write Func[1:00F80] = Len:0001x0080 00 00 08 00 00 00 0002   (unknown init?)                    02 01 05 00 00 00
Write Func[1:00F80] = Len:0001x0080 00 00 08 00 00 00 0002   (unknown init?)                    03 01 05 00 00 00
Write Func[1:00F80] = Len:0001x0080 00 00 08 00 00 00 0002   (unknown init?)                    04 01 05 00 00 00
Write Func[1:00F80] = Len:0001x0080 00 00 02 00 00 00 0004   (unknown init??)                   -
Write Func[1:00418] = Len:0001x0004 D1 00 03 01
Write Func[0:00004] = 03
Write Mem[0052B2A0] = 00000002
Write Func[1:00F80] = Len:0001x0080 01 01 06 00 00 00 0022 WMI_TARGET_ERROR_REPORT_BITMASK_CMD  7F 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 06 00 00 00 0047 WMI_SET_FRAMERATES_CMD               02 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 06 00 00 00 0022 WMI_TARGET_ERROR_REPORT_BITMASK_CMD  7F 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 02 00 00 00 000E WMI_GET_CHANNEL_LIST_CMD             -
Write Func[1:00F80] = Len:0001x0080 01 01 25 00 00 00 000A WMI_SET_PROBED_SSID_CMD              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 08 00 00 00 0011 WMI_SET_CHANNEL_PARAMS_CMD           00 00 02 01 6C 09
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0008 WMI_SET_SCAN_PARAMS_CMD              FF FF FF FF FF FF 6A 00 6A 00 00 01 6A 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               01 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0007 WMI_START_SCAN_CMD                   00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00
Delay 0003+0003
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 25 00 00 00 000A WMI_SET_PROBED_SSID_CMD              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 08 00 00 00 0011 WMI_SET_CHANNEL_PARAMS_CMD           00 00 02 01 6C 09
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0008 WMI_SET_SCAN_PARAMS_CMD              FF FF FF FF FF FF 6A 00 6A 00 00 01 6A 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               01 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0007 WMI_START_SCAN_CMD                   00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00
Delay 0004
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 25 00 00 00 000A WMI_SET_PROBED_SSID_CMD              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 08 00 00 00 0011 WMI_SET_CHANNEL_PARAMS_CMD           00 00 02 01 6C 09
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0008 WMI_SET_SCAN_PARAMS_CMD              FF FF FF FF FF FF 6A 00 6A 00 00 01 6A 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               01 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0007 WMI_START_SCAN_CMD                   00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00
Delay 0002+0002+0002
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 25 00 00 00 000A WMI_SET_PROBED_SSID_CMD              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 08 00 00 00 0011 WMI_SET_CHANNEL_PARAMS_CMD           00 00 02 01 76 09
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0008 WMI_SET_SCAN_PARAMS_CMD              FF FF FF FF FF FF 6B 00 6B 00 00 01 6B 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               01 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0007 WMI_START_SCAN_CMD                   00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00
Delay 0004
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 25 00 00 00 000A WMI_SET_PROBED_SSID_CMD              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 08 00 00 00 0011 WMI_SET_CHANNEL_PARAMS_CMD           00 00 02 01 76 09
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0008 WMI_SET_SCAN_PARAMS_CMD              FF FF FF FF FF FF 6B 00 6B 00 00 01 6B 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               01 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0007 WMI_START_SCAN_CMD                   00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00
Delay 0005
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 25 00 00 00 000A WMI_SET_PROBED_SSID_CMD              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 08 00 00 00 0011 WMI_SET_CHANNEL_PARAMS_CMD           00 00 02 01 80 09
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0008 WMI_SET_SCAN_PARAMS_CMD              FF FF FF FF FF FF 6F 00 6F 00 00 01 6F 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               01 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0007 WMI_START_SCAN_CMD                   00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00
Delay 0004+0002
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 25 00 00 00 000A WMI_SET_PROBED_SSID_CMD              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 08 00 00 00 0011 WMI_SET_CHANNEL_PARAMS_CMD           00 00 02 01 8A 09
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0008 WMI_SET_SCAN_PARAMS_CMD              FF FF FF FF FF FF 70 00 70 00 00 01 70 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               01 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0007 WMI_START_SCAN_CMD                   00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 01 00 00 00 00 00 00 00
Delay 0003
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 06 00 00 00 0022 WMI_TARGET_ERROR_REPORT_BITMASK_CMD  7F 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 0A 00 00 00 0009 WMI_SET_BSS_FILTER_CMD               00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 25 00 00 00 000A WMI_SET_PROBED_SSID_CMD              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 16 00 00 00 0008 WMI_SET_SCAN_PARAMS_CMD              FF FF FF FF FF FF C8 00 C8 00 00 05 C8 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 08 00 00 00 0011 WMI_SET_CHANNEL_PARAMS_CMD           00 00 02 01 85 09
Write Func[1:00F80] = Len:0001x0080 01 01 05 00 00 00 F000 WMI_SET_BITRATE_CMD                  FF 00 00
Write Func[1:00F80] = Len:0001x0080 01 01 06 00 00 00 0048 WMI_SET_AP_PS_CMD                    01 A4 F7 FF
Write Func[1:00F80] = Len:0001x0080 01 01 03 00 00 00 0004 WMI_SYNCHRONIZE_CMD                  00
Write Func[1:00F80] = Len:0001x0080 01 01 03 00 00 00 0012 WMI_SET_POWER_MODE_CMD               02
Write Func[1:00F80] = Len:0001x0080 01 01 03 00 00 00 0004 WMI_SYNCHRONIZE_CMD                  00
Write Func[1:00F80] = Len:0001x0080 01 01 41 00 00 00 0005 WMI_CREATE_PSTREAM_CMD               14 00 00 00 14 00 00 00 7F 96 98 00 FF FF FF FF 00 00 00 00 00 45 01 00 00 45 01 00 00 45 01 00 00 00 00 00 00 00 00 00 80 8D 5B 00 00 20 00 00 00 00 00 00 D0 80 D0 00 00 02 FF 01 00 05 00
Write Func[1:00F80] = Len:0001x0080 01 01 03 00 00 00 0041 WMI_SET_WSC_STATUS_CMD               00
Write Func[1:00F80] = Len:0001x0080 01 01 03 00 00 00 000D WMI_SET_DISCONNECT_TIMEOUT   (_CMD)  02
Write Func[1:00F80] = Len:0001x0080 01 01 2F 00 00 00 0016 WMI_ADD_CIPHER_KEY_CMD               00 02 03 0D 00 00 00 00 00 00 00 00 "dslink-dslink" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
Write Func[1:00F80] = Len:0001x0080 01 01 2F 00 08 20 0016 WMI_ADD_CIPHER_KEY_CMD               01 02 01 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
Write Func[1:00F80] = Len:0001x0080 01 01 2F 00 00 00 0016 WMI_ADD_CIPHER_KEY_CMD               02 02 01 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
Write Func[1:00F80] = Len:0001x0080 01 01 2F 00 00 00 0016 WMI_ADD_CIPHER_KEY_CMD               03 02 01 0D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03
Write Func[1:00F80] = Len:0001x0080 01 01 03 00 00 00 003D WMI_SET_KEEPALIVE_CMD                00
Write Func[1:00F80] = Len:0001x0080 01 01 36 00 00 00 0001 WMI_CONNECT_CMD                      01 02 01 02 00 02 00 03 "ead" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 85 09 aa aa aa aa aa aa 00 00 00 00
Delay 0006+0007+001E+0006
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 02 00 00 00 00 00 00 00
Delay 0009+0002+000E
Write Func[1:00E80] = Len:0003x0080 02 00 60 01 00 00 0000   (data)                             FF FF FF FF FF FF mm mm mm mm mm mm 01 50 AA AA 03 00 00 00 08 00 45 00 01 48 00 01 00 00 80 11 39 A5 00 00 00 00 FF FF FF FF 00 44 00 43 01 34 CE 2E 01 01 06 00 5E 20 82 7D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 mm mm mm mm mm mm 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 35 01 01 3D 07 01 mm mm mm mm mm mm 0C 0A "NintendoDS" 37 03 01 03 06 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Delay 0009
Write Func[1:00F80] = Len:0001x0080 01 01 41 00 00 00 0005 WMI_CREATE_PSTREAM_CMD               00 00 00 00 00 00 00 00 88 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 FF 06
Delay 0002+0003+0013
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 03 00 00 00 00 00 00 00
Delay 000C
Write Func[1:00E80] = Len:0003x0080 02 00 60 01 00 00 0000   (data)                             FF FF FF FF FF FF mm mm mm mm mm mm 01 50 AA AA 03 00 00 00 08 00 45 00 01 48 00 02 00 00 80 11 39 A4 00 00 00 00 FF FF FF FF 00 44 00 43 01 34 57 64 01 01 06 00 A6 CA 35 B2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 mm mm mm mm mm mm 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 35 01 03 3D 07 01 mm mm mm mm mm mm 0C 0A "NintendoDS" 37 03 01 03 06 32 04 C0 A8 01 1E 36 04 C0 A8 01 01 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Delay 002E
Write Func[1:00F80] = Len:0001x0080 02 00 34 00 00 00 1C00   (special data?)                    FF FF FF FF FF FF mm mm mm mm mm mm 00 24 AA AA 03 00 00 00 08 06 00 01 08 00 06 04 00 01 mm mm mm mm mm mm C0 A8 01 1E 00 00 00 00 00 00 C0 A8 01 1E
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 04 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 02 00 34 00 00 00 1C00   (special data?)                    FF FF FF FF FF FF mm mm mm mm mm mm 00 24 AA AA 03 00 00 00 08 06 00 01 08 00 06 04 00 01 mm mm mm mm mm mm C0 A8 01 1E 00 00 00 00 00 00 C0 A8 01 01
Delay 0005
Write Func[1:00F80] = Len:0001x0080 02 00 34 00 00 00 1C00   (special data?)                    FF FF FF FF FF FF mm mm mm mm mm mm 00 24 AA AA 03 00 00 00 08 06 00 01 08 00 06 04 00 01 mm mm mm mm mm mm C0 A8 01 1E 00 00 00 00 00 00 C0 A8 01 1E
Write Func[1:00F80] = Len:0001x0080 02 01 5F 00 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 4F AA AA 03 00 00 00 08 00 45 00 00 47 00 03 00 00 80 11 B7 33 C0 A8 01 1E C0 A8 01 01 12 E6 00 35 00 33 C1 41 F7 83 01 00 00 01 00 00 00 00 00 00 08 "conntest" 0C "nintendowifi" 03 "net" 00 00 01 00 01
Write Func[1:00F80] = Len:0001x0080 02 00 48 00 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 38 AA AA 03 00 00 00 08 00 45 00 00 30 00 04 00 00 80 06 A8 58 C0 A8 01 1E 45 19 8B 8C 12 E7 00 50 47 B7 F9 BF 00 00 00 00 70 02 0B 68 91 01 00 00 02 04 05 50 01 01 04 02
Delay 0007+0003
Write Func[1:00F80] = Len:0001x0080 02 00 34 00 00 00 1C00   (special data?)                    bb bb bb bb bb bb mm mm mm mm mm mm 00 24 AA AA 03 00 00 00 08 06 00 01 08 00 06 04 00 02 mm mm mm mm mm mm C0 A8 01 1E bb bb bb bb bb bb C0 A8 01 01
Write Func[1:00F80] = Len:0001x0080 01 01 41 00 00 00 0005 WMI_CREATE_PSTREAM_CMD               00 00 00 00 00 00 00 00 88 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 FF 01
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 05 00 00 80 06 A8 5F C0 A8 01 1E 45 19 8B 8C 12 E7 00 50 47 B7 F9 C0 9E C7 66 EE 50 10 0B 68 B7 9B 00 00
Write Func[1:00F00] = Len:0002x0080 02 01 86 00 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 76 AA AA 03 00 00 00 08 00 45 00 00 6E 00 06 00 00 80 06 A8 18 C0 A8 01 1E 45 19 8B 8C 12 E7 00 50 47 B7 F9 C0 9E C7 66 EE 50 18 0B 68 59 55 00 00 GET / HTTP/1.0Host: conntest.nintendowifi.netConnection: close
Delay 000A
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 07 00 00 80 06 A8 5D C0 A8 01 1E 45 19 8B 8C 12 E7 00 50 47 B7 FA 06 9E C7 68 62 50 11 09 F5 B7 53 00 00
Write Func[1:00F80] = Len:0001x0080 02 01 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 08 00 00 80 06 A8 5C C0 A8 01 1E 45 19 8B 8C 12 E7 00 50 47 B7 FA 06 9E C7 68 62 50 10 0B 68 B5 E1 00 00
Delay 000A
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 09 00 00 80 06 A8 5B C0 A8 01 1E 45 19 8B 8C 12 E7 00 50 47 B7 FA 07 00 00 00 00 50 04 00 00 C8 7E 00 00
Delay 0012
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 05 00 00 00 00 00 00 00
Delay 003B
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 06 00 00 00 00 00 00 00
Delay 003B
Write Func[1:00F80] = Len:0001x0080 02 00 34 00 00 00 1C00   (special data?)                    FF FF FF FF FF FF mm mm mm mm mm mm 00 24 AA AA 03 00 00 00 08 06 00 01 08 00 06 04 00 01 mm mm mm mm mm mm C0 A8 01 1E 00 00 00 00 00 00 C0 A8 01 01
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 07 00 00 00 00 00 00 00
Delay 000F+0021+000C
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 08 00 00 00 00 00 00 00
Delay 0026+0004+0010
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 09 00 00 00 00 00 00 00
Delay 000C+0005+002A
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 0A 00 00 00 00 00 00 00
Delay 003C
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 0B 00 00 00 00 00 00 00
Delay 0029+0013
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 0C 00 00 00 00 00 00 00
Delay 0020+001C
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 0D 00 00 00 00 00 00 00
Delay 003B
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 0E 00 00 00 00 00 00 00
Delay 003B
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 0F 00 00 00 00 00 00 00
Delay 0020+001B
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 10 00 00 00 00 00 00 00
Delay 003C
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 11 00 00 00 00 00 00 00
Delay 0005+0007+0024
Write Func[1:00F80] = Len:0001x0080 01 01 41 00 08 20 0005 WMI_CREATE_PSTREAM_CMD               00 00 00 00 00 00 00 00 88 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 FF 06
Delay 0006+0005
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 12 00 00 00 00 00 00 00
Delay 000A+0030
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 13 00 00 00 00 00 00 00
Delay 000A+0003+000C+0023
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 14 00 00 00 00 00 00 00
Delay 000D+000A+001B+000A
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 15 00 00 00 00 00 00 00
Delay 000C+000A+0014+0011
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 01 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 16 00 00 00 00 00 00 00
Delay 000D+0009+0014+0004+000D
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 17 00 00 00 00 00 00 00
Delay 000D+0004+0005+0015+000D
Write Func[1:00F80] = Len:0001x0080 02 00 56 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 46 AA AA 03 00 00 00 08 00 45 00 00 3E 00 0A 00 00 80 11 B7 35 C0 A8 01 1E C0 A8 01 01 12 E8 00 35 00 2A 68 A0 00 01 01 00 00 01 00 00 00 00 00 00 0D "problemkaputt" 02 "de" 00 00 01 00 01
Write Func[1:00F80] = Len:0001x0080 02 00 48 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 38 AA AA 03 00 00 00 08 00 45 00 00 30 00 0B 00 00 80 06 DE 62 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 7B 74 00 00 00 00 70 02 80 00 FD F7 00 00 02 04 05 50 01 01 04 02
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 0C 00 00 80 06 DE 69 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 7B 75 21 7A 6C 94 50 10 80 00 9C 39 00 00
Write Func[1:00E00] = Len:0004x0080 02 01 BF 01 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 01 AF AA AA 03 00 00 00 08 00 45 00 01 A7 00 0D 00 00 80 06 DC E9 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 7B 75 21 7A 6C 94 50 18 80 00 A8 12 00 00 GET / HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Connection: Keep-Alive
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 01 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 18 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 0E 00 00 80 06 DE 67 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 7C F4 21 7A 72 54 50 10 7A 40 9A BA 00 00
Delay 000C+0008
Write Func[1:00D80] = Len:0005x0080 02 00 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 0F 00 00 80 06 DC 86 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 7C F4 21 7A 72 54 50 18 7A 40 04 7A 00 00 GET /char-f.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00F80] = Len:0001x0080 02 00 48 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 38 AA AA 03 00 00 00 08 00 45 00 00 30 00 10 00 00 80 06 DE 5D C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 70 7B 00 00 00 00 70 02 80 00 31 94 00 00 02 04 05 50 01 01 04 02
Write Func[1:00D80] = Len:0005x0080 02 01 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 11 00 00 80 06 DC 84 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 7E D4 21 7A 74 27 50 18 78 6D FA 99 00 00 GET /char-n.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 12 00 00 80 06 DE 63 C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 70 7C 0E B3 15 F9 50 10 80 00 39 38 00 00
Delay 0002
Write Func[1:00D80] = Len:0005x0080 02 01 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 13 00 00 80 06 DC 82 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 80 B4 21 7A 76 06 50 18 76 8E 05 BA 00 00 GET /char-a.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00D80] = Len:0005x0080 02 00 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 14 00 00 80 06 DC 81 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 82 94 21 7A 77 DA 50 18 74 BA FF D9 00 00 GET /char-e.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Delay 0003
Write Func[1:00D80] = Len:0005x0080 02 00 1D 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 0D AA AA 03 00 00 00 08 00 45 00 02 05 00 15 00 00 80 06 DC 83 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 84 74 21 7A 79 A8 50 18 72 EC 60 7D 00 00 GET /yep.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Delay 000B
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 16 00 00 80 06 DE 5F C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 86 51 21 7A 7B 57 50 10 71 3D 91 5D 00 00
Delay 0005
Write Func[1:00D80] = Len:0005x0080 02 01 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 17 00 00 80 06 DC 7E C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 86 51 21 7A 7B 57 50 18 80 00 DD 59 00 00 GET /char-u.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00D80] = Len:0005x0080 02 00 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 18 00 00 80 06 DC 7D C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 70 7C 0E B3 15 F9 50 18 80 00 91 F7 00 00 GET /char-w.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00D80] = Len:0005x0080 02 00 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 19 00 00 80 06 DC 7C C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 72 5C 0E B3 17 D3 50 18 7E 26 95 17 00 00 GET /char-r.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00D80] = Len:0005x0080 02 00 21 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 11 AA AA 03 00 00 00 08 00 45 00 02 09 00 1A 00 00 80 06 DC 7A C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 74 3C 0E B3 19 AD 50 18 7C 4C 2C 32 00 00 GET /breath2.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 19 00 00 00 00 00 00 00
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 1B 00 00 80 06 DE 5A C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 76 1D 0E B3 24 4D 50 10 71 AC 33 97 00 00
Write Func[1:00F80] = Len:0001x0080 02 01 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 1D 00 00 80 06 DE 58 C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 77 FD 0E B3 2E ED 50 10 67 0C 31 B7 00 00
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 1E 00 00 80 06 DE 57 C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 77 FD 0E B3 39 8D 50 10 5C 6C 31 B7 00 00
Write Func[1:00D80] = Len:0005x0080 02 00 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 1C 00 00 80 06 DC 79 C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 76 1D 0E B3 24 4D 50 18 71 AC A3 F1 00 00 GET /nonazi.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 20 00 00 80 06 DE 55 C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 77 FD 0E B3 4B 9A 50 10 62 5F 19 B7 00 00
Write Func[1:00F80] = Len:0001x0080 02 01 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 21 00 00 80 06 DE 54 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 88 31 21 7A 7D 2A 50 10 7E 2D 80 BA 00 00
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 22 00 00 80 06 DE 53 C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 77 FD 0E B3 56 3A 50 10 57 BF 19 B7 00 00
Write Func[1:00F80] = Len:0001x0080 02 01 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 23 00 00 80 06 DE 52 C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 77 FD 0E B3 5C 7F 50 10 51 7A 19 B7 00 00
Delay 0002
Write Func[1:00D80] = Len:0005x0080 02 00 20 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 10 AA AA 03 00 00 00 08 00 45 00 02 08 00 24 00 00 80 06 DC 71 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 88 31 21 7A 7D 2A 50 18 7E 2D F1 14 00 00 GET /nonazi.gif HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailers
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 25 00 00 80 06 DE 50 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 8A 11 21 7A 87 CA 50 10 73 8D 7E DA 00 00
Write Func[1:00F80] = Len:0001x0080 02 01 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 26 00 00 80 06 DE 4F C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 8A 11 21 7A 92 6A 50 10 68 ED 7E DA 00 00
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 27 00 00 80 06 DE 4E C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 8A 11 21 7A 93 5F 50 10 80 00 66 D2 00 00
Delay 0006
Write Func[1:00F80] = Len:0001x0080 02 01 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 28 00 00 80 06 DE 4D C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 77 FD 0E B3 5C 7F 50 10 80 00 EB 30 00 00
Delay 0008
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 29 00 00 80 06 DE 4C C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 77 FD 0E B3 5C 7F 50 11 80 00 EB 2F 00 00
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 2A 00 00 80 06 DE 4B C0 A8 01 1E 58 C6 41 CE 12 EA 00 50 F1 DE 77 FE 0E B3 5C 80 50 10 80 00 EB 2E 00 00
Delay 0003
Write Func[1:00D80] = Len:0005x0080 02 01 21 02 00 00 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 02 11 AA AA 03 00 00 00 08 00 45 00 02 09 00 2B 00 00 80 06 DC 69 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 8A 11 21 7A 93 5F 50 18 80 00 65 41 00 00 GET /favicon.ico HTTP/1.1User-Agent: Opera/9.50 (Nintendo DSi; Opera/507; U; en-GB)Host: problemkaputt.deAccept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1Accept-Language: enAccept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0Referer: http://problemkaputt.de/Connection: Keep-Alive, TETE: deflate, gzip, chunked, identity, trailer
Write Func[1:00F80] = Len:0001x0080 02 00 40 00 08 20 0000   (data)                             bb bb bb bb bb bb mm mm mm mm mm mm 00 30 AA AA 03 00 00 00 08 00 45 00 00 28 00 2C 00 00 80 06 DE 49 C0 A8 01 1E 58 C6 41 CE 12 E9 00 50 1A 83 8B F2 21 7A 99 2D 50 10 7A 32 64 F1 00 00
Delay 0012+0009
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 1A 00 00 00 00 00 00 00
Delay 0023+0018
Write Func[1:00F80] = Len:0001x0080 01 01 0E 00 02 00 002E WMIX_HB_CHALLENGE_RESP_CMD           08 20 00 00 1B 00 00 00 00 00 00 00
Delay 0008+000B
Last edited by nocash on Sun Dec 02, 2018 4:22 am, edited 4 times in total.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

Here's a summary of the MBOX headers spotted in the log. Any ideas what the <Unknown> entries are good for? Or about the other "?" questions marks?

I have tried to find info about those MBOX headers in source code... but I couldn't anything useful... does somebody have more luck there?
File wmi.h contains some snippets that might be header fragments... but it's hard to tell which header bytes those snippets might refer to.

Code: Select all

DSi Atheros Wifi - MBOX Transfer Headers
----------------------------------------

MBOX transfers include a small header for distinguishing between Data Packets
and Commands/Events, and for indicating the actual length (as opposed to the
MBOX transfer length, which is usually garbage-padded to 80h-byte boundary).
The exception are BMI Bootloader commands/responses (which don't have such
headers or padding).

SDIO Functions used after BMI init
  Func[0:00005h]        R   1     Interrupt Flags (bit1=Function 1 IRQ)
  Func[1:00400h]        R   10h   Interrupt Status, etc.
  Func[1:00474h]        R   4     WINDOW DATA (uh, without prior ADDR ?)
  Func[1:00xxxh..00FFF] R/W ..    MBOX0

 ________________________________ Send Headers ________________________________

Header for Sending UNKNOWN Crap
  00h 1  Must be 00h for UNKNOWN Crap
  01h 1  <Unknown1>?? 00h
  02h 2  Length of entries [06h..end]
  04h 2  <Unknown4>?? 0000h
  06h 2  <Unknown6>?? 0002h or 0004h
  08h .. Unknown Parameters (if any)
DSi Browser is sending six such unknown crap things right after the BMI phase.
Purpose is totally unknown, however, one could just send the same crap without
knowning its purpose.

Header for Sending WMI Commands
  00h 1  Must be 01h for WMI Commands
  01h 1  <Unknown1>?? 01h
  02h 2  Length of entries [06h..end]
  04h 2  <Unknown4>?? 0000h, or 0101h/0002h/0102h=HB, or 2008h=2ndCipherKey???
  06h 2  WMI Command Number
  08h .. Parameters (plus leading 4-byte command suffix if CMD=002Eh:000020xxh)
Unknown4 looks kinda random/garbage (eg. 2008h occurs in 2nd CIPHER_KEY, and in
4th PSTREAM command), in so far it's apparently unrelated to the current
command (however, it might be a reply/ack for some previous stuff?).

Header for Sending DATA Packets
  00h 1  Must be 02h for DATA Packets
  01h 1  <Unknown1>?? 00h or 01h        ;maybe two "channels" for simult. GETs?
  02h 2  Length of entries [06h..end]
  04h 2  <Unknown4>?? 0000h or 2008h    ;maybe related to cmd 002Eh:2008h ?
  06h 2  <Unknown6>?? 0000h or 1C00h    ;maybe whatever ?
  08h 6  Destination (MAC Addr of Router) (or FF:FF:FF:FF:FF:FF=Broadcast)
  0Eh 6  Source      (MAC Addr of DSi console)
  14h 2  Length of entries [16h..end]
  16h .. Data (usually starting with LLC stuff, ie. AAh,AAh,03h,00h...)

 ______________________________ Receive Headers ______________________________

Header for Receiving UNKNOWN Crap
  00h 1  Must be 00h for UNKNOWN Crap
  01h .. <Unknown1>?? 00h
DSi Browser is receiving six such unknown crap things right after the BMI
phase. Purpose is totally unknown, however, one could just sent same replies as
being used by the DSi browser.
Moreover, DSi Browser is receiving MORE such unknown crap every once and then,
maybe containing ACKs or other handshake info?

Header for Receiving WMI Events
  00h 1  Must be 01h for WMI Events
  01h 1  <Unknown1>?? 02h    ;EDIT: actually 00h or 02h
  02h 2  Length of entries [06h..end]
  04h 2  <Unknown4>?? 0008h, 000Ch, or FF08h
  06h 2  WMI Event Number
  08h .. Parameters

Header for Receiving DATA Packets
  00h 1  Must be 02h for DATA Packets
  01h 1  <Unknown1>?? 00h or 01h or 02h   ;EDIT: actually always 02h
  02h 2  Length of entries [06h..end]
  04h 2  <Unknown4>?? 0000h, 0008h, 000Ch, 2008h, 7F08h, F408h, F40Ch, FF08h
  06h 1  RSSI (Received Signal Strength Indicator) (00h..3Ch) (aka 0..60)
  07h 1  <Unknown7> 00h
  08h 6  Whatever Address (MAC Addr of Router)        ;\or sometimes swapped?
  0Eh 6  Whatever Address (MAC Addr of DSi console)   ;/
  14h 2  Length of entries [16h..end]
  16h .. Data (usually LLC stuff, ie. AAh,AAh,03h.. or, once F0h,F0h,03h..??)
The send/receive DATA headers are apparently containing incomplete wifi "Frame Headers":
-- without 3rd address field
-- without WEP entries (those are apparently automatically inserted)
-- without Frame Control, Duration/ID, Sequence Control
-- in lack of Frame Control, there seem to be only Data Frames (no Managment/Control Frames)
Unless some of the missing info would be encoded in the <Unknown> header entries.
Last edited by nocash on Sat Dec 01, 2018 2:51 am, edited 3 times in total.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: DSi Wifi rev-engineering

Post by nocash »

I've edited the above post: Byte[01h] for Receive/Event and Receive/Data was wrong. And [06h] for Receive/Data, I had listed 0000h and 1C00h, but that wrong (those values show up only on Sending, not on Receiving; ie. the receive actual values were 0033h..0039h).

For that Receive/Data Byte[06h], Stephen Stair suggested that the values in range 33h..39h might be RSSI (Received Signal Strength Indicator), and that looks just right: Several webpages say that atheros uses 00h..3Ch (0..60) as RSSI range, so 33h..39h would be a strong signal (distance between DSi and Access Point was around 50cm). After walking 4 meters away and hiding behind a cupboard, the values dropped to 13h..24h. So, that's confirmed to be RSSI, at least 6bits, or maybe it's zeropadded to 8bits or even 16bits.
Post Reply