DSWifi
Loading...
Searching...
No Matches
Internet mode guide

DSWifi supports Internet communications. However, DSi mode WiFi isn't supported yet, so it is restricted to open and WEP-encrypted networks. DSWifi includes the library lwIP to handle connections. It supports IPv4, as well as TCP and UDP.

1. Initialization

You can initialize the library in autoconnect mode or in manual connection mode. With autoconnect mode DSWifi will check the WiFi networks stored in the firmware of the console and it will try to connect to them:

#define WFC_CONNECT
Init library and try to connect to firmware AP.
Definition dswifi9.h:81
bool Wifi_InitDefault(unsigned int flags)
Initializes WiFi library.

However, this isn't very flexible. The function will simply wait until the connection works (or until the library times out). It will also make it impossible to switch between local multiplayer and Internet modes.

It's generally better to initialize the library in manual mode and to give the user the option to do different things. Initialize the library with this (it starts by default in Internet mode, not multiplayer mode):

#define INIT_ONLY
Init library only, don't try to connect to AP.
Definition dswifi9.h:84

If all you want to do is to use Internet mode you can use this to use the additional DSi WiFi capabilities (like WPA2 support):

#define WIFI_ATTEMPT_DSI_MODE
Try to initialize DSWiFi in DSi mode.
Definition dswifi9.h:51

Without WIFI_ATTEMPT_DSI_MODE the library will start in DS compatibility mode.

On the ARM7, hardware timer number LIBNDS_DEFAULT_TIMER_WIFI will be used by the WiFi library after this call. On the ARM9, hardware timer number LIBNDS_DEFAULT_TIMER_WIFI will also be used. Note that both numbers may be different.

1.1 Connect to WFC settings

You can start autoconnect mode by calling:

void Wifi_AutoConnect(void)
Connect to an Access Point specified by the WFC data in the firmware.

In this case, skip the step of manually looking for access points.

1.2 Manually look for access points

If you don't want to autoconnect to WFC settings you can manually look for access points like this, for example:

// Set the library in scan mode
while (1)
{
cothread_yield_irq(IRQ_VBLANK);
// Get find out how many APs there are in the area
int count = Wifi_GetNumAP();
printf("Number of AP: %d\n", count);
printf("\n");
for (int i = 0; i < count; i++)
{
Wifi_GetAPData(i, &ap);
// We get the name, channel, security type, and even a flag telling us
// that this AP is configured in the WFC settings of the console.
printf("[%.20s]%s\n", ap.ssid,
(ap.flags & WFLAG_APDATA_CONFIG_IN_WFC) ? " WFC" : "");
printf("%s | Channel %2d | RSSI %d\n",
ap.channel, ap.rssi);
printf("\n");
{
// This AP is supported in the current execution mode. WPA2 networks
// are only supported in DSi.
// ...
}
}
}
#define WFLAG_APDATA_CONFIG_IN_WFC
The WFC settings of the console have configuration data for this AP.
Definition dswifi_common.h:43
const char * Wifi_ApSecurityTypeString(Wifi_ApSecurityType type)
Returns a short string that describes the AP security type.
#define WFLAG_APDATA_COMPATIBLE
This AP is compatible with DSWiFI.
Definition dswifi_common.h:37
int Wifi_GetNumAP(void)
Returns the current number of APs that are known and tracked internally.
int Wifi_GetAPData(int apnum, Wifi_AccessPoint *apdata)
Grabs data from internal structures for user code (always succeeds).
void Wifi_ScanMode(void)
Makes the ARM7 go into scan mode and list Internet APs.
Structure that defines information about an Access Point.
Definition dswifi_common.h:229
u8 channel
Valid channels are 1-14.
Definition dswifi_common.h:238
u16 flags
Flags indicating various parameters for the AP.
Definition dswifi_common.h:245
s16 rssi
Running average of the recent RSSI values for this AP, will be set to 0 after not receiving beacons f...
Definition dswifi_common.h:243
Wifi_ApSecurityType security_type
Type of security used in this Access Point.
Definition dswifi_common.h:251
char ssid[33]
Name (SSID) of the Access Point. The max supported length is 32 characters, the last byte of the arra...
Definition dswifi_common.h:232

After you have decided which AP to connect to:

// Setting everything to 0 will make DHCP determine the IP address. You can also
// set the settings manually if you want.
Wifi_SetIP(0, 0, 0, 0, 0);
if (AccessPoint.flags & WFLAG_APDATA_CONFIG_IN_WFC)
{
// If the AP is known, use the password stored in the WFC settings
Wifi_ConnectWfcAP(&AccessPoint);
}
else
{
// This AP isn't in the WFC settings. If the access point requires a WEP/WPA
// password, ask the user to provide it. Note that you can still allow the
// user to call this function with an AP that is saved in the WFC settings,
// but the function will ignore the saved settings in the WFC configuration
// and use the provided password instead.
if (AccessPoint.security_type != AP_SECURITY_OPEN)
{
// WEP passwords can be 5 or 13 characters long, WPA passwords must be at
// most 64 characters long.
const char *password = "MyPassword123";
Wifi_ConnectSecureAP(&AccessPoint, (u8 *)password, strlen(password));
}
else
{
// Open network
Wifi_ConnectSecureAP(&AccessPoint, NULL, 0);
}
}
@ AP_SECURITY_OPEN
Open AP (no security).
Definition dswifi_common.h:90
int Wifi_ConnectWfcAP(Wifi_AccessPoint *apdata)
Connect to an AP that has been configured in the WFC settings.
int Wifi_ConnectSecureAP(Wifi_AccessPoint *apdata, const void *key, size_t key_len)
Connect to an Access Point.
void Wifi_SetIP(u32 IPaddr, u32 gateway, u32 subnetmask, u32 dns1, u32 dns2)
Set the DS's IP address and other IP configuration information.

Wifi_ConnectSecureAP() expects WEP keys as a string (usually called "ASCII" key). If you have an hexadecimal key you have to save it as a string of hexadecimal values. For example, 6162636465 needs to be passed to the function as { 0x61, 0x62, 0x63, 0x64, 0x65 }, not as "6162636465".

1.3 Wait until you connect to the AP

Regardless of which mode you used to start the connection to the AP, wait for the connection to be completed (or to fail!):

while (1)
{
cothread_yield_irq(IRQ_VBLANK);
int status = Wifi_AssocStatus();
{
// We can't connect to this host, try to connect to a different one!
}
if (status == ASSOCSTATUS_ASSOCIATED)
{
// Success!
}
}
int Wifi_AssocStatus(void)
Returns information about the status of connection to an AP.
@ ASSOCSTATUS_CANNOTCONNECT
Error in connecting... (COMPLETE if Wifi_ConnectAP was called to start)
Definition dswifi9.h:263
@ ASSOCSTATUS_ASSOCIATED
Connected! (COMPLETE if Wifi_ConnectAP was called to start)
Definition dswifi9.h:261

1.4 Disconnect from the AP

Eventually, when you want to leave this AP:

int Wifi_DisconnectAP(void)
Disassociate from the Access Point.

If you are done using wireless mode you can disable it to save power by calling:

void Wifi_DisableWifi(void)
Instructs the ARM7 to disengage wireless and stop receiving or transmitting.

If you aren't going to use DSWiFi again and you want to free up even more resources, you can call:

bool Wifi_Deinit(void)
Stops the WiFi library.

It will free all RAM used by the library and the hardware timers. You can call Wifi_InitDefault() at a later time to re-initialize it.

Important note: Wifi_Deinit() doesn't currently work after starting DSWiFi in Internet mode.

1.5 Notes about APs with hidden SSID

APs generally support an option to "hide" the network. This means that they don't openly broadcast their name, and they need to be probed before a client can connect to them.

DSWiFi supports hidden networks that are configured in the WFC settings, and it also supports connecting to networks if the user provides the SSID manually.

However, hiding the SSID isn't part of the WiFi standard. This blog post goes into more detail. The important part is:

‍(CWSP-206 2019) SSID hiding is a technique implemented by WLAN device manufacturers that will remove the information found in the SSID information element from Beacon management frames. Depending on the implementation, SSID hiding may also remove it from Probe Response frames sent from the AP.

APs that don't provide their SSID in their probe responses aren't supported by DSWiFi.

2. Get connection settings

You can get information like the IP address like this:

struct in_addr ip, gateway, mask, dns1, dns2;
ip = Wifi_GetIPInfo(&gateway, &mask, &dns1, &dns2);
printf("\n");
printf("Connection information:\n");
printf("\n");
printf("IP: %s\n", inet_ntoa(ip));
printf("Gateway: %s\n", inet_ntoa(gateway));
printf("Mask: %s\n", inet_ntoa(mask));
printf("DNS1: %s\n", inet_ntoa(dns1));
printf("DNS2: %s\n", inet_ntoa(dns2));
printf("\n");
struct in_addr Wifi_GetIPInfo(struct in_addr *pGateway, struct in_addr *pSnmask, struct in_addr *pDns1, struct in_addr *pDns2)
Returns IP information.

3. Use libc to access the Internet

3.1 Resolve host IPs

You can obtain the IP of a host like this:

const char *url = "www.wikipedia.com";
struct hostent *host = gethostbyname(url);
if (host)
printf("IP: %s\n", inet_ntoa(*(struct in_addr *)host->h_addr_list[0]));
else
printf("Could not get IP\n");

3.2 Communicate using sockets

You can create TCP or UDP sockets with:

socket(AF_INET, SOCK_STREAM, 0); // TCP
socket(AF_INET, SOCK_DGRAM, 0); // UDP

Then, you can use standard socket functions to use it, like connect(), write(), read(), send(), recv(), shutdown() and close().

Note that, by default, sockets start in blocking mode. You can switch to non-blocking mode with:

int opt = 1;
int rc = ioctl(my_socket, FIONBIO, (char *)&opt);

If you use non-blocking sockets, remember to call cothread_yield() or cothread_yield_irq() in your loop to give the socket thread CPU time.

Also, it is a good idea to check the value returned by Wifi_AssocStatus() every now and then to see if the connection is lost at some point.