From d98c431c65c3f7e129b387e6122d8f827b8ee871 Mon Sep 17 00:00:00 2001 From: Tambet Ingo Date: Tue, 22 Dec 2009 09:11:30 +0200 Subject: [PATCH 01/12] system-settings: Fix using hostname from DHCP When a plugin has hostname capability, it's NULL for hostname means "use the hostname from DHCP server". --- src/system-settings/nm-sysconfig-settings.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index 104eb008ab..7580319db0 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -254,6 +254,7 @@ nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self) NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); GSList *iter; char *hostname = NULL; + gboolean have_hostname_providers = FALSE; /* Hostname returned is the hostname returned from the first plugin * that provides one. @@ -263,6 +264,8 @@ nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self) g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL); if (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME) { + have_hostname_providers = TRUE; + g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, &hostname, NULL); if (hostname && strlen (hostname)) return hostname; @@ -271,7 +274,7 @@ nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self) } /* If no plugin provided a hostname, try the original hostname of the machine */ - if (priv->orig_hostname) + if (!have_hostname_providers && priv->orig_hostname) hostname = g_strdup (priv->orig_hostname); return hostname; From 7b10ec29a2de9b7165dec6ac232dedf21a8360c3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Dec 2009 11:52:15 -0800 Subject: [PATCH 02/12] modem: fix enable/disable/disconnect flow NM shouldn't really be calling Enable(False) except in response to direct user requests to turn off WWAN, much like rfkill, since Enable(False) /is/ essentially rfkill for 3G. Instead, we should be powering up the modem before trying to use it, and only disconnecting after we're done. Let the user do enable/disable when they want to. This also fixes issues with other devices like GPS potentially using the modem-manager at the same time as NM and ensures that NM won't punch the modem in the face while GPS is using it. --- src/modem-manager/nm-modem-cdma.c | 27 +++++++++++++++++++-- src/modem-manager/nm-modem-gsm.c | 39 ++++++++++++++++++++++++++----- src/modem-manager/nm-modem.c | 13 +++++++---- 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index 30feb28a79..ee524aa1d5 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -115,12 +115,22 @@ create_connect_properties (NMConnection *connection) return properties; } -static NMActStageReturn -real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +static void +stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { + NMDevice *device = NM_DEVICE (user_data); + GError *error = NULL; NMConnection *connection; GHashTable *properties; + dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); + if (error) { + nm_warning ("CDMA modem connection failed: %s", error->message); + g_error_free (error); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + return; + } + connection = nm_act_request_get_connection (nm_device_get_act_request (device)); g_assert (connection); @@ -130,6 +140,19 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) device, NULL, 120000, DBUS_TYPE_G_MAP_OF_VARIANT, properties, G_TYPE_INVALID); + g_hash_table_destroy (properties); +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + gboolean enable = TRUE; + + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), + "Enable", stage1_enable_done, + device, NULL, 20000, + G_TYPE_BOOLEAN, enable, + G_TYPE_INVALID); return NM_ACT_STAGE_RETURN_POSTPONE; } diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index 2bd8b231a9..d1e97dcbf5 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -247,6 +247,34 @@ create_connect_properties (NMConnection *connection) return properties; } +static void +stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + GError *error = NULL; + NMConnection *connection; + GHashTable *properties; + + dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); + if (error) { + nm_warning ("GSM modem connection failed: %s", error->message); + g_error_free (error); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + return; + } + + connection = nm_act_request_get_connection (nm_device_get_act_request (device)); + g_assert (connection); + + properties = create_connect_properties (connection); + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), + "Connect", stage1_prepare_done, + device, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, properties, + G_TYPE_INVALID); + g_hash_table_destroy (properties); +} + static NMActStageReturn real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { @@ -264,13 +292,12 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) setting_name = nm_connection_need_secrets (connection, &hints); if (!setting_name) { - GHashTable *properties; + gboolean enable = TRUE; - properties = create_connect_properties (connection); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), - "Connect", stage1_prepare_done, - device, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, properties, + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), + "Enable", stage1_enable_done, + device, NULL, 20000, + G_TYPE_BOOLEAN, enable, G_TYPE_INVALID); return NM_ACT_STAGE_RETURN_POSTPONE; diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 3895a7d83e..3bc7bab4a9 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -425,6 +425,10 @@ device_state_changed (NMDeviceInterface *device, { NMModem *self = NM_MODEM (user_data); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + gboolean was_connected = FALSE; + + if (IS_ACTIVATING_STATE (old_state) || (old_state == NM_DEVICE_STATE_ACTIVATED)) + was_connected = TRUE; /* Make sure we don't leave the serial device open */ switch (new_state) { @@ -436,10 +440,11 @@ device_state_changed (NMDeviceInterface *device, case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_DISCONNECTED: - dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, NULL), - "Enable", - G_TYPE_BOOLEAN, FALSE, - G_TYPE_INVALID); + if (was_connected) { + dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM), + "Disconnect", + G_TYPE_INVALID); + } break; default: break; From 052cf6b2e25dfd46880ad96a51cd9fa805e90978 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Dec 2009 23:36:57 -0800 Subject: [PATCH 03/12] core: generalize interface for enabling/disabling devices We'll use it for WWAN too. --- src/nm-device-interface.c | 9 +++++++++ src/nm-device-interface.h | 4 ++++ src/nm-device-wifi.c | 20 +++++++++++++------- src/nm-device-wifi.h | 2 -- src/nm-manager.c | 6 +++--- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c index f53a6028b8..70cce8b624 100644 --- a/src/nm-device-interface.c +++ b/src/nm-device-interface.c @@ -355,3 +355,12 @@ nm_device_interface_can_assume_connection (NMDeviceInterface *device) return !!NM_DEVICE_INTERFACE_GET_INTERFACE (device)->connection_match_config; } +void +nm_device_interface_set_enabled (NMDeviceInterface *device, gboolean enabled) +{ + g_return_if_fail (NM_IS_DEVICE_INTERFACE (device)); + + if (NM_DEVICE_INTERFACE_GET_INTERFACE (device)->set_enabled) + return NM_DEVICE_INTERFACE_GET_INTERFACE (device)->set_enabled (device, enabled); +} + diff --git a/src/nm-device-interface.h b/src/nm-device-interface.h index 54b5c41a59..0ec5e3da14 100644 --- a/src/nm-device-interface.h +++ b/src/nm-device-interface.h @@ -97,6 +97,8 @@ struct _NMDeviceInterface { NMConnection * (*connection_match_config) (NMDeviceInterface *device, const GSList *specs); + void (*set_enabled) (NMDeviceInterface *device, gboolean enabled); + /* Signals */ void (*state_changed) (NMDeviceInterface *device, NMDeviceState new_state, @@ -131,4 +133,6 @@ NMConnection * nm_device_interface_connection_match_config (NMDeviceInterface *d gboolean nm_device_interface_can_assume_connection (NMDeviceInterface *device); +void nm_device_interface_set_enabled (NMDeviceInterface *device, gboolean enabled); + #endif /* NM_DEVICE_INTERFACE_H */ diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 20b73fb2fb..972a7de597 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -69,8 +69,10 @@ static gboolean impl_device_get_access_points (NMDeviceWifi *device, #define WIRELESS_SECRETS_TRIES "wireless-secrets-tries" +static void device_interface_init (NMDeviceInterface *iface_class); -G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) +G_DEFINE_TYPE_EXTENDED (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init)) #define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate)) @@ -3420,15 +3422,13 @@ nm_device_wifi_get_activation_ap (NMDeviceWifi *self) return NULL; } -void -nm_device_wifi_set_enabled (NMDeviceWifi *self, gboolean enabled) +static void +real_set_enabled (NMDeviceInterface *device, gboolean enabled) { - NMDeviceWifiPrivate *priv; + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDeviceState state; - g_return_if_fail (NM_IS_DEVICE_WIFI (self)); - - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); if (priv->enabled == enabled) return; @@ -3490,6 +3490,12 @@ nm_device_wifi_new (const char *udi, NULL); } +static void +device_interface_init (NMDeviceInterface *iface_class) +{ + iface_class->set_enabled = real_set_enabled; +} + static void nm_device_wifi_init (NMDeviceWifi * self) { diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h index 126bc13982..c793844c5c 100644 --- a/src/nm-device-wifi.h +++ b/src/nm-device-wifi.h @@ -102,8 +102,6 @@ NM80211Mode nm_device_wifi_get_mode (NMDeviceWifi *self); NMAccessPoint * nm_device_wifi_get_activation_ap (NMDeviceWifi *self); -void nm_device_wifi_set_enabled (NMDeviceWifi *self, gboolean enabled); - guint32 nm_device_wifi_get_ifindex (NMDeviceWifi *self); RfKillState nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self); diff --git a/src/nm-manager.c b/src/nm-manager.c index 14c2a907e0..59d2bbe9d9 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1184,7 +1184,7 @@ manager_set_wireless_enabled (NMManager *manager, gboolean enabled) /* enable/disable wireless devices as required */ for (iter = priv->devices; iter; iter = iter->next) { if (NM_IS_DEVICE_WIFI (iter->data)) - nm_device_wifi_set_enabled (NM_DEVICE_WIFI (iter->data), enabled); + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (iter->data), enabled); } } @@ -1371,7 +1371,7 @@ add_device (NMManager *self, NMDevice *device) * then set this device's rfkill state based on the global state. */ nm_manager_rfkill_update (self); - nm_device_wifi_set_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled); + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), priv->wireless_enabled); } type_desc = nm_device_get_type_desc (device); @@ -2562,7 +2562,7 @@ impl_manager_sleep (NMManager *self, gboolean sleep, GError **error) * to killswitch changes during sleep. */ if (NM_IS_DEVICE_WIFI (iter->data)) - nm_device_wifi_set_enabled (NM_DEVICE_WIFI (iter->data), wifi_enabled); + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (iter->data), wifi_enabled); nm_device_clear_autoconnect_inhibit (device); if (nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs)) From c80b729e77971a073f1b2cc72ba3455dd24bd870 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Dec 2009 23:46:06 -0800 Subject: [PATCH 04/12] udev: add support for other types of rfkill switches --- src/nm-manager.c | 5 ++-- src/nm-rfkill.h | 13 +++++++++ src/nm-udev-manager.c | 68 +++++++++++++++++++++++++++++++------------ src/nm-udev-manager.h | 4 +-- 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 59d2bbe9d9..8ce6e90842 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1280,7 +1280,7 @@ nm_manager_rfkill_update (NMManager *self) RfKillState udev_state, ipw_state, composite; gboolean new_we = TRUE, new_whe = TRUE; - udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr); + udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr, RFKILL_TYPE_WLAN); ipw_state = nm_manager_get_ipw_rfkill_state (self); /* The composite state is the "worst" of either udev or ipw states */ @@ -1692,6 +1692,7 @@ udev_device_removed_cb (NMUdevManager *manager, static void udev_manager_rfkill_changed_cb (NMUdevManager *udev_mgr, + RfKillType rtype, RfKillState udev_state, gpointer user_data) { @@ -2698,7 +2699,7 @@ nm_manager_start (NMManager *self) NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); gboolean we = FALSE; - switch (nm_udev_manager_get_rfkill_state (priv->udev_mgr)) { + switch (nm_udev_manager_get_rfkill_state (priv->udev_mgr, RFKILL_TYPE_WLAN)) { case RFKILL_UNBLOCKED: we = TRUE; priv->wireless_hw_enabled = TRUE; diff --git a/src/nm-rfkill.h b/src/nm-rfkill.h index cc03e9e1fa..d3cd77744b 100644 --- a/src/nm-rfkill.h +++ b/src/nm-rfkill.h @@ -28,5 +28,18 @@ typedef enum { RFKILL_HARD_BLOCKED = 2 } RfKillState; +typedef enum { + RFKILL_TYPE_WLAN = 0, + RFKILL_TYPE_WWAN = 1, + RFKILL_TYPE_WIMAX = 2, + + /* UNKNOWN and MAX should always be 1 more than + * the last rfkill type since RFKILL_TYPE_MAX is + * used as an array size. + */ + RFKILL_TYPE_UNKNOWN = 3, /* KEEP LAST */ + RFKILL_TYPE_MAX = RFKILL_TYPE_UNKNOWN +} RfKillType; + #endif /* NM_RFKILL_H */ diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index be0825c6b3..956068de41 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -43,7 +43,7 @@ typedef struct { GUdevClient *client; /* Authoritative rfkill state (RFKILL_* enum) */ - RfKillState rfkill_state; + RfKillState rfkill_states[RFKILL_TYPE_MAX]; GSList *killswitches; gboolean disposed; @@ -69,19 +69,21 @@ typedef struct { guint64 seqnum; char *path; char *driver; + RfKillType rtype; gint state; } Killswitch; RfKillState -nm_udev_manager_get_rfkill_state (NMUdevManager *self) +nm_udev_manager_get_rfkill_state (NMUdevManager *self, RfKillType rtype) { g_return_val_if_fail (self != NULL, RFKILL_UNBLOCKED); + g_return_val_if_fail (rtype < RFKILL_TYPE_MAX, RFKILL_UNBLOCKED); - return NM_UDEV_MANAGER_GET_PRIVATE (self)->rfkill_state; + return NM_UDEV_MANAGER_GET_PRIVATE (self)->rfkill_states[rtype]; } static Killswitch * -killswitch_new (GUdevDevice *device) +killswitch_new (GUdevDevice *device, RfKillType rtype) { Killswitch *ks; GUdevDevice *parent = NULL; @@ -91,6 +93,7 @@ killswitch_new (GUdevDevice *device) ks->name = g_strdup (g_udev_device_get_name (device)); ks->seqnum = g_udev_device_get_seqnum (device); ks->path = g_strdup (g_udev_device_get_sysfs_path (device)); + ks->rtype = rtype; driver = g_udev_device_get_property (device, "DRIVER"); if (!driver) { @@ -147,7 +150,12 @@ recheck_killswitches (NMUdevManager *self) { NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); GSList *iter; - RfKillState poll_state = RFKILL_UNBLOCKED; + RfKillState poll_states[RFKILL_TYPE_MAX]; + int i; + + /* Default state is unblocked */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) + poll_states[i] = RFKILL_UNBLOCKED; for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) { Killswitch *ks = iter->data; @@ -159,15 +167,17 @@ recheck_killswitches (NMUdevManager *self) continue; dev_state = sysfs_state_to_nm_state (g_udev_device_get_property_as_int (device, "RFKILL_STATE")); - if (dev_state > poll_state) - poll_state = dev_state; + if (dev_state > poll_states[ks->rtype]) + poll_states[ks->rtype] = dev_state; g_object_unref (device); } - if (poll_state != priv->rfkill_state) { - priv->rfkill_state = poll_state; - g_signal_emit (self, signals[RFKILL_CHANGED], 0, priv->rfkill_state); + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + if (poll_states[i] != priv->rfkill_states[i]) { + priv->rfkill_states[i] = poll_states[i]; + g_signal_emit (self, signals[RFKILL_CHANGED], 0, i, priv->rfkill_states[i]); + } } } @@ -188,21 +198,39 @@ killswitch_find_by_name (NMUdevManager *self, const char *name) return NULL; } +static const RfKillType +rfkill_type_to_enum (const char *str) +{ + g_return_val_if_fail (str != NULL, RFKILL_TYPE_UNKNOWN); + + if (!strcmp (str, "wlan")) + return RFKILL_TYPE_WLAN; + else if (!strcmp (str, "wwan")) + return RFKILL_TYPE_WWAN; + else if (!strcmp (str, "wimax")) + return RFKILL_TYPE_WIMAX; + + return RFKILL_TYPE_UNKNOWN; +} + static void add_one_killswitch (NMUdevManager *self, GUdevDevice *device) { NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - const char *type; + const char *str_type; + RfKillType rtype; Killswitch *ks; - type = g_udev_device_get_property (device, "RFKILL_TYPE"); - if (!type || strcmp (type, "wlan")) + str_type = g_udev_device_get_property (device, "RFKILL_TYPE"); + rtype = rfkill_type_to_enum (str_type); + if (rtype == RFKILL_TYPE_UNKNOWN) return; - ks = killswitch_new (device); + ks = killswitch_new (device, rtype); priv->killswitches = g_slist_prepend (priv->killswitches, ks); - nm_info ("Found radio killswitch %s (at %s) (driver %s)", + nm_info ("Found %s radio killswitch %s (at %s) (driver %s)", + str_type, ks->name, ks->path, ks->driver ? ks->driver : ""); @@ -422,8 +450,11 @@ nm_udev_manager_init (NMUdevManager *self) NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); const char *subsys[3] = { "rfkill", "net", NULL }; GList *switches, *iter; + guint32 i; + + for (i = 0; i < RFKILL_TYPE_MAX; i++) + priv->rfkill_states[i] = RFKILL_UNBLOCKED; - priv->rfkill_state = RFKILL_UNBLOCKED; priv->client = g_udev_client_new (subsys); g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); @@ -492,8 +523,7 @@ nm_udev_manager_class_init (NMUdevManagerClass *klass) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMUdevManagerClass, rfkill_changed), NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, - G_TYPE_UINT); + _nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); } diff --git a/src/nm-udev-manager.h b/src/nm-udev-manager.h index 61b60a40c3..06a2d35ce3 100644 --- a/src/nm-udev-manager.h +++ b/src/nm-udev-manager.h @@ -57,7 +57,7 @@ typedef struct { void (*device_removed) (NMUdevManager *manager, GUdevDevice *device); - void (*rfkill_changed) (NMUdevManager *manager, RfKillState state); + void (*rfkill_changed) (NMUdevManager *manager, RfKillType rtype, RfKillState state); } NMUdevManagerClass; GType nm_udev_manager_get_type (void); @@ -66,7 +66,7 @@ NMUdevManager *nm_udev_manager_new (void); void nm_udev_manager_query_devices (NMUdevManager *manager); -RfKillState nm_udev_manager_get_rfkill_state (NMUdevManager *manager); +RfKillState nm_udev_manager_get_rfkill_state (NMUdevManager *manager, RfKillType rtype); #endif /* NM_UDEV_MANAGER_H */ From 843c251d261a57bfde7e439654db6b3671ae6c13 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 22 Dec 2009 23:51:08 -0800 Subject: [PATCH 05/12] core: add statefile support for WWAN devices --- src/NetworkManager.c | 15 ++++++++++++--- src/nm-device-olpc-mesh.c | 2 +- src/nm-manager.c | 1 + src/nm-manager.h | 1 + 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/NetworkManager.c b/src/NetworkManager.c index a79d5c86ec..257a996a0e 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -329,6 +329,7 @@ static gboolean parse_state_file (const char *filename, gboolean *net_enabled, gboolean *wifi_enabled, + gboolean *wwan_enabled, GError **error) { GKeyFile *state_file; @@ -337,6 +338,7 @@ parse_state_file (const char *filename, g_return_val_if_fail (net_enabled != NULL, FALSE); g_return_val_if_fail (wifi_enabled != NULL, FALSE); + g_return_val_if_fail (wwan_enabled != NULL, FALSE); state_file = g_key_file_new (); if (!state_file) { @@ -374,6 +376,7 @@ parse_state_file (const char *filename, /* Write out the initial state to the state file */ g_key_file_set_boolean (state_file, "main", "NetworkingEnabled", *net_enabled); g_key_file_set_boolean (state_file, "main", "WirelessEnabled", *wifi_enabled); + g_key_file_set_boolean (state_file, "main", "WWANEnabled", *wwan_enabled); data = g_key_file_to_data (state_file, &len, NULL); if (data) @@ -426,7 +429,7 @@ main (int argc, char *argv[]) char *pidfile = NULL, *user_pidfile = NULL; char *config = NULL, *plugins = NULL; char *state_file = NM_DEFAULT_SYSTEM_STATE_FILE; - gboolean wifi_enabled = TRUE, net_enabled = TRUE; + gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE; gboolean success; NMPolicy *policy = NULL; NMVPNManager *vpn_manager = NULL; @@ -509,7 +512,7 @@ main (int argc, char *argv[]) g_clear_error (&error); /* Parse the state file */ - if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &error)) { + if (!parse_state_file (state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &error)) { g_warning ("State file %s parsing failed: (%d) %s.", state_file, error ? error->code : -1, @@ -583,7 +586,13 @@ main (int argc, char *argv[]) goto done; } - manager = nm_manager_get (config, plugins, state_file, net_enabled, wifi_enabled, &error); + manager = nm_manager_get (config, + plugins, + state_file, + net_enabled, + wifi_enabled, + wwan_enabled, + &error); if (manager == NULL) { nm_error ("Failed to initialize the network manager: %s", error && error->message ? error->message : "(unknown)"); diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c index fb47cf7d56..ad81a5a78b 100644 --- a/src/nm-device-olpc-mesh.c +++ b/src/nm-device-olpc-mesh.c @@ -909,7 +909,7 @@ check_companion_cb (gpointer user_data) if (priv->device_added_cb != 0) return FALSE; - manager = nm_manager_get (NULL, NULL, NULL, FALSE, FALSE, NULL); + manager = nm_manager_get (NULL, NULL, NULL, FALSE, FALSE, FALSE, NULL); priv->device_added_cb = g_signal_connect (manager, "device-added", G_CALLBACK (device_added_cb), self); diff --git a/src/nm-manager.c b/src/nm-manager.c index 8ce6e90842..0d315f4bbc 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2742,6 +2742,7 @@ nm_manager_get (const char *config_file, const char *state_file, gboolean initial_net_enabled, gboolean initial_wifi_enabled, + gboolean initial_wwan_enabled, GError **error) { static NMManager *singleton = NULL; diff --git a/src/nm-manager.h b/src/nm-manager.h index a17323d42f..5e8fcda11c 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -79,6 +79,7 @@ NMManager *nm_manager_get (const char *config_file, const char *state_file, gboolean initial_net_enabled, gboolean initial_wifi_enabled, + gboolean initial_wwan_enabled, GError **error); void nm_manager_start (NMManager *manager); From 5605709e806ecec46b03ff3c4afc4c12692d165d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Dec 2009 00:03:45 -0800 Subject: [PATCH 06/12] manager: generalize rfkill operations So it's easier to support other killswitches like WWAN and WiMAX. --- src/nm-manager.c | 227 +++++++++++++++++++++++++++++++++-------------- src/nm-manager.h | 5 -- 2 files changed, 160 insertions(+), 72 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 0d315f4bbc..10f5388f93 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -57,6 +57,11 @@ #define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd" #define NM_AUTOIP_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd" +#define NM_MANAGER_STATE "state" +#define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" +#define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" +#define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections" + static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err); static void impl_manager_activate_connection (NMManager *manager, const char *service_name, @@ -142,6 +147,21 @@ typedef struct { guint timeout_id; } PendingConnectionInfo; +typedef struct { + gboolean enabled; + gboolean hw_enabled; + const char *desc; + const char *key; + const char *prop; + const char *hw_prop; + /* Hack for WWAN for 0.8 release; we'll start using udev + * after 0.8 gets out. + */ + gboolean ignore_udev; + RfKillState (*other_enabled_func) (NMManager *); + gboolean (*object_filter_func) (GObject *); +} RadioState; + typedef struct { char *config_file; char *state_file; @@ -163,8 +183,8 @@ typedef struct { GSList *secrets_calls; PendingConnectionInfo *pending_connection_info; - gboolean wireless_enabled; - gboolean wireless_hw_enabled; + + RadioState radio_states[RFKILL_TYPE_MAX]; gboolean sleeping; NMVPNManager *vpn_manager; @@ -1147,28 +1167,34 @@ write_value_to_state_file (const char *filename, } static void -manager_set_wireless_enabled (NMManager *manager, gboolean enabled) +manager_set_radio_enabled (NMManager *manager, + RadioState *rstate, + gboolean enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); GSList *iter; GError *error = NULL; - if (priv->wireless_enabled == enabled) + /* Do nothing for radio types not yet implemented */ + if (!rstate->prop) + return; + + if (rstate->enabled == enabled) return; /* Can't set wireless enabled if it's disabled in hardware */ - if (!priv->wireless_hw_enabled && enabled) + if (!rstate->hw_enabled && enabled) return; - priv->wireless_enabled = enabled; + rstate->enabled = enabled; - g_object_notify (G_OBJECT (manager), NM_MANAGER_WIRELESS_ENABLED); + g_object_notify (G_OBJECT (manager), rstate->prop); - /* Update "WirelessEnabled" key in state file */ + /* Update enabled key in state file */ if (priv->state_file) { if (!write_value_to_state_file (priv->state_file, - "main", "WirelessEnabled", - G_TYPE_BOOLEAN, (gpointer) &priv->wireless_enabled, + "main", rstate->key, + G_TYPE_BOOLEAN, (gpointer) &enabled, &error)) { g_warning ("Writing to state file %s failed: (%d) %s.", priv->state_file, @@ -1183,7 +1209,7 @@ manager_set_wireless_enabled (NMManager *manager, gboolean enabled) /* enable/disable wireless devices as required */ for (iter = priv->devices; iter; iter = iter->next) { - if (NM_IS_DEVICE_WIFI (iter->data)) + if (rstate->object_filter_func (G_OBJECT (iter->data))) nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (iter->data), enabled); } } @@ -1273,48 +1299,79 @@ nm_manager_get_ipw_rfkill_state (NMManager *self) return ipw_state; } +static gboolean +rfkill_wlan_filter (GObject *object) +{ + return NM_IS_DEVICE_WIFI (object); +} + static void -nm_manager_rfkill_update (NMManager *self) +manager_rfkill_update_one_type (NMManager *self, + RadioState *rstate, + RfKillType rtype) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - RfKillState udev_state, ipw_state, composite; - gboolean new_we = TRUE, new_whe = TRUE; + RfKillState udev_state = RFKILL_UNBLOCKED; + RfKillState other_state = RFKILL_UNBLOCKED; + RfKillState composite; + gboolean new_e = TRUE, new_he = TRUE; - udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr, RFKILL_TYPE_WLAN); - ipw_state = nm_manager_get_ipw_rfkill_state (self); + if (!rstate->ignore_udev) + udev_state = nm_udev_manager_get_rfkill_state (priv->udev_mgr, rtype); - /* The composite state is the "worst" of either udev or ipw states */ - if (udev_state == RFKILL_HARD_BLOCKED || ipw_state == RFKILL_HARD_BLOCKED) + if (rstate->other_enabled_func) + other_state = rstate->other_enabled_func (self); + + /* The composite state is the "worst" of either udev or other states */ + if (udev_state == RFKILL_HARD_BLOCKED || other_state == RFKILL_HARD_BLOCKED) composite = RFKILL_HARD_BLOCKED; - else if (udev_state == RFKILL_SOFT_BLOCKED || ipw_state == RFKILL_SOFT_BLOCKED) + else if (udev_state == RFKILL_SOFT_BLOCKED || other_state == RFKILL_SOFT_BLOCKED) composite = RFKILL_SOFT_BLOCKED; else composite = RFKILL_UNBLOCKED; switch (composite) { case RFKILL_UNBLOCKED: - new_we = TRUE; - new_whe = TRUE; + new_e = TRUE; + new_he = TRUE; break; case RFKILL_SOFT_BLOCKED: - new_we = FALSE; - new_whe = TRUE; + new_e = FALSE; + new_he = TRUE; break; case RFKILL_HARD_BLOCKED: - new_we = FALSE; - new_whe = FALSE; + new_e = FALSE; + new_he = FALSE; break; default: break; } - nm_info ("Wireless now %s by radio killswitch", - (new_we && new_whe) ? "enabled" : "disabled"); - if (new_whe != priv->wireless_hw_enabled) { - priv->wireless_hw_enabled = new_whe; - g_object_notify (G_OBJECT (self), NM_MANAGER_WIRELESS_HARDWARE_ENABLED); + if (new_he != rstate->hw_enabled) { + nm_info ("%s now %s by radio killswitch", + rstate->desc, + (new_e && new_he) ? "enabled" : "disabled"); + + rstate->hw_enabled = new_he; + g_object_notify (G_OBJECT (self), rstate->hw_prop); } - manager_set_wireless_enabled (self, new_we); + manager_set_radio_enabled (self, rstate, new_e); +} + +static void +nm_manager_rfkill_update (NMManager *self, RfKillType rtype) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + guint i; + + if (rtype != RFKILL_TYPE_UNKNOWN) { + manager_rfkill_update_one_type (self, &priv->radio_states[rtype], rtype); + return; + } + + /* Otherwise sync all radio types */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) + manager_rfkill_update_one_type (self, &priv->radio_states[i], i); } static void @@ -1322,7 +1379,7 @@ manager_ipw_rfkill_state_changed (NMDeviceWifi *device, GParamSpec *pspec, gpointer user_data) { - nm_manager_rfkill_update (NM_MANAGER (user_data)); + nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WLAN); } static void @@ -1370,8 +1427,9 @@ add_device (NMManager *self, NMDevice *device) /* Update global rfkill state with this device's rfkill state, and * then set this device's rfkill state based on the global state. */ - nm_manager_rfkill_update (self); - nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), priv->wireless_enabled); + nm_manager_rfkill_update (self, RFKILL_TYPE_WLAN); + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), + priv->radio_states[RFKILL_TYPE_WLAN].enabled); } type_desc = nm_device_get_type_desc (device); @@ -1696,7 +1754,7 @@ udev_manager_rfkill_changed_cb (NMUdevManager *udev_mgr, RfKillState udev_state, gpointer user_data) { - nm_manager_rfkill_update (NM_MANAGER (user_data)); + nm_manager_rfkill_update (NM_MANAGER (user_data), rtype); } GSList * @@ -2552,18 +2610,23 @@ impl_manager_sleep (NMManager *self, gboolean sleep, GError **error) /* Ensure rfkill state is up-to-date since we don't respond to state * changes during sleep. */ - nm_manager_rfkill_update (self); + nm_manager_rfkill_update (self, RFKILL_TYPE_UNKNOWN); /* Re-manage managed devices */ for (iter = priv->devices; iter; iter = iter->next) { NMDevice *device = NM_DEVICE (iter->data); - gboolean wifi_enabled = (priv->wireless_hw_enabled && priv->wireless_enabled); + guint i; /* enable/disable wireless devices since that we don't respond * to killswitch changes during sleep. */ - if (NM_IS_DEVICE_WIFI (iter->data)) - nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (iter->data), wifi_enabled); + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + RadioState *rstate = &priv->radio_states[i]; + gboolean enabled = (rstate->hw_enabled && rstate->enabled); + + if (rstate->object_filter_func (G_OBJECT (iter->data))) + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (iter->data), enabled); + } nm_device_clear_autoconnect_inhibit (device); if (nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs)) @@ -2697,30 +2760,43 @@ void nm_manager_start (NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - gboolean we = FALSE; + guint i; - switch (nm_udev_manager_get_rfkill_state (priv->udev_mgr, RFKILL_TYPE_WLAN)) { - case RFKILL_UNBLOCKED: - we = TRUE; - priv->wireless_hw_enabled = TRUE; - break; - case RFKILL_SOFT_BLOCKED: - we = FALSE; - priv->wireless_hw_enabled = TRUE; - break; - case RFKILL_HARD_BLOCKED: - we = FALSE; - priv->wireless_hw_enabled = FALSE; - break; - default: - break; + /* Set initial radio enabled/disabled state */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) { + RadioState *rstate = &priv->radio_states[i]; + gboolean enabled = TRUE, hw_enabled = TRUE; + + if (!rstate->desc) + continue; + + if (!rstate->ignore_udev) { + switch (nm_udev_manager_get_rfkill_state (priv->udev_mgr, i)) { + case RFKILL_UNBLOCKED: + enabled = TRUE; + hw_enabled = TRUE; + break; + case RFKILL_SOFT_BLOCKED: + enabled = FALSE; + hw_enabled = TRUE; + break; + case RFKILL_HARD_BLOCKED: + enabled = FALSE; + hw_enabled = FALSE; + break; + default: + break; + } + } + + rstate->hw_enabled = hw_enabled; + nm_info ("%s %s by radio killswitch; %s by state file", + rstate->desc, + (rstate->hw_enabled && enabled) ? "enabled" : "disabled", + (rstate->enabled) ? "enabled" : "disabled"); + manager_set_radio_enabled (self, rstate, rstate->enabled && enabled); } - nm_info ("Wireless %s by radio killswitch; %s by state file", - (priv->wireless_hw_enabled && we) ? "enabled" : "disabled", - (priv->wireless_enabled) ? "enabled" : "disabled"); - manager_set_wireless_enabled (self, priv->wireless_enabled && we); - system_unmanaged_devices_changed_cb (priv->sys_settings, NULL, self); system_hostname_changed_cb (priv->sys_settings, NULL, self); system_query_connections (self); @@ -2773,7 +2849,7 @@ nm_manager_get (const char *config_file, priv->sleeping = !initial_net_enabled; - priv->wireless_enabled = initial_wifi_enabled; + priv->radio_states[RFKILL_TYPE_WLAN].enabled = initial_wifi_enabled; g_signal_connect (priv->sys_settings, "notify::" NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS, G_CALLBACK (system_unmanaged_devices_changed_cb), singleton); @@ -2890,9 +2966,14 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { + NMManager *self = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + switch (prop_id) { case PROP_WIRELESS_ENABLED: - manager_set_wireless_enabled (NM_MANAGER (object), g_value_get_boolean (value)); + manager_set_radio_enabled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WLAN], + g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -2913,10 +2994,10 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->state); break; case PROP_WIRELESS_ENABLED: - g_value_set_boolean (value, priv->wireless_enabled); + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].enabled); break; case PROP_WIRELESS_HARDWARE_ENABLED: - g_value_set_boolean (value, priv->wireless_hw_enabled); + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); break; case PROP_ACTIVE_CONNECTIONS: g_value_take_boxed (value, get_active_connections (self, NULL)); @@ -2938,10 +3019,22 @@ nm_manager_init (NMManager *manager) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); DBusGConnection *g_connection; - guint id; + guint id, i; + + /* Initialize rfkill structures and states */ + memset (priv->radio_states, 0, sizeof (priv->radio_states)); + + priv->radio_states[RFKILL_TYPE_WLAN].enabled = TRUE; + priv->radio_states[RFKILL_TYPE_WLAN].key = "WirelessEnabled"; + priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED; + priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED; + priv->radio_states[RFKILL_TYPE_WLAN].desc = "WiFi"; + priv->radio_states[RFKILL_TYPE_WLAN].other_enabled_func = nm_manager_get_ipw_rfkill_state; + priv->radio_states[RFKILL_TYPE_WLAN].object_filter_func = rfkill_wlan_filter; + + for (i = 0; i < RFKILL_TYPE_MAX; i++) + priv->radio_states[i].hw_enabled = TRUE; - priv->wireless_enabled = TRUE; - priv->wireless_hw_enabled = TRUE; priv->sleeping = FALSE; priv->state = NM_STATE_DISCONNECTED; diff --git a/src/nm-manager.h b/src/nm-manager.h index 5e8fcda11c..1090409a9b 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -35,11 +35,6 @@ #define NM_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_MANAGER)) #define NM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MANAGER, NMManagerClass)) -#define NM_MANAGER_STATE "state" -#define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" -#define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" -#define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections" - /* Not exported */ #define NM_MANAGER_HOSTNAME "hostname" #define NM_MANAGER_SLEEPING "sleeping" From a0f732c8cb7e1148b262bd7f95141ee53d50d08f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Dec 2009 00:09:24 -0800 Subject: [PATCH 07/12] modem: proxy the ModemManager Enabled property --- src/modem-manager/nm-modem.c | 168 ++++++++++++++++++++++++++++++++++- src/modem-manager/nm-modem.h | 3 + 2 files changed, 167 insertions(+), 4 deletions(-) diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 3bc7bab4a9..a0e83c4512 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -15,8 +15,12 @@ #include "nm-utils.h" #include "nm-serial-device-glue.h" #include "NetworkManagerUtils.h" +#include "nm-dbus-glib-types.h" -G_DEFINE_TYPE (NMModem, nm_modem, NM_TYPE_DEVICE) +static void device_interface_init (NMDeviceInterface *iface_class); + +G_DEFINE_TYPE_EXTENDED (NMModem, nm_modem, NM_TYPE_DEVICE, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_INTERFACE, device_interface_init)) #define NM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM, NMModemPrivate)) @@ -25,19 +29,24 @@ enum { PROP_DEVICE, PROP_PATH, PROP_IP_METHOD, + PROP_ENABLED, LAST_PROP }; typedef struct { NMDBusManager *dbus_mgr; - char *path; DBusGProxy *proxy; + DBusGProxy *props_proxy; + + char *path; NMPPPManager *ppp_manager; NMIP4Config *pending_ip4_config; guint32 ip_method; char *device; + gboolean mm_enabled; + /* PPP stats */ guint32 in_bytes; guint32 out_bytes; @@ -60,6 +69,14 @@ nm_modem_get_ppp_manager (NMModem *self) return NM_MODEM_GET_PRIVATE (self)->ppp_manager; } +gboolean +nm_modem_get_mm_enabled (NMModem *self) +{ + g_return_val_if_fail (NM_IS_MODEM (self), TRUE); + + return NM_MODEM_GET_PRIVATE (self)->mm_enabled; +} + DBusGProxy * nm_modem_get_proxy (NMModem *self, const char *interface) @@ -74,6 +91,9 @@ nm_modem_get_proxy (NMModem *self, if (interface == NULL) interface = MM_DBUS_INTERFACE_MODEM; + if (interface && !strcmp (interface, DBUS_INTERFACE_PROPERTIES)) + return priv->props_proxy; + current_iface = dbus_g_proxy_get_interface (priv->proxy); if (!current_iface || strcmp (current_iface, interface)) dbus_g_proxy_set_interface (priv->proxy, interface); @@ -485,8 +505,110 @@ real_hw_bring_up (NMDevice *device, gboolean *no_firmware) return TRUE; } +static void +get_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMModem *self = NM_MODEM (user_data); + GError *error = NULL; + GValue value = { 0, }; + + if (!dbus_g_proxy_end_call (proxy, call_id, &error, + G_TYPE_VALUE, &value, + G_TYPE_INVALID)) { + g_warning ("%s: failed get modem enabled state: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + return; + } + + if (G_VALUE_HOLDS_BOOLEAN (&value)) { + NM_MODEM_GET_PRIVATE (self)->mm_enabled = g_value_get_boolean (&value); + g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); + } else + g_warning ("%s: failed get modem enabled state: unexpected reply type", __func__); + + g_value_unset (&value); +} + +static void +query_mm_enabled (NMModem *self) +{ + dbus_g_proxy_begin_call (NM_MODEM_GET_PRIVATE (self)->props_proxy, + "Get", get_mm_enabled_done, + self, NULL, + G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM, + G_TYPE_STRING, "Enabled", + G_TYPE_INVALID); +} + +static void +set_mm_enabled_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + GError *error = NULL; + + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { + g_warning ("%s: failed to enable/disable modem: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } + + /* Update enabled/disabled state again */ + query_mm_enabled (NM_MODEM (user_data)); +} + +static void +real_set_enabled (NMDeviceInterface *device, gboolean enabled) +{ + NMModem *self = NM_MODEM (device); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + + /* FIXME: For now this just toggles the ModemManager enabled state. In the + * future we want to tie this into rfkill state instead so that the user can + * toggle rfkill status of the WWAN modem. + */ + + if (priv->mm_enabled != enabled) { + DBusGProxy *proxy; + + proxy = nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM); + dbus_g_proxy_begin_call (proxy, + "Enable", set_mm_enabled_done, + device, NULL, + G_TYPE_BOOLEAN, enabled, + G_TYPE_INVALID); + } +} + +static void +modem_properties_changed (DBusGProxy *proxy, + const char *interface, + GHashTable *props, + gpointer user_data) +{ + NMModem *self = NM_MODEM (user_data); + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + GValue *value; + + if (strcmp (interface, MM_DBUS_INTERFACE_MODEM)) + return; + + value = g_hash_table_lookup (props, "Enabled"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + priv->mm_enabled = g_value_get_boolean (value); + g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); + } +} + /*****************************************************************************/ +static void +device_interface_init (NMDeviceInterface *iface_class) +{ + iface_class->set_enabled = real_set_enabled; +} + static void nm_modem_init (NMModem *self) { @@ -502,6 +624,7 @@ constructor (GType type, { GObject *object; NMModemPrivate *priv; + DBusGConnection *bus; object = G_OBJECT_CLASS (nm_modem_parent_class)->constructor (type, n_construct_params, @@ -521,11 +644,32 @@ constructor (GType type, goto err; } - priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - MM_DBUS_SERVICE, priv->path, MM_DBUS_INTERFACE_MODEM); + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + priv->proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + priv->path, + MM_DBUS_INTERFACE_MODEM); + + priv->props_proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + priv->path, + DBUS_INTERFACE_PROPERTIES); + dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, + G_TYPE_NONE, + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->props_proxy, "MmPropertiesChanged", + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->props_proxy, "MmPropertiesChanged", + G_CALLBACK (modem_properties_changed), + object, + NULL); g_signal_connect (object, "state-changed", G_CALLBACK (device_state_changed), object); + query_mm_enabled (NM_MODEM (object)); + return object; err: @@ -549,6 +693,9 @@ get_property (GObject *object, guint prop_id, case PROP_IP_METHOD: g_value_set_uint (value, priv->ip_method); break; + case PROP_ENABLED: + g_value_set_boolean (value, priv->mm_enabled); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -574,6 +721,8 @@ set_property (GObject *object, guint prop_id, case PROP_IP_METHOD: priv->ip_method = g_value_get_uint (value); break; + case PROP_ENABLED: + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -588,6 +737,9 @@ finalize (GObject *object) if (priv->proxy) g_object_unref (priv->proxy); + if (priv->props_proxy) + g_object_unref (priv->props_proxy); + g_object_unref (priv->dbus_mgr); g_free (priv->path); @@ -644,6 +796,14 @@ nm_modem_class_init (NMModemClass *klass) MM_MODEM_IP_METHOD_PPP, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + g_object_class_install_property + (object_class, PROP_ENABLED, + g_param_spec_boolean (NM_MODEM_ENABLED, + "Enabled", + "Enabled", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | NM_PROPERTY_PARAM_NO_EXPORT)); + /* Signals */ signals[PPP_STATS] = g_signal_new ("ppp-stats", diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index cd638039f7..fefc6347ca 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -19,6 +19,7 @@ G_BEGIN_DECLS #define NM_MODEM_PATH "path" #define NM_MODEM_DEVICE "device" #define NM_MODEM_IP_METHOD "ip-method" +#define NM_MODEM_ENABLED "enabled" typedef struct { NMDevice parent; @@ -46,6 +47,8 @@ DBusGProxy *nm_modem_get_proxy (NMModem *self, const char *nm_modem_get_ppp_name (NMModem *self, NMConnection *connection); +gboolean nm_modem_get_mm_enabled (NMModem *self); + G_END_DECLS #endif /* NM_MODEM_H */ From 8f4d4c0463d6f101b852afed5117d902c3174e15 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Dec 2009 00:18:18 -0800 Subject: [PATCH 08/12] manager: add WWAN enable/disable support --- introspection/nm-manager-client.xml | 2 + introspection/nm-manager.xml | 12 ++++ src/nm-manager.c | 89 +++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/introspection/nm-manager-client.xml b/introspection/nm-manager-client.xml index cf89611438..9a0d4da214 100644 --- a/introspection/nm-manager-client.xml +++ b/introspection/nm-manager-client.xml @@ -41,6 +41,8 @@ object. dbus-glib generates the same bound function names for D-Bus the methods + + diff --git a/introspection/nm-manager.xml b/introspection/nm-manager.xml index 02e8bcf51a..8303f4d469 100644 --- a/introspection/nm-manager.xml +++ b/introspection/nm-manager.xml @@ -108,6 +108,18 @@ + + + Indicates if mobile broadband devices are currently enabled or not. + + + + + + Indicates if the mobile broadband hardware is currently enabled, i.e. the state of the RF kill switch. + + + List of active connection object paths. diff --git a/src/nm-manager.c b/src/nm-manager.c index 10f5388f93..d094d2ff53 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -60,6 +60,8 @@ #define NM_MANAGER_STATE "state" #define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" #define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" +#define NM_MANAGER_WWAN_ENABLED "wwan-enabled" +#define NM_MANAGER_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled" #define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections" static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err); @@ -226,6 +228,8 @@ enum { PROP_STATE, PROP_WIRELESS_ENABLED, PROP_WIRELESS_HARDWARE_ENABLED, + PROP_WWAN_ENABLED, + PROP_WWAN_HARDWARE_ENABLED, PROP_ACTIVE_CONNECTIONS, /* Not exported */ @@ -1299,12 +1303,41 @@ nm_manager_get_ipw_rfkill_state (NMManager *self) return ipw_state; } +static RfKillState +nm_manager_get_modem_enabled_state (NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GSList *iter; + RfKillState wwan_state = RFKILL_UNBLOCKED; + + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMDevice *candidate = NM_DEVICE (iter->data); + RfKillState candidate_state = RFKILL_UNBLOCKED; + + if (NM_IS_MODEM (candidate)) { + if (nm_modem_get_mm_enabled (NM_MODEM (candidate)) == FALSE) + candidate_state = RFKILL_SOFT_BLOCKED; + + if (candidate_state > wwan_state) + wwan_state = candidate_state; + } + } + + return wwan_state; +} + static gboolean rfkill_wlan_filter (GObject *object) { return NM_IS_DEVICE_WIFI (object); } +static gboolean +rfkill_wwan_filter (GObject *object) +{ + return NM_IS_MODEM (object); +} + static void manager_rfkill_update_one_type (NMManager *self, RadioState *rstate, @@ -1382,6 +1415,14 @@ manager_ipw_rfkill_state_changed (NMDeviceWifi *device, nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WLAN); } +static void +manager_modem_enabled_changed (NMModem *device, + GParamSpec *pspec, + gpointer user_data) +{ + nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WWAN); +} + static void add_device (NMManager *self, NMDevice *device) { @@ -1430,6 +1471,18 @@ add_device (NMManager *self, NMDevice *device) nm_manager_rfkill_update (self, RFKILL_TYPE_WLAN); nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), priv->radio_states[RFKILL_TYPE_WLAN].enabled); + } else if (NM_IS_MODEM (device)) { + g_signal_connect (device, "notify::" NM_MODEM_ENABLED, + G_CALLBACK (manager_modem_enabled_changed), + self); + + nm_manager_rfkill_update (self, RFKILL_TYPE_WWAN); + /* Until we start respecting WWAN rfkill switches the modem itself + * is the source of the enabled/disabled state, so the manager shouldn't + * touch it here. + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), + priv->radio_states[RFKILL_TYPE_WWAN].enabled); + */ } type_desc = nm_device_get_type_desc (device); @@ -2850,6 +2903,7 @@ nm_manager_get (const char *config_file, priv->sleeping = !initial_net_enabled; priv->radio_states[RFKILL_TYPE_WLAN].enabled = initial_wifi_enabled; + priv->radio_states[RFKILL_TYPE_WWAN].enabled = initial_wwan_enabled; g_signal_connect (priv->sys_settings, "notify::" NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS, G_CALLBACK (system_unmanaged_devices_changed_cb), singleton); @@ -2975,6 +3029,11 @@ set_property (GObject *object, guint prop_id, &priv->radio_states[RFKILL_TYPE_WLAN], g_value_get_boolean (value)); break; + case PROP_WWAN_ENABLED: + manager_set_radio_enabled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WWAN], + g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2999,6 +3058,12 @@ get_property (GObject *object, guint prop_id, case PROP_WIRELESS_HARDWARE_ENABLED: g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); break; + case PROP_WWAN_ENABLED: + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].enabled); + break; + case PROP_WWAN_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); + break; case PROP_ACTIVE_CONNECTIONS: g_value_take_boxed (value, get_active_connections (self, NULL)); break; @@ -3032,6 +3097,14 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WLAN].other_enabled_func = nm_manager_get_ipw_rfkill_state; priv->radio_states[RFKILL_TYPE_WLAN].object_filter_func = rfkill_wlan_filter; + priv->radio_states[RFKILL_TYPE_WWAN].enabled = TRUE; + priv->radio_states[RFKILL_TYPE_WWAN].key = "WWANEnabled"; + priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; + priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; + priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; + priv->radio_states[RFKILL_TYPE_WWAN].other_enabled_func = nm_manager_get_modem_enabled_state; + priv->radio_states[RFKILL_TYPE_WWAN].object_filter_func = rfkill_wwan_filter; + for (i = 0; i < RFKILL_TYPE_MAX; i++) priv->radio_states[i].hw_enabled = TRUE; @@ -3126,6 +3199,22 @@ nm_manager_class_init (NMManagerClass *manager_class) TRUE, G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_WWAN_ENABLED, + g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, + "WwanEnabled", + "Is mobile broadband enabled", + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, PROP_WWAN_HARDWARE_ENABLED, + g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, + "WwanHardwareEnabled", + "Whether WWAN is disabled by a hardware switch or not", + TRUE, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_ACTIVE_CONNECTIONS, g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, From ec56c4d0937856876082f301d044c2afa2056df3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Dec 2009 00:22:47 -0800 Subject: [PATCH 09/12] libnm-glib: add WWAN enable/disable support --- libnm-glib/Makefile.am | 2 +- libnm-glib/libnm-glib.ver | 3 + libnm-glib/nm-client.c | 142 ++++++++++++++++++++++++++++++++++++++ libnm-glib/nm-client.h | 7 ++ 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index f91623e1b9..2aa6124e76 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -105,7 +105,7 @@ libnm_glib_la_LIBADD = \ $(GUDEV_LIBS) libnm_glib_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib.ver \ - -version-info "3:0:1" + -version-info "4:0:2" noinst_PROGRAMS = libnm-glib-test diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 25556391dd..1caa2d42ba 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -40,6 +40,9 @@ global: nm_client_wireless_get_enabled; nm_client_wireless_hardware_get_enabled; nm_client_wireless_set_enabled; + nm_client_wwan_get_enabled; + nm_client_wwan_hardware_get_enabled; + nm_client_wwan_set_enabled; nm_dbus_settings_get_connection_by_path; nm_dbus_settings_get_type; nm_dbus_settings_new; diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c index 07f77cedde..05fa4dbf24 100644 --- a/libnm-glib/nm-client.c +++ b/libnm-glib/nm-client.c @@ -60,6 +60,9 @@ typedef struct { gboolean wireless_enabled; gboolean wireless_hw_enabled; + + gboolean wwan_enabled; + gboolean wwan_hw_enabled; } NMClientPrivate; enum { @@ -68,6 +71,8 @@ enum { PROP_MANAGER_RUNNING, PROP_WIRELESS_ENABLED, PROP_WIRELESS_HARDWARE_ENABLED, + PROP_WWAN_ENABLED, + PROP_WWAN_HARDWARE_ENABLED, PROP_ACTIVE_CONNECTIONS, LAST_PROP @@ -153,6 +158,36 @@ wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data) poke_wireless_devices_with_rf_status (NM_CLIENT (object)); } +static void +update_wwan_status (NMClient *client, gboolean notify) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); + gboolean val; + + val = _nm_object_get_boolean_property (NM_OBJECT (client), + NM_DBUS_INTERFACE, + "WwanHardwareEnabled"); + if (val != priv->wwan_hw_enabled) { + priv->wwan_hw_enabled = val; + if (notify) + _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_HARDWARE_ENABLED); + } + + if (priv->wwan_hw_enabled == FALSE) + val = FALSE; + else { + val = _nm_object_get_boolean_property (NM_OBJECT (client), + NM_DBUS_INTERFACE, + "WwanEnabled"); + } + + if (val != priv->wwan_enabled) { + priv->wwan_enabled = val; + if (notify) + _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_ENABLED); + } +} + static GObject * new_active_connection (DBusGConnection *connection, const char *path) { @@ -217,6 +252,8 @@ register_for_property_changed (NMClient *client) { NM_CLIENT_STATE, _nm_object_demarshal_generic, &priv->state }, { NM_CLIENT_WIRELESS_ENABLED, _nm_object_demarshal_generic, &priv->wireless_enabled }, { NM_CLIENT_WIRELESS_HARDWARE_ENABLED, _nm_object_demarshal_generic, &priv->wireless_hw_enabled }, + { NM_CLIENT_WWAN_ENABLED, _nm_object_demarshal_generic, &priv->wwan_enabled }, + { NM_CLIENT_WWAN_HARDWARE_ENABLED, _nm_object_demarshal_generic, &priv->wwan_hw_enabled }, { NM_CLIENT_ACTIVE_CONNECTIONS, demarshal_active_connections, &priv->active_connections }, { NULL }, }; @@ -291,6 +328,7 @@ constructor (GType type, if (priv->manager_running) { update_wireless_status (NM_CLIENT (object), FALSE); + update_wwan_status (NM_CLIENT (object), FALSE); nm_client_get_state (NM_CLIENT (object)); } @@ -353,6 +391,20 @@ set_property (GObject *object, guint prop_id, _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WIRELESS_HARDWARE_ENABLED); } break; + case PROP_WWAN_ENABLED: + b = g_value_get_boolean (value); + if (priv->wwan_enabled != b) { + priv->wwan_enabled = b; + _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WWAN_ENABLED); + } + break; + case PROP_WWAN_HARDWARE_ENABLED: + b = g_value_get_boolean (value); + if (priv->wwan_hw_enabled != b) { + priv->wwan_hw_enabled = b; + _nm_object_queue_notify (NM_OBJECT (object), NM_CLIENT_WWAN_HARDWARE_ENABLED); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -381,6 +433,12 @@ get_property (GObject *object, case PROP_WIRELESS_HARDWARE_ENABLED: g_value_set_boolean (value, priv->wireless_hw_enabled); break; + case PROP_WWAN_ENABLED: + g_value_set_boolean (value, priv->wwan_enabled); + break; + case PROP_WWAN_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->wwan_hw_enabled); + break; case PROP_ACTIVE_CONNECTIONS: g_value_set_boxed (value, nm_client_get_active_connections (self)); break; @@ -457,6 +515,32 @@ nm_client_class_init (NMClientClass *client_class) TRUE, G_PARAM_READABLE)); + /** + * NMClient::wwan-enabled: + * + * Whether WWAN functionality is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WWAN_ENABLED, + g_param_spec_boolean (NM_CLIENT_WWAN_ENABLED, + "WwanEnabled", + "Is WWAN enabled", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /** + * NMClient::wwan-hardware-enabled: + * + * Whether the WWAN hardware is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WWAN_HARDWARE_ENABLED, + g_param_spec_boolean (NM_CLIENT_WWAN_HARDWARE_ENABLED, + "WwanHardwareEnabled", + "Is WWAN hardware enabled", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** * NMClient::active-connections: * @@ -566,9 +650,12 @@ proxy_name_owner_changed (DBusGProxy *proxy, free_object_array (&priv->active_connections); priv->wireless_enabled = FALSE; priv->wireless_hw_enabled = FALSE; + priv->wwan_enabled = FALSE; + priv->wwan_hw_enabled = FALSE; } else { _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING); update_wireless_status (client, TRUE); + update_wwan_status (client, TRUE); } } @@ -873,6 +960,61 @@ nm_client_wireless_hardware_get_enabled (NMClient *client) return NM_CLIENT_GET_PRIVATE (client)->wireless_hw_enabled; } +/** + * nm_client_wwan_get_enabled: + * @client: a #NMClient + * + * Determines whether WWAN is enabled. + * + * Returns: %TRUE if WWAN is enabled + **/ +gboolean +nm_client_wwan_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return NM_CLIENT_GET_PRIVATE (client)->wwan_enabled; +} + +/** + * nm_client_wwan_set_enabled: + * @client: a #NMClient + * @enabled: %TRUE to enable WWAN + * + * Enables or disables WWAN devices. + **/ +void +nm_client_wwan_set_enabled (NMClient *client, gboolean enabled) +{ + GValue value = {0,}; + + g_return_if_fail (NM_IS_CLIENT (client)); + + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, enabled); + + _nm_object_set_property (NM_OBJECT (client), + NM_DBUS_INTERFACE, + "WwanEnabled", + &value); +} + +/** + * nm_client_wwan_hardware_get_enabled: + * @client: a #NMClient + * + * Determines whether the WWAN hardware is enabled. + * + * Returns: %TRUE if the WWAN hardware is enabled + **/ +gboolean +nm_client_wwan_hardware_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return NM_CLIENT_GET_PRIVATE (client)->wwan_hw_enabled; +} + /** * nm_client_get_state: * @client: a #NMClient diff --git a/libnm-glib/nm-client.h b/libnm-glib/nm-client.h index d6df98ec5b..6aafc0872c 100644 --- a/libnm-glib/nm-client.h +++ b/libnm-glib/nm-client.h @@ -45,6 +45,8 @@ G_BEGIN_DECLS #define NM_CLIENT_MANAGER_RUNNING "manager-running" #define NM_CLIENT_WIRELESS_ENABLED "wireless-enabled" #define NM_CLIENT_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" +#define NM_CLIENT_WWAN_ENABLED "wwan-enabled" +#define NM_CLIENT_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled" #define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections" typedef struct { @@ -89,6 +91,11 @@ void nm_client_deactivate_connection (NMClient *client, NMActiveConnection *acti 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); + +gboolean nm_client_wwan_get_enabled (NMClient *client); +void nm_client_wwan_set_enabled (NMClient *client, gboolean enabled); +gboolean nm_client_wwan_hardware_get_enabled (NMClient *client); + NMState nm_client_get_state (NMClient *client); gboolean nm_client_get_manager_running (NMClient *client); const GPtrArray *nm_client_get_active_connections (NMClient *client); From f61af8e139a35cfa52e443fdc66ad4c05851085f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Dec 2009 00:29:17 -0800 Subject: [PATCH 10/12] modem: enable modem before connecting if required --- src/modem-manager/nm-modem-cdma.c | 61 +++++++++++++++++------------ src/modem-manager/nm-modem-gsm.c | 65 +++++++++++++++++++------------ 2 files changed, 77 insertions(+), 49 deletions(-) diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index ee524aa1d5..b6ca3caeee 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -92,7 +92,9 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d if (!error) nm_device_activate_schedule_stage2_device_config (device); else { - nm_warning ("CDMA modem connection failed: %s", error->message); + nm_warning ("CDMA modem connection failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); g_error_free (error); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); } @@ -115,44 +117,55 @@ create_connect_properties (NMConnection *connection) return properties; } +static void +do_connect (NMModem *modem) +{ + NMConnection *connection; + GHashTable *properties; + + connection = nm_act_request_get_connection (nm_device_get_act_request (NM_DEVICE (modem))); + g_assert (connection); + + properties = create_connect_properties (connection); + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE), + "Connect", stage1_prepare_done, + modem, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, properties, + G_TYPE_INVALID); + g_hash_table_destroy (properties); +} + static void stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); GError *error = NULL; - NMConnection *connection; - GHashTable *properties; - dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); - if (error) { - nm_warning ("CDMA modem connection failed: %s", error->message); + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) + do_connect (NM_MODEM (device)); + else { + nm_warning ("CDMA modem enable failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); g_error_free (error); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); - return; } - - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); - g_assert (connection); - - properties = create_connect_properties (connection); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), - "Connect", stage1_prepare_done, - device, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, properties, - G_TYPE_INVALID); - g_hash_table_destroy (properties); } static NMActStageReturn real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { - gboolean enable = TRUE; + gboolean enabled = nm_modem_get_mm_enabled (NM_MODEM (device)); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), - "Enable", stage1_enable_done, - device, NULL, 20000, - G_TYPE_BOOLEAN, enable, - G_TYPE_INVALID); + if (enabled) + do_connect (NM_MODEM (device)); + else { + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), + "Enable", stage1_enable_done, + device, NULL, 20000, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID); + } return NM_ACT_STAGE_RETURN_POSTPONE; } diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index d1e97dcbf5..8abfe06787 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -173,8 +173,11 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_d clear_pin (device); required_secret = NM_SETTING_GSM_PIN; retry_secret = TRUE; - } else - nm_warning ("GSM modem connection failed: %s", error->message); + } else { + nm_warning ("GSM modem connection failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } if (required_secret) { nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); @@ -247,32 +250,39 @@ create_connect_properties (NMConnection *connection) return properties; } +static void +do_connect (NMModem *modem) +{ + NMConnection *connection; + GHashTable *properties; + + connection = nm_act_request_get_connection (nm_device_get_act_request (NM_DEVICE (modem))); + g_assert (connection); + + properties = create_connect_properties (connection); + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM_SIMPLE), + "Connect", stage1_prepare_done, + modem, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, properties, + G_TYPE_INVALID); + g_hash_table_destroy (properties); +} + static void stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); GError *error = NULL; - NMConnection *connection; - GHashTable *properties; - dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); - if (error) { - nm_warning ("GSM modem connection failed: %s", error->message); + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) + do_connect (NM_MODEM (device)); + else { + nm_warning ("GSM modem enable failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); g_error_free (error); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); - return; } - - connection = nm_act_request_get_connection (nm_device_get_act_request (device)); - g_assert (connection); - - properties = create_connect_properties (connection); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), - "Connect", stage1_prepare_done, - device, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, properties, - G_TYPE_INVALID); - g_hash_table_destroy (properties); } static NMActStageReturn @@ -292,13 +302,18 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) setting_name = nm_connection_need_secrets (connection, &hints); if (!setting_name) { - gboolean enable = TRUE; + NMModem *modem = NM_MODEM (device); + gboolean enabled = nm_modem_get_mm_enabled (modem); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), - "Enable", stage1_enable_done, - device, NULL, 20000, - G_TYPE_BOOLEAN, enable, - G_TYPE_INVALID); + if (enabled) + do_connect (modem); + else { + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (modem, MM_DBUS_INTERFACE_MODEM), + "Enable", stage1_enable_done, + modem, NULL, 20000, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID); + } return NM_ACT_STAGE_RETURN_POSTPONE; } From 154a41dec9f22432dc6c42cce0d465eb188a080f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Dec 2009 01:23:38 -0800 Subject: [PATCH 11/12] modem: ensure device is deactivated if the modem is disabled underneath NM --- src/modem-manager/nm-modem.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index a0e83c4512..c44103e3a2 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -596,8 +596,17 @@ modem_properties_changed (DBusGProxy *proxy, value = g_hash_table_lookup (props, "Enabled"); if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + NMDeviceState state; + priv->mm_enabled = g_value_get_boolean (value); g_object_notify (G_OBJECT (self), NM_MODEM_ENABLED); + + state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self)); + if (IS_ACTIVATING_STATE (state) || (state == NM_DEVICE_STATE_ACTIVATED)) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_NONE); + } } } From ac38d65d6df2b1ad5a457554612151fa925fecee Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 23 Dec 2009 01:27:47 -0800 Subject: [PATCH 12/12] modem: fix activation after 1379af271138202d406de585cbdcd491ac11ed01 Got the return semantics of dbus_g_proxy_end_call() wrong... --- src/modem-manager/nm-modem-cdma.c | 2 +- src/modem-manager/nm-modem-gsm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index b6ca3caeee..07f1cf83bd 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -141,7 +141,7 @@ stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_da NMDevice *device = NM_DEVICE (user_data); GError *error = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) + if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) do_connect (NM_MODEM (device)); else { nm_warning ("CDMA modem enable failed: (%d) %s", diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index 8abfe06787..8484d0ae4f 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -274,7 +274,7 @@ stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_da NMDevice *device = NM_DEVICE (user_data); GError *error = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) + if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) do_connect (NM_MODEM (device)); else { nm_warning ("GSM modem enable failed: (%d) %s",