aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTambet Ingo <tambet@gmail.com>2008-09-12 17:05:43 +0300
committerTambet Ingo <tambet@gmail.com>2008-09-12 17:05:43 +0300
commitb4176325e5c51bc920366e4475c3c75bf1bc3757 (patch)
tree70600217acd714659755fe0b13a79a8d79d07c66
parent567278d19dc95880d1091794fd9fa0c3f77fb99d (diff)
Update the patches for NetworkManager and nm-applet.
Implement modem properties dialog for the applet which shows all sorts of information about the modem, allows to scan for visible networks and create NMConnections based on scan results.
-rw-r--r--NetworkManager-r4060-use-modem-manager.patch (renamed from NetworkManager-r4027-use-modem-manager.patch)112
-rw-r--r--nm-applet-r874-use-modem-manager.patch427
-rw-r--r--nm-applet-r884-use-modem-manager.patch1524
3 files changed, 1620 insertions, 443 deletions
diff --git a/NetworkManager-r4027-use-modem-manager.patch b/NetworkManager-r4060-use-modem-manager.patch
index 929d8419..bac492db 100644
--- a/NetworkManager-r4027-use-modem-manager.patch
+++ b/NetworkManager-r4060-use-modem-manager.patch
@@ -1,8 +1,8 @@
diff --git a/configure.in b/configure.in
-index 9f7db7c..bee43d8 100644
+index bd86fc2..fdc4369 100644
--- a/configure.in
+++ b/configure.in
-@@ -444,6 +444,7 @@ src/dhcp-manager/Makefile
+@@ -477,6 +477,7 @@ src/dhcp-manager/Makefile
src/supplicant-manager/Makefile
src/ppp-manager/Makefile
src/dnsmasq-manager/Makefile
@@ -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..0b75e6c
+index 0000000..271e23f
--- /dev/null
+++ b/src/modem-manager/nm-gsm-modem.c
-@@ -0,0 +1,316 @@
+@@ -0,0 +1,329 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include <string.h>
@@ -981,20 +981,33 @@ index 0000000..0b75e6c
+ dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID);
+
+ if (error) {
-+ if (dbus_g_error_has_name (error, MM_MODEM_ERROR_PIN_NEEDED)) {
++ g_debug ("%s", dbus_g_error_get_name (error));
++
++ if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PIN)) {
+ secret = setting->pin;
+ secret_name = NM_SETTING_GSM_PIN;
+ priv->modem_state = MODEM_STATE_SET_PIN;
-+ } else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_PUK_NEEDED)) {
++ } else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_PUK)) {
+ secret = setting->puk;
+ secret_name = NM_SETTING_GSM_PUK;
+ priv->modem_state = MODEM_STATE_SET_PIN;
-+ } else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_INVALID_SECRET)) {
++ } else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_SIM_WRONG)) {
+ g_free (setting->pin);
+ setting->pin = NULL;
+ secret_name = NM_SETTING_GSM_PIN;
+ retry_secret = TRUE;
+ priv->modem_state = MODEM_STATE_SET_PIN;
++ }
++
++ /* FIXME: Hacks to ignore failures of setting band and network mode for now
++ since only Huawei module supports it. Remove when ModemManager rules.
++ */
++ else if (dbus_g_error_has_name (error, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED) &&
++ (priv->modem_state == MODEM_STATE_SET_BAND ||
++ priv->modem_state == MODEM_STATE_SET_NETWORK_MODE)) {
++
++ nm_warning ("Modem does not support setting %s, ignoring",
++ priv->modem_state == MODEM_STATE_SET_BAND ? "band" : "network mode");
+ } else {
+ priv->modem_state = MODEM_STATE_FAILED;
+ nm_warning ("GSM modem connection failed: %s", error->message);
@@ -1019,7 +1032,7 @@ index 0000000..0b75e6c
+ if (secret) {
+ priv->modem_state = MODEM_STATE_ENABLE;
+ dbus_g_proxy_begin_call (get_proxy (modem, MM_DBUS_INTERFACE_MODEM_GSM_CARD),
-+ "SetPin", state_machine,
++ "SendPin", state_machine,
+ modem, NULL,
+ G_TYPE_STRING, secret,
+ G_TYPE_INVALID);
@@ -1254,10 +1267,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..0a198f7
+index 0000000..c5ea8c6
--- /dev/null
+++ b/src/modem-manager/nm-modem-device.c
-@@ -0,0 +1,464 @@
+@@ -0,0 +1,467 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include <string.h>
@@ -1566,6 +1579,9 @@ index 0000000..0a198f7
+ /* Make sure we don't leave the serial device open */
+ switch (new_state) {
+ case NM_DEVICE_STATE_NEED_AUTH:
++ if (priv->ppp_manager)
++ break;
++ /* else fall through */
+ case NM_DEVICE_STATE_UNMANAGED:
+ case NM_DEVICE_STATE_UNAVAILABLE:
+ case NM_DEVICE_STATE_FAILED:
@@ -2230,10 +2246,10 @@ index 0000000..ec62f84
+#endif /* NM_MODEM_MANAGER_H */
diff --git a/src/modem-manager/nm-modem-types.h b/src/modem-manager/nm-modem-types.h
new file mode 100644
-index 0000000..bd76796
+index 0000000..f5cbe10
--- /dev/null
+++ b/src/modem-manager/nm-modem-types.h
-@@ -0,0 +1,25 @@
+@@ -0,0 +1,89 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#ifndef NM_MODEM_TYPES_H
@@ -2253,10 +2269,74 @@ index 0000000..bd76796
+#define MM_MODEM_TYPE_GSM 1
+#define MM_MODEM_TYPE_CDMA 2
+
-+#define MM_MODEM_ERROR_GENERAL MM_DBUS_INTERFACE_MODEM ".GeneralError"
-+#define MM_MODEM_ERROR_PIN_NEEDED MM_DBUS_INTERFACE_MODEM ".PINNeeded"
-+#define MM_MODEM_ERROR_PUK_NEEDED MM_DBUS_INTERFACE_MODEM ".PUKNeeded"
-+#define MM_MODEM_ERROR_INVALID_SECRET MM_DBUS_INTERFACE_MODEM ".InvalidSecret"
++/* Errors */
++
++#define MM_SERIAL_OPEN_FAILED MM_DBUS_INTERFACE_MODEM ".SerialOpenFailed"
++#define MM_SERIAL_SEND_FAILED MM_DBUS_INTERFACE_MODEM ".SerialSendFailed"
++#define MM_SERIAL_RESPONSE_TIMEOUT MM_DBUS_INTERFACE_MODEM ".SerialResponseTimeout"
++
++#define MM_MODEM_ERROR_GENERAL MM_DBUS_INTERFACE_MODEM ".General"
++#define MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED MM_DBUS_INTERFACE_MODEM ".OperationNotSupported"
++
++#define MM_MODEM_CONNECT_ERROR_NO_CARRIER MM_DBUS_INTERFACE_MODEM ".NoCarrier"
++#define MM_MODEM_CONNECT_ERROR_NO_DIALTONE MM_DBUS_INTERFACE_MODEM ".NoDialtone"
++#define MM_MODEM_CONNECT_ERROR_BUSY MM_DBUS_INTERFACE_MODEM ".Busy"
++#define MM_MODEM_CONNECT_ERROR_NO_ANSWER MM_DBUS_INTERFACE_MODEM ".NoAnswer"
++
++#define MM_MODEM_ERROR "org.freedesktop.ModemManager.Modem.Gsm"
++
++#define MM_MODEM_ERROR_PHONE_FAILURE MM_MODEM_ERROR ".PhoneFailure"
++#define MM_MODEM_ERROR_NO_CONNECTION MM_MODEM_ERROR ".NoConnection"
++#define MM_MODEM_ERROR_LINK_RESERVED MM_MODEM_ERROR ".LinkReserved"
++#define MM_MODEM_ERROR_NOT_ALLOWED MM_MODEM_ERROR ".OperationNotAllowed"
++#define MM_MODEM_ERROR_NOT_SUPPORTED MM_MODEM_ERROR ".OperationNotSupported"
++#define MM_MODEM_ERROR_PH_SIM_PIN MM_MODEM_ERROR ".PhSimPinRequired"
++#define MM_MODEM_ERROR_PH_FSIM_PIN MM_MODEM_ERROR ".PhFSimPinRequired"
++#define MM_MODEM_ERROR_PH_FSIM_PUK MM_MODEM_ERROR ".PhFPukRequired"
++#define MM_MODEM_ERROR_SIM_NOT_INSERTED MM_MODEM_ERROR ".SimNotInserted"
++#define MM_MODEM_ERROR_SIM_PIN MM_MODEM_ERROR ".SimPinRequired"
++#define MM_MODEM_ERROR_SIM_PUK MM_MODEM_ERROR ".SimPukRequired"
++#define MM_MODEM_ERROR_SIM_FAILURE MM_MODEM_ERROR ".SimFailure"
++#define MM_MODEM_ERROR_SIM_BUSY MM_MODEM_ERROR ".SimBusy"
++#define MM_MODEM_ERROR_SIM_WRONG MM_MODEM_ERROR ".SimWrong"
++#define MM_MODEM_ERROR_WRONG_PASSWORD MM_MODEM_ERROR ".IncorrectPassword"
++#define MM_MODEM_ERROR_SIM_PIN2 MM_MODEM_ERROR ".SimPin2Required"
++#define MM_MODEM_ERROR_SIM_PUK2 MM_MODEM_ERROR ".SimPuk2Required"
++#define MM_MODEM_ERROR_MEMORY_FULL MM_MODEM_ERROR ".MemoryFull"
++#define MM_MODEM_ERROR_INVALID_INDEX MM_MODEM_ERROR ".InvalidIndex"
++#define MM_MODEM_ERROR_NOT_FOUND MM_MODEM_ERROR ".NotFound"
++#define MM_MODEM_ERROR_MEMORY_FAILURE MM_MODEM_ERROR ".MemoryFailure"
++#define MM_MODEM_ERROR_TEXT_TOO_LONG MM_MODEM_ERROR ".TextTooLong"
++#define MM_MODEM_ERROR_INVALID_CHARS MM_MODEM_ERROR ".InvalidChars"
++#define MM_MODEM_ERROR_DIAL_STRING_TOO_LONG MM_MODEM_ERROR ".DialStringTooLong"
++#define MM_MODEM_ERROR_DIAL_STRING_INVALID MM_MODEM_ERROR ".InvalidDialString"
++#define MM_MODEM_ERROR_NO_NETWORK MM_MODEM_ERROR ".NoNetwork"
++#define MM_MODEM_ERROR_NETWORK_TIMEOUT MM_MODEM_ERROR ".NetworkTimeout"
++#define MM_MODEM_ERROR_NETWORK_NOT_ALLOWED MM_MODEM_ERROR ".NetworkNotAllowed"
++#define MM_MODEM_ERROR_NETWORK_PIN MM_MODEM_ERROR ".NetworkPinRequired"
++#define MM_MODEM_ERROR_NETWORK_PUK MM_MODEM_ERROR ".NetworkPukRequired"
++#define MM_MODEM_ERROR_NETWORK_SUBSET_PIN MM_MODEM_ERROR ".NetworkSubsetPinRequired"
++#define MM_MODEM_ERROR_NETWORK_SUBSET_PUK MM_MODEM_ERROR ".NetworkSubsetPukRequired"
++#define MM_MODEM_ERROR_SERVICE_PIN MM_MODEM_ERROR ".ServicePinRequired"
++#define MM_MODEM_ERROR_SERVICE_PUK MM_MODEM_ERROR ".ServicePukRequired"
++#define MM_MODEM_ERROR_CORP_PIN MM_MODEM_ERROR ".CorporatePinRequired"
++#define MM_MODEM_ERROR_CORP_PUK MM_MODEM_ERROR ".CorporatePukRequired"
++#define MM_MODEM_ERROR_HIDDEN_KEY MM_MODEM_ERROR ".HiddenKeyRequired"
++#define MM_MODEM_ERROR_EAP_NOT_SUPPORTED MM_MODEM_ERROR ".EapMethodNotSupported"
++#define MM_MODEM_ERROR_INCORRECT_PARAMS MM_MODEM_ERROR ".IncorrectParams"
++#define MM_MODEM_ERROR_UNKNOWN MM_MODEM_ERROR ".Unknown"
++#define MM_MODEM_ERROR_GPRS_ILLEGAL_MS MM_MODEM_ERROR ".GprsIllegalMs"
++#define MM_MODEM_ERROR_GPRS_ILLEGAL_ME MM_MODEM_ERROR ".GprsIllegalMe"
++#define MM_MODEM_ERROR_GPRS_SERVICE_NOT_ALLOWED MM_MODEM_ERROR ".GprsServiceNotAllowed"
++#define MM_MODEM_ERROR_GPRS_PLMN_NOT_ALLOWED MM_MODEM_ERROR ".GprsPlmnNotAllowed"
++#define MM_MODEM_ERROR_GPRS_LOCATION_NOT_ALLOWED MM_MODEM_ERROR ".GprsLocationNotAllowed"
++#define MM_MODEM_ERROR_GPRS_ROAMING_NOT_ALLOWED MM_MODEM_ERROR ".GprsRoamingNotAllowed"
++#define MM_MODEM_ERROR_GPRS_OPTION_NOT_SUPPORTED MM_MODEM_ERROR ".GprsOptionNotSupported"
++#define MM_MODEM_ERROR_GPRS_NOT_SUBSCRIBED MM_MODEM_ERROR ".GprsNotSubscribed"
++#define MM_MODEM_ERROR_GPRS_OUT_OF_ORDER MM_MODEM_ERROR ".GprsOutOfOrder"
++#define MM_MODEM_ERROR_GPRS_PDP_AUTH_FAILURE MM_MODEM_ERROR ".GprsPdpAuthFailure"
++#define MM_MODEM_ERROR_GPRS_UNKNOWN MM_MODEM_ERROR ".GprsUnspecified"
++#define MM_MODEM_ERROR_GPRS_INVALID_CLASS MM_MODEM_ERROR ".GprsInvalidClass"
+
+#endif /* NM_MODEM_TYPES_H */
diff --git a/src/nm-cdma-device.c b/src/nm-cdma-device.c
diff --git a/nm-applet-r874-use-modem-manager.patch b/nm-applet-r874-use-modem-manager.patch
deleted file mode 100644
index 4d965461..00000000
--- a/nm-applet-r874-use-modem-manager.patch
+++ /dev/null
@@ -1,427 +0,0 @@
-diff --git a/src/Makefile.am b/src/Makefile.am
-index de8ccb4..fe60b87 100644
---- a/src/Makefile.am
-+++ b/src/Makefile.am
-@@ -49,6 +49,9 @@ nm_applet_SOURCES = \
- applet-device-gsm.c \
- applet-device-cdma.h \
- applet-device-cdma.c \
-+ mm-types.h \
-+ nma-gsm-modem.c \
-+ nma-gsm-modem.h \
- $(NULL)
-
- nm_applet_LDADD = \
-diff --git a/src/applet-device-gsm.c b/src/applet-device-gsm.c
-index 1641661..fd2601d 100644
---- a/src/applet-device-gsm.c
-+++ b/src/applet-device-gsm.c
-@@ -39,6 +39,8 @@
-
- #include "applet.h"
- #include "applet-device-gsm.h"
-+#include "nma-gsm-modem.h"
-+#include "mm-types.h"
- #include "utils.h"
-
- typedef struct {
-@@ -277,16 +279,64 @@ out:
- }
-
- static void
-+signal_quality_changed (NMAGsmModem *modem, guint32 quality, gpointer user_data)
-+{
-+ applet_schedule_update_icon (NM_APPLET (user_data));
-+}
-+
-+static void
- gsm_device_state_changed (NMDevice *device,
- NMDeviceState state,
- 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);
-+ NMAGsmModem *modem;
-+ char *oper_code;
-+ char *oper_name;
-+ char *msg;
-+ guint32 reg_status;
-+
-+ if (state != NM_DEVICE_STATE_ACTIVATED)
-+ return;
-+
-+ modem = (NMAGsmModem *) g_object_get_data (G_OBJECT (device), "gsm-modem");
-+ if (!modem) {
-+ DBusGConnection *bus;
-+
-+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
-+ if (!bus)
-+ return;
-+
-+ modem = nma_gsm_modem_new (bus, nm_device_get_udi (device));
-+ dbus_g_connection_unref (bus);
-+
-+ g_object_set_data_full (G_OBJECT (device), "gsm-modem", modem, g_object_unref);
-+
-+ g_signal_connect (modem, "signal-quality",
-+ G_CALLBACK (signal_quality_changed),
-+ applet);
- }
-+
-+ g_message ("Signal quality: %d", nma_gsm_modem_get_signal_quality (modem));
-+ g_message ("Network mode: %d", nma_gsm_modem_get_network_mode (modem));
-+
-+ oper_code = NULL;
-+ oper_name = NULL;
-+
-+ reg_status = nma_gsm_modem_get_registration_info (modem, &oper_code, &oper_name);
-+
-+ g_message ("Reg status: %d code: %s name: %s", reg_status, oper_code, oper_name);
-+
-+ msg = g_strdup_printf (_("You are now connected to the %s GSM network '%s'."),
-+ reg_status == MM_GSM_MODEM_REG_STATUS_ROAMING ? _("roaming") : _("home"),
-+ oper_name);
-+
-+ applet_do_notify (applet, NOTIFY_URGENCY_LOW,
-+ _("Connection Established"), msg,
-+ "nm-device-wwan", NULL, NULL, NULL, NULL);
-+
-+ g_free (oper_code);
-+ g_free (oper_name);
-+ g_free (msg);
- }
-
- static GdkPixbuf *
-@@ -295,6 +345,7 @@ gsm_get_icon (NMDevice *device,
- char **tip,
- NMApplet *applet)
- {
-+ NMAGsmModem *modem;
- GdkPixbuf *pixbuf = NULL;
- const char *iface;
-
-@@ -311,8 +362,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"));
-- pixbuf = applet->wwan_icon;
-+ modem = (NMAGsmModem *) g_object_get_data (G_OBJECT (device), "gsm-modem");
-+ if (modem) {
-+ char *oper_code;
-+ char *oper_name;
-+ guint32 reg_status;
-+ guint32 quality;
-+
-+ quality = nma_gsm_modem_get_signal_quality (modem);
-+ quality = CLAMP (quality, 0, 100);
-+
-+ if (quality > 80)
-+ pixbuf = applet->wireless_100_icon;
-+ else if (quality > 55)
-+ pixbuf = applet->wireless_75_icon;
-+ else if (quality > 30)
-+ pixbuf = applet->wireless_50_icon;
-+ else if (quality > 5)
-+ pixbuf = applet->wireless_25_icon;
-+ else
-+ pixbuf = applet->wireless_00_icon;
-+
-+ reg_status = nma_gsm_modem_get_registration_info (modem, &oper_code, &oper_name);
-+ *tip = g_strdup_printf (_("%s GSM connection '%s' (%d%%)"),
-+ reg_status == MM_GSM_MODEM_REG_STATUS_ROAMING ? _("Roaming") : _("Home"),
-+ oper_name, quality);
-+
-+ g_free (oper_name);
-+ g_free (oper_code);
-+
-+ } else {
-+ pixbuf = applet->wireless_00_icon;
-+ *tip = g_strdup_printf (_("GSM connection"));
-+ }
-+
- break;
- default:
- break;
-diff --git a/src/mm-types.h b/src/mm-types.h
-new file mode 100644
-index 0000000..a1f9979
---- /dev/null
-+++ b/src/mm-types.h
-@@ -0,0 +1,18 @@
-+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
-+
-+#ifndef MM_TYPES_H
-+#define MM_TYPES_H
-+
-+#define MM_DBUS_SERVICE "org.freedesktop.ModemManager"
-+#define MM_DBUS_INTERFACE_MODEM_GSM "org.freedesktop.ModemManager.Modem.Gsm.Network"
-+
-+enum {
-+ MM_GSM_MODEM_REG_STATUS_IDLE = 0,
-+ MM_GSM_MODEM_REG_STATUS_HOME = 1,
-+ MM_GSM_MODEM_REG_STATUS_SEARCHING = 2,
-+ MM_GSM_MODEM_REG_STATUS_DENIED = 3,
-+ MM_GSM_MODEM_REG_STATUS_UNKNOWN = 4,
-+ MM_GSM_MODEM_REG_STATUS_ROAMING = 5
-+};
-+
-+#endif /* MM_TYPES_H */
-diff --git a/src/nma-gsm-modem.c b/src/nma-gsm-modem.c
-new file mode 100644
-index 0000000..584090b
---- /dev/null
-+++ b/src/nma-gsm-modem.c
-@@ -0,0 +1,198 @@
-+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
-+
-+#include "nma-gsm-modem.h"
-+#include "mm-types.h"
-+
-+G_DEFINE_TYPE (NMAGsmModem, nma_gsm_modem, G_TYPE_OBJECT)
-+
-+#define NMA_GSM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMA_TYPE_GSM_MODEM, NMAGsmModemPrivate))
-+
-+typedef struct {
-+ DBusGProxy *proxy;
-+ int signal_quality;
-+
-+ gboolean disposed;
-+} NMAGsmModemPrivate;
-+
-+enum {
-+ SIGNAL_QUALITY,
-+ NETWORK_MODE,
-+
-+ LAST_SIGNAL
-+};
-+
-+static guint signals[LAST_SIGNAL] = { 0 };
-+
-+static void
-+signal_quality_proxy (DBusGProxy *proxy,
-+ guint32 signal_quality,
-+ gpointer user_data)
-+{
-+ NMAGsmModem *modem = NMA_GSM_MODEM (user_data);
-+
-+ NMA_GSM_MODEM_GET_PRIVATE (modem)->signal_quality = signal_quality;
-+
-+ g_signal_emit (modem, signals[SIGNAL_QUALITY], 0, signal_quality);
-+}
-+
-+static void
-+network_mode_proxy (DBusGProxy *proxy,
-+ guint32 network_mode,
-+ gpointer user_data)
-+{
-+ NMAGsmModem *modem = NMA_GSM_MODEM (user_data);
-+
-+ g_signal_emit (modem, signals[NETWORK_MODE], 0, network_mode);
-+}
-+
-+NMAGsmModem *
-+nma_gsm_modem_new (DBusGConnection *bus, const char *object_path)
-+{
-+ NMAGsmModem *modem;
-+ NMAGsmModemPrivate *priv;
-+
-+ g_return_val_if_fail (bus != NULL, NULL);
-+ g_return_val_if_fail (object_path != NULL, NULL);
-+
-+ modem = (NMAGsmModem *) g_object_new (NMA_TYPE_GSM_MODEM, NULL);
-+ if (!modem)
-+ return NULL;
-+
-+ priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
-+ priv->proxy = dbus_g_proxy_new_for_name (bus, MM_DBUS_SERVICE, object_path, MM_DBUS_INTERFACE_MODEM_GSM);
-+
-+ dbus_g_proxy_add_signal (priv->proxy, "SignalQuality", G_TYPE_UINT, G_TYPE_INVALID);
-+ dbus_g_proxy_connect_signal (priv->proxy, "SignalQuality",
-+ G_CALLBACK (signal_quality_proxy),
-+ modem,
-+ NULL);
-+
-+ dbus_g_proxy_add_signal (priv->proxy, "NetworkMode", G_TYPE_UINT, G_TYPE_INVALID);
-+ dbus_g_proxy_connect_signal (priv->proxy, "NetworkMode",
-+ G_CALLBACK (network_mode_proxy),
-+ modem,
-+ NULL);
-+
-+ return modem;
-+}
-+
-+guint32
-+nma_gsm_modem_get_signal_quality (NMAGsmModem *modem)
-+{
-+ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
-+ GError *err = NULL;
-+
-+ g_return_val_if_fail (NMA_IS_GSM_MODEM (modem), 0);
-+
-+ if (priv->signal_quality == -1) {
-+ if (dbus_g_proxy_call (priv->proxy, "GetSignalQuality", &err,
-+ G_TYPE_INVALID,
-+ G_TYPE_UINT, &priv->signal_quality,
-+ G_TYPE_INVALID)) {
-+ g_warning ("Error in getting signal quality: %s", err->message);
-+ g_error_free (err);
-+ }
-+ }
-+
-+ return priv->signal_quality;
-+}
-+
-+guint32
-+nma_gsm_modem_get_registration_info (NMAGsmModem *modem,
-+ char **operator_code,
-+ char **operator_name)
-+{
-+ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
-+ GError *err = NULL;
-+ guint32 status = MM_GSM_MODEM_REG_STATUS_UNKNOWN;
-+
-+ g_return_val_if_fail (NMA_IS_GSM_MODEM (modem), 0);
-+
-+ if (!dbus_g_proxy_call (priv->proxy, "GetRegistrationInfo", &err,
-+ G_TYPE_INVALID,
-+ G_TYPE_UINT, &status,
-+ G_TYPE_STRING, operator_code,
-+ G_TYPE_STRING, operator_name,
-+ G_TYPE_INVALID)) {
-+ g_warning ("Error in getting network mode: %s", err->message);
-+ g_error_free (err);
-+ }
-+
-+ return status;
-+}
-+
-+guint32
-+nma_gsm_modem_get_network_mode (NMAGsmModem *modem)
-+{
-+ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
-+ GError *err = NULL;
-+ guint32 network_mode = 0;
-+
-+ g_return_val_if_fail (NMA_IS_GSM_MODEM (modem), 0);
-+
-+ if (!dbus_g_proxy_call (priv->proxy, "GetNetworkMode", &err,
-+ G_TYPE_INVALID,
-+ G_TYPE_UINT, &network_mode,
-+ G_TYPE_INVALID)) {
-+ g_warning ("Error in getting network mode: %s", err->message);
-+ g_error_free (err);
-+ }
-+
-+ return network_mode;
-+}
-+
-+static void
-+nma_gsm_modem_init (NMAGsmModem *modem)
-+{
-+ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
-+
-+ priv->signal_quality = -1;
-+}
-+
-+static void
-+dispose (GObject *object)
-+{
-+ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (object);
-+
-+ if (priv->disposed)
-+ return;
-+
-+ priv->disposed = TRUE;
-+
-+ if (priv->proxy)
-+ g_object_unref (priv->proxy);
-+
-+ G_OBJECT_CLASS (nma_gsm_modem_parent_class)->dispose (object);
-+}
-+
-+static void
-+nma_gsm_modem_class_init (NMAGsmModemClass *modem_class)
-+{
-+ GObjectClass *object_class = G_OBJECT_CLASS (modem_class);
-+
-+ g_type_class_add_private (modem_class, sizeof (NMAGsmModemPrivate));
-+
-+ /* virtual methods */
-+ object_class->dispose = dispose;
-+
-+ /* Signals */
-+ signals[SIGNAL_QUALITY] =
-+ g_signal_new ("signal-quality",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_FIRST,
-+ G_STRUCT_OFFSET (NMAGsmModemClass, signal_quality),
-+ NULL, NULL,
-+ g_cclosure_marshal_VOID__UINT,
-+ G_TYPE_NONE, 1,
-+ G_TYPE_UINT);
-+
-+ signals[NETWORK_MODE] =
-+ g_signal_new ("network-mode",
-+ G_OBJECT_CLASS_TYPE (object_class),
-+ G_SIGNAL_RUN_FIRST,
-+ G_STRUCT_OFFSET (NMAGsmModemClass, network_mode),
-+ NULL, NULL,
-+ g_cclosure_marshal_VOID__UINT,
-+ G_TYPE_NONE, 1,
-+ G_TYPE_UINT);
-+}
-diff --git a/src/nma-gsm-modem.h b/src/nma-gsm-modem.h
-new file mode 100644
-index 0000000..90e7ae0
---- /dev/null
-+++ b/src/nma-gsm-modem.h
-@@ -0,0 +1,45 @@
-+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
-+
-+#ifndef NMA_GSM_MODEM_H
-+#define NMA_GSM_MODEM_H
-+
-+#include <glib/gtypes.h>
-+#include <glib-object.h>
-+#include <dbus/dbus-glib.h>
-+
-+G_BEGIN_DECLS
-+
-+#define NMA_TYPE_GSM_MODEM (nma_gsm_modem_get_type ())
-+#define NMA_GSM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_GSM_MODEM, NMAGsmModem))
-+#define NMA_GSM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_GSM_MODEM, NMAGsmModemClass))
-+#define NMA_IS_GSM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_GSM_MODEM))
-+#define NMA_IS_GSM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NMA_TYPE_GSM_MODEM))
-+#define NMA_GSM_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_GSM_MODEM, NMAGsmModemClass))
-+
-+typedef struct {
-+ GObject parent;
-+} NMAGsmModem;
-+
-+typedef struct {
-+ GObjectClass parent;
-+
-+ /* Signals */
-+ void (*signal_quality) (NMAGsmModem *modem, guint32 signal_quality);
-+ void (*network_mode) (NMAGsmModem *modem, guint32 network_mode);
-+} NMAGsmModemClass;
-+
-+GType nma_gsm_modem_get_type (void);
-+
-+NMAGsmModem *nma_gsm_modem_new (DBusGConnection *bus,
-+ const char *object_path);
-+
-+guint32 nma_gsm_modem_get_signal_quality (NMAGsmModem *modem);
-+guint32 nma_gsm_modem_get_registration_info (NMAGsmModem *modem,
-+ char **operator_code,
-+ char **operator_name);
-+
-+guint32 nma_gsm_modem_get_network_mode (NMAGsmModem *modem);
-+
-+G_END_DECLS
-+
-+#endif /* NMA_GSM_MODEM_H */
diff --git a/nm-applet-r884-use-modem-manager.patch b/nm-applet-r884-use-modem-manager.patch
new file mode 100644
index 00000000..7c141345
--- /dev/null
+++ b/nm-applet-r884-use-modem-manager.patch
@@ -0,0 +1,1524 @@
+diff --git a/configure.ac b/configure.ac
+index 9e64b77..77ad2ac 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -221,6 +221,7 @@ src/utils/Makefile
+ src/gconf-helpers/Makefile
+ src/wireless-security/Makefile
+ src/connection-editor/Makefile
++src/modems/Makefile
+ icons/Makefile
+ po/Makefile.in
+ ])
+diff --git a/src/Makefile.am b/src/Makefile.am
+index de8ccb4..2be2217 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1,4 +1,4 @@
+-SUBDIRS = marshallers utils gconf-helpers wireless-security connection-editor
++SUBDIRS = marshallers utils gconf-helpers wireless-security connection-editor modems
+
+ NULL=
+
+@@ -49,6 +49,9 @@ nm_applet_SOURCES = \
+ applet-device-gsm.c \
+ applet-device-cdma.h \
+ applet-device-cdma.c \
++ mm-types.h \
++ nma-gsm-modem.c \
++ nma-gsm-modem.h \
+ $(NULL)
+
+ nm_applet_LDADD = \
+diff --git a/src/applet-device-gsm.c b/src/applet-device-gsm.c
+index 1641661..f0a31e6 100644
+--- a/src/applet-device-gsm.c
++++ b/src/applet-device-gsm.c
+@@ -24,6 +24,9 @@
+ #include <config.h>
+ #endif
+
++#include <sys/types.h>
++#include <unistd.h>
++
+ #include <glib/gi18n.h>
+ #include <gtk/gtkwidget.h>
+ #include <gtk/gtkmenuitem.h>
+@@ -39,6 +42,8 @@
+
+ #include "applet.h"
+ #include "applet-device-gsm.h"
++#include "nma-gsm-modem.h"
++#include "mm-types.h"
+ #include "utils.h"
+
+ typedef struct {
+@@ -165,6 +170,50 @@ add_default_connection_item (NMDevice *device,
+ }
+
+ static void
++child_setup (gpointer user_data G_GNUC_UNUSED)
++{
++ /* We are in the child process at this point */
++ pid_t pid = getpid ();
++ setpgid (pid, pid);
++}
++
++static void
++gsm_properties_cb (GtkMenuItem *mi, gpointer user_data)
++{
++ NMDevice *device = NM_DEVICE (user_data);
++ char *argv[3];
++ GError *error = NULL;
++ gboolean success;
++
++ argv[0] = BINDIR "/nm-modem-properties";
++ argv[1] = (char *) nm_device_get_udi (device);
++ argv[2] = NULL;
++
++ success = g_spawn_async ("/", argv, NULL, 0, &child_setup, NULL, NULL, &error);
++ if (!success) {
++ g_warning ("Error launching modem properties dialog: %s", error->message);
++ g_error_free (error);
++ }
++}
++
++static void
++add_properties_item (NMDevice *device,
++ GtkWidget *menu)
++{
++ GtkWidget *item;
++
++ if (nm_device_get_state (device) != NM_DEVICE_STATE_DISCONNECTED)
++ return;
++
++ item = gtk_menu_item_new_with_label (_("Properties"));
++ g_signal_connect (item, "activate",
++ G_CALLBACK (gsm_properties_cb),
++ device);
++
++ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
++}
++
++static void
+ gsm_menu_item_deactivate (GtkMenuItem *item, gpointer user_data)
+ {
+ GSMMenuItemInfo *info = (GSMMenuItemInfo *) user_data;
+@@ -270,23 +319,66 @@ gsm_add_menu_item (NMDevice *device,
+ add_connection_items (device, connections, active, menu, applet);
+ else
+ add_default_connection_item (device, menu, applet);
++
+ add_disconnect_item (device, menu, applet);
++ add_properties_item (device, menu);
+
+ out:
+ g_slist_free (connections);
+ }
+
+ static void
++signal_quality_changed (NMAGsmModem *modem, guint32 quality, gpointer user_data)
++{
++ applet_schedule_update_icon (NM_APPLET (user_data));
++}
++
++static void
+ gsm_device_state_changed (NMDevice *device,
+ NMDeviceState state,
+ 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);
++ NMAGsmModem *modem;
++ char *oper_code;
++ char *oper_name;
++ char *msg;
++ guint32 reg_status;
++
++ if (state != NM_DEVICE_STATE_ACTIVATED)
++ return;
++
++ modem = (NMAGsmModem *) g_object_get_data (G_OBJECT (device), "gsm-modem");
++ if (!modem) {
++ DBusGConnection *bus;
++
++ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
++ if (!bus)
++ return;
++
++ modem = nma_gsm_modem_new (bus, nm_device_get_udi (device));
++ dbus_g_connection_unref (bus);
++
++ g_object_set_data_full (G_OBJECT (device), "gsm-modem", modem, g_object_unref);
++
++ g_signal_connect (modem, "signal-quality",
++ G_CALLBACK (signal_quality_changed),
++ applet);
+ }
++
++ oper_code = NULL;
++ oper_name = NULL;
++ reg_status = nma_gsm_modem_get_registration_info (modem, &oper_code, &oper_name);
++ msg = g_strdup_printf (_("You are now connected to the %s GSM network '%s'."),
++ reg_status == MM_GSM_MODEM_REG_STATUS_ROAMING ? _("roaming") : _("home"),
++ oper_name);
++
++ applet_do_notify (applet, NOTIFY_URGENCY_LOW,
++ _("Connection Established"), msg,
++ "nm-device-wwan", NULL, NULL, NULL, NULL);
++
++ g_free (oper_code);
++ g_free (oper_name);
++ g_free (msg);
+ }
+
+ static GdkPixbuf *
+@@ -295,6 +387,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,
+ *tip = g_strdup_printf (_("Waiting for user authentication on device '%s'..."), iface);
+ break;
+ case NM_DEVICE_STATE_ACTIVATED:
+- *tip = g_strdup (_("GSM connection"));
+- pixbuf = applet->wwan_icon;
++ modem = (NMAGsmModem *) g_object_get_data (G_OBJECT (device), "gsm-modem");
++ if (modem) {
++ char *oper_code;
++ char *oper_name;
++ guint32 reg_status;
++ guint32 quality;
++
++ quality = nma_gsm_modem_get_signal_quality (modem);
++ quality = CLAMP (quality, 0, 100);
++
++ if (quality > 80)
++ pixbuf = applet->wireless_100_icon;
++ else if (quality > 55)
++ pixbuf = applet->wireless_75_icon;
++ else if (quality > 30)
++ pixbuf = applet->wireless_50_icon;
++ else if (quality > 5)
++ pixbuf = applet->wireless_25_icon;
++ else
++ pixbuf = applet->wireless_00_icon;
++
++ reg_status = nma_gsm_modem_get_registration_info (modem, &oper_code, &oper_name);
++ *tip = g_strdup_printf (_("%s GSM connection '%s' (%d%%)"),
++ reg_status == MM_GSM_MODEM_REG_STATUS_ROAMING ? _("Roaming") : _("Home"),
++ oper_name, quality);
++
++ g_free (oper_name);
++ g_free (oper_code);
++
++ } else {
++ pixbuf = applet->wireless_00_icon;
++ *tip = g_strdup_printf (_("GSM connection"));
++ }
++
+ break;
+ default:
+ break;
+diff --git a/src/mm-types.h b/src/mm-types.h
+new file mode 100644
+index 0000000..a1f9979
+--- /dev/null
++++ b/src/mm-types.h
+@@ -0,0 +1,18 @@
++/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
++
++#ifndef MM_TYPES_H
++#define MM_TYPES_H
++
++#define MM_DBUS_SERVICE "org.freedesktop.ModemManager"
++#define MM_DBUS_INTERFACE_MODEM_GSM "org.freedesktop.ModemManager.Modem.Gsm.Network"
++
++enum {
++ MM_GSM_MODEM_REG_STATUS_IDLE = 0,
++ MM_GSM_MODEM_REG_STATUS_HOME = 1,
++ MM_GSM_MODEM_REG_STATUS_SEARCHING = 2,
++ MM_GSM_MODEM_REG_STATUS_DENIED = 3,
++ MM_GSM_MODEM_REG_STATUS_UNKNOWN = 4,
++ MM_GSM_MODEM_REG_STATUS_ROAMING = 5
++};
++
++#endif /* MM_TYPES_H */
+diff --git a/src/modems/Makefile.am b/src/modems/Makefile.am
+new file mode 100644
+index 0000000..206ee52
+--- /dev/null
++++ b/src/modems/Makefile.am
+@@ -0,0 +1,25 @@
++bin_PROGRAMS = nm-modem-properties
++
++nm_modem_properties_CPPFLAGS = \
++ $(NMA_CFLAGS) \
++ -DICONDIR=\""$(datadir)/icons"\" \
++ -DGLADEDIR=\""$(gladedir)"\" \
++ -DBINDIR=\""$(bindir)"\" \
++ -DSYSCONFDIR=\""$(sysconfdir)"\" \
++ -DLIBDIR=\""$(libdir)"\" \
++ -DNMALOCALEDIR=\"$(datadir)/locale\" \
++ $(DBUS_CFLAGS) \
++ -I${top_srcdir}/src/gconf-helpers
++
++nm_modem_properties_SOURCES = \
++ main.c
++
++nm_modem_properties_LDADD = \
++ $(top_builddir)/src/gconf-helpers/libgconf-helpers.la \
++ $(NMA_LIBS)
++
++gladedir = $(datadir)/nm-applet
++glade_DATA = nm-modem-properties.glade
++
++CLEANFILES = *.bak *.gladep
++EXTRA_DIST = $(glade_DATA)
+diff --git a/src/modems/main.c b/src/modems/main.c
+new file mode 100644
+index 0000000..27e700c
+--- /dev/null
++++ b/src/modems/main.c
+@@ -0,0 +1,592 @@
++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
++
++#include <string.h>
++#include <gtk/gtk.h>
++#include <glade/glade.h>
++#include <dbus/dbus-glib.h>
++#include <gconf/gconf-client.h>
++#include <nm-connection.h>
++#include <nm-setting-connection.h>
++#include <nm-setting-gsm.h>
++#include <nm-setting-serial.h>
++#include <nm-setting-ppp.h>
++#include <nm-utils.h>
++#include "gconf-helpers.h"
++
++#define MM_DBUS_SERVICE "org.freedesktop.ModemManager"
++#define MM_DBUS_PATH "/org/freedesktop/ModemManager"
++#define MM_DBUS_INTERFACE "org.freedesktop.ModemManager"
++#define MM_DBUS_INTERFACE_MODEM "org.freedesktop.ModemManager.Modem"
++
++#define MM_DBUS_INTERFACE_MODEM_GSM_CARD "org.freedesktop.ModemManager.Modem.Gsm.Card"
++#define MM_DBUS_INTERFACE_MODEM_GSM_NETWORK "org.freedesktop.ModemManager.Modem.Gsm.Network"
++
++#define MM_MODEM_TYPE_UNKNOWN 0
++#define MM_MODEM_TYPE_GSM 1
++#define MM_MODEM_TYPE_CDMA 2
++
++#define SCAN_COL_NAME 0
++#define SCAN_COL_STATUS 1
++#define SCAN_COL_OPER_ID 2
++
++typedef struct {
++ /* 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;
++
++ GtkDialog *create_network_dialog;
++ GtkEntry *create_network_name;
++
++ /* DBus */
++ DBusGConnection *bus;
++ DBusGProxy *proxy;
++ DBusGProxy *gsm_net_proxy;
++
++ 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_error_free (error);
++ } else {
++ add_info_row (info->table, info->row, info->label, result);
++ g_free (result);
++ }
++}
++
++static void
++get_card_info_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
++{
++ GtkTable *table = GTK_TABLE (user_data);
++ char *manufacturer = NULL;
++ char *model = NULL;
++ char *version = NULL;
++ GError *error = NULL;
++
++ if (!dbus_g_proxy_end_call (proxy, call_id, &error,
++ G_TYPE_STRING, &manufacturer,
++ G_TYPE_STRING, &model,
++ G_TYPE_STRING, &version,
++ G_TYPE_INVALID)) {
++ 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);
++
++ add_info_row (table, 1, "Model", model);
++ g_free (model);
++
++ add_info_row (table, 2, "Version", version);
++ g_free (version);
++ }
++}
++
++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_error_free (error);
++ } else {
++ add_info_row (info->table, info->row, info->label, g_value_get_string (&value));
++ g_value_unset (&value);
++ }
++}
++
++static gboolean
++get_info (gpointer data)
++{
++ AppData *app_data = (AppData *) data;
++
++ 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,
++ 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,
++ G_TYPE_INVALID);
++
++ dbus_g_proxy_begin_call (app_data->proxy, "GetInfo", get_card_info_done,
++ app_data->info_table, 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,
++ 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,
++ G_TYPE_STRING, MM_DBUS_INTERFACE_MODEM,
++ G_TYPE_STRING, "DataDevice",
++ G_TYPE_INVALID);
++
++ return FALSE;
++}
++
++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_error_free (error);
++ } else {
++ char *tmp;
++
++ tmp = g_strdup_printf ("%d%%", quality);
++ gtk_label_set_text (app_data->signal_quality_label, tmp);
++ g_free (tmp);
++ }
++}
++
++static void
++signal_quality_changed (DBusGProxy *proxy,
++ 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);
++ g_free (tmp);
++}
++
++static gboolean
++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);
++
++ 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);
++
++ 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);
++
++ dbus_g_proxy_begin_call (app_data->gsm_net_proxy, "GetSignalQuality", got_signal_quality,
++ app_data, NULL,
++ G_TYPE_INVALID);
++
++ return FALSE;
++}
++
++static void
++got_scan_results (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
++{
++ AppData *app_data = (AppData *) user_data;
++ GPtrArray *array = NULL;
++ GError *error = NULL;
++ GType type;
++
++ type = dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_STRING_STRING_HASHTABLE);
++
++ if (!dbus_g_proxy_end_call (proxy, call_id, &error, type, &array, G_TYPE_INVALID)) {
++ g_warning ("Couldn't scan: %s", error->message);
++ g_error_free (error);
++ } else {
++ GtkTreeIter iter;
++ int i;
++
++ for (i = 0; i < array->len; i++) {
++ GHashTable *hash = (GHashTable *) g_ptr_array_index (array, i);
++ char *status;
++ const char *status_str;
++
++ status = g_hash_table_lookup (hash, "status");
++ if (!strcmp (status, "1"))
++ status_str = "Available";
++ else if (!strcmp (status, "2"))
++ status_str = "Current";
++ else if (!strcmp (status, "3"))
++ status_str = "Forbidden";
++ else
++ status_str = "Unknown";
++
++ gtk_list_store_append (app_data->network_store, &iter);
++ gtk_list_store_set (app_data->network_store, &iter,
++ SCAN_COL_NAME, g_hash_table_lookup (hash, "operator-long"),
++ SCAN_COL_STATUS, status_str,
++ SCAN_COL_OPER_ID, g_hash_table_lookup (hash, "operator-num"),
++ -1);
++
++ g_hash_table_destroy (hash);
++ }
++
++ g_ptr_array_free (array, TRUE);
++ }
++
++ gtk_widget_set_sensitive (app_data->scan_button, TRUE);
++}
++
++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);
++
++ gtk_widget_set_sensitive (app_data->scan_button, FALSE);
++ gtk_list_store_clear (app_data->network_store);
++ /* FIXME: Add "Scanning..." dialog */
++}
++
++static void
++modem_enabled (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
++{
++ AppData *app_data = (AppData *) user_data;
++ GError *error = NULL;
++
++ if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) {
++ g_warning ("Couldn't enable modem: %s", error->message);
++ g_error_free (error);
++ g_main_loop_quit (app_data->main_loop);
++ return;
++ }
++
++ g_idle_add (get_info, app_data);
++ g_idle_add (monitor_signal_quality, app_data);
++}
++
++static void
++modem_enable (AppData *app_data)
++{
++ dbus_g_proxy_begin_call (app_data->proxy, "Enable", modem_enabled,
++ app_data, NULL,
++ G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID);
++}
++
++static void
++create_network (const char *name, const char *oper_code)
++{
++ NMConnection *connection;
++ NMSettingGsm *s_gsm;
++ NMSettingSerial *s_serial;
++ NMSettingPPP *s_ppp;
++ NMSettingConnection *s_con;
++ GConfClient *gconf_client;
++
++ connection = nm_connection_new ();
++
++ s_gsm = NM_SETTING_GSM (nm_setting_gsm_new ());
++ s_gsm->number = g_strdup ("*99#"); /* This should be a sensible default as it's seems to be quite standard */
++ s_gsm->network_id = g_strdup (oper_code);
++ nm_connection_add_setting (connection, NM_SETTING (s_gsm));
++
++ /* Serial setting */
++ s_serial = (NMSettingSerial *) nm_setting_serial_new ();
++ s_serial->baud = 115200;
++ s_serial->bits = 8;
++ s_serial->parity = 'n';
++ s_serial->stopbits = 1;
++ nm_connection_add_setting (connection, NM_SETTING (s_serial));
++
++ s_ppp = (NMSettingPPP *) nm_setting_ppp_new ();
++ nm_connection_add_setting (connection, NM_SETTING (s_ppp));
++
++ s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
++ s_con->id = g_strdup (name);
++ s_con->type = g_strdup (NM_SETTING (s_gsm)->name);
++ s_con->autoconnect = FALSE;
++ s_con->uuid = nm_utils_uuid_generate ();
++ nm_connection_add_setting (connection, NM_SETTING (s_con));
++
++ gconf_client = gconf_client_get_default ();
++ if (gconf_client) {
++ char *dir = NULL;
++ int i;
++
++ /* Find free GConf directory */
++ for (i = 0; i < G_MAXUINT32; i++) {
++ char buf[255];
++
++ snprintf (&buf[0], 255, GCONF_PATH_CONNECTIONS"/%d", i);
++ if (!gconf_client_dir_exists (gconf_client, buf, NULL)) {
++ dir = g_strdup (buf);
++ break;
++ }
++ }
++
++ nm_gconf_write_connection (connection, gconf_client, dir);
++ gconf_client_notify (gconf_client, dir);
++ gconf_client_suggest_sync (gconf_client, NULL);
++ g_free (dir);
++ g_object_unref (gconf_client);
++ } else
++ g_warning ("Writing conneciton failed");
++
++ g_object_unref (connection);
++}
++
++static void
++create_network_clicked (GtkButton *button, gpointer user_data)
++{
++ AppData *app_data = (AppData *) user_data;
++ GtkTreeSelection *selection;
++ GList *selected_rows;
++ GtkTreeModel *model = NULL;
++ GtkTreeIter iter;
++
++ selection = gtk_tree_view_get_selection (app_data->network_list);
++ selected_rows = gtk_tree_selection_get_selected_rows (selection, &model);
++ if (!selected_rows)
++ return;
++
++ if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) selected_rows->data)) {
++ char *oper_name = NULL;
++ char *oper_id = NULL;
++ gint result;
++
++ gtk_tree_model_get (model, &iter, SCAN_COL_NAME, &oper_name, -1);
++ gtk_tree_model_get (model, &iter, SCAN_COL_OPER_ID, &oper_id, -1);
++
++ gtk_entry_set_text (app_data->create_network_name, oper_name);
++ gtk_editable_select_region (GTK_EDITABLE (app_data->create_network_name), 0, -1);
++ gtk_widget_grab_focus (GTK_WIDGET (app_data->create_network_name));
++
++ result = gtk_dialog_run (app_data->create_network_dialog);
++ gtk_widget_hide (GTK_WIDGET (app_data->create_network_dialog));
++
++ if (result == GTK_RESPONSE_OK)
++ create_network (gtk_entry_get_text (app_data->create_network_name), oper_id);
++
++ g_free (oper_name);
++ g_free (oper_id);
++ }
++
++ /* free memory */
++ g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
++ g_list_free (selected_rows);
++}
++
++static void
++network_list_selection_changed (GtkTreeSelection *selection, gpointer user_data)
++{
++ AppData *app_data = (AppData *) user_data;
++ GtkTreeIter iter;
++ GtkTreeModel *model;
++
++ if (gtk_tree_selection_get_selected (selection, &model, &iter))
++ gtk_widget_set_sensitive (app_data->create_net_button, TRUE);
++ else
++ gtk_widget_set_sensitive (app_data->create_net_button, FALSE);
++}
++
++
++static void
++app_data_destroy (AppData *app_data)
++{
++ if (app_data->bus)
++ dbus_g_connection_unref (app_data->bus);
++
++ if (app_data->proxy)
++ g_object_unref (app_data->proxy);
++
++ if (app_data->gsm_net_proxy)
++ g_object_unref (app_data->gsm_net_proxy);
++
++ if (app_data->glade_xml)
++ g_object_unref (app_data->glade_xml);
++
++ if (app_data->main_loop)
++ g_main_loop_unref (app_data->main_loop);
++
++ g_slice_free (AppData, app_data);
++}
++
++static void
++close_cb (GtkDialog *dialog,
++ gint response_id,
++ gpointer user_data)
++{
++ AppData *app_data = (AppData *) user_data;
++
++ dbus_g_proxy_set_interface (app_data->proxy, MM_DBUS_INTERFACE_MODEM);
++ dbus_g_proxy_call_no_reply (app_data->proxy, "Enable", G_TYPE_BOOLEAN, FALSE, G_TYPE_INVALID);
++
++ g_main_loop_quit (app_data->main_loop);
++ app_data_destroy (app_data);
++}
++
++
++static GtkListStore *
++prepare_network_list (GtkTreeView *treeview)
++{
++ GtkListStore *store;
++
++ store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
++ gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));
++ g_object_unref (store);
++
++ gtk_tree_view_insert_column_with_attributes (treeview,
++ -1, "Name", gtk_cell_renderer_text_new (),
++ "text", SCAN_COL_NAME,
++ NULL);
++
++ gtk_tree_view_insert_column_with_attributes (treeview,
++ -1, "Status", gtk_cell_renderer_text_new (),
++ "text", SCAN_COL_STATUS,
++ NULL);
++
++ return store;
++}
++
++static AppData *
++app_data_create (const char *udi)
++{
++ AppData *app_data;
++ GtkTreeSelection *selection;
++ GError *error = NULL;
++
++ app_data = g_slice_new0 (AppData);
++
++ /* DBus */
++ app_data->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
++ if (!app_data->bus) {
++ g_error ("Couldn't connect to DBus: %s", error->message);
++ g_error_free (error);
++ g_slice_free (AppData, app_data);
++
++ return NULL;
++ }
++
++ app_data->proxy = dbus_g_proxy_new_for_name (app_data->bus, MM_DBUS_SERVICE, udi, MM_DBUS_INTERFACE_MODEM);
++ app_data->gsm_net_proxy = dbus_g_proxy_new_from_proxy (app_data->proxy, MM_DBUS_INTERFACE_MODEM_GSM_NETWORK, NULL);
++
++ /* UI */
++ app_data->glade_xml = glade_xml_new (GLADEDIR "/nm-modem-properties.glade", NULL, NULL);
++ if (!app_data->glade_xml) {
++ g_error ("Could not load Glade file");
++ g_slice_free (AppData, app_data);
++
++ return NULL;
++ }
++
++ app_data->main_dialog = GTK_DIALOG (glade_xml_get_widget (app_data->glade_xml, "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->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);
++ selection = gtk_tree_view_get_selection (app_data->network_list);
++ g_signal_connect (selection, "changed", G_CALLBACK (network_list_selection_changed), app_data);
++
++ app_data->create_network_dialog = GTK_DIALOG (glade_xml_get_widget (app_data->glade_xml, "create_network_dialog"));
++ app_data->create_network_name = GTK_ENTRY (glade_xml_get_widget (app_data->glade_xml, "create_network_name"));
++
++ app_data->main_loop = g_main_loop_new (NULL, FALSE);
++
++ return app_data;
++}
++
++int
++main (int argc, char *argv[])
++{
++ //const char *udi = "/org/freedesktop/Hal/devices/usb_device_12d1_1003_noserial_if0_serial_usb_0";
++ AppData *app_data;
++
++ if (argc != 2) {
++ g_print ("Usage: %s <udi>\n", argv[0]);
++ return 1;
++ }
++
++ gtk_init (&argc, &argv);
++
++ app_data = app_data_create (argv[1]);
++ if (app_data) {
++ modem_enable (app_data);
++ g_main_loop_run (app_data->main_loop);
++ }
++
++ return 0;
++}
+diff --git a/src/modems/nm-modem-properties.glade b/src/modems/nm-modem-properties.glade
+new file mode 100644
+index 0000000..61038b8
+--- /dev/null
++++ b/src/modems/nm-modem-properties.glade
+@@ -0,0 +1,381 @@
++<?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">
++ <property name="visible">True</property>
++ <property name="title" translatable="yes">GSM modem properties</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">True</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-vbox1">
++ <property name="visible">True</property>
++ <property name="homogeneous">False</property>
++ <property name="spacing">0</property>
++
++ <child internal-child="action_area">
++ <widget class="GtkHButtonBox" id="dialog-action_area1">
++ <property name="visible">True</property>
++ <property name="layout_style">GTK_BUTTONBOX_END</property>
++
++ <child>
++ <widget class="GtkButton" id="closebutton1">
++ <property name="visible">True</property>
++ <property name="can_default">True</property>
++ <property name="can_focus">True</property>
++ <property name="label">gtk-close</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">-7</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="vbox1">
++ <property name="visible">True</property>
++ <property name="homogeneous">False</property>
++ <property name="spacing">6</property>
++
++ <child>
++ <widget class="GtkFrame" id="frame1">
++ <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>
++
++ <child>
++ <widget class="GtkAlignment" id="alignment1">
++ <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>
++ <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>
++ </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="GtkFrame" id="frame2">
++ <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>
++
++ <child>
++ <widget class="GtkAlignment" id="alignment2">
++ <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>
++ <widget class="GtkHBox" id="hbox1">
++ <property name="visible">True</property>
++ <property name="homogeneous">False</property>
++ <property name="spacing">6</property>
++
++ <child>
++ <widget class="GtkScrolledWindow" id="scrolledwindow1">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
++ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
++ <property name="shadow_type">GTK_SHADOW_IN</property>
++ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
++
++ <child>
++ <widget class="GtkTreeView" id="network_list">
++ <property name="visible">True</property>
++ <property name="can_focus">True</property>
++ <property name="headers_visible">False</property>
++ <property name="rules_hint">False</property>
++ <property name="reorderable">False</property>
++ <property name="enable_search">True</property>
++ <property name="fixed_height_mode">False</property>
++ <property name="hover_selection">False</property>
++ <property name="hover_expand">False</property>
++ </widget>
++ </child>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">True</property>
++ <property name="fill">True</property>
++ </packing>
++ </child>
++
++ <child>
++ <widget class="GtkVButtonBox" id="vbuttonbox1">
++ <property name="visible">True</property>
++ <property name="layout_style">GTK_BUTTONBOX_START</property>
++ <property name="spacing">0</property>
++
++ <child>
++ <widget class="GtkButton" id="scan_button">
++ <property name="visible">True</property>
++ <property name="can_default">True</property>
++ <property name="can_focus">True</property>
++ <property name="label" translatable="yes">Scan</property>
++ <property name="use_underline">True</property>
++ <property name="relief">GTK_RELIEF_NORMAL</property>
++ <property name="focus_on_click">True</property>
++ </widget>
++ </child>
++
++ <child>
++ <widget class="GtkButton" id="create_connection_button">
++ <property name="visible">True</property>
++ <property name="can_default">True</property>
++ <property name="can_focus">True</property>
++ <property name="label" translatable="yes">Create connection</property>
++ <property name="use_underline">True</property>
++ <property name="relief">GTK_RELIEF_NORMAL</property>
++ <property name="focus_on_click">True</property>
++ </widget>
++ </child>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">False</property>
++ <property name="fill">False</property>
++ </packing>
++ </child>
++ </widget>
++ </child>
++ </widget>
++ </child>
++
++ <child>
++ <widget class="GtkLabel" id="label2">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">&lt;b&gt;Networks&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>
++ </widget>
++ <packing>
++ <property name="padding">0</property>
++ <property name="expand">True</property>
++ <property name="fill">True</property>
++ </packing>
++ </child>
++ </widget>
++ </child>
++</widget>
++
++<widget class="GtkDialog" id="create_network_dialog">
++ <property name="title" translatable="yes">Create new connection</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-vbox2">
++ <property name="visible">True</property>
++ <property name="homogeneous">False</property>
++ <property name="spacing">0</property>
++
++ <child internal-child="action_area">
++ <widget class="GtkHButtonBox" id="dialog-action_area2">
++ <property name="visible">True</property>
++ <property name="layout_style">GTK_BUTTONBOX_END</property>
++
++ <child>
++ <widget class="GtkButton" id="cancelbutton1">
++ <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="okbutton1">
++ <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="vbox2">
++ <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="label3">
++ <property name="visible">True</property>
++ <property name="label" translatable="yes">Please choose a name for the connection</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="create_network_name">
++ <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">True</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
+index 0000000..0dba9cd
+--- /dev/null
++++ b/src/nma-gsm-modem.c
+@@ -0,0 +1,198 @@
++/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
++
++#include "nma-gsm-modem.h"
++#include "mm-types.h"
++
++G_DEFINE_TYPE (NMAGsmModem, nma_gsm_modem, G_TYPE_OBJECT)
++
++#define NMA_GSM_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMA_TYPE_GSM_MODEM, NMAGsmModemPrivate))
++
++typedef struct {
++ DBusGProxy *proxy;
++ int signal_quality;
++
++ gboolean disposed;
++} NMAGsmModemPrivate;
++
++enum {
++ SIGNAL_QUALITY,
++ NETWORK_MODE,
++
++ LAST_SIGNAL
++};
++
++static guint signals[LAST_SIGNAL] = { 0 };
++
++static void
++signal_quality_proxy (DBusGProxy *proxy,
++ guint32 signal_quality,
++ gpointer user_data)
++{
++ NMAGsmModem *modem = NMA_GSM_MODEM (user_data);
++
++ NMA_GSM_MODEM_GET_PRIVATE (modem)->signal_quality = signal_quality;
++
++ g_signal_emit (modem, signals[SIGNAL_QUALITY], 0, signal_quality);
++}
++
++static void
++network_mode_proxy (DBusGProxy *proxy,
++ guint32 network_mode,
++ gpointer user_data)
++{
++ NMAGsmModem *modem = NMA_GSM_MODEM (user_data);
++
++ g_signal_emit (modem, signals[NETWORK_MODE], 0, network_mode);
++}
++
++NMAGsmModem *
++nma_gsm_modem_new (DBusGConnection *bus, const char *object_path)
++{
++ NMAGsmModem *modem;
++ NMAGsmModemPrivate *priv;
++
++ g_return_val_if_fail (bus != NULL, NULL);
++ g_return_val_if_fail (object_path != NULL, NULL);
++
++ modem = (NMAGsmModem *) g_object_new (NMA_TYPE_GSM_MODEM, NULL);
++ if (!modem)
++ return NULL;
++
++ priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
++ priv->proxy = dbus_g_proxy_new_for_name (bus, MM_DBUS_SERVICE, object_path, MM_DBUS_INTERFACE_MODEM_GSM);
++
++ dbus_g_proxy_add_signal (priv->proxy, "SignalQuality", G_TYPE_UINT, G_TYPE_INVALID);
++ dbus_g_proxy_connect_signal (priv->proxy, "SignalQuality",
++ G_CALLBACK (signal_quality_proxy),
++ modem,
++ NULL);
++
++ dbus_g_proxy_add_signal (priv->proxy, "NetworkMode", G_TYPE_UINT, G_TYPE_INVALID);
++ dbus_g_proxy_connect_signal (priv->proxy, "NetworkMode",
++ G_CALLBACK (network_mode_proxy),
++ modem,
++ NULL);
++
++ return modem;
++}
++
++guint32
++nma_gsm_modem_get_signal_quality (NMAGsmModem *modem)
++{
++ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
++ GError *err = NULL;
++
++ g_return_val_if_fail (NMA_IS_GSM_MODEM (modem), 0);
++
++ if (priv->signal_quality == -1) {
++ if (!dbus_g_proxy_call (priv->proxy, "GetSignalQuality", &err,
++ G_TYPE_INVALID,
++ G_TYPE_UINT, &priv->signal_quality,
++ G_TYPE_INVALID)) {
++ g_warning ("Error in getting signal quality: %s", err->message);
++ g_error_free (err);
++ }
++ }
++
++ return priv->signal_quality;
++}
++
++guint32
++nma_gsm_modem_get_registration_info (NMAGsmModem *modem,
++ char **operator_code,
++ char **operator_name)
++{
++ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
++ GError *err = NULL;
++ guint32 status = MM_GSM_MODEM_REG_STATUS_UNKNOWN;
++
++ g_return_val_if_fail (NMA_IS_GSM_MODEM (modem), 0);
++
++ if (!dbus_g_proxy_call (priv->proxy, "GetRegistrationInfo", &err,
++ G_TYPE_INVALID,
++ G_TYPE_UINT, &status,
++ G_TYPE_STRING, operator_code,
++ G_TYPE_STRING, operator_name,
++ G_TYPE_INVALID)) {
++ g_warning ("Error in getting network mode: %s", err->message);
++ g_error_free (err);
++ }
++
++ return status;
++}
++
++guint32
++nma_gsm_modem_get_network_mode (NMAGsmModem *modem)
++{
++ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
++ GError *err = NULL;
++ guint32 network_mode = 0;
++
++ g_return_val_if_fail (NMA_IS_GSM_MODEM (modem), 0);
++
++ if (!dbus_g_proxy_call (priv->proxy, "GetNetworkMode", &err,
++ G_TYPE_INVALID,
++ G_TYPE_UINT, &network_mode,
++ G_TYPE_INVALID)) {
++ g_warning ("Error in getting network mode: %s", err->message);
++ g_error_free (err);
++ }
++
++ return network_mode;
++}
++
++static void
++nma_gsm_modem_init (NMAGsmModem *modem)
++{
++ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (modem);
++
++ priv->signal_quality = -1;
++}
++
++static void
++dispose (GObject *object)
++{
++ NMAGsmModemPrivate *priv = NMA_GSM_MODEM_GET_PRIVATE (object);
++
++ if (priv->disposed)
++ return;
++
++ priv->disposed = TRUE;
++
++ if (priv->proxy)
++ g_object_unref (priv->proxy);
++
++ G_OBJECT_CLASS (nma_gsm_modem_parent_class)->dispose (object);
++}
++
++static void
++nma_gsm_modem_class_init (NMAGsmModemClass *modem_class)
++{
++ GObjectClass *object_class = G_OBJECT_CLASS (modem_class);
++
++ g_type_class_add_private (modem_class, sizeof (NMAGsmModemPrivate));
++
++ /* virtual methods */
++ object_class->dispose = dispose;
++
++ /* Signals */
++ signals[SIGNAL_QUALITY] =
++ g_signal_new ("signal-quality",
++ G_OBJECT_CLASS_TYPE (object_class),
++ G_SIGNAL_RUN_FIRST,
++ G_STRUCT_OFFSET (NMAGsmModemClass, signal_quality),
++ NULL, NULL,
++ g_cclosure_marshal_VOID__UINT,
++ G_TYPE_NONE, 1,
++ G_TYPE_UINT);
++
++ signals[NETWORK_MODE] =
++ g_signal_new ("network-mode",
++ G_OBJECT_CLASS_TYPE (object_class),
++ G_SIGNAL_RUN_FIRST,
++ G_STRUCT_OFFSET (NMAGsmModemClass, network_mode),
++ NULL, NULL,
++ g_cclosure_marshal_VOID__UINT,
++ G_TYPE_NONE, 1,
++ G_TYPE_UINT);
++}
+diff --git a/src/nma-gsm-modem.h b/src/nma-gsm-modem.h
+new file mode 100644
+index 0000000..90e7ae0
+--- /dev/null
++++ b/src/nma-gsm-modem.h
+@@ -0,0 +1,45 @@
++/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
++
++#ifndef NMA_GSM_MODEM_H
++#define NMA_GSM_MODEM_H
++
++#include <glib/gtypes.h>
++#include <glib-object.h>
++#include <dbus/dbus-glib.h>
++
++G_BEGIN_DECLS
++
++#define NMA_TYPE_GSM_MODEM (nma_gsm_modem_get_type ())
++#define NMA_GSM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMA_TYPE_GSM_MODEM, NMAGsmModem))
++#define NMA_GSM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMA_TYPE_GSM_MODEM, NMAGsmModemClass))
++#define NMA_IS_GSM_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMA_TYPE_GSM_MODEM))
++#define NMA_IS_GSM_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NMA_TYPE_GSM_MODEM))
++#define NMA_GSM_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMA_TYPE_GSM_MODEM, NMAGsmModemClass))
++
++typedef struct {
++ GObject parent;
++} NMAGsmModem;
++
++typedef struct {
++ GObjectClass parent;
++
++ /* Signals */
++ void (*signal_quality) (NMAGsmModem *modem, guint32 signal_quality);
++ void (*network_mode) (NMAGsmModem *modem, guint32 network_mode);
++} NMAGsmModemClass;
++
++GType nma_gsm_modem_get_type (void);
++
++NMAGsmModem *nma_gsm_modem_new (DBusGConnection *bus,
++ const char *object_path);
++
++guint32 nma_gsm_modem_get_signal_quality (NMAGsmModem *modem);
++guint32 nma_gsm_modem_get_registration_info (NMAGsmModem *modem,
++ char **operator_code,
++ char **operator_name);
++
++guint32 nma_gsm_modem_get_network_mode (NMAGsmModem *modem);
++
++G_END_DECLS
++
++#endif /* NMA_GSM_MODEM_H */