DSWifi
Loading...
Searching...
No Matches
Library design

DSWifi is a library that runs on the ARM9 and ARM7 simultaneously, and it has a fundamentally asynchronous design. The ARM9 sends commands to the ARM7 using shared RAM, and the ARM7 eventually handles the commands. This design is consistent with how WiFi works: some actions require a long time to complete, sometimes up to a few seconds!

The ARM7 can do several operations without intervention from the ARM9. It can look for access points and connect to them. It can act as an access point (when acting as a multiplayer host) and accept and deny connections. This means that, in practice, the ARM9 sets the desired state of the ARM7 and the ARM7 performs steps in the direction that will reach the desired state of the ARM9.

1. Library modes

The library supports three global modes:

  • Internet mode.
  • Local multiplayer host.
  • Local multiplayer client.

It also supports other internal modes:

  • Disabled: The WiFi hardware is powered off.
  • Normal/Idle: The WiFi hardware is powered on, but not doing anything. This is the only mode in which the library can switch between the three global modes. If a library mode change is requested, it will first go to normal mode.
  • Scan: DSWifi is iterating through all channels looking for access points. In Internet mode it lists all available APs. In local multiplayer client mode it only lists APs with Nintendo metadata. Note that the list of APs is cleared whenever scan mode is entered.
  • Associate: DSWifi is trying to connect to an AP (either in Internet mode or in local multiplayer mode).
  • Associated: DSWifi has managed to connect to the AP.
  • Can't associate: DSWifi has failed to connect to the AP. The library must return to normal mode before attempting another connection.
  • Access point: The DS is acting as an access point. This mode can only be used when DSWifi is acting as a local multiplayer host.

2. Transmitting and receiving packets

As an initial explanation: DSWifi has three queues in regular RAM, and two in WiFi MAC RAM.

Both the ARM9 and ARM7 can transmit packets. The ARM7 sends management packets and manages the responses. For example, this is done to connect to APs, and to let other DS devices connect to a DS acting as host. If the ARM9 had to handle the connection handshake it would be much less efficient.

2.1 TX packets

When transmitting packets generated by the ARM7, they are saved to a temporary buffer (at the moment, this buffer can only hold one packet).

When transmitting packets from the ARM9 they are saved in a circular buffer in shared memory between the ARM7 and ARM9. Then, the ARM9 sends a sync FIFO message to the ARM7 to notify it that there are packets in that buffer.

The ARM7 has priority transmitting packets over the ARM9. If there is any packet in the ARM7 queue, that one will be transmitted over the ones waiting to be transmitted from the ARM9.

Regardless of the origin, in the end, the packet is copied to MAC RAM, and the transfer is started. After the transmission is complete, an interrupt is generated, and the ARM7 checks the queues again. Only one packet is ever copied to MAC RAM at any point.

When a transfer is requiested, the WiFi hardware modifies some fields in the packet header (like the duration) and it transfers it.

2.2 RX packets

When receiving packets, they are saved by the hardware in MAC RAM in a circular buffer. When packets are received, an interrupt is triggered, and the ARM7 starts handling them.

Some packets are handled directly by the ARM7 and they are never sent to the ARM9 (authentication and beacon packets, for example). Data packets are saved to a circular buffer in shared RAM between ARM7 and ARM9. Whenever a packet is saved to this buffer, the ARM7 sends a sync FIFO message to the ARM9 to notify it. Eventually, the ARM9 will check the buffer and handle it.

When in Internet mode, data packets are sent to sgIP. When in multiplayer mode, data packets are sent to the packet handlers defined by the developer.

2.3 Beacon packets

When in multiplayer host mode, it is required to regularly send beacon packets. This packet is generated on the ARM9 and sent to the ARM7 using the regular TX queues, but it isn't sent by the ARM7 as usual. It is saved in a specific part of MAC RAM reserved for beacon packets. The hardware regularly sends this packet without any kind of DSWifi intervention.

2.4 Multiplayer packets

CMD packets are handled like regular ARM9 packets, only the hardware transmission step is different.

REPLY packets are different. There are two memory regions in MAC RAM reserved for REPLY packets. They are independent from the TX buffer region, so a multiplayer client can still send regular messages while a REPLY packet is ready to be sent.

Multiplayer packets are handled like regular data packets when they are received. They are sent to the ARM9 using the same queue as regular data packets.

3. Debug messages of DSWifi

DSWifi can send debug messages from the ARM7 to the ARM9 with different information about the status of the library and potential errors. The debug messages are disabled in release builds of the library, you need to link the debug version of DSWifi if you want to check them.

In the ARM9 you need to setup a libnds console. Then, assign it to the ARM7:

consoleArm7Setup(&myConsole, 1024);

You don't need to modify anything in the ARM7 code. However, in your ARM7 Makefile you need to link with libdswifi7d.a instead of libdswifi7.a. Look for LIBS and replace -ldswifi7 by -ldswifi7d.

If you have an ARM9-only project, you will need to convert it to a combined ARM7 + ARM9 project. Currently BlocksDS doesn't distribute any default ARM7 binary with debug DSWifi messages.

4. Connecting to APs

The WiFi hardware of the DS isn't fully compatible with the IEEE 802.11b standard. It only supports 1 and 2 Mbit/s transfer rates, and it doesn't support 5.5 and 11. However, some routers really don't like this.

When connecting to an AP the device needs to communicate the supported transfer rates. Initially, DSWifi tries to connect to them by being honest. However, it's fairly common that routers reject the connection with status code 18 "Association denied due to requesting station not supporting all data rates in the BSSBasicRateSet parameter, where BSS refers to basic service set".

It retries by lying and saying it supports 5.5 and 11 Mbit/s as well. This works because the AP retries with slower transfer rates if it doesn't get any response after sending a packet with the fast transfer rates.

Note that in multiplayer mode all communications are done at 2 Mbit/s, and there is no possibility of being rejected by the host because DSWifi can accept any client that only supports 1 and 2 Mbit/s.

5. Multiplayer mode design

The WiFI hardware of the DS supports an efficient way to transfer packets while in multiplayer mode. Normally, when sending packets between a device and an AP, it is needed to do a handshake. The transmitter sends a RTS (request to send) packet, the receiver sends a CTS (clear to send) packet, the transmitter sends the actual packet it wants to send, and the receiver sends an ACK (acknowledgement) packet. This handshake is okay when there are only two devices communicating, and DSWifi supports it, but it can really slow things down when multiple clients are connecting to the same underpowered device (like a DS).

In order to solve this issue, the DS supports sending packets using what DSWifi calls CMD/REPLY messages. With this system, the DS acting as host (which is just an AP) starts a contention free period (CFP). It sends a CF-Poll packet (CMD packet), and all clients connected to it send a CF-ACK packets as a response. The clients send the CF-ACK packets in order based on their association IDs (AID), this is done automatically by the hardware. Finally, when the last client has sent its data, the host sends a CF-ACK with no data to finalize the process. This process is more efficient than the 4-way handshake explained before because there are no handshakes between the initial CF-Poll and the last CF-ACK packets.

CMD packets can be sent like regular packets, but they require more setup. DSWifi needs to fill more fields in the header (and the body!) of the packet, and DSWifi needs to caclulate the duration of the transmission periods of host and clients. It also needs to setup a countdown timer that will cancel the process when it reaches 0.

A REPLY packet needs to be saved to WiFi RAM. Then, its address is written to a WiFi register. When the client determines it needs to send a message, it checks this register. If it's disabled, it will send an empty CF-ACK packet with no body. If this register is enabled, it will send the packet it points to.

6. IEEE 802.11 packet format

The format of WiFi packets is defined by the IEEE 802.11 standard. There's no point in documenting this in DSWifi as there are much better references that can be used. The main reference used to develop DSWifi after the creation of BlockDS is "802.11 Wireless Networks: The Definitive Guide" by Matthew Gast. This book has enough low-level information to develop everything that DSWifi needs. Another book that was used as reference is "IEEE 802.11 Handbook: A Designer's Companion" by Bob O'Hara, Al Petrick, but this book doesn't have enough low-level information to be used on its own.