manager: track Adapter objects + clear list on disable
Promote Adapter to a first-class manager object (Iwd_Adapter with PropertiesChanged subscription). iwd_manager_set_powered now drives the adapter directly, so Enable still works after Disable has torn down the device hash. State recomputation also looks at any powered adapter, and the popup hides the network list while state == IWD_STATE_OFF. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
293a858799
commit
1b5dd32c0b
7 changed files with 239 additions and 12 deletions
103
src/iwd/iwd_adapter.c
Normal file
103
src/iwd/iwd_adapter.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#include "iwd_adapter.h"
|
||||
#include "iwd_dbus.h"
|
||||
#include "iwd_props.h"
|
||||
#include "iwd_manager.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
_prop_cb(void *data, const char *key, Eldbus_Message_Iter *v)
|
||||
{
|
||||
Iwd_Adapter *a = data;
|
||||
if (!strcmp(key, "Powered")) a->powered = iwd_props_bool(v);
|
||||
}
|
||||
|
||||
void
|
||||
iwd_adapter_apply_props(Iwd_Adapter *a, Eldbus_Message_Iter *props)
|
||||
{
|
||||
iwd_props_for_each(props, _prop_cb, a);
|
||||
}
|
||||
|
||||
static void
|
||||
_on_props_changed(void *data, const Eldbus_Message *msg)
|
||||
{
|
||||
Iwd_Adapter *a = data;
|
||||
const char *iface;
|
||||
Eldbus_Message_Iter *changed, *invalidated;
|
||||
if (!eldbus_message_arguments_get(msg, "sa{sv}as", &iface, &changed, &invalidated))
|
||||
return;
|
||||
if (strcmp(iface, IWD_IFACE_ADAPTER) != 0) return;
|
||||
iwd_props_for_each(changed, _prop_cb, a);
|
||||
if (a->manager) iwd_manager_notify(a->manager);
|
||||
}
|
||||
|
||||
Iwd_Adapter *
|
||||
iwd_adapter_new(Eldbus_Connection *conn, const char *path, void *manager)
|
||||
{
|
||||
Iwd_Adapter *a = calloc(1, sizeof(*a));
|
||||
if (!a) return NULL;
|
||||
a->path = path ? strdup(path) : NULL;
|
||||
a->manager = manager;
|
||||
a->obj = eldbus_object_get(conn, IWD_BUS_NAME, path);
|
||||
if (a->obj)
|
||||
{
|
||||
a->proxy = eldbus_proxy_get(a->obj, IWD_IFACE_ADAPTER);
|
||||
if (a->proxy)
|
||||
a->sh_props = eldbus_proxy_properties_changed_callback_add(
|
||||
a->proxy, _on_props_changed, a);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
iwd_adapter_free(Iwd_Adapter *a)
|
||||
{
|
||||
if (!a) return;
|
||||
if (a->sh_props) eldbus_signal_handler_del(a->sh_props);
|
||||
if (a->_props_proxy_keepalive) eldbus_proxy_unref(a->_props_proxy_keepalive);
|
||||
if (a->proxy) eldbus_proxy_unref(a->proxy);
|
||||
if (a->obj) eldbus_object_unref(a->obj);
|
||||
free(a->path);
|
||||
free(a);
|
||||
}
|
||||
|
||||
static void
|
||||
_on_set_reply(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED)
|
||||
{
|
||||
const char *what = data;
|
||||
const char *en, *em;
|
||||
if (eldbus_message_error_get(msg, &en, &em))
|
||||
fprintf(stderr, "e_iwd: %s failed: %s: %s\n", what, en, em);
|
||||
else
|
||||
fprintf(stderr, "e_iwd: %s ok\n", what);
|
||||
}
|
||||
|
||||
void
|
||||
iwd_adapter_set_powered(Iwd_Adapter *a, Eina_Bool on)
|
||||
{
|
||||
if (!a || !a->obj) return;
|
||||
|
||||
/* Call org.freedesktop.DBus.Properties.Set explicitly so we control the
|
||||
* variant marshaling exactly. eldbus_proxy_property_set silently swallows
|
||||
* Adapter.Powered on this iwd version. */
|
||||
Eldbus_Proxy *props = eldbus_proxy_get(a->obj, "org.freedesktop.DBus.Properties");
|
||||
if (!props) return;
|
||||
|
||||
Eldbus_Message *msg = eldbus_proxy_method_call_new(props, "Set");
|
||||
Eldbus_Message_Iter *iter = eldbus_message_iter_get(msg);
|
||||
const char *iface = IWD_IFACE_ADAPTER;
|
||||
const char *prop = "Powered";
|
||||
eldbus_message_iter_basic_append(iter, 's', iface);
|
||||
eldbus_message_iter_basic_append(iter, 's', prop);
|
||||
Eldbus_Message_Iter *variant = eldbus_message_iter_container_new(iter, 'v', "b");
|
||||
Eina_Bool v = on;
|
||||
eldbus_message_iter_basic_append(variant, 'b', v);
|
||||
eldbus_message_iter_container_close(iter, variant);
|
||||
|
||||
eldbus_proxy_send(props, msg, _on_set_reply,
|
||||
on ? "Adapter.Powered=true" : "Adapter.Powered=false", -1);
|
||||
/* Keep the props proxy alive on the adapter so the call isn't canceled. */
|
||||
if (a->_props_proxy_keepalive) eldbus_proxy_unref(a->_props_proxy_keepalive);
|
||||
a->_props_proxy_keepalive = props;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue