2008-04-29 Dan Williams <dcbw@redhat.com>

Handle HAL dropouts better; allow NM to start up even if HAL isn't up yet.

	* marshallers/nm-marshal.list
		- Add marshaller

	* src/NetworkManager.c
		- (main): let the NMManager handle the NMHalManager

	* src/nm-hal-manager.c
	  src/nm-hal-manager.h
		- convert to a GObject, and emit singals when stuff changes.  Let the
			NMManager handle the signals, instead of the NMHalManager calling
			into the NMManager.  

	* src/nm-manager.c
	  src/nm-manager.h
		- (remove_one_device): consolidate device removals here
		- (dispose): use remove_one_device()
		- (nm_manager_get_device_by_udi): make static
		- (deferred_hal_manager_query_devices): idle handler to query the HAL
			manager for devices at startup or wakeup time
		- (nm_manager_new): create and monitor the HAL manager
		- (hal_manager_udi_added_cb): new function; do what
			nm_manager_add_device() used to do when signalled by the hal manager
		- (hal_manager_udi_removed_cb): new function; do what
			nm_manager_remove_device() used to do when signalled by the hal
			manager
		- (hal_manager_rfkill_changed_cb): handle rfkill changes from the
			hal manager
		- (hal_manager_hal_reappeared_cb): when HAL comes back, remove devices
			in our device list that aren't known to HAL
		- (impl_manager_sleep): on wakeup, re-add devices from an idle handler;
			see comments on nm-hal-manager.c::nm_manager_state_changed() a few
			commits ago
		- (nm_manager_get_device_by_path, nm_manager_is_udi_managed,
		   nm_manager_activation_pending, nm_manager_wireless_enabled,
		   nm_manager_wireless_hardware_enabled,
		   nm_manager_set_wireless_hardware_enabled): remove, unused



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3619 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams 2008-04-29 23:03:00 +00:00
parent 9be3804c7f
commit 079f2bd560
7 changed files with 595 additions and 432 deletions

View file

@ -1,3 +1,44 @@
2008-04-29 Dan Williams <dcbw@redhat.com>
Handle HAL dropouts better; allow NM to start up even if HAL isn't up yet.
* marshallers/nm-marshal.list
- Add marshaller
* src/NetworkManager.c
- (main): let the NMManager handle the NMHalManager
* src/nm-hal-manager.c
src/nm-hal-manager.h
- convert to a GObject, and emit singals when stuff changes. Let the
NMManager handle the signals, instead of the NMHalManager calling
into the NMManager.
* src/nm-manager.c
src/nm-manager.h
- (remove_one_device): consolidate device removals here
- (dispose): use remove_one_device()
- (nm_manager_get_device_by_udi): make static
- (deferred_hal_manager_query_devices): idle handler to query the HAL
manager for devices at startup or wakeup time
- (nm_manager_new): create and monitor the HAL manager
- (hal_manager_udi_added_cb): new function; do what
nm_manager_add_device() used to do when signalled by the hal manager
- (hal_manager_udi_removed_cb): new function; do what
nm_manager_remove_device() used to do when signalled by the hal
manager
- (hal_manager_rfkill_changed_cb): handle rfkill changes from the
hal manager
- (hal_manager_hal_reappeared_cb): when HAL comes back, remove devices
in our device list that aren't known to HAL
- (impl_manager_sleep): on wakeup, re-add devices from an idle handler;
see comments on nm-hal-manager.c::nm_manager_state_changed() a few
commits ago
- (nm_manager_get_device_by_path, nm_manager_is_udi_managed,
nm_manager_activation_pending, nm_manager_wireless_enabled,
nm_manager_wireless_hardware_enabled,
nm_manager_set_wireless_hardware_enabled): remove, unused
2008-04-28 Dan Williams <dcbw@redhat.com>
Fix the device up/down ambiguities. Up/down state used to be a

View file

@ -8,6 +8,7 @@ VOID:UINT,UINT
VOID:STRING,STRING
VOID:STRING,UCHAR
VOID:STRING,OBJECT
VOID:STRING,STRING,POINTER
VOID:OBJECT,UINT,UINT
VOID:STRING,INT
VOID:STRING,UINT

View file

@ -43,7 +43,6 @@
#include "NetworkManagerUtils.h"
#include "nm-device-interface.h"
#include "nm-manager.h"
#include "nm-hal-manager.h"
#include "nm-device.h"
#include "nm-device-802-3-ethernet.h"
#include "nm-device-802-11-wireless.h"
@ -205,13 +204,6 @@ write_pidfile (const char *pidfile)
nm_warning ("Closing %s failed: %s", pidfile, strerror (errno));
}
static gboolean
start_hal (gpointer user_data)
{
nm_hal_manager_start ((NMHalManager *) user_data);
return FALSE;
}
/*
* main
*
@ -225,7 +217,6 @@ main (int argc, char *argv[])
char * user_pidfile = NULL;
gboolean success;
NMPolicy *policy = NULL;
NMHalManager *hal_manager = NULL;
NMVPNManager *vpn_manager = NULL;
NMNamedManager *named_mgr = NULL;
NMDBusManager * dbus_mgr = NULL;
@ -347,11 +338,6 @@ main (int argc, char *argv[])
goto done;
}
hal_manager = nm_hal_manager_new (manager);
if (!hal_manager)
goto done;
g_idle_add (start_hal, hal_manager);
/* Bring up the loopback interface. */
nm_system_enable_loopback ();
@ -362,9 +348,6 @@ main (int argc, char *argv[])
g_main_loop_run (main_loop);
done:
if (hal_manager)
nm_hal_manager_destroy (hal_manager);
if (policy)
nm_policy_destroy (policy);

View file

@ -8,6 +8,7 @@
#include <dbus/dbus-glib-lowlevel.h>
#include "nm-hal-manager.h"
#include "nm-marshal.h"
#include "nm-dbus-manager.h"
#include "nm-utils.h"
#include "nm-device-802-11-wireless.h"
@ -16,47 +17,61 @@
#include "nm-cdma-device.h"
/* Killswitch poll frequency in seconds */
#define NM_HAL_MANAGER_KILLSWITCH_POLL_FREQUENCY 6
#define RFKILL_POLL_FREQUENCY 6
struct _NMHalManager {
#define HAL_DBUS_SERVICE "org.freedesktop.Hal"
typedef struct {
LibHalContext *hal_ctx;
NMDBusManager *dbus_mgr;
NMManager *nm_manager;
GSList *device_creators;
gboolean nm_sleeping;
guint add_devices_id;
/* Killswitch handling */
GSList *killswitch_list;
guint32 killswitch_poll_id;
char *kswitch_err;
gboolean rfkilled;
gboolean disposed;
} NMHalManagerPrivate;
#define NM_HAL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_HAL_MANAGER, NMHalManagerPrivate))
G_DEFINE_TYPE (NMHalManager, nm_hal_manager, G_TYPE_OBJECT)
enum {
UDI_ADDED,
UDI_REMOVED,
RFKILL_CHANGED,
HAL_REAPPEARED,
LAST_SIGNAL
};
/* Device creators */
static guint signals[LAST_SIGNAL] = { 0 };
typedef NMDevice *(*NMDeviceCreatorFn) (NMHalManager *manager,
const char *udi,
gboolean managed);
/* Device creators */
typedef struct {
char *device_type_name;
char *capability_str;
gboolean (*is_device_fn) (NMHalManager *manager, const char *udi);
gboolean (*is_device_fn) (NMHalManager *self, const char *udi);
NMDeviceCreatorFn creator_fn;
} DeviceCreator;
static DeviceCreator *
get_creator (NMHalManager *manager, const char *udi)
get_creator (NMHalManager *self, const char *udi)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
DeviceCreator *creator;
GSList *iter;
for (iter = manager->device_creators; iter; iter = iter->next) {
for (iter = priv->device_creators; iter; iter = g_slist_next (iter)) {
creator = (DeviceCreator *) iter->data;
if (libhal_device_query_capability (manager->hal_ctx, udi, creator->capability_str, NULL) &&
creator->is_device_fn (manager, udi))
if (libhal_device_query_capability (priv->hal_ctx, udi, creator->capability_str, NULL) &&
creator->is_device_fn (self, udi))
return creator;
}
@ -92,15 +107,16 @@ nm_get_device_driver_name (LibHalContext *ctx, const char *udi)
/* Wired device creator */
static gboolean
is_wired_device (NMHalManager *manager, const char *udi)
is_wired_device (NMHalManager *self, const char *udi)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
char *category;
gboolean is_wired = FALSE;
if (libhal_device_property_exists (manager->hal_ctx, udi, "net.linux.ifindex", NULL) &&
libhal_device_property_exists (manager->hal_ctx, udi, "info.category", NULL)) {
if (libhal_device_property_exists (priv->hal_ctx, udi, "net.linux.ifindex", NULL) &&
libhal_device_property_exists (priv->hal_ctx, udi, "info.category", NULL)) {
category = libhal_device_get_property_string (manager->hal_ctx, udi, "info.category", NULL);
category = libhal_device_get_property_string (priv->hal_ctx, udi, "info.category", NULL);
if (category) {
is_wired = strcmp (category, "net.80203") == 0;
libhal_free_string (category);
@ -110,21 +126,22 @@ is_wired_device (NMHalManager *manager, const char *udi)
return is_wired;
}
static NMDevice *
wired_device_creator (NMHalManager *manager, const char *udi, gboolean managed)
static GObject *
wired_device_creator (NMHalManager *self, const char *udi, gboolean managed)
{
NMDevice *device;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
GObject *device;
char *iface;
char *driver;
iface = libhal_device_get_property_string (manager->hal_ctx, udi, "net.interface", NULL);
iface = libhal_device_get_property_string (priv->hal_ctx, udi, "net.interface", NULL);
if (!iface) {
nm_warning ("Couldn't get interface for %s, ignoring.", udi);
return NULL;
}
driver = nm_get_device_driver_name (manager->hal_ctx, udi);
device = (NMDevice *) nm_device_802_3_ethernet_new (udi, iface, driver, managed);
driver = nm_get_device_driver_name (priv->hal_ctx, udi);
device = (GObject *) nm_device_802_3_ethernet_new (udi, iface, driver, managed);
libhal_free_string (iface);
g_free (driver);
@ -135,15 +152,16 @@ wired_device_creator (NMHalManager *manager, const char *udi, gboolean managed)
/* Wireless device creator */
static gboolean
is_wireless_device (NMHalManager *manager, const char *udi)
is_wireless_device (NMHalManager *self, const char *udi)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
char *category;
gboolean is_wireless = FALSE;
if (libhal_device_property_exists (manager->hal_ctx, udi, "net.linux.ifindex", NULL) &&
libhal_device_property_exists (manager->hal_ctx, udi, "info.category", NULL)) {
if (libhal_device_property_exists (priv->hal_ctx, udi, "net.linux.ifindex", NULL) &&
libhal_device_property_exists (priv->hal_ctx, udi, "info.category", NULL)) {
category = libhal_device_get_property_string (manager->hal_ctx, udi, "info.category", NULL);
category = libhal_device_get_property_string (priv->hal_ctx, udi, "info.category", NULL);
if (category) {
is_wireless = strcmp (category, "net.80211") == 0;
libhal_free_string (category);
@ -153,21 +171,22 @@ is_wireless_device (NMHalManager *manager, const char *udi)
return is_wireless;
}
static NMDevice *
wireless_device_creator (NMHalManager *manager, const char *udi, gboolean managed)
static GObject *
wireless_device_creator (NMHalManager *self, const char *udi, gboolean managed)
{
NMDevice *device;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
GObject *device;
char *iface;
char *driver;
iface = libhal_device_get_property_string (manager->hal_ctx, udi, "net.interface", NULL);
iface = libhal_device_get_property_string (priv->hal_ctx, udi, "net.interface", NULL);
if (!iface) {
nm_warning ("Couldn't get interface for %s, ignoring.", udi);
return NULL;
}
driver = nm_get_device_driver_name (manager->hal_ctx, udi);
device = (NMDevice *) nm_device_802_11_wireless_new (udi, iface, driver, managed);
driver = nm_get_device_driver_name (priv->hal_ctx, udi);
device = (GObject *) nm_device_802_11_wireless_new (udi, iface, driver, managed);
libhal_free_string (iface);
g_free (driver);
@ -178,14 +197,15 @@ wireless_device_creator (NMHalManager *manager, const char *udi, gboolean manage
/* Modem device creator */
static gboolean
is_modem_device (NMHalManager *manager, const char *udi)
is_modem_device (NMHalManager *self, const char *udi)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
gboolean is_modem = FALSE;
if (libhal_device_property_exists (manager->hal_ctx, udi, "info.category", NULL)) {
if (libhal_device_property_exists (priv->hal_ctx, udi, "info.category", NULL)) {
char *category;
category = libhal_device_get_property_string (manager->hal_ctx, udi, "info.category", NULL);
category = libhal_device_get_property_string (priv->hal_ctx, udi, "info.category", NULL);
if (category) {
is_modem = strcmp (category, "serial") == 0;
libhal_free_string (category);
@ -195,30 +215,31 @@ is_modem_device (NMHalManager *manager, const char *udi)
return is_modem;
}
static NMDevice *
modem_device_creator (NMHalManager *manager, const char *udi, gboolean managed)
static GObject *
modem_device_creator (NMHalManager *self, const char *udi, gboolean managed)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
char *serial_device;
char *parent_udi;
char *driver_name = NULL;
NMDevice *device = NULL;
GObject *device = NULL;
char **capabilities, **iter;
gboolean type_gsm = FALSE;
gboolean type_cdma = FALSE;
serial_device = libhal_device_get_property_string (manager->hal_ctx, udi, "serial.device", NULL);
serial_device = libhal_device_get_property_string (priv->hal_ctx, udi, "serial.device", NULL);
/* Get the driver */
parent_udi = libhal_device_get_property_string (manager->hal_ctx, udi, "info.parent", NULL);
parent_udi = libhal_device_get_property_string (priv->hal_ctx, udi, "info.parent", NULL);
if (parent_udi) {
driver_name = libhal_device_get_property_string (manager->hal_ctx, parent_udi, "info.linux.driver", NULL);
driver_name = libhal_device_get_property_string (priv->hal_ctx, parent_udi, "info.linux.driver", NULL);
libhal_free_string (parent_udi);
}
if (!serial_device || !driver_name)
goto out;
capabilities = libhal_device_get_property_strlist (manager->hal_ctx, udi, "modem.command_sets", NULL);
capabilities = libhal_device_get_property_strlist (priv->hal_ctx, udi, "modem.command_sets", NULL);
for (iter = capabilities; *iter; iter++) {
if (!strcmp (*iter, "GSM-07.07")) {
type_gsm = TRUE;
@ -233,7 +254,7 @@ modem_device_creator (NMHalManager *manager, const char *udi, gboolean managed)
/* Compatiblity with the pre-specification bits */
if (!type_gsm && !type_cdma) {
capabilities = libhal_device_get_property_strlist (manager->hal_ctx, udi, "info.capabilities", NULL);
capabilities = libhal_device_get_property_strlist (priv->hal_ctx, udi, "info.capabilities", NULL);
for (iter = capabilities; *iter; iter++) {
if (!strcmp (*iter, "gsm")) {
type_gsm = TRUE;
@ -248,9 +269,9 @@ modem_device_creator (NMHalManager *manager, const char *udi, gboolean managed)
}
if (type_gsm)
device = (NMDevice *) nm_gsm_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed);
device = (GObject *) nm_gsm_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed);
else if (type_cdma)
device = (NMDevice *) nm_cdma_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed);
device = (GObject *) nm_cdma_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed);
out:
libhal_free_string (serial_device);
@ -260,8 +281,9 @@ out:
}
static void
register_built_in_creators (NMHalManager *manager)
register_built_in_creators (NMHalManager *self)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
DeviceCreator *creator;
/* Wired device */
@ -270,7 +292,7 @@ register_built_in_creators (NMHalManager *manager)
creator->capability_str = g_strdup ("net.80203");
creator->is_device_fn = is_wired_device;
creator->creator_fn = wired_device_creator;
manager->device_creators = g_slist_append (manager->device_creators, creator);
priv->device_creators = g_slist_append (priv->device_creators, creator);
/* Wireless device */
creator = g_slice_new0 (DeviceCreator);
@ -278,7 +300,7 @@ register_built_in_creators (NMHalManager *manager)
creator->capability_str = g_strdup ("net.80211");
creator->is_device_fn = is_wireless_device;
creator->creator_fn = wireless_device_creator;
manager->device_creators = g_slist_append (manager->device_creators, creator);
priv->device_creators = g_slist_append (priv->device_creators, creator);
/* Modem */
creator = g_slice_new0 (DeviceCreator);
@ -286,91 +308,53 @@ register_built_in_creators (NMHalManager *manager)
creator->capability_str = g_strdup ("modem");
creator->is_device_fn = is_modem_device;
creator->creator_fn = modem_device_creator;
manager->device_creators = g_slist_append (manager->device_creators, creator);
}
static void
create_device_and_add_to_list (NMHalManager *manager,
DeviceCreator *creator,
const char *udi)
{
NMDevice *dev;
gboolean managed;
/* Make sure the device is not already in the device list */
if ((dev = nm_manager_get_device_by_udi (manager->nm_manager, udi)))
return;
managed = nm_manager_is_udi_managed (manager->nm_manager, udi);
dev = creator->creator_fn (manager, udi, managed);
if (dev) {
nm_info ("Found new %s device '%s'.",
creator->device_type_name,
nm_device_get_iface (dev));
nm_manager_add_device (manager->nm_manager, dev);
g_object_unref (dev);
}
priv->device_creators = g_slist_append (priv->device_creators, creator);
}
static void
device_added (LibHalContext *ctx, const char *udi)
{
NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx);
NMHalManager *self = NM_HAL_MANAGER (libhal_ctx_get_user_data (ctx));
DeviceCreator *creator;
// nm_debug ("New device added (hal udi is '%s').", udi );
/* Ignore device additions while asleep, all devices will
* be found and set up again on wake.
*/
if (nm_manager_get_state (manager->nm_manager) == NM_STATE_ASLEEP)
return;
/* Sometimes the device's properties (like net.interface) are not set up yet,
* so this call will fail, and it will actually be added when hal sets the device's
* capabilities a bit later on.
*/
creator = get_creator (manager, udi);
creator = get_creator (self, udi);
if (creator)
create_device_and_add_to_list (manager, creator, udi);
g_signal_emit (self, signals[UDI_ADDED], 0, udi, creator->device_type_name, creator->creator_fn);
}
static void
device_removed (LibHalContext *ctx, const char *udi)
{
NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx);
NMDevice *dev;
NMHalManager *self = NM_HAL_MANAGER (libhal_ctx_get_user_data (ctx));
// nm_debug ("Device removed (hal udi is '%s').", udi );
if ((dev = nm_manager_get_device_by_udi (manager->nm_manager, udi)))
nm_manager_remove_device (manager->nm_manager, dev, TRUE);
g_signal_emit (self, signals[UDI_REMOVED], 0, udi);
}
static void
device_new_capability (LibHalContext *ctx, const char *udi, const char *capability)
{
NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx);
NMHalManager *self = NM_HAL_MANAGER (libhal_ctx_get_user_data (ctx));
DeviceCreator *creator;
/*nm_debug ("nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );*/
// nm_debug ("nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );
/* Ignore device additions while asleep, all devices will
* be found and set up again on wake.
*/
if (nm_manager_get_state (manager->nm_manager) == NM_STATE_ASLEEP)
return;
creator = get_creator (manager, udi);
creator = get_creator (self, udi);
if (creator)
create_device_and_add_to_list (manager, creator, udi);
g_signal_emit (self, signals[UDI_ADDED], 0, udi, creator->device_type_name, creator->creator_fn);
}
static gboolean
add_initial_devices (gpointer user_data)
static void
add_initial_devices (NMHalManager *self)
{
NMHalManager *manager = (NMHalManager *) user_data;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
DeviceCreator *creator;
GSList *iter;
char **devices;
@ -378,13 +362,11 @@ add_initial_devices (gpointer user_data)
int i;
DBusError err;
manager->add_devices_id = 0;
for (iter = manager->device_creators; iter; iter = iter->next) {
for (iter = priv->device_creators; iter; iter = g_slist_next (iter)) {
creator = (DeviceCreator *) iter->data;
dbus_error_init (&err);
devices = libhal_find_device_by_capability (manager->hal_ctx,
devices = libhal_find_device_by_capability (priv->hal_ctx,
creator->capability_str,
&num_devices,
&err);
@ -396,21 +378,19 @@ add_initial_devices (gpointer user_data)
if (devices) {
for (i = 0; i < num_devices; i++) {
if (creator->is_device_fn (manager, devices[i]))
create_device_and_add_to_list (manager, creator, devices[i]);
if (!creator->is_device_fn (self, devices[i]))
continue;
g_signal_emit (self, signals[UDI_ADDED], 0, devices[i], creator->device_type_name, creator->creator_fn);
}
}
libhal_free_string_array (devices);
}
return FALSE;
}
typedef struct {
NMHalManager *manager;
gboolean initial_state;
gboolean changed;
gboolean rfkilled;
guint32 pending_polls;
GSList *proxies;
} NMKillswitchPollInfo;
@ -419,16 +399,20 @@ static void
killswitch_getpower_done (gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager);
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->pending_polls > 0)
return;
if (info->changed)
nm_manager_set_wireless_hardware_enabled (info->manager->nm_manager, !info->initial_state);
g_slist_foreach (info->proxies, (GFunc) g_object_unref, NULL);
g_slist_free (info->proxies);
info->proxies = NULL;
if (info->rfkilled != priv->rfkilled) {
priv->rfkilled = info->rfkilled;
g_signal_emit (info->manager, signals[RFKILL_CHANGED], 0, priv->rfkilled);
}
}
@ -438,23 +422,22 @@ killswitch_getpower_reply (DBusGProxy *proxy,
gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
int status;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager);
int power;
GError *err = NULL;
if (dbus_g_proxy_end_call (proxy, call_id, &err,
G_TYPE_INT, &status,
G_TYPE_INT, &power,
G_TYPE_INVALID)) {
if (!info->changed && info->initial_state != (status == 0) ? FALSE : TRUE)
info->changed = TRUE;
if (power == 0)
info->rfkilled = TRUE;
} else {
const char *prev_err = info->manager->kswitch_err;
/* Only print the error if we haven't seen it before */
if ( err->message
&& (!prev_err || strcmp (prev_err, err->message) != 0)) {
&& (!priv->kswitch_err || strcmp (priv->kswitch_err, err->message) != 0)) {
nm_warning ("Error getting killswitch power: %s.", err->message);
g_free (info->manager->kswitch_err);
info->manager->kswitch_err = g_strdup (err->message);
g_free (priv->kswitch_err);
priv->kswitch_err = g_strdup (err->message);
}
g_error_free (err);
}
@ -464,9 +447,10 @@ static void
poll_killswitches_real (gpointer data, gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager);
DBusGProxy *proxy;
proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (info->manager->dbus_mgr),
proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
"org.freedesktop.Hal",
(char *) data,
"org.freedesktop.Hal.Device.KillSwitch");
@ -484,12 +468,12 @@ static gboolean
poll_killswitches (gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager);
info->initial_state = nm_manager_wireless_hardware_enabled (info->manager->nm_manager);
info->changed = FALSE;
info->rfkilled = FALSE;
info->pending_polls = 0;
g_slist_foreach (info->manager->killswitch_list, poll_killswitches_real, info);
g_slist_foreach (priv->killswitch_list, poll_killswitches_real, info);
return TRUE;
}
@ -506,12 +490,13 @@ killswitch_poll_destroy (gpointer data)
}
static void
add_killswitch_device (NMHalManager *manager, const char *udi)
add_killswitch_device (NMHalManager *self, const char *udi)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
char *type;
GSList *iter;
type = libhal_device_get_property_string (manager->hal_ctx, udi, "killswitch.type", NULL);
type = libhal_device_get_property_string (priv->hal_ctx, udi, "killswitch.type", NULL);
if (!type)
return;
@ -519,27 +504,27 @@ add_killswitch_device (NMHalManager *manager, const char *udi)
goto out;
/* see if it's already in the list */
for (iter = manager->killswitch_list; iter; iter = iter->next) {
for (iter = priv->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) {
if (!priv->killswitch_list) {
NMKillswitchPollInfo *info;
info = g_slice_new0 (NMKillswitchPollInfo);
info->manager = manager;
info->manager = self;
manager->killswitch_poll_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
NM_HAL_MANAGER_KILLSWITCH_POLL_FREQUENCY * 1000,
priv->killswitch_poll_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
RFKILL_POLL_FREQUENCY * 1000,
poll_killswitches,
info,
killswitch_poll_destroy);
}
manager->killswitch_list = g_slist_append (manager->killswitch_list, g_strdup (udi));
priv->killswitch_list = g_slist_append (priv->killswitch_list, g_strdup (udi));
nm_info ("Found radio killswitch %s", udi);
out:
@ -547,15 +532,16 @@ out:
}
static void
add_killswitch_devices (NMHalManager *manager)
add_killswitch_devices (NMHalManager *self)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
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);
udis = libhal_find_device_by_capability (priv->hal_ctx, "killswitch", &num_udis, &err);
if (!udis)
return;
@ -566,44 +552,45 @@ add_killswitch_devices (NMHalManager *manager)
}
for (i = 0; i < num_udis; i++)
add_killswitch_device (manager, udis[i]);
add_killswitch_device (self, udis[i]);
libhal_free_string_array (udis);
}
static gboolean
hal_init (NMHalManager *manager)
hal_init (NMHalManager *self)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
DBusError error;
DBusGConnection *connection;
manager->hal_ctx = libhal_ctx_new ();
if (!manager->hal_ctx) {
priv->hal_ctx = libhal_ctx_new ();
if (!priv->hal_ctx) {
nm_warning ("Could not get connection to the HAL service.");
return FALSE;
}
connection = nm_dbus_manager_get_connection (manager->dbus_mgr);
libhal_ctx_set_dbus_connection (manager->hal_ctx,
connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
libhal_ctx_set_dbus_connection (priv->hal_ctx,
dbus_g_connection_get_connection (connection));
dbus_error_init (&error);
if (!libhal_ctx_init (manager->hal_ctx, &error)) {
nm_error ("libhal_ctx_init() failed: %s\n"
"Make sure the hal daemon is running?",
error.message);
if (!libhal_ctx_init (priv->hal_ctx, &error)) {
nm_warning ("libhal_ctx_init() failed: %s\n"
"Make sure the hal daemon is running?",
error.message);
goto error;
}
libhal_ctx_set_user_data (manager->hal_ctx, manager);
libhal_ctx_set_device_added (manager->hal_ctx, device_added);
libhal_ctx_set_device_removed (manager->hal_ctx, device_removed);
libhal_ctx_set_device_new_capability (manager->hal_ctx, device_new_capability);
libhal_ctx_set_user_data (priv->hal_ctx, self);
libhal_ctx_set_device_added (priv->hal_ctx, device_added);
libhal_ctx_set_device_removed (priv->hal_ctx, device_removed);
libhal_ctx_set_device_new_capability (priv->hal_ctx, device_new_capability);
libhal_device_property_watch_all (manager->hal_ctx, &error);
libhal_device_property_watch_all (priv->hal_ctx, &error);
if (dbus_error_is_set (&error)) {
nm_error ("libhal_device_property_watch_all(): %s", error.message);
libhal_ctx_shutdown (manager->hal_ctx, NULL);
libhal_ctx_shutdown (priv->hal_ctx, NULL);
goto error;
}
@ -612,41 +599,42 @@ hal_init (NMHalManager *manager)
error:
if (dbus_error_is_set (&error))
dbus_error_free (&error);
if (manager->hal_ctx) {
libhal_ctx_free (manager->hal_ctx);
manager->hal_ctx = NULL;
if (priv->hal_ctx) {
libhal_ctx_free (priv->hal_ctx);
priv->hal_ctx = NULL;
}
return FALSE;
}
static void
hal_deinit (NMHalManager *manager)
hal_deinit (NMHalManager *self)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
DBusError error;
if (manager->killswitch_poll_id) {
g_source_remove (manager->killswitch_poll_id);
manager->killswitch_poll_id = 0;
if (priv->killswitch_poll_id) {
g_source_remove (priv->killswitch_poll_id);
priv->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 (priv->killswitch_list) {
g_slist_foreach (priv->killswitch_list, (GFunc) g_free, NULL);
g_slist_free (priv->killswitch_list);
priv->killswitch_list = NULL;
}
if (!manager->hal_ctx)
if (!priv->hal_ctx)
return;
dbus_error_init (&error);
libhal_ctx_shutdown (manager->hal_ctx, &error);
libhal_ctx_shutdown (priv->hal_ctx, &error);
if (dbus_error_is_set (&error)) {
nm_warning ("libhal shutdown failed - %s", error.message);
dbus_error_free (&error);
}
libhal_ctx_free (manager->hal_ctx);
manager->hal_ctx = NULL;
libhal_ctx_free (priv->hal_ctx);
priv->hal_ctx = NULL;
}
static void
@ -656,21 +644,25 @@ name_owner_changed (NMDBusManager *dbus_mgr,
const char *new,
gpointer user_data)
{
NMHalManager *manager = (NMHalManager *) user_data;
NMHalManager *self = NM_HAL_MANAGER (user_data);
gboolean old_owner_good = (old && (strlen (old) > 0));
gboolean new_owner_good = (new && (strlen (new) > 0));
/* Only care about signals from HAL */
if (strcmp (name, "org.freedesktop.Hal"))
if (strcmp (name, HAL_DBUS_SERVICE))
return;
if (!old_owner_good && new_owner_good) {
nm_info ("HAL re-appeared");
/* HAL just appeared */
if (!hal_init (manager))
exit (1);
if (!hal_init (self))
nm_warning ("Could not re-connect to HAL!!");
else
g_signal_emit (self, signals[HAL_REAPPEARED], 0);
} else if (old_owner_good && !new_owner_good) {
/* HAL went away. Bad HAL. */
hal_deinit (manager);
nm_info ("HAL disappeared");
hal_deinit (self);
}
}
@ -679,94 +671,80 @@ connection_changed (NMDBusManager *dbus_mgr,
DBusGConnection *connection,
gpointer user_data)
{
NMHalManager *manager = (NMHalManager *) user_data;
char *owner;
NMHalManager *self = NM_HAL_MANAGER (user_data);
if (!connection) {
hal_deinit (manager);
hal_deinit (self);
return;
}
if ((owner = nm_dbus_manager_get_name_owner (dbus_mgr, "org.freedesktop.Hal"))) {
if (!hal_init (manager))
exit (1);
g_free (owner);
if (nm_dbus_manager_name_has_owner (dbus_mgr, HAL_DBUS_SERVICE)) {
if (!hal_init (self))
nm_warning ("Could not re-connect to HAL!!");
}
}
static void
nm_manager_state_changed (NMManager *nm_manager, NMState state, gpointer user_data)
{
NMHalManager *manager = (NMHalManager *) user_data;
if (state == NM_STATE_ASLEEP) {
/* Save the sleep state */
manager->nm_sleeping = TRUE;
} else if (manager->nm_sleeping) {
/* If the previous state was sleep, the next one means we just woke up */
manager->nm_sleeping = FALSE;
/* Punt adding back devices to an idle handler to give the manager
* time to push signals out over D-Bus when it wakes up. Since the
* signal emission might ref the old pre-sleep device, when the new
* device gets found there will be a D-Bus object path conflict between
* the old device and the new device, and dbus-glib "helpfully" asserts
* here and we die.
*/
if (manager->add_devices_id)
g_source_remove (manager->add_devices_id);
manager->add_devices_id = g_idle_add_full (G_PRIORITY_LOW,
add_initial_devices,
manager,
NULL);
}
}
NMHalManager *
nm_hal_manager_new (NMManager *nm_manager)
{
NMHalManager *manager;
NMDBusManager *dbus_mgr;
g_return_val_if_fail (NM_IS_MANAGER (nm_manager), NULL);
dbus_mgr = nm_dbus_manager_get ();
if (!nm_dbus_manager_name_has_owner (dbus_mgr, "org.freedesktop.Hal")) {
nm_warning ("Could not initialize connection to the HAL daemon.");
return NULL;
}
manager = g_slice_new0 (NMHalManager);
manager->nm_manager = g_object_ref (nm_manager);
manager->dbus_mgr = dbus_mgr;
register_built_in_creators (manager);
g_signal_connect (manager->dbus_mgr,
"name-owner-changed",
G_CALLBACK (name_owner_changed),
manager);
g_signal_connect (manager->dbus_mgr,
"dbus-connection-changed",
G_CALLBACK (connection_changed),
manager);
g_signal_connect (nm_manager,
"state-changed",
G_CALLBACK (nm_manager_state_changed),
manager);
hal_init (manager);
return manager;
}
void
nm_hal_manager_start (NMHalManager *manager)
nm_hal_manager_query_devices (NMHalManager *self)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
/* Find hardware we care about */
add_killswitch_devices (manager);
add_initial_devices (manager);
if (priv->hal_ctx) {
add_killswitch_devices (self);
add_initial_devices (self);
}
}
gboolean
nm_hal_manager_udi_exists (NMHalManager *self, const char *udi)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
return libhal_device_property_exists (priv->hal_ctx, udi, "info.udi", NULL);
}
NMHalManager *
nm_hal_manager_new (void)
{
NMHalManager *self;
NMHalManagerPrivate *priv;
self = NM_HAL_MANAGER (g_object_new (NM_TYPE_HAL_MANAGER, NULL));
priv = NM_HAL_MANAGER_GET_PRIVATE (self);
if (!nm_dbus_manager_name_has_owner (priv->dbus_mgr, HAL_DBUS_SERVICE)) {
nm_info ("Waiting for HAL to start...");
return self;
}
if (!hal_init (self)) {
g_object_unref (self);
self = NULL;
}
return self;
}
static void
nm_hal_manager_init (NMHalManager *self)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
priv->rfkilled = FALSE;
priv->dbus_mgr = nm_dbus_manager_get ();
register_built_in_creators (self);
g_signal_connect (priv->dbus_mgr,
"name-owner-changed",
G_CALLBACK (name_owner_changed),
self);
g_signal_connect (priv->dbus_mgr,
"dbus-connection-changed",
G_CALLBACK (connection_changed),
self);
}
static void
@ -779,23 +757,88 @@ destroy_creator (gpointer data, gpointer user_data)
g_slice_free (DeviceCreator, data);
}
void
nm_hal_manager_destroy (NMHalManager *manager)
static void
dispose (GObject *object)
{
if (!manager)
NMHalManager *self = NM_HAL_MANAGER (object);
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
if (priv->disposed) {
G_OBJECT_CLASS (nm_hal_manager_parent_class)->dispose (object);
return;
if (manager->add_devices_id) {
g_source_remove (manager->add_devices_id);
manager->add_devices_id = 0;
}
priv->disposed = TRUE;
g_free (manager->kswitch_err);
g_object_unref (priv->dbus_mgr);
g_slist_foreach (manager->device_creators, destroy_creator, NULL);
g_slist_free (manager->device_creators);
g_slist_foreach (priv->device_creators, destroy_creator, NULL);
g_slist_free (priv->device_creators);
hal_deinit (manager);
g_object_unref (manager->nm_manager);
g_slice_free (NMHalManager, manager);
hal_deinit (self);
G_OBJECT_CLASS (nm_hal_manager_parent_class)->dispose (object);
}
static void
finalize (GObject *object)
{
NMHalManager *self = NM_HAL_MANAGER (object);
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
g_free (priv->kswitch_err);
G_OBJECT_CLASS (nm_hal_manager_parent_class)->finalize (object);
}
static void
nm_hal_manager_class_init (NMHalManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (NMHalManagerPrivate));
/* virtual methods */
object_class->dispose = dispose;
object_class->finalize = finalize;
/* Signals */
signals[UDI_ADDED] =
g_signal_new ("udi-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMHalManagerClass, udi_added),
NULL, NULL,
nm_marshal_VOID__STRING_STRING_POINTER,
G_TYPE_NONE, 3,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
signals[UDI_REMOVED] =
g_signal_new ("udi-removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMHalManagerClass, udi_removed),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1,
G_TYPE_STRING);
signals[RFKILL_CHANGED] =
g_signal_new ("rfkill-changed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMHalManagerClass, rfkill_changed),
NULL, NULL,
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1,
G_TYPE_BOOLEAN);
signals[HAL_REAPPEARED] =
g_signal_new ("hal-reappeared",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMHalManagerClass, hal_reappeared),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}

View file

@ -1,12 +1,47 @@
#ifndef NM_HAL_MANAGER_H
#define NM_HAL_MANAGER_H
#include "nm-manager.h"
#include <glib/gtypes.h>
#include <glib-object.h>
typedef struct _NMHalManager NMHalManager;
G_BEGIN_DECLS
NMHalManager *nm_hal_manager_new (NMManager *nm_manager);
void nm_hal_manager_start (NMHalManager *manager);
void nm_hal_manager_destroy (NMHalManager *manager);
#define NM_TYPE_HAL_MANAGER (nm_hal_manager_get_type ())
#define NM_HAL_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_HAL_MANAGER, NMHalManager))
#define NM_HAL_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_HAL_MANAGER, NMHalManagerClass))
#define NM_IS_HAL_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_HAL_MANAGER))
#define NM_IS_HAL_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_HAL_MANAGER))
#define NM_HAL_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_HAL_MANAGER, NMHalManagerClass))
typedef struct {
GObject parent;
} NMHalManager;
typedef GObject *(*NMDeviceCreatorFn) (NMHalManager *manager,
const char *udi,
gboolean managed);
typedef struct {
GObjectClass parent;
/* Virtual functions */
void (*udi_added) (NMHalManager *manager,
const char *udi,
const char *type_name,
NMDeviceCreatorFn creator_fn);
void (*udi_removed) (NMHalManager *manager, const char *udi);
void (*rfkill_changed) (NMHalManager *manager, gboolean hw_enabled);
void (*hal_reappeared) (NMHalManager *manager);
} NMHalManagerClass;
GType nm_hal_manager_get_type (void);
NMHalManager *nm_hal_manager_new (void);
gboolean nm_hal_manager_get_rfkilled (NMHalManager *manager);
void nm_hal_manager_query_devices (NMHalManager *manager);
gboolean nm_hal_manager_udi_exists (NMHalManager *manager, const char *udi);
#endif /* NM_HAL_MANAGER_H */

View file

@ -17,6 +17,7 @@
#include "nm-setting-vpn.h"
#include "nm-marshal.h"
#include "nm-dbus-glib-types.h"
#include "nm-hal-manager.h"
static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err);
static void impl_manager_activate_connection (NMManager *manager,
@ -49,6 +50,27 @@ static void connection_added_default_handler (NMManager *manager,
NMConnection *connection,
NMConnectionScope scope);
static void manager_device_state_changed (NMDevice *device,
NMDeviceState state,
gpointer user_data);
static void hal_manager_udi_added_cb (NMHalManager *hal_mgr,
const char *udi,
const char *type_name,
NMDeviceCreatorFn creator_fn,
gpointer user_data);
static void hal_manager_udi_removed_cb (NMHalManager *hal_mgr,
const char *udi,
gpointer user_data);
static void hal_manager_rfkill_changed_cb (NMHalManager *hal_mgr,
gboolean rfkilled,
gpointer user_data);
static void hal_manager_hal_reappeared_cb (NMHalManager *hal_mgr,
gpointer user_data);
#define SSD_POKE_INTERVAL 120000
typedef struct {
@ -65,6 +87,7 @@ typedef struct {
NMState state;
NMDBusManager *dbus_mgr;
NMHalManager *hal_mgr;
GHashTable *user_connections;
DBusGProxy *user_proxy;
@ -80,6 +103,7 @@ typedef struct {
gboolean sleeping;
guint poke_id;
guint add_devices_id;
NMVPNManager *vpn_manager;
guint vpn_manager_id;
@ -277,6 +301,18 @@ pending_connection_info_destroy (PendingConnectionInfo *info)
g_slice_free (PendingConnectionInfo, info);
}
static void
remove_one_device (NMManager *manager, NMDevice *device)
{
if (nm_device_get_managed (device))
nm_device_set_managed (device, FALSE);
g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager);
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device);
g_object_unref (device);
}
static void
dispose (GObject *object)
{
@ -292,8 +328,15 @@ dispose (GObject *object)
pending_connection_info_destroy (priv->pending_connection_info);
priv->pending_connection_info = NULL;
while (g_slist_length (priv->devices))
nm_manager_remove_device (manager, NM_DEVICE (priv->devices->data), TRUE);
if (priv->add_devices_id) {
g_source_remove (priv->add_devices_id);
priv->add_devices_id = 0;
}
while (g_slist_length (priv->devices)) {
remove_one_device (manager, NM_DEVICE (priv->devices->data));
priv->devices = g_slist_remove_link (priv->devices, priv->devices);
}
nm_manager_connections_destroy (manager, NM_CONNECTION_SCOPE_USER);
g_hash_table_destroy (priv->user_connections);
@ -322,6 +365,7 @@ dispose (GObject *object)
g_object_unref (priv->vpn_manager);
g_object_unref (priv->dbus_mgr);
g_object_unref (priv->hal_mgr);
G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object);
}
@ -919,6 +963,18 @@ query_connections (NMManager *manager,
G_TYPE_INVALID);
}
static NMDevice *
nm_manager_get_device_by_udi (NMManager *manager, const char *udi)
{
GSList *iter;
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
if (!strcmp (nm_device_get_udi (NM_DEVICE (iter->data)), udi))
return NM_DEVICE (iter->data);
}
return NULL;
}
static void
handle_unmanaged_devices (NMManager *manager, GPtrArray *ops)
{
@ -1140,6 +1196,17 @@ initial_get_connections (gpointer user_data)
return FALSE;
}
static gboolean
deferred_hal_manager_query_devices (gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
priv->add_devices_id = 0;
nm_hal_manager_query_devices (priv->hal_mgr);
return FALSE;
}
NMManager *
nm_manager_new (void)
@ -1161,6 +1228,29 @@ nm_manager_new (void)
g_idle_add ((GSourceFunc) initial_get_connections, NM_MANAGER (object));
priv->hal_mgr = nm_hal_manager_new ();
g_idle_add (deferred_hal_manager_query_devices, object);
g_signal_connect (priv->hal_mgr,
"udi-added",
G_CALLBACK (hal_manager_udi_added_cb),
NM_MANAGER (object));
g_signal_connect (priv->hal_mgr,
"udi-removed",
G_CALLBACK (hal_manager_udi_removed_cb),
NM_MANAGER (object));
g_signal_connect (priv->hal_mgr,
"rfkill-changed",
G_CALLBACK (hal_manager_rfkill_changed_cb),
NM_MANAGER (object));
g_signal_connect (priv->hal_mgr,
"hal-reappeared",
G_CALLBACK (hal_manager_hal_reappeared_cb),
NM_MANAGER (object));
return NM_MANAGER (object);
}
@ -1235,7 +1325,7 @@ manager_set_wireless_enabled (NMManager *manager, gboolean enabled)
}
static void
manager_device_state_changed (NMDeviceInterface *device, NMDeviceState state, gpointer user_data)
manager_device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data)
{
NMManager *manager = NM_MANAGER (user_data);
@ -1308,21 +1398,44 @@ next:
g_slist_free (connections);
}
void
nm_manager_add_device (NMManager *manager, NMDevice *device)
static void
hal_manager_udi_added_cb (NMHalManager *hal_mgr,
const char *udi,
const char *type_name,
NMDeviceCreatorFn creator_fn,
gpointer user_data)
{
NMManagerPrivate *priv;
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
gboolean managed = TRUE;
GObject *device;
GSList *iter;
const char *iface;
g_return_if_fail (NM_IS_MANAGER (manager));
g_return_if_fail (NM_IS_DEVICE (device));
if (priv->sleeping)
return;
priv = NM_MANAGER_GET_PRIVATE (manager);
/* Make sure the device is not already in the device list */
if (nm_manager_get_device_by_udi (self, udi))
return;
priv->devices = g_slist_append (priv->devices, g_object_ref (device));
/* Figure out if the device is managed or not */
for (iter = priv->unmanaged_udis; iter; iter = g_slist_next (iter)) {
if (!strcmp (udi, iter->data)) {
managed = FALSE;
break;
}
}
device = creator_fn (hal_mgr, udi, managed);
if (!device)
return;
priv->devices = g_slist_append (priv->devices, device);
g_signal_connect (device, "state-changed",
G_CALLBACK (manager_device_state_changed),
manager);
self);
/* Attach to the access-point-added signal so that the manager can fill
* non-SSID-broadcasting APs with an SSID.
@ -1330,50 +1443,88 @@ nm_manager_add_device (NMManager *manager, NMDevice *device)
if (NM_IS_DEVICE_802_11_WIRELESS (device)) {
g_signal_connect (device, "hidden-ap-found",
G_CALLBACK (manager_hidden_ap_found),
manager);
self);
/* Set initial rfkill state */
nm_device_802_11_wireless_set_enabled (NM_DEVICE_802_11_WIRELESS (device), priv->wireless_enabled);
}
nm_info ("(%s): exported as %s",
nm_device_get_iface (device),
nm_device_get_udi (device));
iface = nm_device_get_iface (NM_DEVICE (device));
nm_info ("Found new %s device '%s'.", type_name, iface);
dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (priv->dbus_mgr),
nm_device_get_udi (device),
G_OBJECT (device));
nm_device_get_udi (NM_DEVICE (device)),
device);
nm_info ("(%s): exported as %s", iface, udi);
g_signal_emit (manager, signals[DEVICE_ADDED], 0, device);
g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
}
void
nm_manager_remove_device (NMManager *manager, NMDevice *device, gboolean deactivate)
static void
hal_manager_udi_removed_cb (NMHalManager *manager,
const char *udi,
gpointer user_data)
{
NMManagerPrivate *priv;
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GSList *iter;
g_return_if_fail (NM_IS_MANAGER (manager));
g_return_if_fail (NM_IS_DEVICE (device));
priv = NM_MANAGER_GET_PRIVATE (manager);
g_return_if_fail (udi != NULL);
for (iter = priv->devices; iter; iter = iter->next) {
if (iter->data == device) {
NMDevice *device = NM_DEVICE (iter->data);
if (!strcmp (nm_device_get_udi (device), udi)) {
priv->devices = g_slist_delete_link (priv->devices, iter);
if (nm_device_get_managed (device))
nm_device_set_managed (device, FALSE);
g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager);
g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device);
g_object_unref (device);
remove_one_device (self, device);
break;
}
}
}
static void
hal_manager_rfkill_changed_cb (NMHalManager *hal_mgr,
gboolean rfkilled,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
gboolean enabled = !rfkilled;
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 (self), NM_MANAGER_WIRELESS_HARDWARE_ENABLED);
manager_set_wireless_enabled (self, enabled);
}
}
static void
hal_manager_hal_reappeared_cb (NMHalManager *hal_mgr,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GSList *iter;
/* Remove devices which are no longer known to HAL */
for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
NMDevice *device = NM_DEVICE (iter->data);
GSList *next = iter->next;
if (nm_hal_manager_udi_exists (priv->hal_mgr, nm_device_get_udi (device)))
continue;
priv->devices = g_slist_delete_link (priv->devices, iter);
remove_one_device (self, device);
iter = next;
}
/* Get any new ones */
nm_hal_manager_query_devices (priv->hal_mgr);
}
GSList *
nm_manager_get_devices (NMManager *manager)
{
@ -1396,41 +1547,6 @@ impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err)
return TRUE;
}
NMDevice *
nm_manager_get_device_by_path (NMManager *manager, const char *path)
{
GSList *iter;
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
g_return_val_if_fail (path != NULL, NULL);
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
NMDevice *device = NM_DEVICE (iter->data);
if (!strcmp (nm_device_get_udi (device), path))
return device;
}
return NULL;
}
NMDevice *
nm_manager_get_device_by_udi (NMManager *manager, const char *udi)
{
GSList *iter;
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) {
NMDevice *device = NM_DEVICE (iter->data);
if (!strcmp (nm_device_get_udi (device), udi))
return device;
}
return NULL;
}
static NMActRequest *
nm_manager_get_act_request_by_path (NMManager *manager,
const char *path,
@ -1494,14 +1610,6 @@ internal_activate_device (NMManager *manager,
return success ? nm_act_request_get_active_connection_path (req) : NULL;
}
gboolean
nm_manager_activation_pending (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->pending_connection_info != NULL;
}
static gboolean
wait_for_connection_expired (gpointer data)
{
@ -1578,7 +1686,7 @@ nm_manager_activate_connection (NMManager *manager,
NMDeviceState state;
/* Device-based connection */
device = nm_manager_get_device_by_path (manager, device_path);
device = nm_manager_get_device_by_udi (manager, device_path);
if (!device) {
g_set_error (error,
NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
@ -1773,41 +1881,6 @@ impl_manager_deactivate_connection (NMManager *manager,
return nm_manager_deactivate_connection (manager, connection_path, error);
}
gboolean
nm_manager_wireless_enabled (NMManager *manager)
{
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
return NM_MANAGER_GET_PRIVATE (manager)->wireless_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);
}
}
static gboolean
impl_manager_sleep (NMManager *manager, gboolean sleep, GError **error)
{
@ -1839,10 +1912,24 @@ impl_manager_sleep (NMManager *manager, gboolean sleep, GError **error)
} else {
nm_info ("Waking up...");
while (g_slist_length (priv->devices))
nm_manager_remove_device (manager, NM_DEVICE (priv->devices->data), FALSE);
while (g_slist_length (priv->devices)) {
remove_one_device (manager, NM_DEVICE (priv->devices->data));
priv->devices = g_slist_remove_link (priv->devices, priv->devices);
}
priv->devices = NULL;
/* Punt adding back devices to an idle handler to give the manager
* time to push signals out over D-Bus when it wakes up. Since the
* signal emission might ref the old pre-sleep device, when the new
* device gets found there will be a D-Bus object path conflict between
* the old device and the new device, and dbus-glib "helpfully" asserts
* here and we die.
*/
if (priv->add_devices_id)
g_source_remove (priv->add_devices_id);
priv->add_devices_id = g_idle_add_full (G_PRIORITY_LOW,
deferred_hal_manager_query_devices,
manager,
NULL);
}
nm_manager_update_state (manager);
@ -1960,19 +2047,3 @@ nm_manager_get_active_connections_by_connection (NMManager *manager,
return get_active_connections (manager, connection);
}
gboolean
nm_manager_is_udi_managed (NMManager *manager, const char *udi)
{
NMManagerPrivate *priv;
GSList *iter;
g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE);
priv = NM_MANAGER_GET_PRIVATE (manager);
for (iter = priv->unmanaged_udis; iter; iter = g_slist_next (iter)) {
if (!strcmp (udi, iter->data))
return FALSE;
}
return TRUE;
}

View file

@ -56,12 +56,7 @@ NMManager *nm_manager_new (void);
/* Device handling */
void nm_manager_add_device (NMManager *manager, NMDevice *device);
void nm_manager_remove_device (NMManager *manager, NMDevice *device, gboolean deactivate);
GSList *nm_manager_get_devices (NMManager *manager);
NMDevice *nm_manager_get_device_by_path (NMManager *manager, const char *path);
NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi);
gboolean nm_manager_is_udi_managed (NMManager *manager, const char *udi);
const char * nm_manager_activate_connection (NMManager *manager,
NMConnection *connection,
@ -74,15 +69,9 @@ gboolean nm_manager_deactivate_connection (NMManager *manager,
const char *connection_path,
GError **error);
gboolean nm_manager_activation_pending (NMManager *manager);
/* State handling */
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);
/* Connections */