From f3c04907f11d5a6f6d11428b988316b6618d6f46 Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Mon, 12 Jan 2026 10:05:33 +0100 Subject: [PATCH 1/9] Add WD implementation. --- Makefile | 2 +- gc/ogc/wd.h | 106 ++++++++++++++++++++++++++ libogc/wd.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 gc/ogc/wd.h create mode 100644 libogc/wd.c diff --git a/Makefile b/Makefile index f2f058f7..61432aed 100644 --- a/Makefile +++ b/Makefile @@ -152,7 +152,7 @@ OGCOBJ := \ console_font_8x16.o timesupp.o lock_supp.o usbgecko.o usbmouse.o \ sbrk.o malloc_lock.o kprintf.o stm.o aes.o sha.o ios.o es.o isfs.o usb.o network_common.o \ sdgecko_io.o sdgecko_buf.o gcsd.o argv.o network_wii.o wiisd.o conf.o usbstorage.o \ - texconv.o wiilaunch.o sys_report.o + texconv.o wiilaunch.o wd.o sys_report.o #--------------------------------------------------------------------------------- MODOBJ := freqtab.o mixer.o modplay.o semitonetab.o gcmodplay.o diff --git a/gc/ogc/wd.h b/gc/ogc/wd.h new file mode 100644 index 00000000..a7215abd --- /dev/null +++ b/gc/ogc/wd.h @@ -0,0 +1,106 @@ +/*----------------------------------------------------------------------- + + wd.h -- Wireless Driver Implementation. + + Copyright: + + - (C) 2025-2026 B. Abdelali (Abdelali221) (Author) + - (C) 2008 Dolphin Emulator Project (For providing data structures) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +-----------------------------------------------------------------------*/ + +#ifndef __WD_H_ +#define __WD_H_ +#include + +#define SSID_LENGTH 32 +#define BSSID_LENGTH 6 + +enum MODES +{ + Unintialized = 0, + DSCommunications = 1, + NA0 = 2, + AOSSAPScan = 3, + NA1 = 4, + NA2 = 5, + NA3 = 6 +}; + +typedef struct WDInfo +{ + u8 MAC[6]; + u16 EnableChannelsMask; + u16 NTRallowedChannelsMask; + u8 CountryCode[4]; + u8 channel; + u8 initialized; + u8 version[80]; + u8 unknown[48]; +} WDInfo; + +typedef struct ScanParameters +{ + u16 ChannelBitmap; + u16 MaxChannelTime; + u8 BSSID[BSSID_LENGTH]; + u16 ScanType; + + u16 SSIDLength; + u8 SSID[SSID_LENGTH]; + u8 SSIDMatchMask[6]; + +} ScanParameters; + +typedef struct BSSDescriptor +{ + u16 length; + u16 RSSI; + u8 BSSID[6]; + u16 SSIDLength; + u8 SSID[32]; + u16 Capabilities; + struct + { + u16 basic; + u16 support; + } rateSet; + u16 beacon_period; + u16 DTIM_period; + u16 channel; + u16 CF_period; + u16 CF_max_duration; + u16 element_info_length; + u16 element_info[1]; +} BSSDescriptor; + +s32 NCD_LockWirelessDriver(); +u32 NCD_UnlockWirelessDriver(s32 lockid); +int WD_Init(u8 mode); +void WD_Deinit(); +int WD_GetInfo(WDInfo* inf); +u8 WD_GetRadioLevel(BSSDescriptor* Bss); +int WD_Scan(ScanParameters *settings, u8* buff, u16 buffsize); +int WD_ScanOnce(ScanParameters *settings, u8* buff, u16 buffsize); +void WD_SetDefaultScanParameters(ScanParameters* set); + +#endif \ No newline at end of file diff --git a/libogc/wd.c b/libogc/wd.c new file mode 100644 index 00000000..40af6fb9 --- /dev/null +++ b/libogc/wd.c @@ -0,0 +1,211 @@ +/*----------------------------------------------------------------------- + + wd.h -- Wireless Driver Implementation. + + Copyright (C) 2025-2026 B. Abdelali (Abdelali221) + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +-----------------------------------------------------------------------*/ + +#include "wd.h" +#include "ipc.h" +#include +#include +#include +#include +#include + +#define WD_HEAP_SIZE 0x1000 + +extern void usleep(u32 t); + +s32 wd_fd = -1; +s32 wd_heap = -1; + +s32* WD_GetWork() { + return &wd_fd; +} + +u8 NCDcommonbuff[0x20] __attribute__((aligned(32))); +s32 NCDheap; + +s32 NCD_LockWirelessDriver() { + s32 NCD = IOS_Open("/dev/net/ncd/manage", 0); + + memset(NCDcommonbuff, 0, 0x20); + + ioctlv vector = {0}; + vector.data = NCDcommonbuff; + vector.len = 0x20; + + IOS_Ioctlv(NCD, 1, 0, 1, &vector); + + s32 lockid = 0; + memcpy(&lockid, NCDcommonbuff, 4); + + IOS_Close(NCD); + NCD = -1; + + return lockid; +} + +u32 NCD_UnlockWirelessDriver(s32 lockid) { + s32 NCD = IOS_Open("/dev/net/ncd/manage", 0); + if (NCD < 0) return -1; + + u8 NCDresult[0x20] __attribute__((aligned(32))); + memcpy(NCDresult, &lockid, 4); + + ioctlv vectors[2] = {0}; + vectors[1].data = NCDresult; + vectors[1].len = 4; + vectors[0].data = NCDcommonbuff; + vectors[0].len = 0x20; + + IOS_Ioctlv(NCD, 2, 1, 1, vectors); + + u32 ret; + memcpy(&ret, NCDresult, 4); + + IOS_Close(NCD); + + NCD = -1; + return ret; +} + +s32 WD_CreateHeap() { + s32 heap; + u32 level; + + _CPU_ISR_Disable(level); + heap = iosCreateHeap(WD_HEAP_SIZE); + _CPU_ISR_Restore(level); + + return heap; +} + +void WD_SetDefaultScanParameters(ScanParameters* set) { + set->ChannelBitmap = 0xfffe; + set->MaxChannelTime = 100; // 100 ms + + memset(set->BSSID, 0xff, BSSID_LENGTH); + + set->ScanType = 0; + set->SSIDLength = 0; + + memset(set->SSID, 0x00, SSID_LENGTH); + memset(set->SSIDMatchMask, 0xff, 6); +} + +int WD_Init(u8 mode) { + if(wd_fd < 0) { + wd_fd = IOS_Open("/dev/net/wd/command", 0x10000 | mode); + if (wd_fd < 0) return -1; + } + return 0; +} + +void WD_Deinit() { + if(wd_fd < 0) return; + + u32 level; + + _CPU_ISR_Disable(level); + IOS_Close(*WD_GetWork()); + wd_fd = -1; + _CPU_ISR_Restore(level); +} + +u8 WD_GetRadioLevel(BSSDescriptor* Bss) { + u8 ret; + + if (Bss->RSSI < 0xc4) { + if (Bss->RSSI < 0xb5) { + if (Bss->RSSI < 0xab) { + ret = 0; + } else { + ret = 1; + } + } else { + ret = 2; + } + } else { + ret = 3; + } + return ret; +} + +int WD_GetInfo(WDInfo* info) { + s32 lockid = NCD_LockWirelessDriver(); + + if(WD_Init(AOSSAPScan) < 0) return -1; + + u8 inf[sizeof(WDInfo)] __attribute__((aligned(32))); + + ioctlv vector; + vector.data = inf; + vector.len = sizeof(WDInfo); + + IOS_Ioctlv(wd_fd, 0x100e, 0, 1, &vector); + memcpy(info, inf, sizeof(WDInfo)); + + WD_Deinit(); + NCD_UnlockWirelessDriver(lockid); + + return 0; +} + +int WD_Scan(ScanParameters *settings, u8* buff, u16 buffsize) { + if(wd_fd < 0) return -1; + + u8 buf[buffsize + 2] __attribute__((aligned(32))); + u8 settingsbuf[0x4e] __attribute__((aligned(32))); + + memset(settingsbuf, 0, 0x4e); + memset(buf, 0, buffsize + 2); + memcpy(settingsbuf, settings, 0x1a); + + ioctlv vectors[2]; + vectors[0].data = settingsbuf; + vectors[0].len = 0x4e; + vectors[1].data = buf; + vectors[1].len = buffsize; + + IOS_Ioctlv(wd_fd, 0x100a, 1, 1, vectors); + usleep(100000); + memcpy(buff, buf, buffsize); + + return 0; +} + +int WD_ScanOnce(ScanParameters *settings, u8* buff, u16 buffsize) { + s32 lockid = NCD_LockWirelessDriver(); + + if(WD_Init(AOSSAPScan) < 0) return -1; + usleep(100000); + + WD_Scan(settings, buff, buffsize); + + WD_Deinit(); + NCD_UnlockWirelessDriver(lockid); + + return 0; +} \ No newline at end of file From 21d2ef89b9e8c7e36a40c54e232ec18de530be47 Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Mon, 12 Jan 2026 10:16:37 +0100 Subject: [PATCH 2/9] Add a few comments + Get rid of some magic numbers. --- libogc/wd.c | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/libogc/wd.c b/libogc/wd.c index 40af6fb9..8b7b5cb2 100644 --- a/libogc/wd.c +++ b/libogc/wd.c @@ -33,7 +33,32 @@ #include #include -#define WD_HEAP_SIZE 0x1000 +//#define WD_HEAP_SIZE 0x1000 + +#define DEFAULT_CHANNEL_BITMAP 0xfffe + +enum WDIOCTLV +{ + IOCTLV_WD_INVALID = 0x1000, + IOCTLV_WD_GET_MODE = 0x1001, // WD_GetMode + IOCTLV_WD_SET_LINKSTATE = 0x1002, // WD_SetLinkState + IOCTLV_WD_GET_LINKSTATE = 0x1003, // WD_GetLinkState + IOCTLV_WD_SET_CONFIG = 0x1004, // WD_SetConfig + IOCTLV_WD_GET_CONFIG = 0x1005, // WD_GetConfig + IOCTLV_WD_CHANGE_BEACON = 0x1006, // WD_ChangeBeacon + IOCTLV_WD_DISASSOC = 0x1007, // WD_DisAssoc + IOCTLV_WD_MP_SEND_FRAME = 0x1008, // WD_MpSendFrame + IOCTLV_WD_SEND_FRAME = 0x1009, // WD_SendFrame + IOCTLV_WD_SCAN = 0x100a, // WD_Scan + IOCTLV_WD_CALL_WL = 0x100c, // WD_CallWL + IOCTLV_WD_MEASURE_CHANNEL = 0x100b, // WD_MeasureChannel + IOCTLV_WD_GET_LASTERROR = 0x100d, // WD_GetLastError + IOCTLV_WD_GET_INFO = 0x100e, // WD_GetInfo + IOCTLV_WD_CHANGE_GAMEINFO = 0x100f, // WD_ChangeGameInfo + IOCTLV_WD_CHANGE_VTSF = 0x1010, // WD_ChangeVTSF + IOCTLV_WD_RECV_FRAME = 0x8000, // WD_ReceiveFrame + IOCTLV_WD_RECV_NOTIFICATION = 0x8001 // WD_ReceiveNotification +}; extern void usleep(u32 t); @@ -45,7 +70,7 @@ s32* WD_GetWork() { } u8 NCDcommonbuff[0x20] __attribute__((aligned(32))); -s32 NCDheap; +//s32 NCDheap; s32 NCD_LockWirelessDriver() { s32 NCD = IOS_Open("/dev/net/ncd/manage", 0); @@ -90,8 +115,8 @@ u32 NCD_UnlockWirelessDriver(s32 lockid) { NCD = -1; return ret; } - -s32 WD_CreateHeap() { +/* +s32 WD_CreateHeap() { // Currently unused. s32 heap; u32 level; @@ -101,10 +126,11 @@ s32 WD_CreateHeap() { return heap; } +*/ void WD_SetDefaultScanParameters(ScanParameters* set) { - set->ChannelBitmap = 0xfffe; - set->MaxChannelTime = 100; // 100 ms + set->ChannelBitmap = DEFAULT_CHANNEL_BITMAP; + set->MaxChannelTime = 100; memset(set->BSSID, 0xff, BSSID_LENGTH); @@ -140,15 +166,15 @@ u8 WD_GetRadioLevel(BSSDescriptor* Bss) { if (Bss->RSSI < 0xc4) { if (Bss->RSSI < 0xb5) { if (Bss->RSSI < 0xab) { - ret = 0; + ret = 0; // Very Weak } else { - ret = 1; + ret = 1; // Weak } } else { - ret = 2; + ret = 2; // Medium } } else { - ret = 3; + ret = 3; // Strong } return ret; } @@ -164,7 +190,7 @@ int WD_GetInfo(WDInfo* info) { vector.data = inf; vector.len = sizeof(WDInfo); - IOS_Ioctlv(wd_fd, 0x100e, 0, 1, &vector); + IOS_Ioctlv(wd_fd, IOCTLV_WD_GET_INFO, 0, 1, &vector); memcpy(info, inf, sizeof(WDInfo)); WD_Deinit(); @@ -189,7 +215,7 @@ int WD_Scan(ScanParameters *settings, u8* buff, u16 buffsize) { vectors[1].data = buf; vectors[1].len = buffsize; - IOS_Ioctlv(wd_fd, 0x100a, 1, 1, vectors); + IOS_Ioctlv(wd_fd, IOCTLV_WD_SCAN, 1, 1, vectors); usleep(100000); memcpy(buff, buf, buffsize); @@ -200,7 +226,6 @@ int WD_ScanOnce(ScanParameters *settings, u8* buff, u16 buffsize) { s32 lockid = NCD_LockWirelessDriver(); if(WD_Init(AOSSAPScan) < 0) return -1; - usleep(100000); WD_Scan(settings, buff, buffsize); From e63114e09dfd353a55befae514afa97c0f47ce91 Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Sat, 17 Jan 2026 09:34:28 +0100 Subject: [PATCH 3/9] Add HW_RVL check. --- libogc/wd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libogc/wd.c b/libogc/wd.c index 8b7b5cb2..ae01088a 100644 --- a/libogc/wd.c +++ b/libogc/wd.c @@ -25,6 +25,8 @@ -----------------------------------------------------------------------*/ +#if defined(HW_RVL) + #include "wd.h" #include "ipc.h" #include @@ -233,4 +235,6 @@ int WD_ScanOnce(ScanParameters *settings, u8* buff, u16 buffsize) { NCD_UnlockWirelessDriver(lockid); return 0; -} \ No newline at end of file +} + +#endif \ No newline at end of file From 25f9cbe87d2a6c556edfa8c391090ba8ae355b68 Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Sat, 17 Jan 2026 10:58:42 +0100 Subject: [PATCH 4/9] Remove ISR calls in WD_Deinit() + Remove heap references + Pass wd_fd instead of WD_GetWork() in WD_Deinit(). --- libogc/wd.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/libogc/wd.c b/libogc/wd.c index ae01088a..c2b56096 100644 --- a/libogc/wd.c +++ b/libogc/wd.c @@ -35,8 +35,6 @@ #include #include -//#define WD_HEAP_SIZE 0x1000 - #define DEFAULT_CHANNEL_BITMAP 0xfffe enum WDIOCTLV @@ -65,14 +63,8 @@ enum WDIOCTLV extern void usleep(u32 t); s32 wd_fd = -1; -s32 wd_heap = -1; - -s32* WD_GetWork() { - return &wd_fd; -} u8 NCDcommonbuff[0x20] __attribute__((aligned(32))); -//s32 NCDheap; s32 NCD_LockWirelessDriver() { s32 NCD = IOS_Open("/dev/net/ncd/manage", 0); @@ -117,18 +109,6 @@ u32 NCD_UnlockWirelessDriver(s32 lockid) { NCD = -1; return ret; } -/* -s32 WD_CreateHeap() { // Currently unused. - s32 heap; - u32 level; - - _CPU_ISR_Disable(level); - heap = iosCreateHeap(WD_HEAP_SIZE); - _CPU_ISR_Restore(level); - - return heap; -} -*/ void WD_SetDefaultScanParameters(ScanParameters* set) { set->ChannelBitmap = DEFAULT_CHANNEL_BITMAP; @@ -154,12 +134,8 @@ int WD_Init(u8 mode) { void WD_Deinit() { if(wd_fd < 0) return; - u32 level; - - _CPU_ISR_Disable(level); - IOS_Close(*WD_GetWork()); + IOS_Close(wd_fd); wd_fd = -1; - _CPU_ISR_Restore(level); } u8 WD_GetRadioLevel(BSSDescriptor* Bss) { From bf54c607847cd811af6cc97ad630e2aae16ee99a Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Wed, 21 Jan 2026 18:44:58 +0100 Subject: [PATCH 5/9] Add IE (Information Elements) operations. GetLength, GetIE (Get the data), GetNumberOfIEs. --- gc/ogc/wd.h | 49 ++++++++++++++++++++++++++++++-- libogc/wd.c | 81 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 104 insertions(+), 26 deletions(-) diff --git a/gc/ogc/wd.h b/gc/ogc/wd.h index a7215abd..acd80d26 100644 --- a/gc/ogc/wd.h +++ b/gc/ogc/wd.h @@ -35,6 +35,35 @@ #define SSID_LENGTH 32 #define BSSID_LENGTH 6 +enum WDIOCTLV +{ + IOCTLV_WD_INVALID = 0x1000, + IOCTLV_WD_GET_MODE = 0x1001, // WD_GetMode + IOCTLV_WD_SET_LINKSTATE = 0x1002, // WD_SetLinkState + IOCTLV_WD_GET_LINKSTATE = 0x1003, // WD_GetLinkState + IOCTLV_WD_SET_CONFIG = 0x1004, // WD_SetConfig + IOCTLV_WD_GET_CONFIG = 0x1005, // WD_GetConfig + IOCTLV_WD_CHANGE_BEACON = 0x1006, // WD_ChangeBeacon + IOCTLV_WD_DISASSOC = 0x1007, // WD_DisAssoc + IOCTLV_WD_MP_SEND_FRAME = 0x1008, // WD_MpSendFrame + IOCTLV_WD_SEND_FRAME = 0x1009, // WD_SendFrame + IOCTLV_WD_SCAN = 0x100a, // WD_Scan + IOCTLV_WD_CALL_WL = 0x100c, // WD_CallWL + IOCTLV_WD_MEASURE_CHANNEL = 0x100b, // WD_MeasureChannel + IOCTLV_WD_GET_LASTERROR = 0x100d, // WD_GetLastError + IOCTLV_WD_GET_INFO = 0x100e, // WD_GetInfo + IOCTLV_WD_CHANGE_GAMEINFO = 0x100f, // WD_ChangeGameInfo + IOCTLV_WD_CHANGE_VTSF = 0x1010, // WD_ChangeVTSF + IOCTLV_WD_RECV_FRAME = 0x8000, // WD_ReceiveFrame + IOCTLV_WD_RECV_NOTIFICATION = 0x8001 // WD_ReceiveNotification +}; + +// Capability flags : + +#define CAPAB_SECURED_FLAG 0x10 + +// WD Modes : + enum MODES { Unintialized = 0, @@ -46,6 +75,8 @@ enum MODES NA3 = 6 }; +// WD Information : + typedef struct WDInfo { u8 MAC[6]; @@ -58,6 +89,8 @@ typedef struct WDInfo u8 unknown[48]; } WDInfo; +// Scan parameters : + typedef struct ScanParameters { u16 ChannelBitmap; @@ -71,6 +104,8 @@ typedef struct ScanParameters } ScanParameters; +// BSS Descriptor : + typedef struct BSSDescriptor { u16 length; @@ -89,18 +124,26 @@ typedef struct BSSDescriptor u16 channel; u16 CF_period; u16 CF_max_duration; - u16 element_info_length; - u16 element_info[1]; -} BSSDescriptor; + // IE -> Information Elements + u16 IEs_length; +} BSSDescriptor; + +// General Purpose : s32 NCD_LockWirelessDriver(); u32 NCD_UnlockWirelessDriver(s32 lockid); int WD_Init(u8 mode); void WD_Deinit(); int WD_GetInfo(WDInfo* inf); + +// AP Scan related : + u8 WD_GetRadioLevel(BSSDescriptor* Bss); int WD_Scan(ScanParameters *settings, u8* buff, u16 buffsize); int WD_ScanOnce(ScanParameters *settings, u8* buff, u16 buffsize); +u8 WD_GetNumberOfIEs(BSSDescriptor* Bss); +u8 WD_GetIELength(BSSDescriptor* Bss, u8 ID); +int WD_GetIE(BSSDescriptor* Bss, u8 ID, u8* buff, u8 buffsize); void WD_SetDefaultScanParameters(ScanParameters* set); #endif \ No newline at end of file diff --git a/libogc/wd.c b/libogc/wd.c index c2b56096..293bd272 100644 --- a/libogc/wd.c +++ b/libogc/wd.c @@ -37,29 +37,6 @@ #define DEFAULT_CHANNEL_BITMAP 0xfffe -enum WDIOCTLV -{ - IOCTLV_WD_INVALID = 0x1000, - IOCTLV_WD_GET_MODE = 0x1001, // WD_GetMode - IOCTLV_WD_SET_LINKSTATE = 0x1002, // WD_SetLinkState - IOCTLV_WD_GET_LINKSTATE = 0x1003, // WD_GetLinkState - IOCTLV_WD_SET_CONFIG = 0x1004, // WD_SetConfig - IOCTLV_WD_GET_CONFIG = 0x1005, // WD_GetConfig - IOCTLV_WD_CHANGE_BEACON = 0x1006, // WD_ChangeBeacon - IOCTLV_WD_DISASSOC = 0x1007, // WD_DisAssoc - IOCTLV_WD_MP_SEND_FRAME = 0x1008, // WD_MpSendFrame - IOCTLV_WD_SEND_FRAME = 0x1009, // WD_SendFrame - IOCTLV_WD_SCAN = 0x100a, // WD_Scan - IOCTLV_WD_CALL_WL = 0x100c, // WD_CallWL - IOCTLV_WD_MEASURE_CHANNEL = 0x100b, // WD_MeasureChannel - IOCTLV_WD_GET_LASTERROR = 0x100d, // WD_GetLastError - IOCTLV_WD_GET_INFO = 0x100e, // WD_GetInfo - IOCTLV_WD_CHANGE_GAMEINFO = 0x100f, // WD_ChangeGameInfo - IOCTLV_WD_CHANGE_VTSF = 0x1010, // WD_ChangeVTSF - IOCTLV_WD_RECV_FRAME = 0x8000, // WD_ReceiveFrame - IOCTLV_WD_RECV_NOTIFICATION = 0x8001 // WD_ReceiveNotification -}; - extern void usleep(u32 t); s32 wd_fd = -1; @@ -213,4 +190,62 @@ int WD_ScanOnce(ScanParameters *settings, u8* buff, u16 buffsize) { return 0; } +u8 WD_GetNumberOfIEs(BSSDescriptor* Bss) { + u8 ret = 0; + + u8* ptr = (u8*)Bss; + size_t offset = 0; + + for(; + offset < Bss->IEs_length && ptr[offset + 0x3F] != 0; + offset += ptr[offset + 0x3F]) + { + ret++; + } + + return ret; +} + +u8 WD_GetIELength(BSSDescriptor* Bss, u8 ID) { + if(ID > WD_GetNumberOfIEs(Bss)) return -1; + + + u16 IEslen = Bss->IEs_length; + + u8* ptr = (u8*)Bss; + size_t offset = 0; + + for(u8 IE = 0; + (IE < ID) && ((offset + ptr[offset + 0x3F]) < IEslen && ptr[offset + 0x3F] != 0); + offset += ptr[offset + 0x3F]) + { + IE++; + } + + return ptr[offset + 0x3F]; +} + +int WD_GetIE(BSSDescriptor* Bss, u8 ID, u8* buff, u8 buffsize) { + if(ID > WD_GetNumberOfIEs(Bss)) return -1; + + if(!buff) return -2; + + u16 IEslen = Bss->IEs_length; + + u8* ptr = (u8*)Bss; + size_t offset = 0; + + for(u8 IE = 0; + (IE < ID) && ((offset + WD_GetIELength(Bss, ID)) < IEslen && WD_GetIELength(Bss, ID) != 0); + offset += WD_GetIELength(Bss, ID)) + { + IE++; + } + + memset(buff, 0, buffsize); + memcpy(buff, &ptr[offset + 0x3F + 1], WD_GetIELength(Bss, ID)); + + return 0; +} + #endif \ No newline at end of file From 4a65ed76f40a8593e8b3459c8b138847578bc630 Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Thu, 22 Jan 2026 18:51:00 +0100 Subject: [PATCH 6/9] Full rewrite IE operations. The way I interpreted IEs was wrong, which lead to the code being absolutely useless and broken (The last commit happened because of the lack of tests). --- gc/ogc/wd.h | 17 +++++++++++++++-- libogc/wd.c | 47 ++++++++++++++++++++++++----------------------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/gc/ogc/wd.h b/gc/ogc/wd.h index acd80d26..972fbdb7 100644 --- a/gc/ogc/wd.h +++ b/gc/ogc/wd.h @@ -62,6 +62,12 @@ enum WDIOCTLV #define CAPAB_SECURED_FLAG 0x10 +// Information Elements IDs : + +#define IEID_SSID 0x0 +#define IEID_VENDORSPECIFIC 0xDD +#define IEID_SECURITY 0x30 + // WD Modes : enum MODES @@ -124,10 +130,17 @@ typedef struct BSSDescriptor u16 channel; u16 CF_period; u16 CF_max_duration; - // IE -> Information Elements u16 IEs_length; } BSSDescriptor; +// Information Element Header : + +typedef struct IE_hdr +{ + u8 ID; + u8 len; +} IE_hdr; + // General Purpose : s32 NCD_LockWirelessDriver(); @@ -142,7 +155,7 @@ u8 WD_GetRadioLevel(BSSDescriptor* Bss); int WD_Scan(ScanParameters *settings, u8* buff, u16 buffsize); int WD_ScanOnce(ScanParameters *settings, u8* buff, u16 buffsize); u8 WD_GetNumberOfIEs(BSSDescriptor* Bss); -u8 WD_GetIELength(BSSDescriptor* Bss, u8 ID); +int WD_GetIELength(BSSDescriptor* Bss, u8 ID, u8* len); int WD_GetIE(BSSDescriptor* Bss, u8 ID, u8* buff, u8 buffsize); void WD_SetDefaultScanParameters(ScanParameters* set); diff --git a/libogc/wd.c b/libogc/wd.c index 293bd272..e238b340 100644 --- a/libogc/wd.c +++ b/libogc/wd.c @@ -194,56 +194,57 @@ u8 WD_GetNumberOfIEs(BSSDescriptor* Bss) { u8 ret = 0; u8* ptr = (u8*)Bss; - size_t offset = 0; + IE_hdr* hdr = (IE_hdr*)&ptr[sizeof(BSSDescriptor)]; + u16 offset = 0; - for(; - offset < Bss->IEs_length && ptr[offset + 0x3F] != 0; - offset += ptr[offset + 0x3F]) + while(offset < Bss->IEs_length && hdr->len != 0 ) { + hdr = (IE_hdr*)&ptr[sizeof(BSSDescriptor) + offset]; + offset += hdr->len + sizeof(IE_hdr); ret++; } return ret; } -u8 WD_GetIELength(BSSDescriptor* Bss, u8 ID) { - if(ID > WD_GetNumberOfIEs(Bss)) return -1; - - +int WD_GetIELength(BSSDescriptor* Bss, u8 ID, u8* len) { u16 IEslen = Bss->IEs_length; u8* ptr = (u8*)Bss; - size_t offset = 0; + IE_hdr* hdr = (IE_hdr*)&ptr[sizeof(BSSDescriptor)]; + u16 offset = 0; - for(u8 IE = 0; - (IE < ID) && ((offset + ptr[offset + 0x3F]) < IEslen && ptr[offset + 0x3F] != 0); - offset += ptr[offset + 0x3F]) + while(hdr->ID != ID && (offset + hdr->len) < IEslen && hdr->len != 0) { - IE++; + hdr = (IE_hdr*)&ptr[sizeof(BSSDescriptor) + offset]; + offset += hdr->len + sizeof(IE_hdr); } - - return ptr[offset + 0x3F]; + + if(hdr->ID != ID) return -1; + + *len = hdr->len; + return 0; } int WD_GetIE(BSSDescriptor* Bss, u8 ID, u8* buff, u8 buffsize) { - if(ID > WD_GetNumberOfIEs(Bss)) return -1; - if(!buff) return -2; u16 IEslen = Bss->IEs_length; u8* ptr = (u8*)Bss; - size_t offset = 0; + IE_hdr* hdr = (IE_hdr*)&ptr[sizeof(BSSDescriptor)]; + u16 offset = 0; - for(u8 IE = 0; - (IE < ID) && ((offset + WD_GetIELength(Bss, ID)) < IEslen && WD_GetIELength(Bss, ID) != 0); - offset += WD_GetIELength(Bss, ID)) + while(hdr->ID != ID && (offset + hdr->len) < IEslen && hdr->len != 0) { - IE++; + hdr = (IE_hdr*)&ptr[sizeof(BSSDescriptor) + offset]; + offset += hdr->len + sizeof(IE_hdr); } + if(hdr->ID != ID) return -1; + memset(buff, 0, buffsize); - memcpy(buff, &ptr[offset + 0x3F + 1], WD_GetIELength(Bss, ID)); + memcpy(buff, &ptr[offset + sizeof(BSSDescriptor) + sizeof(IE_hdr)], hdr->len); return 0; } From bd2033155c8fe445a86531e66fde71eb857e2fb8 Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Thu, 22 Jan 2026 20:31:41 +0100 Subject: [PATCH 7/9] Return length instead of using a pointer. --- gc/ogc/wd.h | 2 +- libogc/wd.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gc/ogc/wd.h b/gc/ogc/wd.h index 972fbdb7..901f6004 100644 --- a/gc/ogc/wd.h +++ b/gc/ogc/wd.h @@ -155,7 +155,7 @@ u8 WD_GetRadioLevel(BSSDescriptor* Bss); int WD_Scan(ScanParameters *settings, u8* buff, u16 buffsize); int WD_ScanOnce(ScanParameters *settings, u8* buff, u16 buffsize); u8 WD_GetNumberOfIEs(BSSDescriptor* Bss); -int WD_GetIELength(BSSDescriptor* Bss, u8 ID, u8* len); +int WD_GetIELength(BSSDescriptor* Bss, u8 ID); int WD_GetIE(BSSDescriptor* Bss, u8 ID, u8* buff, u8 buffsize); void WD_SetDefaultScanParameters(ScanParameters* set); diff --git a/libogc/wd.c b/libogc/wd.c index e238b340..4230568a 100644 --- a/libogc/wd.c +++ b/libogc/wd.c @@ -207,7 +207,7 @@ u8 WD_GetNumberOfIEs(BSSDescriptor* Bss) { return ret; } -int WD_GetIELength(BSSDescriptor* Bss, u8 ID, u8* len) { +int WD_GetIELength(BSSDescriptor* Bss, u8 ID) { u16 IEslen = Bss->IEs_length; u8* ptr = (u8*)Bss; @@ -222,8 +222,7 @@ int WD_GetIELength(BSSDescriptor* Bss, u8 ID, u8* len) { if(hdr->ID != ID) return -1; - *len = hdr->len; - return 0; + return hdr->len; } int WD_GetIE(BSSDescriptor* Bss, u8 ID, u8* buff, u8 buffsize) { From 599ec82ca508f376c8d7f6d92b7d7b8d9de0946e Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Thu, 22 Jan 2026 20:48:45 +0100 Subject: [PATCH 8/9] Simplify if cases in WD_GetRadioLevel. --- libogc/wd.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/libogc/wd.c b/libogc/wd.c index 4230568a..f71c07c4 100644 --- a/libogc/wd.c +++ b/libogc/wd.c @@ -116,22 +116,17 @@ void WD_Deinit() { } u8 WD_GetRadioLevel(BSSDescriptor* Bss) { - u8 ret; - - if (Bss->RSSI < 0xc4) { - if (Bss->RSSI < 0xb5) { - if (Bss->RSSI < 0xab) { - ret = 0; // Very Weak - } else { - ret = 1; // Weak - } - } else { - ret = 2; // Medium - } - } else { - ret = 3; // Strong - } - return ret; + if (Bss->RSSI >= 0xc4) + return 3; // Strong + + if (Bss->RSSI >= 0xb5) + return 2; // Normal + + if (Bss->RSSI >= 0xab) + return 1; // Weak + + return 0; // Very Weak + } int WD_GetInfo(WDInfo* info) { From 54a5d1ffc1abecee9b7044d9dc63c04fdf2ebe09 Mon Sep 17 00:00:00 2001 From: Abdelali <196317120+abdelali221@users.noreply.github.com> Date: Thu, 22 Jan 2026 21:38:04 +0100 Subject: [PATCH 9/9] Use defined values for signal strength. --- gc/ogc/wd.h | 7 +++++++ libogc/wd.c | 9 ++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/gc/ogc/wd.h b/gc/ogc/wd.h index 901f6004..6f9a2578 100644 --- a/gc/ogc/wd.h +++ b/gc/ogc/wd.h @@ -68,6 +68,13 @@ enum WDIOCTLV #define IEID_VENDORSPECIFIC 0xDD #define IEID_SECURITY 0x30 +// Signal Strength : + +#define WD_SIGNAL_STRONG 3 +#define WD_SIGNAL_NORMAL 2 +#define WD_SIGNAL_FAIR 1 +#define WD_SIGNAL_WEAK 0 + // WD Modes : enum MODES diff --git a/libogc/wd.c b/libogc/wd.c index f71c07c4..5d7a00b5 100644 --- a/libogc/wd.c +++ b/libogc/wd.c @@ -117,16 +117,15 @@ void WD_Deinit() { u8 WD_GetRadioLevel(BSSDescriptor* Bss) { if (Bss->RSSI >= 0xc4) - return 3; // Strong + return WD_SIGNAL_STRONG; // Strong if (Bss->RSSI >= 0xb5) - return 2; // Normal + return WD_SIGNAL_NORMAL; // Normal if (Bss->RSSI >= 0xab) - return 1; // Weak + return WD_SIGNAL_FAIR; // Fair - return 0; // Very Weak - + return WD_SIGNAL_WEAK; // Weak } int WD_GetInfo(WDInfo* info) {