[network-manager-applet/btdun] bluetooth: support DUN in the gnome-bluetooth wizard
- From: Dan Williams <dcbw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [network-manager-applet/btdun] bluetooth: support DUN in the gnome-bluetooth wizard
- Date: Sat, 3 Oct 2009 08:02:13 +0000 (UTC)
commit c1c13b9dff6772bf13ab6217a2eecb986bd67687
Author: Dan Williams <dcbw redhat com>
Date: Sat Oct 3 01:01:12 2009 -0700
bluetooth: support DUN in the gnome-bluetooth wizard
PAN is preferred, but if the phone doesn't support PAN, do DUN.
src/gnome-bluetooth/Makefile.am | 18 +-
src/gnome-bluetooth/network-manager-applet.c | 798 ++++++++++++++++++++++++--
src/marshallers/nma-marshal.list | 1 +
3 files changed, 777 insertions(+), 40 deletions(-)
---
diff --git a/src/gnome-bluetooth/Makefile.am b/src/gnome-bluetooth/Makefile.am
index 8f20b1f..f430c2f 100644
--- a/src/gnome-bluetooth/Makefile.am
+++ b/src/gnome-bluetooth/Makefile.am
@@ -6,15 +6,27 @@ INCLUDES = \
-DLOCALEDIR="\"$(datadir)/locale\"" \
-I$(top_srcdir)/src/gconf-helpers/ \
-I$(top_builddir) \
+ -I${top_builddir}/src/marshallers \
+ -I${top_srcdir}/src/utils \
$(GNOME_BLUETOOTH_CFLAGS) \
$(WARN_CFLAGS)
if HAVE_GBT
plugin_LTLIBRARIES = libnma.la
-libnma_la_SOURCES = network-manager-applet.c
+libnma_la_SOURCES = \
+ network-manager-applet.c \
+ bling-spinner.c \
+ bling-spinner.h
+
libnma_la_LDFLAGS = -module -avoid-version
-libnma_la_LIBADD = $(top_builddir)/src/gconf-helpers/libgconf-helpers.la $(GNOME_BLUETOOTH_LIBS)
+
+libnma_la_LIBADD = \
+ $(top_builddir)/src/gconf-helpers/libgconf-helpers.la \
+ $(GNOME_BLUETOOTH_LIBS)
endif
-EXTRA_DIST = network-manager-applet.c
+EXTRA_DIST = \
+ network-manager-applet.c \
+ bling-spinner.c \
+ bling-spinner.h
diff --git a/src/gnome-bluetooth/network-manager-applet.c b/src/gnome-bluetooth/network-manager-applet.c
index 0b8ac47..4df2603 100644
--- a/src/gnome-bluetooth/network-manager-applet.c
+++ b/src/gnome-bluetooth/network-manager-applet.c
@@ -35,20 +35,95 @@
#include <nm-setting-connection.h>
#include <nm-setting-bluetooth.h>
#include <nm-setting-ip4-config.h>
+#include <nm-setting-cdma.h>
+#include <nm-setting-gsm.h>
+#include <nm-setting-serial.h>
+#include <nm-setting-ppp.h>
#include <nm-utils.h>
#include <nma-gconf-settings.h>
-static gboolean
-has_config_widget (const char *bdaddr, const char **uuids)
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "nma-marshal.h"
+#include "bling-spinner.h"
+#include "mobile-wizard.h"
+
+#define DBUS_TYPE_G_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
+
+#define BLUEZ_SERVICE "org.bluez"
+#define BLUEZ_MANAGER_PATH "/"
+#define BLUEZ_MANAGER_INTERFACE "org.bluez.Manager"
+#define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter"
+#define BLUEZ_DEVICE_INTERFACE "org.bluez.Device"
+#define BLUEZ_SERIAL_INTERFACE "org.bluez.Serial"
+#define BLUEZ_NETWORK_INTERFACE "org.bluez.Network"
+
+#define MM_SERVICE "org.freedesktop.ModemManager"
+#define MM_PATH "/org/freedesktop/ModemManager"
+#define MM_INTERFACE "org.freedesktop.ModemManager"
+#define MM_MODEM_INTERFACE "org.freedesktop.ModemManager.Modem"
+
+typedef enum {
+ BT_METHOD_UNKNOWN = 0,
+ BT_METHOD_PAN = 1,
+ BT_METHOD_DUN = 2
+} BtMethod;
+
+typedef struct {
+ char *bdaddr;
+ BtMethod method;
+ GtkWidget *button;
+ guint toggled_id;
+
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *spinner;
+ NMSettingsConnectionInterface *connection;
+
+ /* DUN stuff */
+ DBusGConnection *bus;
+ DBusGProxy *bluez_proxy;
+ DBusGProxy *adapter_proxy;
+ DBusGProxy *dun_proxy;
+
+ DBusGProxy *mm_proxy;
+ GSList *modem_proxies;
+
+ char *rfcomm_iface;
+ guint dun_timeout_id;
+
+ NMDeviceType devtype;
+
+ MobileWizard *wizard;
+ GtkWindowGroup *window_group;
+} PluginInfo;
+
+static BtMethod
+get_best_method (const char *bdaddr, const char **uuids)
{
guint i;
+ gboolean has_nap = FALSE, has_dun = FALSE;
for (i = 0; uuids && uuids[i] != NULL; i++) {
g_message ("has_config_widget %s %s", bdaddr, uuids[i]);
if (g_str_equal (uuids[i], "NAP"))
- return TRUE;
+ has_nap = TRUE;
+ if (g_str_equal (uuids[i], "DialupNetworking"))
+ has_dun = TRUE;
}
- return FALSE;
+
+ if (has_nap)
+ return BT_METHOD_PAN;
+ else if (has_dun)
+ return BT_METHOD_DUN;
+ return BT_METHOD_UNKNOWN;
+}
+
+static gboolean
+has_config_widget (const char *bdaddr, const char **uuids)
+{
+ return !!get_best_method (bdaddr, uuids);
}
static GByteArray *
@@ -67,8 +142,10 @@ get_array_from_bdaddr (const char *str)
return NULL;
}
+/*******************************************************************/
+
static NMSettingsConnectionInterface *
-add_setup (const char *bdaddr)
+add_pan_connection (const char *bdaddr)
{
NMConnection *connection;
NMSetting *setting, *bt_setting, *ip_setting;
@@ -122,37 +199,639 @@ add_setup (const char *bdaddr)
return NULL;
}
+/*******************************************************************/
+
+static void
+dun_cleanup (PluginInfo *info, const char *message, gboolean uncheck)
+{
+ GSList *iter;
+
+ for (iter = info->modem_proxies; iter; iter = g_slist_next (iter))
+ g_object_unref (DBUS_G_PROXY (iter->data));
+ g_slist_free (info->modem_proxies);
+ info->modem_proxies = NULL;
+
+ if (info->dun_proxy) {
+ if (info->rfcomm_iface) {
+ dbus_g_proxy_call_no_reply (info->dun_proxy, "Disconnect",
+ G_TYPE_STRING, info->rfcomm_iface,
+ G_TYPE_INVALID);
+ }
+
+ g_object_unref (info->dun_proxy);
+ info->dun_proxy = NULL;
+ }
+
+ g_free (info->rfcomm_iface);
+ info->rfcomm_iface = NULL;
+
+ if (info->adapter_proxy) {
+ g_object_unref (info->adapter_proxy);
+ info->adapter_proxy = NULL;
+ }
+
+ if (info->bluez_proxy) {
+ g_object_unref (info->bluez_proxy);
+ info->bluez_proxy = NULL;
+ }
+
+ if (info->bus) {
+ dbus_g_connection_unref (info->bus);
+ info->bus = NULL;
+ }
+
+ if (info->dun_timeout_id) {
+ g_source_remove (info->dun_timeout_id);
+ info->dun_timeout_id = 0;
+ }
+
+ if (info->window_group) {
+ g_object_unref (info->window_group);
+ info->window_group = NULL;
+ }
+
+ if (info->wizard) {
+ mobile_wizard_destroy (info->wizard);
+ info->wizard = NULL;
+ }
+
+ info->devtype = NM_DEVICE_TYPE_UNKNOWN;
+
+ if (info->spinner) {
+ bling_spinner_stop (BLING_SPINNER (info->spinner));
+ gtk_widget_hide (info->spinner);
+ }
+ gtk_label_set_text (GTK_LABEL (info->label), message);
+ gtk_widget_set_sensitive (info->button, TRUE);
+
+ if (uncheck) {
+ g_signal_handler_block (info->button, info->toggled_id);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (info->button), FALSE);
+ g_signal_handler_unblock (info->button, info->toggled_id);
+ }
+}
+
+static void
+dun_error (PluginInfo *info, const char *func, GError *error, const char *fallback)
+{
+ char *message;
+
+ message = g_strdup_printf (_("Error: %s"), (error && error->message) ? error->message : fallback);
+ g_warning ("%s: %s", func, message);
+ dun_cleanup (info, message, TRUE);
+ g_free (message);
+}
+
+static NMConnection *
+dun_new_cdma (MobileWizardAccessMethod *method)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+ char *uuid, *id;
+
+ connection = nm_connection_new ();
+
+ setting = nm_setting_cdma_new ();
+ g_object_set (setting,
+ NM_SETTING_CDMA_NUMBER, "#777",
+ NM_SETTING_CDMA_USERNAME, method->username,
+ NM_SETTING_CDMA_PASSWORD, method->password,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ /* Serial setting */
+ setting = nm_setting_serial_new ();
+ g_object_set (setting,
+ NM_SETTING_SERIAL_BAUD, 115200,
+ NM_SETTING_SERIAL_BITS, 8,
+ NM_SETTING_SERIAL_PARITY, 'n',
+ NM_SETTING_SERIAL_STOPBITS, 1,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ nm_connection_add_setting (connection, nm_setting_ppp_new ());
+
+ setting = nm_setting_connection_new ();
+ if (method->plan_name)
+ id = g_strdup_printf ("%s %s", method->provider_name, method->plan_name);
+ else
+ id = g_strdup_printf ("%s connection", method->provider_name);
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_ID, id,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_CDMA_SETTING_NAME,
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NULL);
+ g_free (uuid);
+ g_free (id);
+ nm_connection_add_setting (connection, setting);
+
+ return connection;
+}
+
+static NMConnection *
+dun_new_gsm (MobileWizardAccessMethod *method)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+ char *uuid, *id;
+
+ connection = nm_connection_new ();
+
+ setting = nm_setting_gsm_new ();
+ g_object_set (setting,
+ NM_SETTING_GSM_NUMBER, "*99#",
+ NM_SETTING_GSM_USERNAME, method->username,
+ NM_SETTING_GSM_PASSWORD, method->password,
+ NM_SETTING_GSM_APN, method->gsm_apn,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ /* Serial setting */
+ setting = nm_setting_serial_new ();
+ g_object_set (setting,
+ NM_SETTING_SERIAL_BAUD, 115200,
+ NM_SETTING_SERIAL_BITS, 8,
+ NM_SETTING_SERIAL_PARITY, 'n',
+ NM_SETTING_SERIAL_STOPBITS, 1,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ nm_connection_add_setting (connection, nm_setting_ppp_new ());
+
+ setting = nm_setting_connection_new ();
+ if (method->plan_name)
+ id = g_strdup_printf ("%s %s", method->provider_name, method->plan_name);
+ else
+ id = g_strdup_printf ("%s connection", method->provider_name);
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_ID, id,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_GSM_SETTING_NAME,
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NULL);
+ g_free (uuid);
+ g_free (id);
+ nm_connection_add_setting (connection, setting);
+
+ return connection;
+}
+
+static void
+wizard_done_cb (MobileWizard *self,
+ gboolean canceled,
+ MobileWizardAccessMethod *method,
+ gpointer user_data)
+{
+ PluginInfo *info = user_data;
+ NMConnection *connection = NULL;
+ NMAGConfSettings *gconf_settings;
+ NMAGConfConnection *exported;
+ GByteArray *mac;
+ NMSetting *s_bt;
+
+ g_message ("%s: mobile wizard done", __func__);
+
+ if (canceled || !method) {
+ dun_error (info, __func__, NULL, _("Mobile wizard was canceled"));
+ return;
+ }
+
+ if (method->devtype == NM_DEVICE_TYPE_CDMA)
+ connection = dun_new_cdma (method);
+ else if (method->devtype == NM_DEVICE_TYPE_GSM)
+ connection = dun_new_gsm (method);
+ else {
+ dun_error (info, __func__, NULL, _("Unknown phone device type (not GSM or CDMA)"));
+ return;
+ }
+
+ mobile_wizard_destroy (info->wizard);
+ info->wizard = NULL;
+
+ g_assert (connection);
+
+ /* The Bluetooth settings */
+ mac = get_array_from_bdaddr (info->bdaddr);
+ g_assert (mac);
+ s_bt = nm_setting_bluetooth_new ();
+ g_object_set (G_OBJECT (s_bt),
+ NM_SETTING_BLUETOOTH_BDADDR, mac,
+ NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_DUN,
+ NULL);
+ g_byte_array_free (mac, TRUE);
+ nm_connection_add_setting (connection, s_bt);
+
+ g_message ("%s: adding new setting to GConf", __func__);
+
+ gconf_settings = nma_gconf_settings_new (NULL);
+ exported = nma_gconf_settings_add_connection (gconf_settings, connection);
+ if (exported)
+ info->connection = NM_SETTINGS_CONNECTION_INTERFACE (exported);
+
+ g_message ("%s: success!", __func__);
+ dun_cleanup (info, _("Your phone is now ready to use!"), FALSE);
+}
+
+static void
+modem_get_all_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+ PluginInfo *info = user_data;
+ const char *path;
+ GHashTable *properties = NULL;
+ GError *error = NULL;
+ GValue *value;
+
+ path = dbus_g_proxy_get_path (proxy);
+ g_message ("%s: (%s) processing GetAll reply", __func__, path);
+
+ if (!dbus_g_proxy_end_call (proxy, call, &error,
+ DBUS_TYPE_G_MAP_OF_VARIANT, &properties,
+ G_TYPE_INVALID)) {
+ g_warning ("%s: (%s) Error getting modem properties: (%d) %s",
+ __func__,
+ path,
+ error ? error->code : -1,
+ (error && error->message) ? error->message : "(unknown)");
+ g_error_free (error);
+ goto out;
+ }
+
+ /* check whether this is the device we care about */
+ value = g_hash_table_lookup (properties, "Device");
+ if (value && G_VALUE_HOLDS_STRING (value) && g_value_get_string (value)) {
+ char *basename = g_path_get_basename (info->rfcomm_iface);
+ const char *modem_iface = g_value_get_string (value);
+
+ if (!strcmp (basename, modem_iface)) {
+ /* yay, found it! */
+
+ value = g_hash_table_lookup (properties, "Type");
+ if (value && G_VALUE_HOLDS_UINT (value)) {
+ switch (g_value_get_uint (value)) {
+ case 1:
+ info->devtype = NM_DEVICE_TYPE_GSM;
+ break;
+ case 2:
+ info->devtype = NM_DEVICE_TYPE_CDMA;
+ break;
+ default:
+ g_message ("%s: (%s) unknown modem type", __func__, path);
+ break;
+ }
+ }
+ } else {
+ g_message ("%s: (%s) (%s) not the modem we're looking for (%s)",
+ __func__,
+ path,
+ modem_iface,
+ basename);
+ }
+
+ g_free (basename);
+ } else
+ g_message ("%s: (%s) modem had no 'Device' property", __func__, path);
+
+ g_hash_table_unref (properties);
+
+ if (info->devtype != NM_DEVICE_TYPE_UNKNOWN) {
+ GtkWidget *parent;
+
+ g_message ("%s: (%s) starting the mobile wizard", __func__, path);
+
+ g_source_remove (info->dun_timeout_id);
+ info->dun_timeout_id = 0;
+
+ parent = gtk_widget_get_toplevel (info->hbox);
+ if (GTK_WIDGET_TOPLEVEL (parent)) {
+ info->window_group = gtk_window_group_new ();
+ gtk_window_group_add_window (info->window_group, GTK_WINDOW (parent));
+ } else {
+ parent = NULL;
+ info->window_group = NULL;
+ }
+
+ /* Start the mobile wizard */
+ info->wizard = mobile_wizard_new (parent ? GTK_WINDOW (parent) : NULL,
+ info->window_group,
+ info->devtype,
+ FALSE,
+ wizard_done_cb,
+ info);
+ mobile_wizard_present (info->wizard);
+ }
+
+out:
+ g_message ("%s: finished", __func__);
+}
+
+static void
+modem_added (DBusGProxy *proxy, const char *path, gpointer user_data)
+{
+ PluginInfo *info = user_data;
+ DBusGProxy *props_proxy;
+
+ g_return_if_fail (path != NULL);
+
+ g_message ("%s: (%s) modem found", __func__, path);
+
+ /* Create a proxy for the modem and get its properties */
+ props_proxy = dbus_g_proxy_new_for_name (info->bus,
+ MM_SERVICE,
+ path,
+ "org.freedesktop.DBus.Properties");
+ g_assert (proxy);
+ info->modem_proxies = g_slist_append (info->modem_proxies, props_proxy);
+
+ g_message ("%s: (%s) calling GetAll...", __func__, path);
+
+ dbus_g_proxy_begin_call (props_proxy, "GetAll",
+ modem_get_all_cb,
+ info,
+ NULL,
+ G_TYPE_STRING, MM_MODEM_INTERFACE,
+ G_TYPE_INVALID);
+}
+
+static void
+modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data)
+{
+ PluginInfo *info = user_data;
+ GSList *iter;
+ DBusGProxy *found = NULL;
+
+ g_return_if_fail (path != NULL);
+
+ g_message ("%s: (%s) modem removed", __func__, path);
+
+ /* Clean up if a modem gets removed */
+
+ for (iter = info->modem_proxies; iter; iter = g_slist_next (iter)) {
+ if (!strcmp (path, dbus_g_proxy_get_path (DBUS_G_PROXY (iter->data)))) {
+ found = iter->data;
+ break;
+ }
+ }
+
+ if (found) {
+ info->modem_proxies = g_slist_remove (info->modem_proxies, found);
+ g_object_unref (found);
+ }
+}
+
+static void
+dun_connect_cb (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ void *user_data)
+{
+ PluginInfo *info = user_data;
+ GError *error = NULL;
+ char *device;
+
+ g_message ("%s: processing Connect reply", __func__);
+
+ if (!dbus_g_proxy_end_call (proxy, call, &error,
+ G_TYPE_STRING, &device,
+ G_TYPE_INVALID)) {
+ dun_error (info, __func__, error, _("failed to connect to the phone."));
+ g_clear_error (&error);
+ goto out;
+ }
+
+ if (!device || !strlen (device)) {
+ dun_error (info, __func__, NULL, _("failed to connect to the phone."));
+ g_free (device);
+ goto out;
+ }
+
+ info->rfcomm_iface = device;
+ g_message ("%s: new rfcomm interface '%s'", __func__, device);
+
+out:
+ g_message ("%s: finished", __func__);
+}
+
+static void
+dun_property_changed (DBusGProxy *proxy,
+ const char *property,
+ GValue *value,
+ gpointer user_data)
+{
+ PluginInfo *info = user_data;
+ gboolean connected;
+
+ if (strcmp (property, "Connected"))
+ return;
+
+ connected = g_value_get_boolean (value);
+
+ g_message ("%s: device property Connected changed to %s",
+ __func__,
+ connected ? "TRUE" : "FALSE");
+
+ if (connected) {
+ /* Wait for MM here ? */
+ } else
+ dun_error (info, __func__, NULL, _("unexpectedly disconnected from the phone."));
+}
+
+static void
+find_device_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+ PluginInfo *info = user_data;
+ char *dev_path = NULL;
+ GError *error = NULL;
+
+ g_message ("%s: processing FindDevice reply", __func__);
+
+ if (!dbus_g_proxy_end_call (proxy, call, &error,
+ DBUS_TYPE_G_OBJECT_PATH, &dev_path,
+ G_TYPE_INVALID)) {
+ dun_error (info, __func__, error, _("failed to discover the phone."));
+ g_error_free (error);
+ goto out;
+ }
+
+
+ /* Request a connection to the device and get the port */
+ info->dun_proxy = dbus_g_proxy_new_for_name (info->bus,
+ BLUEZ_SERVICE,
+ dev_path,
+ BLUEZ_SERIAL_INTERFACE);
+ g_assert (info->dun_proxy);
+
+ g_message ("%s: calling Connect...", __func__);
+
+ dbus_g_proxy_begin_call_with_timeout (info->dun_proxy, "Connect",
+ dun_connect_cb,
+ info,
+ NULL,
+ 20000,
+ G_TYPE_STRING, "dun",
+ G_TYPE_INVALID);
+
+ /* Watch for BT device property changes */
+ dbus_g_object_register_marshaller (nma_marshal_VOID__STRING_BOXED,
+ G_TYPE_NONE,
+ G_TYPE_STRING, G_TYPE_VALUE,
+ G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (info->dun_proxy, "PropertyChanged",
+ G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (info->dun_proxy, "PropertyChanged",
+ G_CALLBACK (dun_property_changed), info, NULL);
+
+out:
+ g_message ("%s: finished", __func__);
+}
+
+static void
+default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+ PluginInfo *info = user_data;
+ const char *default_adapter = NULL;
+ GError *error = NULL;
+
+ g_message ("%s: processing DefaultAdapter reply", __func__);
+
+ if (!dbus_g_proxy_end_call (proxy, call, &error,
+ DBUS_TYPE_G_OBJECT_PATH, &default_adapter,
+ G_TYPE_INVALID)) {
+ dun_error (info, __func__, error, _("could not discover Bluetooth adapter."));
+ g_error_free (error);
+ goto out;
+ }
+
+ info->adapter_proxy = dbus_g_proxy_new_for_name (info->bus,
+ BLUEZ_SERVICE,
+ default_adapter,
+ BLUEZ_ADAPTER_INTERFACE);
+ g_assert (info->adapter_proxy);
+
+ g_message ("%s: calling FindDevice...", __func__);
+
+ dbus_g_proxy_begin_call (info->adapter_proxy, "FindDevice",
+ find_device_cb,
+ info, NULL,
+ G_TYPE_STRING, info->bdaddr,
+ G_TYPE_INVALID);
+
+out:
+ g_message ("%s: finished", __func__);
+}
+
+static gboolean
+dun_timeout_cb (gpointer user_data)
+{
+ PluginInfo *info = user_data;
+
+ info->dun_timeout_id = 0;
+ dun_error (info, __func__, NULL, _("timed out detecting phone details."));
+ return FALSE;
+}
+
+static void
+dun_start (PluginInfo *info)
+{
+ GError *error = NULL;
+
+ g_message ("%s: starting DUN device discovery...", __func__);
+
+ /* Set up dbus */
+ info->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (error || !info->bus) {
+ dun_error (info, __func__, error, _("could not connect to the system bus."));
+ g_clear_error (&error);
+ goto out;
+ }
+
+ gtk_label_set_text (GTK_LABEL (info->label), _("Detecting phone configuration..."));
+
+ /* Start the spinner */
+ if (!info->spinner) {
+ info->spinner = bling_spinner_new ();
+ gtk_box_pack_start (GTK_BOX (info->hbox), info->spinner, FALSE, FALSE, 6);
+ }
+ bling_spinner_start (BLING_SPINNER (info->spinner));
+ gtk_widget_show_all (info->hbox);
+
+ gtk_widget_set_sensitive (info->button, FALSE);
+
+ /* ModemManager stuff */
+ info->mm_proxy = dbus_g_proxy_new_for_name (info->bus,
+ MM_SERVICE,
+ MM_PATH,
+ MM_INTERFACE);
+ g_assert (info->mm_proxy);
+
+ dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE,
+ G_TYPE_BOXED,
+ G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (info->mm_proxy, "DeviceAdded",
+ DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (info->mm_proxy, "DeviceAdded",
+ G_CALLBACK (modem_added), info,
+ NULL);
+
+ dbus_g_proxy_add_signal (info->mm_proxy, "DeviceRemoved",
+ DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (info->mm_proxy, "DeviceRemoved",
+ G_CALLBACK (modem_removed), info,
+ NULL);
+
+ /* Bluez stuff */
+ info->bluez_proxy = dbus_g_proxy_new_for_name (info->bus,
+ BLUEZ_SERVICE,
+ BLUEZ_MANAGER_PATH,
+ BLUEZ_MANAGER_INTERFACE);
+ g_assert (info->bluez_proxy);
+
+ g_message ("%s: calling DefaultAdapter...", __func__);
+ dbus_g_proxy_begin_call (info->bluez_proxy, "DefaultAdapter",
+ default_adapter_cb,
+ info,
+ NULL, G_TYPE_INVALID);
+
+ info->dun_timeout_id = g_timeout_add_seconds (30, dun_timeout_cb, info);
+
+out:
+ g_message ("%s: finished", __func__);
+}
+
+/*******************************************************************/
+
static void
delete_cb (NMSettingsConnectionInterface *connection,
GError *error,
gpointer user_data)
{
- if (error)
- g_warning ("Error deleting connection: (%d) %s", error->code, error->message);
- if (user_data)
- g_object_set_data (G_OBJECT (user_data), "conn", NULL);
+ if (error) {
+ g_warning ("Error deleting connection: (%d) %s",
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ }
}
static void
button_toggled (GtkToggleButton *button, gpointer user_data)
{
- NMSettingsConnectionInterface *connection;
- const char *bdaddr;
-
- bdaddr = g_object_get_data (G_OBJECT (button), "bdaddr");
- g_assert (bdaddr);
+ PluginInfo *info = user_data;
if (gtk_toggle_button_get_active (button) == FALSE) {
- connection = g_object_get_data (G_OBJECT (button), "conn");
- nm_settings_connection_interface_delete (connection, delete_cb, button);
+ nm_settings_connection_interface_delete (info->connection, delete_cb, NULL);
+ info->connection = NULL;
} else {
- connection = add_setup (bdaddr);
- g_object_set_data (G_OBJECT (button), "conn", connection);
+ if (info->method == BT_METHOD_PAN)
+ info->connection = add_pan_connection (info->bdaddr);
+ else if (info->method == BT_METHOD_DUN)
+ dun_start (info);
}
}
static NMSettingsConnectionInterface *
-get_connection_for_bdaddr (const char *bdaddr)
+get_connection_for_bdaddr (const char *bdaddr, BtMethod method)
{
NMSettingsConnectionInterface *found = NULL;
NMSettingsInterface *settings;
@@ -174,9 +853,16 @@ get_connection_for_bdaddr (const char *bdaddr)
setting = nm_connection_get_setting_by_name (NM_CONNECTION (candidate), NM_SETTING_BLUETOOTH_SETTING_NAME);
if (setting == NULL)
continue;
+
type = nm_setting_bluetooth_get_connection_type (NM_SETTING_BLUETOOTH (setting));
- if (g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_PANU) != 0)
- continue;
+ if (method == BT_METHOD_PAN) {
+ if (g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_PANU) != 0)
+ continue;
+ } else if (method == BT_METHOD_DUN) {
+ if (g_strcmp0 (type, NM_SETTING_BLUETOOTH_TYPE_DUN) != 0)
+ continue;
+ }
+
addr = nm_setting_bluetooth_get_bdaddr (NM_SETTING_BLUETOOTH (setting));
if (addr == NULL || memcmp (addr->data, array->data, addr->len) != 0)
continue;
@@ -185,27 +871,63 @@ get_connection_for_bdaddr (const char *bdaddr)
}
g_slist_free (list);
+ // FIXME: we intentionally don't free 'settings' here because that does bad things
return found;
}
+static void
+plugin_info_destroy (gpointer data)
+{
+ PluginInfo *info = data;
+
+ g_free (info->bdaddr);
+ g_free (info->rfcomm_iface);
+ if (info->connection)
+ g_object_unref (info->connection);
+ if (info->spinner)
+ bling_spinner_stop (BLING_SPINNER (info->spinner));
+ memset (info, 0, sizeof (PluginInfo));
+ g_free (info);
+}
+
static GtkWidget *
get_config_widgets (const char *bdaddr, const char **uuids)
{
- GtkWidget *button;
- NMSettingsConnectionInterface *connection;
+ PluginInfo *info;
+ GtkWidget *vbox, *hbox;
+ BtMethod method;
- button = gtk_check_button_new_with_label (_("Access the Internet using your mobile phone"));
- g_object_set_data_full (G_OBJECT (button),
- "bdaddr", g_strdup (bdaddr),
- (GDestroyNotify) g_free);
- connection = get_connection_for_bdaddr (bdaddr);
- if (connection != NULL) {
- g_object_set_data (G_OBJECT (button), "conn", connection);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
- }
- g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (button_toggled), NULL);
+ method = get_best_method (bdaddr, uuids);
+ if (method == BT_METHOD_UNKNOWN)
+ return NULL;
+
+ info = g_malloc0 (sizeof (PluginInfo));
+ info->bdaddr = g_strdup (bdaddr);
+ info->method = method;
+ info->connection = get_connection_for_bdaddr (bdaddr, method);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ g_object_set_data_full (G_OBJECT (vbox), "info", info, plugin_info_destroy);
+
+ info->button = gtk_check_button_new_with_label (_("Access the Internet using your mobile phone"));
+ if (info->connection)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (info->button), TRUE);
+
+ info->toggled_id = g_signal_connect (G_OBJECT (info->button), "toggled", G_CALLBACK (button_toggled), info);
+
+ gtk_box_pack_start (GTK_BOX (vbox), info->button, FALSE, TRUE, 6);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 6);
+
+ /* Spinner's hbox */
+ info->hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), info->hbox, FALSE, FALSE, 0);
+
+ info->label = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (hbox), info->label, FALSE, TRUE, 6);
- return button;
+ return vbox;
}
static void
@@ -217,9 +939,11 @@ device_removed (const char *bdaddr)
// FIXME: don't just delete any random PAN conenction for this
// bdaddr, actually delete the one this plugin created
- connection = get_connection_for_bdaddr (bdaddr);
- if (connection)
- nm_settings_connection_interface_delete (connection, delete_cb, NULL);
+ do {
+ connection = get_connection_for_bdaddr (bdaddr, BT_METHOD_UNKNOWN);
+ if (connection)
+ nm_settings_connection_interface_delete (connection, delete_cb, NULL);
+ } while (connection);
}
static GbtPluginInfo plugin_info = {
diff --git a/src/marshallers/nma-marshal.list b/src/marshallers/nma-marshal.list
index 4cf3524..60b47ca 100644
--- a/src/marshallers/nma-marshal.list
+++ b/src/marshallers/nma-marshal.list
@@ -4,4 +4,5 @@ VOID:STRING,POINTER,BOOLEAN,POINTER,POINTER
VOID:OBJECT,STRING,POINTER,BOOLEAN,POINTER,POINTER
VOID:POINTER,POINTER
VOID:INT,POINTER
+VOID:STRING,BOXED
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]