From b5fe06631604ae9c6e3fa93a7d3e4605b5444133 Mon Sep 17 00:00:00 2001 From: Gabriel Lima Date: Thu, 9 Apr 2026 21:16:01 -0300 Subject: [PATCH] Wi-Fi SSID and RSSI --- CMakeLists.txt | 8 ++- main.cpp | 145 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1866a2f..d743a55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,7 +73,13 @@ add_executable(${PROJECT_NAME} # another_file.cpp # ) -target_link_libraries(${PROJECT_NAME} PRIVATE gfx_linux_fb) +find_package(PkgConfig REQUIRED) +set(ENV{PKG_CONFIG_SYSROOT_DIR} "${CMAKE_SYSROOT}") +set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig") +pkg_check_modules(LIBNL_GENL REQUIRED libnl-genl-3.0) + +target_include_directories(${PROJECT_NAME} PRIVATE ${LIBNL_GENL_INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} PRIVATE gfx_linux_fb ${LIBNL_GENL_LIBRARIES}) # Install rule (optional) install(TARGETS ${PROJECT_NAME} DESTINATION bin) \ No newline at end of file diff --git a/main.cpp b/main.cpp index bf648e8..cccbb1a 100644 --- a/main.cpp +++ b/main.cpp @@ -17,9 +17,15 @@ #include #include #include +#include #include #include +#include +#include +#include +#include + // --------------------------------------------------------------------------- // Configuration // --------------------------------------------------------------------------- @@ -53,6 +59,132 @@ static std::string get_ip(const char* iface_name) { return result; } +// --------------------------------------------------------------------------- +// Wi-Fi helper — SSID and RSSI via nl80211 / libnl-genl +// --------------------------------------------------------------------------- +struct WifiScanResult { + char ssid[33]; + uint8_t bssid[6]; + bool have_ssid = false; + bool have_bssid = false; +}; + +struct WifiStationResult { + int rssi = 0; + bool have_rssi = false; +}; + +static int scan_handler(struct nl_msg* msg, void* arg) { + auto* result = static_cast(arg); + auto* gnlh = static_cast(nlmsg_data(nlmsg_hdr(msg))); + + struct nlattr* tb[NL80211_ATTR_MAX + 1]; + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), nullptr); + + if (!tb[NL80211_ATTR_BSS]) return NL_SKIP; + + struct nlattr* bss[NL80211_BSS_MAX + 1]; + nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], nullptr); + + // Only process the BSS we are associated with. + if (!bss[NL80211_BSS_STATUS]) return NL_SKIP; + if (nla_get_u32(bss[NL80211_BSS_STATUS]) != NL80211_BSS_STATUS_ASSOCIATED) + return NL_SKIP; + + if (bss[NL80211_BSS_BSSID]) { + std::memcpy(result->bssid, nla_data(bss[NL80211_BSS_BSSID]), 6); + result->have_bssid = true; + } + + // Walk Information Elements to find SSID (IE id 0). + if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { + const auto* ie = static_cast( + nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS])); + int ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); + while (ie_len >= 2) { + if (ie[0] == 0 && ie[1] > 0 && ie[1] <= 32) { + std::memcpy(result->ssid, ie + 2, ie[1]); + result->ssid[ie[1]] = '\0'; + result->have_ssid = true; + break; + } + ie_len -= 2 + ie[1]; + ie += 2 + ie[1]; + } + } + + return NL_SKIP; +} + +static int station_handler(struct nl_msg* msg, void* arg) { + auto* result = static_cast(arg); + auto* gnlh = static_cast(nlmsg_data(nlmsg_hdr(msg))); + + struct nlattr* tb[NL80211_ATTR_MAX + 1]; + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), nullptr); + + if (!tb[NL80211_ATTR_STA_INFO]) return NL_SKIP; + + struct nlattr* sta[NL80211_STA_INFO_MAX + 1]; + nla_parse_nested(sta, NL80211_STA_INFO_MAX, + tb[NL80211_ATTR_STA_INFO], nullptr); + + if (sta[NL80211_STA_INFO_SIGNAL]) { + result->rssi = static_cast( + nla_get_u8(sta[NL80211_STA_INFO_SIGNAL])); + result->have_rssi = true; + } + + return NL_SKIP; +} + +static bool get_wifi_info(const char* iface, char* ssid_out, int* rssi_out) { + struct nl_sock* sock = nl_socket_alloc(); + if (!sock) return false; + + if (genl_connect(sock) < 0) { nl_socket_free(sock); return false; } + + int nl80211_id = genl_ctrl_resolve(sock, "nl80211"); + if (nl80211_id < 0) { nl_socket_free(sock); return false; } + + unsigned int if_index = if_nametoindex(iface); + if (!if_index) { nl_socket_free(sock); return false; } + + // --- GET_SCAN dump → find associated BSS, extract SSID --- + WifiScanResult scan{}; + nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, scan_handler, &scan); + + struct nl_msg* msg = nlmsg_alloc(); + genlmsg_put(msg, 0, 0, nl80211_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0); + nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index); + nl_send_auto(sock, msg); + nlmsg_free(msg); + nl_recvmsgs_default(sock); + + if (!scan.have_ssid) { nl_socket_free(sock); return false; } + std::strncpy(ssid_out, scan.ssid, 32); + ssid_out[32] = '\0'; + + // --- GET_STATION for the AP → extract RSSI --- + WifiStationResult station{}; + nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, station_handler, &station); + + msg = nlmsg_alloc(); + genlmsg_put(msg, 0, 0, nl80211_id, 0, 0, NL80211_CMD_GET_STATION, 0); + nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_index); + nla_put(msg, NL80211_ATTR_MAC, 6, scan.bssid); + nl_send_auto(sock, msg); + nlmsg_free(msg); + nl_recvmsgs_default(sock); + + if (station.have_rssi) *rssi_out = station.rssi; + + nl_socket_free(sock); + return true; +} + // --------------------------------------------------------------------------- // Text centering helper // --------------------------------------------------------------------------- @@ -124,6 +256,19 @@ int main(int argc, char* argv[]) { display.setCursor(0, 24); display.print(line_buf); + // --- Wi-Fi SSID / RSSI --- + char ssid[33] = {}; + int rssi = 0; + if (get_wifi_info(WLAN_IFACE, ssid, &rssi)) { + std::snprintf(line_buf, sizeof(line_buf), "SSID: %s", ssid); + display.setCursor(0, 32); + display.print(line_buf); + + std::snprintf(line_buf, sizeof(line_buf), "RSSI: %d dBm", rssi); + display.setCursor(0, 40); + display.print(line_buf); + } + display.update(); // --- Sleep aligned to next whole second ---