2007-10-15 Tambet Ingo <tambet@gmail.com>

Implement killswitch polling through HAL.

        * src/nm-manager.c: Add wireless hardware status property. Add 
        'properties-changed' signal for changes in wireless and wireless
hardware
        state changes.

        * src/nm-hal-manager.c: Poll hal for killswitch statuses in
        * every 6 seconds
        and update NMManager's wireless hardware state when it has
changed.
        (nm_hal_manager_new): Don't try to add initial devices here -
(hal_init)
        already does that.

        * libnm-glib/nm-client.c: Add wireless hardware status property.
        * Cache the
        values of wireless state and wireless hardware state. Listen for
the
        'properties-changed' signals, update the cached values and emit
notify.

        * include/NetworkManager.h: Fix a typo in a comment.



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2975 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Tambet Ingo 2007-10-15 14:46:37 +00:00
parent 799c141b35
commit 7e2a621f0a
9 changed files with 403 additions and 38 deletions

View file

@ -1,3 +1,22 @@
2007-10-15 Tambet Ingo <tambet@gmail.com>
Implement killswitch polling through HAL.
* src/nm-manager.c: Add wireless hardware status property. Add
'properties-changed' signal for changes in wireless and wireless hardware
state changes.
* src/nm-hal-manager.c: Poll hal for killswitch statuses in every 6 seconds
and update NMManager's wireless hardware state when it has changed.
(nm_hal_manager_new): Don't try to add initial devices here - (hal_init)
already does that.
* libnm-glib/nm-client.c: Add wireless hardware status property. Cache the
values of wireless state and wireless hardware state. Listen for the
'properties-changed' signals, update the cached values and emit notify.
* include/NetworkManager.h: Fix a typo in a comment.
2007-10-14 Dan Williams <dcbw@redhat.com>
* libnm-util/nm-setting.c

View file

@ -48,7 +48,7 @@
/*
* Types of NetworkManager devices
* Types of NetworkManager states
*/
typedef enum NMState
{

View file

@ -41,12 +41,17 @@
</method>
<property name="WirelessEnabled" type="b" access="readwrite"/>
<property name="WirelessHardwareEnabled" type="b" access="read"/>
<property name="State" type="u" access="read"/>
<signal name="StateChange">
<arg name="state" type="u"/>
</signal>
<signal name="PropertiesChanged">
<arg name="properties" type="a{sv}"/>
</signal>
<signal name="DeviceAdded">
<arg name="state" type="o"/>
</signal>

View file

@ -41,12 +41,17 @@
</method>
<property name="WirelessEnabled" type="b" access="readwrite"/>
<property name="WirelessHardwareEnabled" type="b" access="read"/>
<property name="State" type="u" access="read"/>
<signal name="StateChange">
<arg name="state" type="u"/>
</signal>
<signal name="PropertiesChanged">
<arg name="properties" type="a{sv}"/>
</signal>
<signal name="DeviceAdded">
<arg name="state" type="o"/>
</signal>

View file

@ -22,8 +22,19 @@ typedef struct {
NMState state;
gboolean have_device_list;
GHashTable *devices;
gboolean wireless_enabled;
gboolean wireless_hw_enabled;
} NMClientPrivate;
enum {
PROP_0,
PROP_WIRELESS_ENABLED,
PROP_WIRELESS_HARDWARE_ENABLED,
LAST_PROP
};
enum {
MANAGER_RUNNING,
DEVICE_ADDED,
@ -58,8 +69,8 @@ nm_client_init (NMClient *client)
static GObject*
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
guint n_construct_params,
GObjectConstructParam *construct_params)
{
NMObject *object;
DBusGConnection *connection;
@ -67,8 +78,8 @@ constructor (GType type,
GError *err = NULL;
object = (NMObject *) G_OBJECT_CLASS (nm_client_parent_class)->constructor (type,
n_construct_params,
construct_params);
n_construct_params,
construct_params);
if (!object)
return NULL;
@ -76,50 +87,61 @@ constructor (GType type,
connection = nm_object_get_connection (object);
priv->client_proxy = dbus_g_proxy_new_for_name (connection,
NM_DBUS_SERVICE,
nm_object_get_path (object),
NM_DBUS_INTERFACE);
NM_DBUS_SERVICE,
nm_object_get_path (object),
NM_DBUS_INTERFACE);
dbus_g_proxy_add_signal (priv->client_proxy, "StateChange", G_TYPE_UINT, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->client_proxy,
"StateChange",
G_CALLBACK (client_state_change_proxy),
object,
NULL);
"StateChange",
G_CALLBACK (client_state_change_proxy),
object,
NULL);
dbus_g_proxy_add_signal (priv->client_proxy, "DeviceAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->client_proxy,
"DeviceAdded",
G_CALLBACK (client_device_added_proxy),
object,
NULL);
"DeviceAdded",
G_CALLBACK (client_device_added_proxy),
object,
NULL);
dbus_g_proxy_add_signal (priv->client_proxy, "DeviceRemoved", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->client_proxy,
"DeviceRemoved",
G_CALLBACK (client_device_removed_proxy),
object,
NULL);
"DeviceRemoved",
G_CALLBACK (client_device_removed_proxy),
object,
NULL);
nm_object_handle_properties_changed (NM_OBJECT (object), priv->client_proxy);
priv->wireless_enabled = nm_object_get_boolean_property (NM_OBJECT (object),
NM_DBUS_INTERFACE,
"WirelessEnabled");
priv->wireless_hw_enabled = priv->wireless_enabled ?
TRUE : nm_object_get_boolean_property (NM_OBJECT (object),
NM_DBUS_INTERFACE,
"WirelessHardwareEnabled");
priv->bus_proxy = dbus_g_proxy_new_for_name (connection,
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus");
"org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus");
dbus_g_proxy_add_signal (priv->bus_proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->bus_proxy,
"NameOwnerChanged",
G_CALLBACK (proxy_name_owner_changed),
object, NULL);
"NameOwnerChanged",
G_CALLBACK (proxy_name_owner_changed),
object, NULL);
if (!dbus_g_proxy_call (priv->bus_proxy,
"NameHasOwner", &err,
G_TYPE_STRING, NM_DBUS_SERVICE,
G_TYPE_INVALID,
G_TYPE_BOOLEAN, &priv->manager_running,
G_TYPE_INVALID)) {
"NameHasOwner", &err,
G_TYPE_STRING, NM_DBUS_SERVICE,
G_TYPE_INVALID,
G_TYPE_BOOLEAN, &priv->manager_running,
G_TYPE_INVALID)) {
g_warning ("Error on NameHasOwner DBUS call: %s", err->message);
g_error_free (err);
}
@ -137,6 +159,56 @@ finalize (GObject *object)
g_hash_table_destroy (priv->devices);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
gboolean b;
switch (prop_id) {
case PROP_WIRELESS_ENABLED:
b = g_value_get_boolean (value);
if (priv->wireless_enabled != b) {
priv->wireless_enabled = b;
g_object_notify (object, NM_CLIENT_WIRELESS_ENABLED);
}
break;
case PROP_WIRELESS_HARDWARE_ENABLED:
b = g_value_get_boolean (value);
if (priv->wireless_hw_enabled != b) {
priv->wireless_hw_enabled = b;
g_object_notify (object, NM_CLIENT_WIRELESS_HARDWARE_ENABLED);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
switch (prop_id) {
case PROP_WIRELESS_ENABLED:
g_value_set_boolean (value, priv->wireless_enabled);
break;
case PROP_WIRELESS_HARDWARE_ENABLED:
g_value_set_boolean (value, priv->wireless_hw_enabled);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
manager_running (NMClient *client, gboolean running)
{
@ -158,10 +230,29 @@ nm_client_class_init (NMClientClass *client_class)
/* virtual methods */
object_class->constructor = constructor;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->finalize = finalize;
client_class->manager_running = manager_running;
/* properties */
g_object_class_install_property
(object_class, PROP_WIRELESS_ENABLED,
g_param_spec_boolean (NM_CLIENT_WIRELESS_ENABLED,
"WirelessEnabled",
"Is wirless enabled",
TRUE,
G_PARAM_READWRITE));
g_object_class_install_property
(object_class, PROP_WIRELESS_HARDWARE_ENABLED,
g_param_spec_boolean (NM_CLIENT_WIRELESS_HARDWARE_ENABLED,
"WirelessHardwareEnabled",
"Is wirless hardware enabled",
TRUE,
G_PARAM_READWRITE));
/* signals */
signals[MANAGER_RUNNING] =
g_signal_new ("manager-running",
@ -548,7 +639,7 @@ nm_client_wireless_get_enabled (NMClient *client)
{
g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
return nm_object_get_boolean_property (NM_OBJECT (client), NM_DBUS_INTERFACE, "WirelessEnabled");
return NM_CLIENT_GET_PRIVATE (client)->wireless_enabled;
}
void
@ -562,9 +653,17 @@ nm_client_wireless_set_enabled (NMClient *client, gboolean enabled)
g_value_set_boolean (&value, enabled);
nm_object_set_property (NM_OBJECT (client),
NM_DBUS_INTERFACE,
"WirelessEnabled",
&value);
NM_DBUS_INTERFACE,
"WirelessEnabled",
&value);
}
gboolean
nm_client_wireless_hardware_get_enabled (NMClient *client)
{
g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
return NM_CLIENT_GET_PRIVATE (client)->wireless_hw_enabled;
}
NMState

View file

@ -19,6 +19,9 @@ G_BEGIN_DECLS
#define NM_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_CLIENT))
#define NM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CLIENT, NMClientClass))
#define NM_CLIENT_WIRELESS_ENABLED "wireless_enabled"
#define NM_CLIENT_WIRELESS_HARDWARE_ENABLED "wireless_hardware_enabled"
typedef struct {
NMObject parent;
} NMClient;
@ -65,6 +68,7 @@ void nm_client_activate_device (NMClient *client,
gboolean nm_client_wireless_get_enabled (NMClient *client);
void nm_client_wireless_set_enabled (NMClient *client, gboolean enabled);
gboolean nm_client_wireless_hardware_get_enabled (NMClient *client);
NMState nm_client_get_state (NMClient *client);
void nm_client_sleep (NMClient *client, gboolean sleep);

View file

@ -1,3 +1,5 @@
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
#include <signal.h>
#include <string.h>
#include <stdlib.h>
@ -8,6 +10,9 @@
#include "nm-device-802-11-wireless.h"
#include "nm-device-802-3-ethernet.h"
/* Killswitch poll frequency in seconds */
#define NM_HAL_MANAGER_KILLSWITCH_POLL_FREQUENCY 6
struct _NMHalManager {
LibHalContext *hal_ctx;
NMDBusManager *dbus_mgr;
@ -15,6 +20,10 @@ struct _NMHalManager {
GSList *device_creators;
gboolean nm_sleeping;
/* Killswitch handling */
GSList *killswitch_list;
guint32 killswitch_poll_id;
};
/* Device creators */
@ -295,6 +304,162 @@ add_initial_devices (NMHalManager *manager)
}
}
typedef struct {
NMHalManager *manager;
gboolean initial_state;
gboolean changed;
guint32 pending_polls;
GSList *proxies;
} NMKillswitchPollInfo;
static void
killswitch_getpower_done (gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
info->pending_polls--;
if (info->pending_polls == 0) {
g_slist_foreach (info->proxies, (GFunc) g_object_unref, NULL);
g_slist_free (info->proxies);
info->proxies = NULL;
if (info->changed)
nm_manager_set_wireless_hardware_enabled (info->manager->nm_manager, !info->initial_state);
}
}
static void
killswitch_getpower_reply (DBusGProxy *proxy,
DBusGProxyCall *call_id,
gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
guint32 status;
GError *err = NULL;
if (dbus_g_proxy_end_call (proxy, call_id, &err,
G_TYPE_UINT, &status,
G_TYPE_INVALID)) {
if (!info->changed && info->initial_state != (status == 0) ? FALSE : TRUE)
info->changed = TRUE;
} else {
nm_warning ("Error getting killswitch power: %s.", err->message);
g_error_free (err);
}
}
static void
poll_killswitches_real (gpointer data, gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
DBusGProxy *proxy;
proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (info->manager->dbus_mgr),
"org.freedesktop.Hal",
(char *) data,
"org.freedesktop.Hal.Device.KillSwitch");
dbus_g_proxy_begin_call (proxy, "GetPower",
killswitch_getpower_reply,
info,
killswitch_getpower_done,
G_TYPE_INVALID);
info->pending_polls++;
info->proxies = g_slist_prepend (info->proxies, proxy);
}
static gboolean
poll_killswitches (gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
info->initial_state = nm_manager_wireless_hardware_enabled (info->manager->nm_manager);
info->changed = FALSE;
info->pending_polls = 0;
g_slist_foreach (info->manager->killswitch_list, poll_killswitches_real, info);
return TRUE;
}
static void
killswitch_poll_destroy (gpointer data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) data;
if (info->proxies) {
g_slist_foreach (info->proxies, (GFunc) g_object_unref, NULL);
g_slist_free (info->proxies);
}
g_slice_free (NMKillswitchPollInfo, info);
}
static void
add_killswitch_device (NMHalManager *manager, const char *udi)
{
char *type;
GSList *iter;
type = libhal_device_get_property_string (manager->hal_ctx, udi, "killswitch.type", NULL);
if (!type)
return;
if (strcmp (type, "wlan"))
goto out;
/* see if it's already in the list */
for (iter = manager->killswitch_list; iter; iter = iter->next) {
const char *list_udi = (const char *) iter->data;
if (!strcmp (list_udi, udi))
goto out;
}
/* Start polling switches if this is the first switch we've found */
if (!manager->killswitch_list) {
NMKillswitchPollInfo *info;
info = g_slice_new0 (NMKillswitchPollInfo);
info->manager = manager;
manager->killswitch_poll_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
NM_HAL_MANAGER_KILLSWITCH_POLL_FREQUENCY * 1000,
poll_killswitches,
info,
killswitch_poll_destroy);
}
manager->killswitch_list = g_slist_append (manager->killswitch_list, g_strdup (udi));
nm_info ("Found radio killswitch %s", udi);
out:
libhal_free_string (type);
}
static void
add_killswitch_devices (NMHalManager *manager)
{
char **udis;
int num_udis;
int i;
DBusError err;
dbus_error_init (&err);
udis = libhal_find_device_by_capability (manager->hal_ctx, "killswitch", &num_udis, &err);
if (!udis)
return;
if (dbus_error_is_set (&err)) {
nm_warning ("Could not find killswitch devices: %s", err.message);
dbus_error_free (&err);
return;
}
for (i = 0; i < num_udis; i++)
add_killswitch_device (manager, udis[i]);
libhal_free_string_array (udis);
}
static gboolean
hal_init (NMHalManager *manager)
{
@ -333,6 +498,7 @@ hal_init (NMHalManager *manager)
}
/* Add any devices we know about */
add_killswitch_devices (manager);
add_initial_devices (manager);
success = TRUE;
@ -354,6 +520,17 @@ hal_deinit (NMHalManager *manager)
{
DBusError error;
if (manager->killswitch_poll_id) {
g_source_remove (manager->killswitch_poll_id);
manager->killswitch_poll_id = 0;
}
if (manager->killswitch_list) {
g_slist_foreach (manager->killswitch_list, (GFunc) g_free, NULL);
g_slist_free (manager->killswitch_list);
manager->killswitch_list = NULL;
}
if (!manager->hal_ctx)
return;
@ -463,7 +640,6 @@ nm_hal_manager_new (NMManager *nm_manager)
manager);
hal_init (manager);
add_initial_devices (manager);
return manager;
}

View file

@ -9,6 +9,7 @@
#include "nm-device-interface.h"
#include "nm-device-802-11-wireless.h"
#include "NetworkManagerSystem.h"
#include "nm-properties-changed-signal.h"
#include "nm-marshal.h"
static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err);
@ -65,6 +66,7 @@ typedef struct {
PendingConnectionInfo *pending_connection_info;
gboolean wireless_enabled;
gboolean wireless_hw_enabled;
gboolean sleeping;
} NMManagerPrivate;
@ -76,6 +78,7 @@ enum {
DEVICE_ADDED,
DEVICE_REMOVED,
STATE_CHANGE,
PROPERTIES_CHANGED,
CONNECTIONS_ADDED,
CONNECTION_ADDED,
CONNECTION_UPDATED,
@ -90,6 +93,7 @@ enum {
PROP_0,
PROP_STATE,
PROP_WIRELESS_ENABLED,
PROP_WIRELESS_HARDWARE_ENABLED,
LAST_PROP
};
@ -100,6 +104,7 @@ nm_manager_init (NMManager *manager)
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
priv->wireless_enabled = TRUE;
priv->wireless_hw_enabled = TRUE;
priv->sleeping = FALSE;
priv->state = NM_STATE_DISCONNECTED;
@ -202,6 +207,9 @@ set_property (GObject *object, guint prop_id,
case PROP_WIRELESS_ENABLED:
manager_set_wireless_enabled (NM_MANAGER (object), g_value_get_boolean (value));
break;
case PROP_WIRELESS_HARDWARE_ENABLED:
nm_manager_set_wireless_hardware_enabled (NM_MANAGER (object), g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -222,6 +230,9 @@ get_property (GObject *object, guint prop_id,
case PROP_WIRELESS_ENABLED:
g_value_set_boolean (value, priv->wireless_enabled);
break;
case PROP_WIRELESS_HARDWARE_ENABLED:
g_value_set_boolean (value, priv->wireless_hw_enabled);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -259,6 +270,14 @@ nm_manager_class_init (NMManagerClass *manager_class)
TRUE,
G_PARAM_READWRITE));
g_object_class_install_property
(object_class, PROP_WIRELESS_HARDWARE_ENABLED,
g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED,
"WirelessHardwareEnabled",
"RF kill state",
TRUE,
G_PARAM_READWRITE));
/* signals */
signals[DEVICE_ADDED] =
g_signal_new ("device-added",
@ -290,6 +309,10 @@ nm_manager_class_init (NMManagerClass *manager_class)
G_TYPE_NONE, 1,
G_TYPE_UINT);
signals[PROPERTIES_CHANGED] =
nm_properties_changed_signal_new (object_class,
G_STRUCT_OFFSET (NMManagerClass, properties_changed));
signals[CONNECTIONS_ADDED] =
g_signal_new ("connections-added",
G_OBJECT_CLASS_TYPE (object_class),
@ -841,6 +864,8 @@ manager_set_wireless_enabled (NMManager *manager, gboolean enabled)
priv->wireless_enabled = enabled;
g_object_notify (G_OBJECT (manager), NM_MANAGER_WIRELESS_ENABLED);
/* Tear down all wireless devices */
for (iter = priv->devices; iter; iter = iter->next) {
if (NM_IS_DEVICE_802_11_WIRELESS (iter->data)) {
@ -1373,6 +1398,33 @@ nm_manager_wireless_enabled (NMManager *manager)
return enabled;
}
gboolean
nm_manager_wireless_hardware_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->wireless_hw_enabled;
}
void
nm_manager_set_wireless_hardware_enabled (NMManager *manager,
gboolean enabled)
{
NMManagerPrivate *priv;
g_return_if_fail (NM_IS_MANAGER (manager));
priv = NM_MANAGER_GET_PRIVATE (manager);
if (priv->wireless_hw_enabled != enabled) {
nm_info ("Wireless now %s by radio killswitch", enabled ? "enabled" : "disabled");
priv->wireless_hw_enabled = enabled;
g_object_notify (G_OBJECT (manager), NM_MANAGER_WIRELESS_HARDWARE_ENABLED);
manager_set_wireless_enabled (manager, enabled);
}
}
void
nm_manager_sleep (NMManager *manager, gboolean sleep)
{

View file

@ -16,6 +16,7 @@
#define NM_MANAGER_STATE "state"
#define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled"
#define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled"
#define NM_MANAGER_CONNECTION_PROXY_TAG "dbus-proxy"
#define NM_MANAGER_CONNECTION_TYPE_TAG "service-type"
@ -37,6 +38,7 @@ typedef struct {
void (*device_added) (NMManager *manager, NMDevice *device);
void (*device_removed) (NMManager *manager, NMDevice *device);
void (*state_change) (NMManager *manager, guint state);
void (*properties_changed) (NMManager *manager, GHashTable *properties);
void (*connections_added) (NMManager *manager, NMConnectionType type);
@ -79,6 +81,9 @@ gboolean nm_manager_activation_pending (NMManager *manager);
NMState nm_manager_get_state (NMManager *manager);
gboolean nm_manager_wireless_enabled (NMManager *manager);
gboolean nm_manager_wireless_hardware_enabled (NMManager *manager);
void nm_manager_set_wireless_hardware_enabled (NMManager *manager,
gboolean enabled);
void nm_manager_sleep (NMManager *manager, gboolean sleep);
/* Connections */