aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NetworkManager-r4160-use-modem-manager.patch (renamed from NetworkManager-r4060-use-modem-manager.patch)816
-rw-r--r--nm-applet-r938-use-modem-manager.patch (renamed from nm-applet-r884-use-modem-manager.patch)995
2 files changed, 1270 insertions, 541 deletions
diff --git a/NetworkManager-r4060-use-modem-manager.patch b/NetworkManager-r4160-use-modem-manager.patch
index bac492db..df10b000 100644
--- a/NetworkManager-r4060-use-modem-manager.patch
+++ b/NetworkManager-r4160-use-modem-manager.patch
@@ -1,5 +1,5 @@
diff --git a/configure.in b/configure.in
-index bd86fc2..fdc4369 100644
+index e63b313..0c2cdfd 100644
--- a/configure.in
+++ b/configure.in
@@ -477,6 +477,7 @@ src/dhcp-manager/Makefile
@@ -120,10 +120,10 @@ index 3c4ce75..3f24eb5 100644
$(top_builddir)/libnm-util/libnm-util.la
diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c
-index c8fa251..432af94 100644
+index 25024c2..f7942d6 100644
--- a/src/NetworkManagerPolicy.c
+++ b/src/NetworkManagerPolicy.c
-@@ -31,9 +31,6 @@
+@@ -35,9 +35,6 @@
#include "nm-device.h"
#include "nm-device-wifi.h"
#include "nm-device-ethernet.h"
@@ -133,30 +133,17 @@ index c8fa251..432af94 100644
#include "nm-dbus-manager.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-connection.h"
-@@ -90,10 +87,10 @@ update_default_route (NMPolicy *policy, NMDevice *new)
- static guint32
- get_device_priority (NMDevice *dev)
- {
-- if (NM_IS_CDMA_DEVICE (dev))
-+ if (nm_device_get_device_type (dev) == NM_DEVICE_TYPE_CDMA)
- return 2;
-
-- if (NM_IS_GSM_DEVICE (dev))
-+ if (nm_device_get_device_type (dev) == NM_DEVICE_TYPE_GSM)
- return 3;
-
- if (NM_IS_DEVICE_WIFI (dev))
-@@ -153,10 +150,6 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update)
- }
+@@ -227,7 +224,9 @@ get_best_device (NMManager *manager, NMActRequest **out_req)
}
-- /* 'hso' devices never get a gateway from the remote end */
+ /* 'hso' devices never get a gateway from the remote end */
- if (!can_default && !NM_IS_HSO_GSM_DEVICE (dev))
-- continue;
--
- prio = get_device_priority (dev);
- if (prio > best_prio) {
- best = dev;
++ /* FIXME */
++ /* if (!can_default && !NM_IS_HSO_GSM_DEVICE (dev)) */
++ if (!can_default)
+ continue;
+
+ prio = nm_device_get_priority (dev);
diff --git a/src/modem-manager/Makefile.am b/src/modem-manager/Makefile.am
new file mode 100644
index 0000000..519636b
@@ -208,10 +195,10 @@ index 0000000..519636b
+CLEANFILES = $(BUILT_SOURCES)
diff --git a/src/modem-manager/nm-cdma-modem.c b/src/modem-manager/nm-cdma-modem.c
new file mode 100644
-index 0000000..fec4540
+index 0000000..8e94fa1
--- /dev/null
+++ b/src/modem-manager/nm-cdma-modem.c
-@@ -0,0 +1,248 @@
+@@ -0,0 +1,261 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include <string.h>
@@ -402,7 +389,7 @@ index 0000000..fec4540
+ return;
+ }
+
-+ g_return_if_fail (caller == SECRETS_CALLER_GSM);
++ g_return_if_fail (caller == SECRETS_CALLER_CDMA);
+ g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH);
+
+ for (iter = updated_settings; iter; iter = g_slist_next (iter)) {
@@ -425,12 +412,23 @@ index 0000000..fec4540
+ nm_device_activate_schedule_stage1_device_prepare (dev);
+}
+
++static const char *
++real_get_ppp_name (NMModemDevice *device, NMConnection *connection)
++{
++ NMSettingCdma *s_cdma;
++
++ s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
++ g_assert (s_cdma);
++
++ return s_cdma->username;
++}
++
+/*****************************************************************************/
+
+static void
+nm_cdma_modem_init (NMCdmaModem *self)
+{
-+ nm_device_set_device_type (NM_DEVICE (self), NM_DEVICE_TYPE_GSM);
++ nm_device_set_device_type (NM_DEVICE (self), NM_DEVICE_TYPE_CDMA);
+}
+
+static void
@@ -438,6 +436,7 @@ index 0000000..fec4540
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
++ NMModemDeviceClass *modem_class = NM_MODEM_DEVICE_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (NMCdmaModemPrivate));
+
@@ -445,6 +444,7 @@ index 0000000..fec4540
+ device_class->get_best_auto_connection = real_get_best_auto_connection;
+ device_class->connection_secrets_updated = real_connection_secrets_updated;
+ device_class->act_stage1_prepare = real_act_stage1_prepare;
++ modem_class->get_ppp_name = real_get_ppp_name;
+
+ /* Signals */
+ signals[SIGNAL_QUALITY] =
@@ -890,10 +890,10 @@ index 0000000..9b16b0b
+#endif /* NM_GSM_MODEM_HSO_H */
diff --git a/src/modem-manager/nm-gsm-modem.c b/src/modem-manager/nm-gsm-modem.c
new file mode 100644
-index 0000000..271e23f
+index 0000000..691f189
--- /dev/null
+++ b/src/modem-manager/nm-gsm-modem.c
-@@ -0,0 +1,329 @@
+@@ -0,0 +1,342 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include <string.h>
@@ -1088,11 +1088,11 @@ index 0000000..271e23f
+
+ case MODEM_STATE_SET_NETWORK_MODE:
+ priv->modem_state = MODEM_STATE_REGISTER;
-+ dbus_g_proxy_begin_call (get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_NETWORK),
-+ "Register", state_machine,
-+ modem, NULL,
-+ G_TYPE_STRING, setting->network_id ? setting->network_id : "",
-+ G_TYPE_INVALID);
++ dbus_g_proxy_begin_call_with_timeout (get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_NETWORK),
++ "Register", state_machine,
++ modem, NULL, 120000,
++ G_TYPE_STRING, setting->network_id ? setting->network_id : "",
++ G_TYPE_INVALID);
+ break;
+
+ case MODEM_STATE_REGISTER:
@@ -1199,6 +1199,17 @@ index 0000000..271e23f
+ nm_device_activate_schedule_stage1_device_prepare (dev);
+}
+
++static const char *
++real_get_ppp_name (NMModemDevice *device, NMConnection *connection)
++{
++ NMSettingGsm *s_gsm;
++
++ s_gsm = (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
++ g_assert (s_gsm);
++
++ return s_gsm->username;
++}
++
+/*****************************************************************************/
+
+static void
@@ -1212,6 +1223,7 @@ index 0000000..271e23f
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
++ NMModemDeviceClass *modem_class = NM_MODEM_DEVICE_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (NMGsmModemPrivate));
+
@@ -1219,6 +1231,7 @@ index 0000000..271e23f
+ device_class->get_best_auto_connection = real_get_best_auto_connection;
+ device_class->connection_secrets_updated = real_connection_secrets_updated;
+ device_class->act_stage1_prepare = real_act_stage1_prepare;
++ modem_class->get_ppp_name = real_get_ppp_name;
+
+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+ &dbus_glib_nm_gsm_device_object_info);
@@ -1267,10 +1280,10 @@ index 0000000..8df8265
+#endif /* NM_GSM_MODEM_H */
diff --git a/src/modem-manager/nm-modem-device.c b/src/modem-manager/nm-modem-device.c
new file mode 100644
-index 0000000..c5ea8c6
+index 0000000..1f49acc
--- /dev/null
+++ b/src/modem-manager/nm-modem-device.c
-@@ -0,0 +1,467 @@
+@@ -0,0 +1,457 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include <string.h>
@@ -1359,6 +1372,19 @@ index 0000000..c5ea8c6
+ NM_MODEM_DEVICE_GET_CLASS (device)->connect (device, number);
+}
+
++const char *
++nm_modem_device_get_ppp_name (NMModemDevice *device,
++ NMConnection *connection)
++{
++ g_return_val_if_fail (NM_IS_MODEM_DEVICE (device), NULL);
++ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
++
++ if (NM_MODEM_DEVICE_GET_CLASS (device)->get_ppp_name)
++ return NM_MODEM_DEVICE_GET_CLASS (device)->get_ppp_name (device, connection);
++
++ return NULL;
++}
++
+static void
+ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data)
+{
@@ -1412,45 +1438,23 @@ index 0000000..c5ea8c6
+ }
+}
+
-+static NMConnection *
-+real_get_best_auto_connection (NMDevice *dev,
-+ GSList *connections,
-+ char **specific_object)
-+{
-+ GSList *iter;
-+
-+ for (iter = connections; iter; iter = g_slist_next (iter)) {
-+ NMConnection *connection = NM_CONNECTION (iter->data);
-+ NMSettingConnection *s_con;
-+
-+ s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
-+ g_assert (s_con);
-+
-+ if (!s_con->autoconnect)
-+ continue;
-+
-+ if (strcmp (s_con->type, NM_SETTING_GSM_SETTING_NAME))
-+ continue;
-+
-+ return connection;
-+ }
-+ return NULL;
-+}
-+
+static NMActStageReturn
+real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
+{
+ NMModemDevicePrivate *priv = NM_MODEM_DEVICE_GET_PRIVATE (device);
+ NMActRequest *req;
++ const char *ppp_name = NULL;
+ GError *err = NULL;
+ NMActStageReturn ret;
+
+ req = nm_device_get_act_request (device);
+ g_assert (req);
+
-+ priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (device));
++ ppp_name = nm_modem_device_get_ppp_name (NM_MODEM_DEVICE (device),
++ nm_act_request_get_connection (req));
+
-+ if (nm_ppp_manager_start (priv->ppp_manager, req, &err)) {
++ priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (device));
++ if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, &err)) {
+ g_signal_connect (priv->ppp_manager, "state-changed",
+ G_CALLBACK (ppp_state_changed),
+ device);
@@ -1537,11 +1541,11 @@ index 0000000..c5ea8c6
+static void
+real_connect (NMModemDevice *modem, const char *number)
+{
-+ dbus_g_proxy_begin_call (nm_modem_device_get_proxy (modem, MM_DBUS_INTERFACE_MODEM),
-+ "Connect", connect_done,
-+ modem, NULL,
-+ G_TYPE_STRING, number ? number : "",
-+ G_TYPE_INVALID);
++ dbus_g_proxy_begin_call_with_timeout (nm_modem_device_get_proxy (modem, MM_DBUS_INTERFACE_MODEM),
++ "Connect", connect_done,
++ modem, NULL, 60000,
++ G_TYPE_STRING, number ? number : "",
++ G_TYPE_INVALID);
+}
+
+static gboolean
@@ -1703,7 +1707,6 @@ index 0000000..c5ea8c6
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+
-+ device_class->get_best_auto_connection = real_get_best_auto_connection;
+ device_class->get_generic_capabilities = real_get_generic_capabilities;
+ device_class->act_stage2_config = real_act_stage2_config;
+ device_class->act_stage4_get_ip4_config = real_act_stage4_get_ip4_config;
@@ -1740,10 +1743,10 @@ index 0000000..c5ea8c6
+}
diff --git a/src/modem-manager/nm-modem-device.h b/src/modem-manager/nm-modem-device.h
new file mode 100644
-index 0000000..6c0de49
+index 0000000..fae6d74
--- /dev/null
+++ b/src/modem-manager/nm-modem-device.h
-@@ -0,0 +1,49 @@
+@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#ifndef NM_MODEM_DEVICE_H
@@ -1774,6 +1777,9 @@ index 0000000..6c0de49
+ void (*connect) (NMModemDevice *device,
+ const char *number);
+
++ const char *(*get_ppp_name) (NMModemDevice *device,
++ NMConnection *connection);
++
+ /* Signals */
+ void (*ppp_stats) (NMModemDevice *device, guint32 in_bytes, guint32 out_bytes);
+ void (*properties_changed) (NMModemDevice *device, GHashTable *properties);
@@ -1790,15 +1796,18 @@ index 0000000..6c0de49
+void nm_modem_device_connect (NMModemDevice *device,
+ const char *number);
+
++const char *nm_modem_device_get_ppp_name (NMModemDevice *device,
++ NMConnection *connection);
++
+G_END_DECLS
+
+#endif /* NM_MODEM_DEVICE_H */
diff --git a/src/modem-manager/nm-modem-manager.c b/src/modem-manager/nm-modem-manager.c
new file mode 100644
-index 0000000..6e37ebd
+index 0000000..66db012
--- /dev/null
+++ b/src/modem-manager/nm-modem-manager.c
-@@ -0,0 +1,404 @@
+@@ -0,0 +1,388 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include <string.h>
@@ -1968,7 +1977,6 @@ index 0000000..6e37ebd
+static void
+modem_added (DBusGProxy *proxy, const char *path, gpointer user_data)
+{
-+ g_print ("Modem added %s\n", path);
+ create_modem (NM_MODEM_MANAGER (user_data), path);
+}
+
@@ -1978,8 +1986,6 @@ index 0000000..6e37ebd
+ NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (user_data);
+ NMModemDevice *modem;
+
-+ g_print ("Modem removed %s\n", path);
-+
+ modem = (NMModemDevice *) g_hash_table_lookup (priv->modems, path);
+ if (modem) {
+ g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, modem);
@@ -1987,8 +1993,29 @@ index 0000000..6e37ebd
+ }
+}
+
++static gboolean
++poke_modem_cb (gpointer user_data)
++{
++ NMModemManager *self = NM_MODEM_MANAGER (user_data);
++ NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
++ DBusGConnection *g_connection;
++ DBusGProxy *proxy;
++
++ g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
++ proxy = dbus_g_proxy_new_for_name (g_connection,
++ MM_DBUS_SERVICE,
++ MM_DBUS_PATH,
++ MM_DBUS_INTERFACE);
++
++ nm_info ("Trying to start the modem-manager...");
++ dbus_g_proxy_call_no_reply (proxy, "EnumerateDevices", G_TYPE_INVALID);
++ g_object_unref (proxy);
++
++ return TRUE;
++}
++
+static void
-+get_modems_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer data)
++enumerate_devices_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer data)
+{
+ NMModemManager *manager = NM_MODEM_MANAGER (data);
+ GPtrArray *modems;
@@ -2005,7 +2032,6 @@ index 0000000..6e37ebd
+ for (i = 0; i < modems->len; i++) {
+ char *path = (char *) g_ptr_array_index (modems, i);
+
-+ g_print ("Got modem: %s\n", path);
+ create_modem (manager, path);
+ g_free (path);
+ }
@@ -2014,71 +2040,55 @@ index 0000000..6e37ebd
+ }
+}
+
-+static gboolean
-+get_modems (gpointer data)
++static void
++modem_manager_appeared (NMModemManager *self)
+{
-+ NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (data);
++ NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
++
++ if (priv->poke_id) {
++ g_source_remove (priv->poke_id);
++ priv->poke_id = 0;
++ }
+
+ priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
+ MM_DBUS_SERVICE, MM_DBUS_PATH, MM_DBUS_INTERFACE);
+
+ dbus_g_proxy_add_signal (priv->proxy, "DeviceAdded", G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (priv->proxy, "DeviceAdded",
-+ G_CALLBACK (modem_added),
-+ data,
++ G_CALLBACK (modem_added), self,
+ NULL);
+
+ dbus_g_proxy_add_signal (priv->proxy, "DeviceRemoved", G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (priv->proxy, "DeviceRemoved",
-+ G_CALLBACK (modem_removed),
-+ data,
++ G_CALLBACK (modem_removed), self,
+ NULL);
+
-+ dbus_g_proxy_begin_call (priv->proxy, "EnumerateDevices", get_modems_cb, data, NULL, G_TYPE_INVALID);
-+
-+ return FALSE;
++ dbus_g_proxy_begin_call (priv->proxy, "EnumerateDevices", enumerate_devices_done, self, NULL, G_TYPE_INVALID);
+}
+
+static gboolean
-+nm_modem_manager_startup (NMModemManager *self)
++remove_one_modem (gpointer key, gpointer value, gpointer user_data)
+{
-+ gboolean running;
++ g_signal_emit (user_data, signals[DEVICE_REMOVED], 0, value);
+
-+ running = nm_dbus_manager_name_has_owner (NM_MODEM_MANAGER_GET_PRIVATE (self)->dbus_mgr, MM_DBUS_SERVICE);
-+ if (running) {
-+ g_idle_add (get_modems, self);
-+ }
-+
-+ return running;
++ return TRUE;
+}
+
-+static gboolean
-+poke_modem_cb (gpointer user_data)
++static void
++modem_manager_disappeared (NMModemManager *self)
+{
-+ NMModemManager *self = NM_MODEM_MANAGER (user_data);
+ NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
-+ DBusGConnection *g_connection;
-+ DBusGProxy *proxy;
+
-+ g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
-+ proxy = dbus_g_proxy_new_for_name (g_connection,
-+ MM_DBUS_SERVICE,
-+ MM_DBUS_PATH,
-+ MM_DBUS_INTERFACE);
-+ if (!proxy) {
-+ nm_warning ("Error: could not init wpa_modem proxy");
-+ goto out;
-+ }
++ g_hash_table_foreach_remove (priv->modems, remove_one_modem, self);
+
-+ nm_info ("Trying to start the modem-manager...");
-+ dbus_g_proxy_call_no_reply (proxy, "EnumerateDevices", G_TYPE_INVALID);
-+ g_object_unref (proxy);
++ if (priv->proxy) {
++ g_object_unref (priv->proxy);
++ priv->proxy = NULL;
++ }
+
-+out:
-+ /* Reschedule the poke */
++ /* Try to activate the modem-manager */
++ poke_modem_cb (self);
+ priv->poke_id = g_timeout_add (MODEM_POKE_INTERVAL, poke_modem_cb, self);
-+
-+ return FALSE;
+}
+
+static void
@@ -2088,58 +2098,40 @@ index 0000000..6e37ebd
+ const char *new_owner,
+ gpointer user_data)
+{
-+ NMModemManager * self = (NMModemManager *) user_data;
-+ NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
-+ gboolean old_owner_good = (old_owner && strlen (old_owner));
-+ gboolean new_owner_good = (new_owner && strlen (new_owner));
++ gboolean old_owner_good;
++ gboolean new_owner_good;
+
+ /* Can't handle the signal if its not from the modem service */
+ if (strcmp (MM_DBUS_SERVICE, name) != 0)
+ return;
+
-+ if (!old_owner_good && new_owner_good) {
-+ gboolean running;
-+
-+ running = nm_modem_manager_startup (self);
-+
-+ if (running && priv->poke_id) {
-+ g_source_remove (priv->poke_id);
-+ priv->poke_id = 0;
-+ }
-+ } else if (old_owner_good && !new_owner_good) {
-+ if (priv->proxy) {
-+ g_object_unref (priv->proxy);
-+ priv->proxy = NULL;
-+ }
++ old_owner_good = (old_owner && strlen (old_owner));
++ new_owner_good = (new_owner && strlen (new_owner));
+
-+ /* Poke the modem so that it gets activated by dbus system bus
-+ * activation.
-+ */
-+ if (!priv->poke_id)
-+ priv->poke_id = g_idle_add (poke_modem_cb, (gpointer) self);
-+ }
++ if (!old_owner_good && new_owner_good)
++ modem_manager_disappeared (NM_MODEM_MANAGER (user_data));
++ else if (old_owner_good && !new_owner_good)
++ modem_manager_appeared (NM_MODEM_MANAGER (user_data));
+}
+
++/*******************************************************/
++
+static void
+nm_modem_manager_init (NMModemManager *self)
+{
+ NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self);
-+ gboolean running;
+
+ priv->modems = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ priv->dbus_mgr = nm_dbus_manager_get ();
+
-+ running = nm_modem_manager_startup (self);
-+
-+ g_signal_connect (priv->dbus_mgr,
-+ "name-owner-changed",
++ g_signal_connect (priv->dbus_mgr, "name-owner-changed",
+ G_CALLBACK (nm_modem_manager_name_owner_changed),
+ self);
+
-+ if (!running) {
-+ /* Try to activate the modem-manager */
-+ priv->poke_id = g_idle_add (poke_modem_cb, (gpointer) self);
-+ }
++ if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, MM_DBUS_SERVICE))
++ modem_manager_appeared (self);
++ else
++ modem_manager_disappeared (self);
+}
+
+static void
@@ -2157,6 +2149,7 @@ index 0000000..6e37ebd
+ priv->poke_id = 0;
+ }
+
++ g_hash_table_foreach_remove (priv->modems, remove_one_modem, object);
+ g_hash_table_destroy (priv->modems);
+
+ if (priv->proxy) {
@@ -2341,10 +2334,10 @@ index 0000000..f5cbe10
+#endif /* NM_MODEM_TYPES_H */
diff --git a/src/nm-cdma-device.c b/src/nm-cdma-device.c
deleted file mode 100644
-index 31023e1..0000000
+index 63e4883..0000000
--- a/src/nm-cdma-device.c
+++ /dev/null
-@@ -1,525 +0,0 @@
+@@ -1,571 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-
-#include <stdio.h>
@@ -2426,6 +2419,7 @@ index 31023e1..0000000
-static void
-dial_done (NMSerialDevice *device,
- int reply_index,
+- const char *reply,
- gpointer user_data)
-{
- NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_UNKNOWN;
@@ -2469,7 +2463,7 @@ index 31023e1..0000000
- NMSettingCdma *setting;
- char *command;
- guint id = 0;
-- char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
+- const char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
-
- setting = NM_SETTING_CDMA (cdma_device_get_setting (NM_CDMA_DEVICE (device), NM_TYPE_SETTING_CDMA));
-
@@ -2485,13 +2479,40 @@ index 31023e1..0000000
-}
-
-static void
+-power_up_response (NMSerialDevice *device,
+- int reply_index,
+- const char *reply,
+- gpointer user_data)
+-{
+- /* Ignore errors */
+- do_dial (device);
+-}
+-
+-static void
+-power_up (NMSerialDevice *device)
+-{
+- const char *responses[] = { "OK", "ERROR", "ERR", NULL };
+- guint id = 0;
+-
+- /* Only works on Sierra cards */
+- nm_info ("(%s): powering up...", nm_device_get_iface (NM_DEVICE (device)));
+- if (nm_serial_device_send_command_string (device, "at!pcstate=1"))
+- id = nm_serial_device_wait_for_reply (device, 10, responses, responses, power_up_response, NULL);
+-
+- /* Ignore errors */
+- if (id == 0)
+- do_dial (device);
+-}
+-
+-static void
-init_done (NMSerialDevice *device,
-- int reply_index,
-- gpointer user_data)
+- int reply_index,
+- const char *reply,
+- gpointer user_data)
-{
- switch (reply_index) {
- case 0:
-- do_dial (device);
+- power_up (device);
- break;
- case -1:
- nm_warning ("Modem initialization timed out");
@@ -2512,7 +2533,7 @@ index 31023e1..0000000
-init_modem (NMSerialDevice *device, gpointer user_data)
-{
- guint id = 0;
-- char *responses[] = { "OK", "ERROR", "ERR", NULL };
+- const char *responses[] = { "OK", "ERROR", "ERR", NULL };
-
- if (nm_serial_device_send_command_string (device, "ATZ E0"))
- id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_done, NULL);
@@ -2631,6 +2652,21 @@ index 31023e1..0000000
- nm_device_activate_schedule_stage1_device_prepare (dev);
-}
-
+-static const char *
+-real_get_ppp_name (NMSerialDevice *device, NMActRequest *req)
+-{
+- NMConnection *connection;
+- NMSettingCdma *s_cdma;
+-
+- connection = nm_act_request_get_connection (req);
+- g_assert (connection);
+-
+- s_cdma = (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
+- g_assert (s_cdma);
+-
+- return s_cdma->username;
+-}
+-
-/*****************************************************************************/
-/* Monitor device handling */
-
@@ -2840,6 +2876,7 @@ index 31023e1..0000000
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- NMDeviceClass *device_class = NM_DEVICE_CLASS (klass);
+- NMSerialDeviceClass *serial_class = NM_SERIAL_DEVICE_CLASS (klass);
-
- g_type_class_add_private (object_class, sizeof (NMCdmaDevicePrivate));
-
@@ -2853,6 +2890,8 @@ index 31023e1..0000000
- device_class->act_stage1_prepare = real_act_stage1_prepare;
- device_class->connection_secrets_updated = real_connection_secrets_updated;
-
+- serial_class->get_ppp_name = real_get_ppp_name;
+-
- /* Properties */
- g_object_class_install_property
- (object_class, PROP_MONITOR_IFACE,
@@ -3093,10 +3132,10 @@ index 32cb705..8cf41e1 100644
static void
diff --git a/src/nm-hso-gsm-device.c b/src/nm-hso-gsm-device.c
deleted file mode 100644
-index 009d803..0000000
+index 30fd8d9..0000000
--- a/src/nm-hso-gsm-device.c
+++ /dev/null
-@@ -1,569 +0,0 @@
+@@ -1,560 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-
-#include <stdio.h>
@@ -3163,12 +3202,12 @@ index 009d803..0000000
-
-static void
-modem_wait_for_reply (NMGsmDevice *self,
-- const char *command,
-- guint timeout,
-- char **responses,
-- char **terminators,
-- NMSerialWaitForReplyFn callback,
-- gpointer user_data)
+- const char *command,
+- guint timeout,
+- const char **responses,
+- const char **terminators,
+- NMSerialWaitForReplyFn callback,
+- gpointer user_data)
-{
- NMSerialDevice *serial = NM_SERIAL_DEVICE (self);
- guint id = 0;
@@ -3180,23 +3219,6 @@ index 009d803..0000000
- nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
-}
-
--static void
--modem_get_reply (NMGsmDevice *self,
-- const char *command,
-- guint timeout,
-- const char *terminators,
-- NMSerialGetReplyFn callback)
--{
-- NMSerialDevice *serial = NM_SERIAL_DEVICE (self);
-- guint id = 0;
--
-- if (nm_serial_device_send_command_string (serial, command))
-- id = nm_serial_device_get_reply (serial, timeout, terminators, callback, NULL);
--
-- if (id == 0)
-- nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
--}
--
-static NMSetting *
-gsm_device_get_setting (NMGsmDevice *device, GType setting_type)
-{
@@ -3218,6 +3240,7 @@ index 009d803..0000000
-static void
-hso_call_done (NMSerialDevice *device,
- int reply_index,
+- const char *reply,
- gpointer user_data)
-{
- gboolean success = FALSE;
@@ -3240,10 +3263,11 @@ index 009d803..0000000
-
-static void
-hso_clear_done (NMSerialDevice *device,
-- int reply_index,
-- gpointer user_data)
+- int reply_index,
+- const char *reply,
+- gpointer user_data)
-{
-- char *responses[] = { "_OWANCALL: ", "ERROR", NULL };
+- const char *responses[] = { "_OWANCALL: ", "ERROR", NULL };
- guint cid = GPOINTER_TO_UINT (user_data);
- char *command;
-
@@ -3256,10 +3280,11 @@ index 009d803..0000000
-static void
-hso_auth_done (NMSerialDevice *device,
- int reply_index,
+- const char *reply,
- gpointer user_data)
-{
- gboolean success = FALSE;
-- char *responses[] = { "_OWANCALL: ", "ERROR", "NO CARRIER", NULL };
+- const char *responses[] = { "_OWANCALL: ", "ERROR", "NO CARRIER", NULL };
- guint cid = GPOINTER_TO_UINT (user_data);
- char *command;
-
@@ -3289,7 +3314,7 @@ index 009d803..0000000
-{
- NMSettingGsm *s_gsm;
- NMActRequest *req;
-- char *responses[] = { "OK", "ERROR", NULL };
+- const char *responses[] = { "OK", "ERROR", "ERR", NULL };
- char *command;
- guint cid;
-
@@ -3368,9 +3393,10 @@ index 009d803..0000000
-#define OWANDATA_TAG "_OWANDATA: "
-
-static void
--hso_ip4_config_done (NMSerialDevice *device,
-- const char *response,
-- gpointer user_data)
+-hso_ip4_config_response (NMSerialDevice *device,
+- int reply_index,
+- const char *response,
+- gpointer user_data)
-{
- NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device);
- NMActRequest *req;
@@ -3379,7 +3405,9 @@ index 009d803..0000000
- NMSettingIP4Address addr = { 0, 32, 0 };
- guint32 dns1 = 0, dns2 = 0;
-
-- if (!response || strncmp (response, OWANDATA_TAG, strlen (OWANDATA_TAG))) {
+- if ( (reply_index < 0)
+- || !response
+- || strncmp (response, OWANDATA_TAG, strlen (OWANDATA_TAG))) {
- nm_device_activate_schedule_stage4_ip_config_timeout (NM_DEVICE (device));
- return;
- }
@@ -3437,17 +3465,18 @@ index 009d803..0000000
-static NMActStageReturn
-real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason)
-{
-- const char terminators[] = { '\r', '\n', '\0' };
- NMActRequest *req;
- char *command;
- gint cid;
+- const char *responses[] = { "_OWANDATA: ", NULL };
+- const char *terminators[] = { "OK", "ERROR", "ERR", NULL };
-
- req = nm_device_get_act_request (device);
- g_assert (req);
-
- cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID));
- command = g_strdup_printf ("AT_OWANDATA=%d", cid);
-- modem_get_reply (NM_GSM_DEVICE (device), command, 5, terminators, hso_ip4_config_done);
+- modem_wait_for_reply (NM_GSM_DEVICE (device), command, 5, responses, terminators, hso_ip4_config_response, NULL);
- g_free (command);
-
- return NM_ACT_STAGE_RETURN_POSTPONE;
@@ -3509,18 +3538,19 @@ index 009d803..0000000
- if (req) {
- cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID));
- if (cid) {
-- command = g_strdup_printf ("AT_OWANCALL=%d,0,1", cid);
-- nm_serial_device_send_command_string (NM_SERIAL_DEVICE (device), command);
-- g_free (command);
+- const char *responses[] = { "OK", "ERROR", "ERR", NULL };
+- int reply;
-
-- /* FIXME: doesn't seem to take the command otherwise, perhaps since
-- * the serial port gets closed right away
+- /* Disconnect and disable asynchonous notification to keep serial
+- * buffer empty after the OK.
- */
-- g_usleep (G_USEC_PER_SEC / 3);
+- command = g_strdup_printf ("AT_OWANCALL=%d,0,0", cid);
+- nm_serial_device_send_command_string (NM_SERIAL_DEVICE (device), command);
+- reply = nm_serial_device_wait_reply_blocking (NM_SERIAL_DEVICE (device), 5, responses, responses);
+- g_free (command);
- }
- }
-
--
- if (NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate_quickly)
- NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate_quickly (device);
-}
@@ -3711,7 +3741,7 @@ index a7498c8..0000000
-
-#endif /* NM_HSO_GSM_DEVICE_H */
diff --git a/src/nm-manager.c b/src/nm-manager.c
-index 62fbb0c..ae7c077 100644
+index b755902..3a31418 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -7,6 +7,7 @@
@@ -3722,17 +3752,18 @@ index 62fbb0c..ae7c077 100644
#include "nm-device-interface.h"
#include "nm-device-private.h"
#include "nm-device-wifi.h"
-@@ -70,6 +71,9 @@ static void hal_manager_rfkill_changed_cb (NMHalManager *hal_mgr,
- static void hal_manager_hal_reappeared_cb (NMHalManager *hal_mgr,
- gpointer user_data);
+@@ -74,6 +75,10 @@ static void system_settings_properties_changed_cb (DBusGProxy *proxy,
+ GHashTable *properties,
+ gpointer user_data);
+static void add_device (NMManager *self, NMDevice *device, const char *type_name);
+static void remove_one_device (NMManager *manager, NMDevice *device);
+
++
#define SSD_POKE_INTERVAL 120000
typedef struct {
-@@ -107,6 +111,10 @@ typedef struct {
+@@ -112,6 +117,10 @@ typedef struct {
NMVPNManager *vpn_manager;
guint vpn_manager_id;
@@ -3743,7 +3774,7 @@ index 62fbb0c..ae7c077 100644
DBusGProxy *aipd_proxy;
gboolean disposed;
-@@ -212,6 +220,33 @@ vpn_manager_connection_deactivated_cb (NMVPNManager *manager,
+@@ -220,6 +229,33 @@ vpn_manager_connection_deactivated_cb (NMVPNManager *manager,
}
static void
@@ -3777,7 +3808,7 @@ index 62fbb0c..ae7c077 100644
aipd_handle_event (DBusGProxy *proxy,
const char *event,
const char *iface,
-@@ -274,6 +309,12 @@ nm_manager_init (NMManager *manager)
+@@ -282,6 +318,12 @@ nm_manager_init (NMManager *manager)
g_free,
g_object_unref);
@@ -3790,7 +3821,7 @@ index 62fbb0c..ae7c077 100644
priv->vpn_manager = nm_vpn_manager_get ();
id = g_signal_connect (G_OBJECT (priv->vpn_manager), "connection-deactivated",
G_CALLBACK (vpn_manager_connection_deactivated_cb), manager);
-@@ -452,6 +493,16 @@ dispose (GObject *object)
+@@ -481,6 +523,16 @@ dispose (GObject *object)
}
g_object_unref (priv->vpn_manager);
@@ -3807,7 +3838,7 @@ index 62fbb0c..ae7c077 100644
g_object_unref (priv->dbus_mgr);
g_object_unref (priv->hal_mgr);
-@@ -1528,58 +1579,66 @@ next:
+@@ -1595,58 +1647,66 @@ next:
}
static void
@@ -3901,11 +3932,11 @@ index 62fbb0c..ae7c077 100644
gpointer user_data)
diff --git a/src/nm-serial-device.c b/src/nm-serial-device.c
deleted file mode 100644
-index 4fa4cb4..0000000
+index b6f97d4..0000000
--- a/src/nm-serial-device.c
+++ /dev/null
-@@ -1,1151 +0,0 @@
--/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+@@ -1,1144 +0,0 @@
+-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-
-#define _GNU_SOURCE /* for strcasestr() */
-
@@ -3917,6 +3948,7 @@ index 4fa4cb4..0000000
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <string.h>
+-#include <stdlib.h>
-#include <glib.h>
-
-#include "nm-serial-device.h"
@@ -3928,7 +3960,7 @@ index 4fa4cb4..0000000
-#include "nm-utils.h"
-#include "nm-serial-device-glue.h"
-
--/* #define NM_DEBUG_SERIAL 1 */
+-static gboolean serial_debug = FALSE;
-
-#define SERIAL_BUF_SIZE 2048
-
@@ -4093,13 +4125,15 @@ index 4fa4cb4..0000000
- return stopbits;
-}
-
--#ifdef NM_DEBUG_SERIAL
-static inline void
--serial_debug (const char *prefix, const char *data, int len)
+-nm_serial_debug (const char *prefix, const char *data, int len)
-{
- GString *str;
- int i;
-
+- if (!serial_debug)
+- return;
+-
- str = g_string_sized_new (len);
- for (i = 0; i < len; i++) {
- if (data[i] == '\0')
@@ -4113,12 +4147,6 @@ index 4fa4cb4..0000000
- nm_debug ("%s '%s'", prefix, str->str);
- g_string_free (str, TRUE);
-}
--#else
--static inline void
--serial_debug (const char *prefix, const char *data, int len)
--{
--}
--#endif /* NM_DEBUG_SERIAL */
-
-static NMSetting *
-serial_device_get_setting (NMSerialDevice *device, GType setting_type)
@@ -4270,7 +4298,7 @@ index 4fa4cb4..0000000
-
-gboolean
-nm_serial_device_open (NMSerialDevice *device,
-- NMSettingSerial *setting)
+- NMSettingSerial *setting)
-{
- NMSerialDevicePrivate *priv;
- const char *iface;
@@ -4321,6 +4349,12 @@ index 4fa4cb4..0000000
- if (priv->pending_id)
- g_source_remove (priv->pending_id);
-
+- if (priv->ppp_manager) {
+- nm_ppp_manager_stop (priv->ppp_manager);
+- g_object_unref (priv->ppp_manager);
+- priv->ppp_manager = NULL;
+- }
+-
- if (priv->fd) {
- nm_debug ("Closing device '%s'", nm_device_get_iface (NM_DEVICE (device)));
-
@@ -4340,33 +4374,41 @@ index 4fa4cb4..0000000
-{
- int fd;
- NMSettingSerial *setting;
-- int i;
-- ssize_t status;
+- int i, eagain_count = 1000;
+- ssize_t written;
+- guint32 send_delay = G_USEC_PER_SEC / 1000;
-
- g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE);
- g_return_val_if_fail (command != NULL, FALSE);
-
- fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd;
- setting = NM_SETTING_SERIAL (serial_device_get_setting (device, NM_TYPE_SETTING_SERIAL));
+- if (setting && setting->send_delay)
+- send_delay = setting->send_delay;
-
-- serial_debug ("Sending:", (char *) command->data, command->len);
--
-- for (i = 0; i < command->len; i++) {
-- again:
-- status = write (fd, command->data + i, 1);
+- nm_serial_debug ("Sending:", (char *) command->data, command->len);
-
-- if (status < 0) {
-- if (errno == EAGAIN)
-- goto again;
+- for (i = 0; i < command->len && eagain_count > 0;) {
+- written = write (fd, command->data + i, 1);
-
-- g_warning ("Error in writing (errno %d)", errno);
-- return FALSE;
+- if (written > 0)
+- i += written;
+- else {
+- /* Treat written == 0 as EAGAIN to ensure we break out of the
+- * for() loop eventually.
+- */
+- if ((written < 0) && (errno != EAGAIN)) {
+- g_warning ("Error in writing (errno %d)", errno);
+- return FALSE;
+- }
+- eagain_count--;
- }
--
-- if (setting->send_delay)
-- usleep (setting->send_delay);
+- g_usleep (send_delay);
- }
-
+- if (eagain_count <= 0)
+- nm_serial_debug ("Error: too many retries sending:", (char *) command->data, command->len);
+-
- return TRUE;
-}
-
@@ -4389,117 +4431,121 @@ index 4fa4cb4..0000000
- return ret;
-}
-
--typedef struct {
-- NMSerialDevice *device;
-- char *terminators;
-- GString *result;
-- NMSerialGetReplyFn callback;
-- gpointer user_data;
--} GetReplyInfo;
--
--static void
--get_reply_done (gpointer data)
+-static gboolean
+-find_terminator (const char *line, const char **terminators)
-{
-- GetReplyInfo *info = (GetReplyInfo *) data;
--
-- nm_serial_device_pending_done (info->device);
+- int i;
-
-- /* Call the callback */
-- info->callback (info->device, info->result->str, info->user_data);
+- for (i = 0; terminators[i]; i++) {
+- if (!strncasecmp (line, terminators[i], strlen (terminators[i])))
+- return TRUE;
+- }
+- return FALSE;
+-}
-
-- /* Free info */
-- g_free (info->terminators);
-- g_string_free (info->result, TRUE);
+-static const char *
+-find_response (const char *line, const char **responses, gint *idx)
+-{
+- int i;
-
-- g_slice_free (GetReplyInfo, info);
+- /* Don't look for a result again if we got one previously */
+- for (i = 0; responses[i]; i++) {
+- if (strcasestr (line, responses[i])) {
+- *idx = i;
+- return line;
+- }
+- }
+- return NULL;
-}
-
--static gboolean
--get_reply_got_data (GIOChannel *source,
-- GIOCondition condition,
-- gpointer data)
+-#define RESPONSE_LINE_MAX 128
+-
+-int
+-nm_serial_device_wait_reply_blocking (NMSerialDevice *device,
+- guint32 timeout_secs,
+- const char **needles,
+- const char **terminators)
-{
-- GetReplyInfo *info = (GetReplyInfo *) data;
-- gsize bytes_read;
- char buf[SERIAL_BUF_SIZE + 1];
-- GIOStatus status;
+- int fd, reply_index = -1, bytes_read;
+- GString *result = NULL;
+- time_t end;
+- const char *response = NULL;
- gboolean done = FALSE;
-- int i;
-
-- if (condition & G_IO_HUP || condition & G_IO_ERR) {
-- g_string_truncate (info->result, 0);
-- return FALSE;
-- }
+- g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), -1);
+- g_return_val_if_fail (timeout_secs <= 60, -1);
+- g_return_val_if_fail (needles != NULL, -1);
-
-- do {
-- GError *err = NULL;
+- fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd;
+- if (fd < 0)
+- return -1;
-
-- status = g_io_channel_read_chars (source, buf, SERIAL_BUF_SIZE, &bytes_read, &err);
-- if (status == G_IO_STATUS_ERROR) {
-- g_warning ("%s", err->message);
-- g_error_free (err);
-- err = NULL;
+- end = time (NULL) + timeout_secs;
+- result = g_string_sized_new (20);
+- do {
+- bytes_read = read (fd, buf, SERIAL_BUF_SIZE);
+- if (bytes_read < 0 && errno != EAGAIN) {
+- nm_warning ("%s: read error: %d (%s)",
+- nm_device_get_iface (NM_DEVICE (device)),
+- errno,
+- strerror (errno));
+- return -1;
- }
-
-- if (bytes_read > 0) {
-- char *p;
+- if (bytes_read == 0)
+- break; /* EOF */
+- else if (bytes_read > 0) {
+- buf[bytes_read] = 0;
+- g_string_append (result, buf);
-
-- serial_debug ("Got:", buf, bytes_read);
+- nm_serial_debug ("Got:", result->str, result->len);
+- }
-
-- p = &buf[0];
-- for (i = 0; i < bytes_read && !done; i++, p++) {
-- int j;
-- gboolean is_terminator = FALSE;
+- /* Look for needles and terminators */
+- if ((bytes_read > 0) && result->str) {
+- char *p = result->str;
-
-- for (j = 0; j < strlen (info->terminators); j++) {
-- if (*p == info->terminators[j]) {
-- is_terminator = TRUE;
-- break;
+- /* Break the response up into lines and process each one */
+- while ((p < result->str + strlen (result->str)) && !done) {
+- char line[RESPONSE_LINE_MAX] = { '\0', };
+- char *tmp;
+- int i;
+- gboolean got_something = FALSE;
+-
+- for (i = 0; *p && (i < RESPONSE_LINE_MAX - 1); p++) {
+- /* Ignore front CR/LF */
+- if ((*p == '\n') || (*p == '\r')) {
+- if (got_something)
+- break;
+- } else {
+- line[i++] = *p;
+- got_something = TRUE;
- }
- }
+- line[i] = '\0';
-
-- if (is_terminator) {
-- /* Ignore terminators in the beginning of the output */
-- if (info->result->len > 0)
-- done = TRUE;
-- } else
-- g_string_append_c (info->result, *p);
+- tmp = g_strstrip (line);
+- if (tmp && strlen (tmp)) {
+- done = find_terminator (tmp, terminators);
+- if (reply_index == -1)
+- response = find_response (tmp, needles, &reply_index);
+- }
- }
- }
-
- /* Limit the size of the buffer */
-- if (info->result->len > SERIAL_BUF_SIZE) {
+- if (result->len > SERIAL_BUF_SIZE) {
- g_warning ("%s (%s): response buffer filled before repsonse received",
-- __func__, nm_device_get_iface (NM_DEVICE (info->device)));
-- g_string_truncate (info->result, 0);
-- done = TRUE;
+- __func__, nm_device_get_iface (NM_DEVICE (device)));
+- break;
- }
-- } while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
-
-- return !done;
--}
+- if (!done)
+- g_usleep (100);
+- } while (!done && (time (NULL) < end));
-
--guint
--nm_serial_device_get_reply (NMSerialDevice *device,
-- guint timeout,
-- const char *terminators,
-- NMSerialGetReplyFn callback,
-- gpointer user_data)
--{
-- GetReplyInfo *info;
--
-- g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0);
-- g_return_val_if_fail (terminators != NULL, 0);
-- g_return_val_if_fail (callback != NULL, 0);
--
-- info = g_slice_new0 (GetReplyInfo);
-- info->device = device;
-- info->terminators = g_strdup (terminators);
-- info->result = g_string_new (NULL);
-- info->callback = callback;
-- info->user_data = user_data;
--
-- return nm_serial_device_set_pending (device, timeout, get_reply_got_data, info, get_reply_done);
+- return reply_index;
-}
-
-typedef struct {
@@ -4510,8 +4556,8 @@ index 4fa4cb4..0000000
- NMSerialWaitForReplyFn callback;
- gpointer user_data;
- int reply_index;
-- guint timeout;
-- time_t start;
+- char *reply_line;
+- time_t end;
-} WaitForReplyInfo;
-
-static void
@@ -4522,47 +4568,20 @@ index 4fa4cb4..0000000
- nm_serial_device_pending_done (info->device);
-
- /* Call the callback */
-- info->callback (info->device, info->reply_index, info->user_data);
+- info->callback (info->device, info->reply_index, info->reply_line, info->user_data);
-
- /* Free info */
- if (info->result)
- g_string_free (info->result, TRUE);
-
+- g_free (info->reply_line);
+-
- g_strfreev (info->str_needles);
- g_strfreev (info->terminators);
- g_slice_free (WaitForReplyInfo, info);
-}
-
-static gboolean
--find_terminator (const char *line, char **terminators)
--{
-- int i;
--
-- for (i = 0; terminators[i]; i++) {
-- if (!strncasecmp (line, terminators[i], strlen (terminators[i])))
-- return TRUE;
-- }
-- return FALSE;
--}
--
--static gboolean
--find_response (const char *line, char **responses, gint *idx)
--{
-- int i;
--
-- /* Don't look for a result again if we got one previously */
-- for (i = 0; responses[i]; i++) {
-- if (strcasestr (line, responses[i])) {
-- *idx = i;
-- return TRUE;
-- }
-- }
-- return FALSE;
--}
--
--#define RESPONSE_LINE_MAX 128
--
--static gboolean
-wait_for_reply_got_data (GIOChannel *source,
- GIOCondition condition,
- gpointer data)
@@ -4571,7 +4590,6 @@ index 4fa4cb4..0000000
- gchar buf[SERIAL_BUF_SIZE + 1];
- gsize bytes_read;
- GIOStatus status;
-- gboolean got_response = FALSE;
- gboolean done = FALSE;
-
- if (condition & G_IO_HUP || condition & G_IO_ERR)
@@ -4591,7 +4609,7 @@ index 4fa4cb4..0000000
- buf[bytes_read] = 0;
- g_string_append (info->result, buf);
-
-- serial_debug ("Got:", info->result->str, info->result->len);
+- nm_serial_debug ("Got:", info->result->str, info->result->len);
- }
-
- /* Look for needles and terminators */
@@ -4599,8 +4617,7 @@ index 4fa4cb4..0000000
- char *p = info->result->str;
-
- /* Break the response up into lines and process each one */
-- while ( (p < info->result->str + strlen (info->result->str))
-- && !(done && got_response)) {
+- while ((p < info->result->str + strlen (info->result->str)) && !done) {
- char line[RESPONSE_LINE_MAX] = { '\0', };
- char *tmp;
- int i;
@@ -4620,20 +4637,19 @@ index 4fa4cb4..0000000
-
- tmp = g_strstrip (line);
- if (tmp && strlen (tmp)) {
-- done = find_terminator (tmp, info->terminators);
-- if (info->reply_index == -1)
-- got_response = find_response (tmp, info->str_needles, &(info->reply_index));
+- done = find_terminator (tmp, (const char **) info->terminators);
+- if (info->reply_index == -1) {
+- if (find_response (tmp, (const char **) info->str_needles, &(info->reply_index)))
+- info->reply_line = g_strdup (tmp);
+- }
- }
- }
--
-- if (done && got_response)
-- break;
- }
-
- /* Limit the size of the buffer */
- if (info->result->len > SERIAL_BUF_SIZE) {
-- g_warning ("%s (%s): response buffer filled before repsonse received",
-- __func__, nm_device_get_iface (NM_DEVICE (info->device)));
+- nm_warning ("(%s): response buffer filled before repsonse received",
+- nm_device_get_iface (NM_DEVICE (info->device)));
- done = TRUE;
- break;
- }
@@ -4643,10 +4659,10 @@ index 4fa4cb4..0000000
- * terminate (terminator not found, whatever) then this should make
- * sure that NM doesn't spin the CPU forever.
- */
-- if (time (NULL) - info->start > info->timeout + 1) {
+- if (time (NULL) > info->end) {
- done = TRUE;
- break;
-- } else
+- } else if (!done)
- g_usleep (50);
- } while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
-
@@ -4655,11 +4671,11 @@ index 4fa4cb4..0000000
-
-guint
-nm_serial_device_wait_for_reply (NMSerialDevice *device,
-- guint timeout,
-- char **responses,
-- char **terminators,
-- NMSerialWaitForReplyFn callback,
-- gpointer user_data)
+- guint timeout,
+- const char **responses,
+- const char **terminators,
+- NMSerialWaitForReplyFn callback,
+- gpointer user_data)
-{
- WaitForReplyInfo *info;
-
@@ -4669,14 +4685,13 @@ index 4fa4cb4..0000000
-
- info = g_slice_new0 (WaitForReplyInfo);
- info->device = device;
-- info->str_needles = g_strdupv (responses);
-- info->terminators = g_strdupv (terminators);
+- info->str_needles = g_strdupv ((char **) responses);
+- info->terminators = g_strdupv ((char **) terminators);
- info->result = g_string_new (NULL);
- info->callback = callback;
- info->user_data = user_data;
- info->reply_index = -1;
-- info->timeout = timeout;
-- info->start = time (NULL);
+- info->end = time (NULL) + timeout;
-
- return nm_serial_device_set_pending (device, timeout, wait_for_reply_got_data, info, wait_for_reply_done);
-}
@@ -4933,15 +4948,20 @@ index 4fa4cb4..0000000
-real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
-{
- NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
+- NMSerialDeviceClass *serial_class = NM_SERIAL_DEVICE_GET_CLASS (device);
- NMActRequest *req;
- GError *err = NULL;
- NMActStageReturn ret;
+- const char *ppp_name = NULL;
-
- req = nm_device_get_act_request (device);
- g_assert (req);
-
+- if (serial_class->get_ppp_name)
+- ppp_name = serial_class->get_ppp_name (NM_SERIAL_DEVICE (device), req);
+-
- priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (device));
-- if (nm_ppp_manager_start (priv->ppp_manager, req, &err)) {
+- if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, &err)) {
- g_signal_connect (priv->ppp_manager, "state-changed",
- G_CALLBACK (ppp_state_changed),
- device);
@@ -4981,12 +5001,11 @@ index 4fa4cb4..0000000
-}
-
-static void
--real_deactivate_quickly (NMDevice *device)
+-cleanup_device (NMSerialDevice *device)
-{
-- NMSerialDevice *self = NM_SERIAL_DEVICE (device);
- NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
-
-- nm_device_set_ip_iface (device, NULL);
+- nm_device_set_ip_iface (NM_DEVICE (device), NULL);
-
- if (priv->pending_ip4_config) {
- g_object_unref (priv->pending_ip4_config);
@@ -4994,12 +5013,14 @@ index 4fa4cb4..0000000
- }
-
- priv->in_bytes = priv->out_bytes = 0;
+-}
-
-- if (priv->ppp_manager) {
-- g_object_unref (priv->ppp_manager);
-- priv->ppp_manager = NULL;
-- }
+-static void
+-real_deactivate_quickly (NMDevice *device)
+-{
+- NMSerialDevice *self = NM_SERIAL_DEVICE (device);
-
+- cleanup_device (self);
- nm_serial_device_close (self);
-}
-
@@ -5014,6 +5035,8 @@ index 4fa4cb4..0000000
-static void
-nm_serial_device_init (NMSerialDevice *self)
-{
+- if (getenv ("NM_SERIAL_DEBUG"))
+- serial_debug = TRUE;
-}
-
-static void
@@ -5021,6 +5044,7 @@ index 4fa4cb4..0000000
-{
- NMSerialDevice *self = NM_SERIAL_DEVICE (object);
-
+- cleanup_device (self);
- nm_serial_device_close (self);
-
- G_OBJECT_CLASS (nm_serial_device_parent_class)->finalize (object);
@@ -5058,10 +5082,10 @@ index 4fa4cb4..0000000
-}
diff --git a/src/nm-serial-device.h b/src/nm-serial-device.h
deleted file mode 100644
-index 41ee520..0000000
+index 024b2e8..0000000
--- a/src/nm-serial-device.h
+++ /dev/null
-@@ -1,89 +0,0 @@
+@@ -1,91 +0,0 @@
-/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
-
-#ifndef NM_SERIAL_DEVICE_H
@@ -5087,6 +5111,8 @@ index 41ee520..0000000
-typedef struct {
- NMDeviceClass parent;
-
+- const char * (*get_ppp_name) (NMSerialDevice *device, NMActRequest *req);
+-
- /* Signals */
- void (*ppp_stats) (NMSerialDevice *device, guint32 in_bytes, guint32 out_bytes);
-} NMSerialDeviceClass;
@@ -5098,8 +5124,9 @@ index 41ee520..0000000
- gpointer user_data);
-
-typedef void (*NMSerialWaitForReplyFn) (NMSerialDevice *device,
-- int reply_index,
-- gpointer user_data);
+- int reply_index,
+- const char *reply,
+- gpointer user_data);
-
-typedef void (*NMSerialWaitQuietFn) (NMSerialDevice *device,
- gboolean timed_out,
@@ -5120,16 +5147,15 @@ index 41ee520..0000000
-gboolean nm_serial_device_send_command_string (NMSerialDevice *device,
- const char *str);
-
--guint nm_serial_device_get_reply (NMSerialDevice *device,
-- guint timeout,
-- const char *terminators,
-- NMSerialGetReplyFn callback,
-- gpointer user_data);
+-int nm_serial_device_wait_reply_blocking (NMSerialDevice *device,
+- guint32 timeout_secs,
+- const char **needles,
+- const char **terminators);
-
-guint nm_serial_device_wait_for_reply (NMSerialDevice *device,
- guint timeout,
-- char **responses,
-- char **terminators,
+- const char **responses,
+- const char **terminators,
- NMSerialWaitForReplyFn callback,
- gpointer user_data);
-
diff --git a/nm-applet-r884-use-modem-manager.patch b/nm-applet-r938-use-modem-manager.patch
index 7c141345..dd1ce92e 100644
--- a/nm-applet-r884-use-modem-manager.patch
+++ b/nm-applet-r938-use-modem-manager.patch
@@ -31,7 +31,7 @@ index de8ccb4..2be2217 100644
nm_applet_LDADD = \
diff --git a/src/applet-device-gsm.c b/src/applet-device-gsm.c
-index 1641661..f0a31e6 100644
+index 90c5e5e..e28d13c 100644
--- a/src/applet-device-gsm.c
+++ b/src/applet-device-gsm.c
@@ -24,6 +24,9 @@
@@ -104,7 +104,7 @@ index 1641661..f0a31e6 100644
gsm_menu_item_deactivate (GtkMenuItem *item, gpointer user_data)
{
GSMMenuItemInfo *info = (GSMMenuItemInfo *) user_data;
-@@ -270,23 +319,66 @@ gsm_add_menu_item (NMDevice *device,
+@@ -264,37 +313,68 @@ gsm_add_menu_item (NMDevice *device,
add_connection_items (device, connections, active, menu, applet);
else
add_default_connection_item (device, menu, applet);
@@ -124,23 +124,36 @@ index 1641661..f0a31e6 100644
+
+static void
gsm_device_state_changed (NMDevice *device,
- NMDeviceState state,
+ NMDeviceState new_state,
+ NMDeviceState old_state,
+ NMDeviceStateReason reason,
NMApplet *applet)
{
-- if (state == NM_DEVICE_STATE_ACTIVATED) {
-- applet_do_notify (applet, NOTIFY_URGENCY_LOW,
-- _("Connection Established"),
-- _("You are now connected to the GSM network."),
-- "nm-device-wwan", NULL, NULL, NULL, NULL);
+- if (new_state == NM_DEVICE_STATE_ACTIVATED) {
+- NMConnection *connection;
+- NMSettingConnection *s_con = NULL;
+- char *str = NULL;
+-
+- connection = applet_find_active_connection_for_device (device, applet, NULL);
+- if (connection) {
+- s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+- if (s_con && s_con->id)
+- str = g_strdup_printf (_("You are now connected to '%s'."), s_con->id);
+- }
+ NMAGsmModem *modem;
+ char *oper_code;
+ char *oper_name;
+ char *msg;
+ guint32 reg_status;
+
-+ if (state != NM_DEVICE_STATE_ACTIVATED)
++ if (new_state != NM_DEVICE_STATE_ACTIVATED)
+ return;
-+
+
+- applet_do_notify (applet, NOTIFY_URGENCY_LOW,
+- _("Connection Established"),
+- str ? str : _("You are now connected to the GSM network."),
+- "nm-device-wwan", NULL, NULL, NULL, NULL);
+- g_free (str);
+ modem = (NMAGsmModem *) g_object_get_data (G_OBJECT (device), "gsm-modem");
+ if (!modem) {
+ DBusGConnection *bus;
@@ -176,19 +189,22 @@ index 1641661..f0a31e6 100644
}
static GdkPixbuf *
-@@ -295,6 +387,7 @@ gsm_get_icon (NMDevice *device,
+@@ -304,6 +384,7 @@ gsm_get_icon (NMDevice *device,
char **tip,
NMApplet *applet)
{
+ NMAGsmModem *modem;
GdkPixbuf *pixbuf = NULL;
const char *iface;
-
-@@ -311,8 +404,40 @@ gsm_get_icon (NMDevice *device,
+ NMSettingConnection *s_con = NULL;
+@@ -323,11 +404,40 @@ gsm_get_icon (NMDevice *device,
*tip = g_strdup_printf (_("Waiting for user authentication on device '%s'..."), iface);
break;
case NM_DEVICE_STATE_ACTIVATED:
-- *tip = g_strdup (_("GSM connection"));
+- if (s_con && s_con->id)
+- *tip = g_strdup_printf (_("Mobile broadband connection '%s'"), s_con->id);
+- else
+- *tip = g_strdup (_("Mobile broadband connection"));
- pixbuf = applet->wwan_icon;
+ modem = (NMAGsmModem *) g_object_get_data (G_OBJECT (device), "gsm-modem");
+ if (modem) {
@@ -227,6 +243,36 @@ index 1641661..f0a31e6 100644
break;
default:
break;
+diff --git a/src/connection-editor/page-mobile.c b/src/connection-editor/page-mobile.c
+index ee627f5..6fd29af 100644
+--- a/src/connection-editor/page-mobile.c
++++ b/src/connection-editor/page-mobile.c
+@@ -107,7 +107,6 @@ populate_gsm_ui (CEPageMobile *self, NMConnection *connection)
+ int type_idx;
+ GHashTable *secrets;
+ GValue *value;
+- GtkWidget *widget;
+
+ if (setting->number)
+ gtk_entry_set_text (priv->number, setting->number);
+@@ -141,17 +140,6 @@ populate_gsm_ui (CEPageMobile *self, NMConnection *connection)
+ }
+ gtk_combo_box_set_active (priv->network_type, type_idx);
+
+- /* Hide network type widgets; not supported yet */
+- gtk_widget_hide (GTK_WIDGET (priv->network_type));
+- widget = glade_xml_get_widget (CE_PAGE (self)->xml, "type_label");
+- gtk_widget_hide (widget);
+-
+- /* Hide Band widgets; not supported yet */
+- widget = glade_xml_get_widget (CE_PAGE (self)->xml, "mobile_band");
+- gtk_widget_hide (widget);
+- widget = glade_xml_get_widget (CE_PAGE (self)->xml, "band_label");
+- gtk_widget_hide (widget);
+-
+ secrets = get_secrets (connection, nm_setting_get_name (priv->setting));
+
+ if (setting->password)
diff --git a/src/mm-types.h b/src/mm-types.h
new file mode 100644
index 0000000..a1f9979
@@ -284,10 +330,10 @@ index 0000000..206ee52
+EXTRA_DIST = $(glade_DATA)
diff --git a/src/modems/main.c b/src/modems/main.c
new file mode 100644
-index 0000000..27e700c
+index 0000000..fe531f0
--- /dev/null
+++ b/src/modems/main.c
-@@ -0,0 +1,592 @@
+@@ -0,0 +1,547 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#include <string.h>
@@ -323,12 +369,13 @@ index 0000000..27e700c
+ /* UI */
+ GladeXML *glade_xml;
+ GtkDialog *main_dialog;
-+ GtkTable *info_table;
+ GtkTreeView *network_list;
+ GtkListStore *network_store;
+ GtkWidget *scan_button;
+ GtkWidget *create_net_button;
-+ GtkLabel *signal_quality_label;
++
++ GtkWidget *scan_dialog;
++ GtkProgressBar *scan_progress_bar;
+
+ GtkDialog *create_network_dialog;
+ GtkEntry *create_network_name;
@@ -341,63 +388,17 @@ index 0000000..27e700c
+ GMainLoop *main_loop;
+} AppData;
+
-+
-+typedef struct {
-+ GtkTable *table;
-+ char *label;
-+ guint row;
-+} InfoData;
-+
-+static InfoData *
-+info_data_new (GtkTable *table, const char *label, guint row)
-+{
-+ InfoData *info;
-+
-+ info = g_slice_new (InfoData);
-+ info->table = table;
-+ info->label = g_strdup (label);
-+ info->row = row;
-+
-+ return info;
-+}
-+
-+static void
-+info_data_free (gpointer data)
-+{
-+ InfoData *info = (InfoData *) data;
-+
-+ g_free (info->label);
-+ g_slice_free (InfoData, data);
-+}
-+
-+static void
-+add_info_row (GtkTable *table, guint row, const char *label, const char *value)
-+{
-+ GtkWidget *w;
-+
-+ w = gtk_label_new (label);
-+ gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0);
-+ gtk_widget_show (w);
-+ gtk_table_attach_defaults (table, w, 0, 1, row, row + 1);
-+
-+ w = gtk_label_new (value);
-+ gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0);
-+ gtk_widget_show (w);
-+ gtk_table_attach_defaults (table, w, 1, 2, row, row + 1);
-+}
-+
+static void
+get_str_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
-+ InfoData *info = (InfoData *) user_data;
+ char *result = NULL;
+ GError *error = NULL;
+
+ if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_STRING, &result, G_TYPE_INVALID)) {
-+ g_warning ("Couldn't get %s: %s", info->label, error->message);
++ g_warning ("%s", error->message);
+ g_error_free (error);
+ } else {
-+ add_info_row (info->table, info->row, info->label, result);
++ gtk_label_set_text (GTK_LABEL (user_data), result);
+ g_free (result);
+ }
+}
@@ -405,7 +406,7 @@ index 0000000..27e700c
+static void
+get_card_info_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
-+ GtkTable *table = GTK_TABLE (user_data);
++ GladeXML *glade_xml = GLADE_XML (user_data);
+ char *manufacturer = NULL;
+ char *model = NULL;
+ char *version = NULL;
@@ -419,13 +420,12 @@ index 0000000..27e700c
+ g_warning ("Couldn't get modem information: %s", error->message);
+ g_error_free (error);
+ } else {
-+ add_info_row (table, 0, "Vendor", manufacturer);
-+ g_free (manufacturer);
++ gtk_label_set_text (GTK_LABEL (glade_xml_get_widget (glade_xml, "vendor_label")), manufacturer);
++ gtk_label_set_text (GTK_LABEL (glade_xml_get_widget (glade_xml, "model_label")), model);
++ gtk_label_set_text (GTK_LABEL (glade_xml_get_widget (glade_xml, "version_label")), version);
+
-+ add_info_row (table, 1, "Model", model);
++ g_free (manufacturer);
+ g_free (model);
-+
-+ add_info_row (table, 2, "Version", version);
+ g_free (version);
+ }
+}
@@ -433,15 +433,14 @@ index 0000000..27e700c
+static void
+get_property_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
-+ InfoData *info = (InfoData *) user_data;
+ GValue value = { 0, };
+ GError *error = NULL;
+
+ if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
-+ g_warning ("Couldn't get %s: %s", info->label, error->message);
++ g_warning ("%s", error->message);
+ g_error_free (error);
+ } else {
-+ add_info_row (info->table, info->row, info->label, g_value_get_string (&value));
++ gtk_label_set_text (GTK_LABEL (user_data), g_value_get_string (&value));
+ g_value_unset (&value);
+ }
+}
@@ -453,27 +452,27 @@ index 0000000..27e700c
+
+ dbus_g_proxy_set_interface (app_data->proxy, MM_DBUS_INTERFACE_MODEM_GSM_CARD);
+ dbus_g_proxy_begin_call (app_data->proxy, "GetImsi", get_str_done,
-+ info_data_new (app_data->info_table, "IMSI", 5), info_data_free,
++ glade_xml_get_widget (app_data->glade_xml, "imsi_label"), NULL,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_begin_call (app_data->proxy, "GetImei", get_str_done,
-+ info_data_new (app_data->info_table, "IMEI", 6), info_data_free,
++ glade_xml_get_widget (app_data->glade_xml, "imei_label"), NULL,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_begin_call (app_data->proxy, "GetInfo", get_card_info_done,
-+ app_data->info_table, NULL,
++ app_data->glade_xml, NULL,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_set_interface (app_data->proxy, "org.freedesktop.DBus.Properties");
+
+ dbus_g_proxy_begin_call (app_data->proxy, "Get", get_property_done,
-+ info_data_new (app_data->info_table, "Driver", 3), info_data_free,
++ glade_xml_get_widget (app_data->glade_xml, "driver_label"), NULL,
+ G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM,
+ G_TYPE_STRING, "Driver",
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_begin_call (app_data->proxy, "Get", get_property_done,
-+ info_data_new (app_data->info_table, "Data device", 4), info_data_free,
++ glade_xml_get_widget (app_data->glade_xml, "device_label"), NULL,
+ G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM,
+ G_TYPE_STRING, "DataDevice",
+ G_TYPE_INVALID);
@@ -484,18 +483,17 @@ index 0000000..27e700c
+static void
+got_signal_quality (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
-+ AppData *app_data = (AppData *) user_data;
+ guint32 quality = 0;
+ GError *error = NULL;
+
+ if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_UINT, &quality, G_TYPE_INVALID)) {
-+ g_warning ("Couldn't get signal quality: %s", error->message);
++ g_warning ("%s", error->message);
+ g_error_free (error);
+ } else {
+ char *tmp;
+
+ tmp = g_strdup_printf ("%d%%", quality);
-+ gtk_label_set_text (app_data->signal_quality_label, tmp);
++ gtk_label_set_text (GTK_LABEL (user_data), tmp);
+ g_free (tmp);
+ }
+}
@@ -505,11 +503,10 @@ index 0000000..27e700c
+ guint32 signal_quality,
+ gpointer user_data)
+{
-+ AppData *app_data = (AppData *) user_data;
+ char *tmp;
+
+ tmp = g_strdup_printf ("%d%%", signal_quality);
-+ gtk_label_set_text (app_data->signal_quality_label, tmp);
++ gtk_label_set_text (GTK_LABEL (user_data), tmp);
+ g_free (tmp);
+}
+
@@ -517,28 +514,17 @@ index 0000000..27e700c
+monitor_signal_quality (gpointer data)
+{
+ AppData *app_data = (AppData *) data;
-+ GtkWidget *w;
-+
-+ w = gtk_label_new ("Signal Quality");
-+ gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0);
-+ gtk_widget_show (w);
-+ gtk_table_attach_defaults (app_data->info_table, w, 0, 1, 7, 8);
++ GtkWidget *label;
+
-+ w = gtk_label_new ("");
-+ gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0);
-+ gtk_widget_show (w);
-+ gtk_table_attach_defaults (app_data->info_table, w, 1, 2, 7, 8);
-+ app_data->signal_quality_label = GTK_LABEL (w);
++ label = glade_xml_get_widget (app_data->glade_xml, "signal_quality_label");
+
+ dbus_g_proxy_add_signal (app_data->gsm_net_proxy, "SignalQuality", G_TYPE_UINT, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (app_data->gsm_net_proxy, "SignalQuality",
+ G_CALLBACK (signal_quality_changed),
-+ app_data,
-+ NULL);
++ label, NULL);
+
-+ dbus_g_proxy_begin_call (app_data->gsm_net_proxy, "GetSignalQuality", got_signal_quality,
-+ app_data, NULL,
-+ G_TYPE_INVALID);
++ dbus_g_proxy_begin_call (app_data->gsm_net_proxy, "GetSignalQuality",
++ got_signal_quality, label, NULL, G_TYPE_INVALID);
+
+ return FALSE;
+}
@@ -588,21 +574,32 @@ index 0000000..27e700c
+ g_ptr_array_free (array, TRUE);
+ }
+
++ gtk_widget_hide (app_data->scan_dialog);
+ gtk_widget_set_sensitive (app_data->scan_button, TRUE);
+}
+
++static gboolean
++scan_pulse (gpointer data)
++{
++ GtkProgressBar *bar = GTK_PROGRESS_BAR (data);
++
++ gtk_progress_bar_pulse (bar);
++ return gdk_window_is_visible (gtk_widget_get_parent_window (GTK_WIDGET (bar)));
++}
++
+static void
+scan (GtkButton *button, gpointer user_data)
+{
+ AppData *app_data = (AppData *) user_data;
+
-+ dbus_g_proxy_begin_call (app_data->gsm_net_proxy, "Scan", got_scan_results,
-+ app_data, NULL,
-+ G_TYPE_INVALID);
++ dbus_g_proxy_begin_call_with_timeout (app_data->gsm_net_proxy, "Scan", got_scan_results,
++ app_data, NULL, 120000, G_TYPE_INVALID);
+
+ gtk_widget_set_sensitive (app_data->scan_button, FALSE);
+ gtk_list_store_clear (app_data->network_store);
-+ /* FIXME: Add "Scanning..." dialog */
++
++ g_timeout_add (200, scan_pulse, app_data->scan_progress_bar);
++ gtk_widget_show (app_data->scan_dialog);
+}
+
+static void
@@ -836,15 +833,19 @@ index 0000000..27e700c
+ return NULL;
+ }
+
-+ app_data->main_dialog = GTK_DIALOG (glade_xml_get_widget (app_data->glade_xml, "dialog"));
++ app_data->main_dialog = GTK_DIALOG (glade_xml_get_widget (app_data->glade_xml, "main_dialog"));
+ g_signal_connect (app_data->main_dialog, "response", G_CALLBACK (close_cb), app_data);
+
-+ app_data->info_table = GTK_TABLE (glade_xml_get_widget (app_data->glade_xml, "info_table"));
+ app_data->network_list = GTK_TREE_VIEW (glade_xml_get_widget (app_data->glade_xml, "network_list"));
+ app_data->network_store = prepare_network_list (app_data->network_list);
+ app_data->scan_button = glade_xml_get_widget (app_data->glade_xml, "scan_button");
+ g_signal_connect (app_data->scan_button, "clicked", G_CALLBACK (scan), app_data);
+
++ app_data->scan_dialog = glade_xml_get_widget (app_data->glade_xml, "scan_dialog");
++ gtk_window_set_transient_for (GTK_WINDOW (app_data->scan_dialog), GTK_WINDOW (app_data->main_dialog));
++
++ app_data->scan_progress_bar = GTK_PROGRESS_BAR (glade_xml_get_widget (app_data->glade_xml, "scan_progress_bar"));
++
+ app_data->create_net_button = glade_xml_get_widget (app_data->glade_xml, "create_connection_button");
+ gtk_widget_set_sensitive (app_data->create_net_button, FALSE);
+ g_signal_connect (app_data->create_net_button, "clicked", G_CALLBACK (create_network_clicked), app_data);
@@ -882,16 +883,16 @@ index 0000000..27e700c
+}
diff --git a/src/modems/nm-modem-properties.glade b/src/modems/nm-modem-properties.glade
new file mode 100644
-index 0000000..61038b8
+index 0000000..12ccf06
--- /dev/null
+++ b/src/modems/nm-modem-properties.glade
-@@ -0,0 +1,381 @@
+@@ -0,0 +1,1083 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
-+<widget class="GtkDialog" id="dialog">
++<widget class="GtkDialog" id="main_dialog">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">GSM modem properties</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
@@ -947,57 +948,572 @@ index 0000000..61038b8
+ <property name="spacing">6</property>
+
+ <child>
-+ <widget class="GtkFrame" id="frame1">
++ <widget class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
-+ <property name="label_xalign">0</property>
-+ <property name="label_yalign">0.5</property>
-+ <property name="shadow_type">GTK_SHADOW_NONE</property>
++ <property name="homogeneous">False</property>
++ <property name="spacing">6</property>
+
+ <child>
-+ <widget class="GtkAlignment" id="alignment1">
++ <widget class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
-+ <property name="xalign">0.5</property>
-+ <property name="yalign">0.5</property>
-+ <property name="xscale">1</property>
-+ <property name="yscale">1</property>
-+ <property name="top_padding">0</property>
-+ <property name="bottom_padding">0</property>
-+ <property name="left_padding">12</property>
-+ <property name="right_padding">0</property>
++ <property name="label_xalign">0</property>
++ <property name="label_yalign">0.5</property>
++ <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
-+ <widget class="GtkTable" id="info_table">
++ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
-+ <property name="n_rows">8</property>
-+ <property name="n_columns">2</property>
-+ <property name="homogeneous">False</property>
-+ <property name="row_spacing">0</property>
-+ <property name="column_spacing">6</property>
++ <property name="xalign">0.5</property>
++ <property name="yalign">0.5</property>
++ <property name="xscale">1</property>
++ <property name="yscale">1</property>
++ <property name="top_padding">0</property>
++ <property name="bottom_padding">0</property>
++ <property name="left_padding">12</property>
++ <property name="right_padding">0</property>
++
++ <child>
++ <widget class="GtkTable" id="info_table">
++ <property name="visible">True</property>
++ <property name="n_rows">8</property>
++ <property name="n_columns">2</property>
++ <property name="homogeneous">False</property>
++ <property name="row_spacing">0</property>
++ <property name="column_spacing">6</property>
++
++ <child>
++ <widget class="GtkLabel" id="label6">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Vendor</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">0</property>
++ <property name="right_attach">1</property>
++ <property name="top_attach">0</property>
++ <property name="bottom_attach">1</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label7">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Model</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">0</property>
++ <property name="right_attach">1</property>
++ <property name="top_attach">1</property>
++ <property name="bottom_attach">2</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label8">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Version</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">0</property>
++ <property name="right_attach">1</property>
++ <property name="top_attach">2</property>
++ <property name="bottom_attach">3</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label9">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Driver</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">0</property>
++ <property name="right_attach">1</property>
++ <property name="top_attach">3</property>
++ <property name="bottom_attach">4</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label10">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Data device</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">0</property>
++ <property name="right_attach">1</property>
++ <property name="top_attach">4</property>
++ <property name="bottom_attach">5</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label11">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">IMSI</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">0</property>
++ <property name="right_attach">1</property>
++ <property name="top_attach">5</property>
++ <property name="bottom_attach">6</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label12">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">IMEI</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">0</property>
++ <property name="right_attach">1</property>
++ <property name="top_attach">6</property>
++ <property name="bottom_attach">7</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label13">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Signal quality</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">0</property>
++ <property name="right_attach">1</property>
++ <property name="top_attach">7</property>
++ <property name="bottom_attach">8</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="vendor_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"></property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">0</property>
++ <property name="bottom_attach">1</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="model_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"></property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">1</property>
++ <property name="bottom_attach">2</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="version_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"></property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">2</property>
++ <property name="bottom_attach">3</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="driver_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"></property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">3</property>
++ <property name="bottom_attach">4</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="device_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"></property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">4</property>
++ <property name="bottom_attach">5</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="imsi_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"></property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">5</property>
++ <property name="bottom_attach">6</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="imei_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"></property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">6</property>
++ <property name="bottom_attach">7</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="signal_quality_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes"></property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0</property>
++ <property name="yalign">0</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="left_attach">1</property>
++ <property name="right_attach">2</property>
++ <property name="top_attach">7</property>
++ <property name="bottom_attach">8</property>
++ <property name="x_options">fill</property>
++ <property name="y_options"></property>
++ </packing>
++ </child>
++ </widget>
++ </child>
++ </widget>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label1">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">&lt;b&gt;Information&lt;/b&gt;</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">True</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0.5</property>
++ <property name="yalign">0.5</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
+ </widget>
++ <packing>
++ <property name="type">label_item</property>
++ </packing>
+ </child>
+ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">True</property>
++ <property name="fill">True</property>
++ </packing>
+ </child>
+
+ <child>
-+ <widget class="GtkLabel" id="label1">
-+ <property name="visible">True</property>
-+ <property name="label" translatable="yes">&lt;b&gt;Information&lt;/b&gt;</property>
-+ <property name="use_underline">False</property>
-+ <property name="use_markup">True</property>
-+ <property name="justify">GTK_JUSTIFY_LEFT</property>
-+ <property name="wrap">False</property>
-+ <property name="selectable">False</property>
-+ <property name="xalign">0.5</property>
-+ <property name="yalign">0.5</property>
-+ <property name="xpad">0</property>
-+ <property name="ypad">0</property>
-+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-+ <property name="width_chars">-1</property>
-+ <property name="single_line_mode">False</property>
-+ <property name="angle">0</property>
++ <widget class="GtkFrame" id="frame3">
++ <property name="label_xalign">0</property>
++ <property name="label_yalign">0.5</property>
++ <property name="shadow_type">GTK_SHADOW_NONE</property>
++
++ <child>
++ <widget class="GtkAlignment" id="alignment3">
++ <property name="visible">True</property>
++ <property name="xalign">0.5</property>
++ <property name="yalign">0.5</property>
++ <property name="xscale">1</property>
++ <property name="yscale">1</property>
++ <property name="top_padding">0</property>
++ <property name="bottom_padding">0</property>
++ <property name="left_padding">12</property>
++ <property name="right_padding">0</property>
++
++ <child>
++ <placeholder/>
++ </child>
++ </widget>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label4">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">&lt;b&gt;PIN operations&lt;/b&gt;</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">True</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0.5</property>
++ <property name="yalign">0.5</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="type">label_item</property>
++ </packing>
++ </child>
+ </widget>
+ <packing>
-+ <property name="type">label_item</property>
++ <property name="padding">0</property>
++ <property name="expand">True</property>
++ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
@@ -1266,6 +1782,193 @@ index 0000000..61038b8
+ </child>
+</widget>
+
++<widget class="GtkWindow" id="scan_dialog">
++ <property name="title" translatable="yes"></property>
++ <property name="type">GTK_WINDOW_TOPLEVEL</property>
++ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
++ <property name="modal">True</property>
++ <property name="resizable">False</property>
++ <property name="destroy_with_parent">False</property>
++ <property name="decorated">False</property>
++ <property name="skip_taskbar_hint">True</property>
++ <property name="skip_pager_hint">True</property>
++ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
++ <property name="gravity">GDK_GRAVITY_CENTER</property>
++ <property name="focus_on_map">True</property>
++ <property name="urgency_hint">False</property>
++
++ <child>
++ <widget class="GtkVBox" id="vbox3">
++ <property name="border_width">6</property>
++ <property name="visible">True</property>
++ <property name="homogeneous">False</property>
++ <property name="spacing">6</property>
++
++ <child>
++ <widget class="GtkLabel" id="label5">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Scanning... Please wait.</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0.5</property>
++ <property name="yalign">0.5</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkProgressBar" id="scan_progress_bar">
++ <property name="visible">True</property>
++ <property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property>
++ <property name="fraction">0</property>
++ <property name="pulse_step">0.10000000149</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ </packing>
++ </child>
++ </widget>
++ </child>
++</widget>
++
++<widget class="GtkDialog" id="pin_dialog">
++ <property name="visible">True</property>
++ <property name="title" translatable="yes">PIN code required</property>
++ <property name="type">GTK_WINDOW_TOPLEVEL</property>
++ <property name="window_position">GTK_WIN_POS_NONE</property>
++ <property name="modal">False</property>
++ <property name="resizable">False</property>
++ <property name="destroy_with_parent">False</property>
++ <property name="decorated">True</property>
++ <property name="skip_taskbar_hint">False</property>
++ <property name="skip_pager_hint">False</property>
++ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
++ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
++ <property name="focus_on_map">True</property>
++ <property name="urgency_hint">False</property>
++ <property name="has_separator">True</property>
++
++ <child internal-child="vbox">
++ <widget class="GtkVBox" id="dialog-vbox3">
++ <property name="homogeneous">False</property>
++ <property name="spacing">0</property>
++
++ <child internal-child="action_area">
++ <widget class="GtkHButtonBox" id="dialog-action_area3">
++ <property name="visible">True</property>
++ <property name="layout_style">GTK_BUTTONBOX_END</property>
++
++ <child>
++ <widget class="GtkButton" id="cancelbutton2">
++ <property name="visible">True</property>
++ <property name="can_default">True</property>
++ <property name="can_focus">True</property>
++ <property name="label">gtk-cancel</property>
++ <property name="use_stock">True</property>
++ <property name="relief">GTK_RELIEF_NORMAL</property>
++ <property name="focus_on_click">True</property>
++ <property name="response_id">-6</property>
++ </widget>
++ </child>
++
++ <child>
++ <widget class="GtkButton" id="okbutton2">
++ <property name="visible">True</property>
++ <property name="can_default">True</property>
++ <property name="can_focus">True</property>
++ <property name="label">gtk-ok</property>
++ <property name="use_stock">True</property>
++ <property name="relief">GTK_RELIEF_NORMAL</property>
++ <property name="focus_on_click">True</property>
++ <property name="response_id">-5</property>
++ </widget>
++ </child>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">False</property>
++ <property name="fill">True</property>
++ <property name="pack_type">GTK_PACK_END</property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkVBox" id="vbox4">
++ <property name="border_width">6</property>
++ <property name="visible">True</property>
++ <property name="homogeneous">False</property>
++ <property name="spacing">6</property>
++
++ <child>
++ <widget class="GtkLabel" id="pin_dialog_label">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Please enter SIM PIN code</property>
++ <property name="use_underline">False</property>
++ <property name="use_markup">False</property>
++ <property name="justify">GTK_JUSTIFY_LEFT</property>
++ <property name="wrap">False</property>
++ <property name="selectable">False</property>
++ <property name="xalign">0.5</property>
++ <property name="yalign">0.5</property>
++ <property name="xpad">0</property>
++ <property name="ypad">0</property>
++ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
++ <property name="width_chars">-1</property>
++ <property name="single_line_mode">False</property>
++ <property name="angle">0</property>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkEntry" id="pin_dialog_entry">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="editable">True</property>
++ <property name="visibility">True</property>
++ <property name="max_length">0</property>
++ <property name="text" translatable="yes"></property>
++ <property name="has_frame">True</property>
++ <property name="invisible_char">●</property>
++ <property name="activates_default">False</property>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ </packing>
++ </child>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">True</property>
++ <property name="fill">True</property>
++ </packing>
++ </child>
++ </widget>
++ </child>
++</widget>
++
+</glade-interface>
diff --git a/src/nma-gsm-modem.c b/src/nma-gsm-modem.c
new file mode 100644