From 29ded04f108d3cee92f24599a44c8a5c35b04791 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Thu, 9 Apr 2026 11:59:48 +0700 Subject: [PATCH] iwd: track per-network signal strength via Station.GetOrderedNetworks Adds Iwd_Network.signal_dbm/have_signal and a signal_tier helper, and calls Station.GetOrderedNetworks on station attach and on scan completion to populate them. Enables signal-aware UI affordances. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/iwd/iwd_device.c | 51 ++++++++++++++++++++++++++++++++++++++++++- src/iwd/iwd_network.c | 13 +++++++++++ src/iwd/iwd_network.h | 8 +++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/iwd/iwd_device.c b/src/iwd/iwd_device.c index c23c58a..3adbb9a 100644 --- a/src/iwd/iwd_device.c +++ b/src/iwd/iwd_device.c @@ -2,9 +2,12 @@ #include "iwd_dbus.h" #include "iwd_props.h" #include "iwd_manager.h" +#include "iwd_network.h" #include #include +static void _refresh_signals(Iwd_Device *d); + static Iwd_Station_State _state_from_str(const char *s) { @@ -36,7 +39,13 @@ _sta_prop_cb(void *data, const char *key, Eldbus_Message_Iter *v) d->station_state = _state_from_str(s); free(s); } - else if (!strcmp(key, "Scanning")) { d->scanning = iwd_props_bool(v); } + else if (!strcmp(key, "Scanning")) + { + Eina_Bool was = d->scanning; + d->scanning = iwd_props_bool(v); + /* When a scan finishes, ask iwd for the ranked list with RSSI. */ + if (was && !d->scanning) _refresh_signals(d); + } else if (!strcmp(key, "ConnectedNetwork")) { free(d->connected_network); d->connected_network = iwd_props_str_dup(v); } } @@ -108,6 +117,7 @@ iwd_device_attach_station(Iwd_Device *d) d->has_station = EINA_TRUE; d->sh_sta_props = eldbus_proxy_properties_changed_callback_add( d->station_proxy, _on_sta_props_changed, d); + _refresh_signals(d); } } @@ -136,6 +146,45 @@ iwd_device_free(Iwd_Device *d) free(d); } +/* Reply to Station.GetOrderedNetworks: a(on) — list of (object_path, RSSI). + * RSSI is a 16-bit signed value in 100*dBm units. */ +static void +_on_ordered_networks(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED) +{ + Iwd_Device *d = data; + const char *en, *em; + if (eldbus_message_error_get(msg, &en, &em)) return; + + Eldbus_Message_Iter *array = NULL; + if (!eldbus_message_arguments_get(msg, "a(on)", &array) || !array) + return; + + const Eina_Hash *nets = d->manager ? iwd_manager_networks(d->manager) : NULL; + Eldbus_Message_Iter *entry; + Eina_Bool any = EINA_FALSE; + while (eldbus_message_iter_get_and_next(array, 'r', &entry)) + { + const char *path = NULL; + int16_t rssi = 0; + if (!eldbus_message_iter_arguments_get(entry, "on", &path, &rssi)) continue; + if (!nets || !path) continue; + Iwd_Network *n = eina_hash_find(nets, path); + if (!n) continue; + n->signal_dbm = rssi; + n->have_signal = EINA_TRUE; + any = EINA_TRUE; + } + if (any && d->manager) iwd_manager_notify(d->manager); +} + +static void +_refresh_signals(Iwd_Device *d) +{ + if (!d || !d->station_proxy) return; + eldbus_proxy_call(d->station_proxy, "GetOrderedNetworks", + _on_ordered_networks, d, -1, ""); +} + void iwd_device_scan(Iwd_Device *d) { diff --git a/src/iwd/iwd_network.c b/src/iwd/iwd_network.c index 4d38f0d..18a84d5 100644 --- a/src/iwd/iwd_network.c +++ b/src/iwd/iwd_network.c @@ -91,6 +91,19 @@ _on_connect_reply(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_ free(data); } +int +iwd_network_signal_tier(const Iwd_Network *n) +{ + if (!n || !n->have_signal) return 0; + /* iwd reports signal in 100*dBm. Cutoffs in dBm: -60/-67/-74/-80. */ + int dbm = n->signal_dbm / 100; + if (dbm >= -60) return 4; + if (dbm >= -67) return 3; + if (dbm >= -74) return 2; + if (dbm >= -80) return 1; + return 1; +} + void iwd_network_connect(Iwd_Network *n) { diff --git a/src/iwd/iwd_network.h b/src/iwd/iwd_network.h index 6e64c7e..dd7d56f 100644 --- a/src/iwd/iwd_network.h +++ b/src/iwd/iwd_network.h @@ -1,6 +1,7 @@ #ifndef IWD_NETWORK_H #define IWD_NETWORK_H +#include #include #include @@ -23,6 +24,10 @@ struct _Iwd_Network Iwd_Security security; Eina_Bool connected; + /* Signal strength in 100*dBm units (iwd convention). Valid iff have_signal. */ + int16_t signal_dbm; + Eina_Bool have_signal; + Eldbus_Object *obj; Eldbus_Proxy *proxy; Eldbus_Signal_Handler *sh_props; @@ -35,6 +40,9 @@ void iwd_network_free(Iwd_Network *n); void iwd_network_apply_props(Iwd_Network *n, Eldbus_Message_Iter *props); +/* 0 = unknown/no signal, 1..4 = weak..excellent. */ +int iwd_network_signal_tier(const Iwd_Network *n); + void iwd_network_connect (Iwd_Network *n); /* Forget acts on the KnownNetwork object referenced by this network. */ void iwd_network_forget (Iwd_Network *n);