diff --git a/nx/include/switch.h b/nx/include/switch.h index 3e83cb1d..83cba60b 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -86,6 +86,7 @@ extern "C" { #include "switch/services/capssc.h" #include "switch/services/capssu.h" #include "switch/services/nfc.h" +#include "switch/services/wlaninf.h" #include "switch/display/binder.h" #include "switch/display/parcel.h" diff --git a/nx/include/switch/services/wlaninf.h b/nx/include/switch/services/wlaninf.h new file mode 100644 index 00000000..d012f29e --- /dev/null +++ b/nx/include/switch/services/wlaninf.h @@ -0,0 +1,26 @@ +/** + * @file wlaninf.h + * @brief WLAN InfraManager service IPC wrapper. + * @author natinusala + * @copyright libnx Authors + */ + +#pragma once +#include "../kernel/ipc.h" +#include "../services/sm.h" + +/// WLAN State. +typedef enum { + WlanInfState_NotConnected = 1, ///< WLAN is disabled or enabled and not connected. + WlanInfState_Connecting, ///< WLAN is connecting. + WlanInfState_Connected, ///< WLAN is connected. +} WlanInfState; + +Result wlaninfInitialize(void); +void wlaninfExit(void); + +Result wlaninfGetState(WlanInfState* out); + +/// Value goes from -30 (really good signal) to -90 (barely enough to stay connected) +/// on a logarithmic scale +Result wlaninfGetRSSI(s32* out); diff --git a/nx/source/services/wlaninf.c b/nx/source/services/wlaninf.c new file mode 100644 index 00000000..51999c00 --- /dev/null +++ b/nx/source/services/wlaninf.c @@ -0,0 +1,107 @@ +/** + * @file wlaninf.c + * @brief WLAN InfraManager service IPC wrapper. + * @author natinusala + * @copyright libnx Authors + */ + +#include "types.h" +#include "result.h" +#include "services/sm.h" +#include "services/wlaninf.h" +#include "arm/atomics.h" + +static Service g_wlaninfSrv; +static u64 g_refCnt; + +Result wlaninfInitialize(void) { + Result rc; + + atomicIncrement64(&g_refCnt); + + if (serviceIsActive(&g_wlaninfSrv)) + return 0; + + rc = smGetService(&g_wlaninfSrv, "wlan:inf"); + + if (R_FAILED(rc)) + wlaninfExit(); + + return rc; +} + +void wlaninfExit(void) { + if (atomicDecrement64(&g_refCnt) == 0) { + serviceClose(&g_wlaninfSrv); + } +} + +Result wlaninfGetState(WlanInfState* out) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_wlaninfSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 10; + + Result rc = serviceIpcDispatch(&g_wlaninfSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + + struct { + u64 magic; + u64 result; + u32 out; + } *resp; + + serviceIpcParse(&g_wlaninfSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + *out = resp->out; + } + + return rc; +} + +Result wlaninfGetRSSI(s32* out) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_wlaninfSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 12; + + Result rc = serviceIpcDispatch(&g_wlaninfSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + + struct { + u64 magic; + u64 result; + s32 out; + } *resp; + + serviceIpcParse(&g_wlaninfSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + *out = resp->out; + } + + return rc; +}