This `MMManager' object takes care of notifying modems added or removed from the
ModemManager1 interface.
---
 src/Makefile.am       |   8 ++
 src/nm-device-bt.c    |  49 ++++++++++---
 src/nm-device-bt.h    |   1 +
 src/nm-device-modem.c |  15 +++-
 src/nm-manager.c      | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 260 insertions(+), 12 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index ba7d2d6..286e91d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -311,6 +311,10 @@ if WITH_CONCHECK
 NetworkManager_CPPFLAGS += $(LIBSOUP_CFLAGS)
 endif
 
+if WITH_MODEM_MANAGER_1
+NetworkManager_CPPFLAGS += $(MM_GLIB_CFLAGS)
+endif
+
 NetworkManager_LDADD = \
        ./generated/libnm-generated.la \
        ./logging/libnm-logging.la \
@@ -342,6 +346,10 @@ if WITH_CONCHECK
 NetworkManager_LDADD += $(LIBSOUP_LIBS)
 endif
 
+if WITH_MODEM_MANAGER_1
+NetworkManager_LDADD += $(MM_GLIB_LIBS)
+endif
+
 NetworkManager_LDFLAGS = -rdynamic
 
 libexec_PROGRAMS = nm-crash-logger
diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c
index d59f345..8dce2f9 100644
--- a/src/nm-device-bt.c
+++ b/src/nm-device-bt.c
@@ -681,22 +681,14 @@ nm_device_bt_modem_added (NMDeviceBt *self,
        return TRUE;
 }
 
-gboolean
-nm_device_bt_modem_removed (NMDeviceBt *self, NMModem *modem)
+static void
+remove_modem (NMDeviceBt *self)
 {
-       NMDeviceBtPrivate *priv;
        NMDeviceState state;
-
-       g_return_val_if_fail (self != NULL, FALSE);
-       g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE);
-       g_return_val_if_fail (modem != NULL, FALSE);
-       g_return_val_if_fail (NM_IS_MODEM (modem), FALSE);
+       NMDeviceBtPrivate *priv;
 
        priv = NM_DEVICE_BT_GET_PRIVATE (self);
 
-       if (modem != priv->modem)
-               return FALSE;
-
        /* Fail the device if the modem was removed while active */
        state = nm_device_get_state (NM_DEVICE (self));
        if (   state == NM_DEVICE_STATE_ACTIVATED
@@ -708,7 +700,42 @@ nm_device_bt_modem_removed (NMDeviceBt *self, NMModem 
*modem)
                g_object_unref (priv->modem);
                priv->modem = NULL;
        }
+}
+
+gboolean
+nm_device_bt_modem_removed_by_path (NMDeviceBt *self, const gchar *path)
+{
+       NMDeviceBtPrivate *priv;
+
+       g_return_val_if_fail (self != NULL, FALSE);
+       g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE);
+       g_return_val_if_fail (path != NULL, FALSE);
+
+       priv = NM_DEVICE_BT_GET_PRIVATE (self);
+
+       if (!g_str_equal (nm_modem_get_path (priv->modem), path))
+               return FALSE;
+
+       remove_modem (self);
+       return TRUE;
+}
+
+gboolean
+nm_device_bt_modem_removed (NMDeviceBt *self, NMModem *modem)
+{
+       NMDeviceBtPrivate *priv;
+
+       g_return_val_if_fail (self != NULL, FALSE);
+       g_return_val_if_fail (NM_IS_DEVICE_BT (self), FALSE);
+       g_return_val_if_fail (modem != NULL, FALSE);
+       g_return_val_if_fail (NM_IS_MODEM (modem), FALSE);
+
+       priv = NM_DEVICE_BT_GET_PRIVATE (self);
+
+       if (modem != priv->modem)
+               return FALSE;
 
+       remove_modem (self);
        return TRUE;
 }
 
diff --git a/src/nm-device-bt.h b/src/nm-device-bt.h
index 0d54d60..be32dad 100644
--- a/src/nm-device-bt.h
+++ b/src/nm-device-bt.h
@@ -72,6 +72,7 @@ gboolean nm_device_bt_modem_added (NMDeviceBt *device,
                                    const char *driver);
 
 gboolean nm_device_bt_modem_removed (NMDeviceBt *device, NMModem *modem);
+gboolean nm_device_bt_modem_removed_by_path (NMDeviceBt *device, const gchar 
*path);
 
 G_END_DECLS
 
diff --git a/src/nm-device-modem.c b/src/nm-device-modem.c
index 8f94491..02c9a4a 100644
--- a/src/nm-device-modem.c
+++ b/src/nm-device-modem.c
@@ -19,6 +19,7 @@
  */
 
 #include <glib.h>
+#include <config.h>
 
 #include "nm-device-modem.h"
 #include "nm-modem.h"
@@ -31,6 +32,10 @@
 #include "nm-logging.h"
 #include "nm-system.h"
 
+#if WITH_MODEM_MANAGER_1
+#include "nm-modem-broadband.h"
+#endif
+
 G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE)
 
 #define NM_DEVICE_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), 
NM_TYPE_DEVICE_MODEM, NMDeviceModemPrivate))
@@ -363,7 +368,15 @@ nm_device_modem_new (NMModem *modem, const char *driver)
                current_caps = caps;
                type_desc = "GSM/UMTS";
                ip_iface = nm_modem_get_data_port (modem);
-       } else {
+       }
+#if WITH_MODEM_MANAGER_1
+       else if (NM_IS_MODEM_BROADBAND (modem)) {
+               nm_modem_broadband_get_capabilities (NM_MODEM_BROADBAND 
(modem), &caps, &current_caps);
+               type_desc = "Broadband";
+               /* data port not yet known in broadband modems */
+       }
+#endif
+       else {
                nm_log_warn (LOGD_MB, "unhandled modem type %s", 
G_OBJECT_TYPE_NAME (modem));
                return NULL;
        }
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 83fbef8..1318874 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -75,6 +75,10 @@
 #include "nm-connectivity.h"
 #endif
 
+#if WITH_MODEM_MANAGER_1
+#include <libmm-glib.h>
+#include "nm-modem-broadband.h"
+#endif
 
 #define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd"
 #define NM_AUTOIP_DBUS_IFACE   "org.freedesktop.nm_avahi_autoipd"
@@ -226,6 +230,14 @@ typedef struct {
        guint modem_added_id;
        guint modem_removed_id;
 
+#if WITH_MODEM_MANAGER_1
+       GDBusConnection *dbus_connection;
+       MMManager *modem_manager_1;
+       guint modem_manager_1_name_owner_changed;
+       guint modem_object_added_id;
+       guint modem_object_removed_id;
+#endif
+
        DBusGProxy *aipd_proxy;
        NMSleepMonitor *sleep_monitor;
 
@@ -567,6 +579,139 @@ modem_removed (NMModemManager *modem_manager,
                priv->devices = remove_one_device (self, priv->devices, found, 
FALSE);
 }
 
+#if WITH_MODEM_MANAGER_1
+
+static void
+modem_object_added (MMManager *modem_manager,
+                    MMObject  *modem_object,
+                    NMManager *self)
+{
+       NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+       gchar *drivers;
+       NMDevice *device;
+       NMDevice *replace_device;
+       MMModem *modem_iface;
+       GSList *iter;
+       NMModem *modem;
+       const gchar *primary_port;
+
+       /* Ensure we have the 'Modem' interface at least */
+       modem_iface = mm_object_peek_modem (modem_object);
+       g_return_if_fail (modem_iface != NULL);
+
+       primary_port = mm_modem_get_primary_port (modem_iface);
+       g_assert (primary_port);
+
+       replace_device = find_device_by_ip_iface (self, primary_port);
+       if (replace_device) {
+               priv->devices = remove_one_device (self,
+                                                  priv->devices,
+                                                  replace_device,
+                                                  FALSE);
+       }
+
+       modem = nm_modem_broadband_new (modem_object);
+       if (!modem)
+               return;
+
+       /* Build a single string with all drivers listed */
+       drivers = g_strjoinv (", ", (gchar **)mm_modem_get_drivers 
(modem_iface));
+
+       /* Give Bluetooth DUN devices first chance to claim the modem */
+       for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
+               if (nm_device_get_device_type (iter->data) == 
NM_DEVICE_TYPE_BT) {
+                       if (nm_device_bt_modem_added (NM_DEVICE_BT 
(iter->data), modem, drivers))
+                               return;
+               }
+       }
+
+       /* If it was a Bluetooth modem and no bluetooth device claimed it, 
ignore
+        * it.  The rfcomm port (and thus the modem) gets created automatically
+        * by the Bluetooth code during the connection process.
+        */
+       if (drivers && strstr (drivers, "bluetooth")) {
+               nm_log_info (LOGD_MB, "(%s) ignoring modem (no associated 
Bluetooth device)",
+                            nm_modem_get_uid (modem));
+               g_object_unref (modem);
+               g_free (drivers);
+               return;
+       }
+
+       device = nm_device_modem_new (modem, drivers);
+       if (device) {
+               nm_log_dbg (LOGD_MB, "(%s) New modem device found at '%s'",
+                           nm_device_get_iface (device),
+                           nm_device_get_udi (device));
+               add_device (self, device);
+       }
+       g_free (drivers);
+}
+
+static void
+modem_object_removed (MMManager *manager,
+                      MMObject  *modem_object,
+                      NMManager *self)
+{
+       NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+       NMDevice *found;
+       GSList *iter;
+
+       /* Give Bluetooth DUN devices first chance to handle the modem removal 
*/
+       for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
+               if (nm_device_get_device_type (iter->data) == 
NM_DEVICE_TYPE_BT) {
+                       if (nm_device_bt_modem_removed_by_path (NM_DEVICE_BT 
(iter->data),
+                                                               
mm_object_get_path (modem_object)))
+                               return;
+               }
+       }
+
+       /* Otherwise remove the standalone modem */
+       found = nm_manager_get_device_by_udi (self,
+                                             mm_object_get_path 
(modem_object));
+       if (found) {
+               nm_log_dbg (LOGD_MB, "(%s) Removed Modem device from '%s'",
+                           nm_device_get_iface (found),
+                           nm_device_get_path (found));
+               priv->devices = remove_one_device (self, priv->devices, found, 
FALSE);
+       }
+}
+
+static void
+update_modems_list (NMManager *self)
+{
+       NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+       GList *modems, *l;
+
+    modems = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER 
(priv->modem_manager_1));
+    for (l = modems; l; l = g_list_next (l))
+           modem_object_added (priv->modem_manager_1, MM_OBJECT (l->data), 
self);
+    g_list_free_full (modems, (GDestroyNotify) g_object_unref);
+}
+
+static gboolean
+update_modems_list_cb (NMManager *self)
+{
+       update_modems_list (self);
+       g_object_unref (self);
+       return FALSE;
+}
+
+static void
+modem_manager_1_name_owner_changed (MMManager *modem_manager_1,
+                                    GParamSpec *pspec,
+                                    NMManager *self)
+{
+       if (!g_dbus_object_manager_client_get_name_owner 
(G_DBUS_OBJECT_MANAGER_CLIENT (modem_manager_1))) {
+               nm_log_info (LOGD_MB, "ModemManager disappeared from bus");
+               return;
+       }
+
+       nm_log_info (LOGD_MB, "ModemManager available in the bus");
+       update_modems_list (self);
+}
+
+#endif /* WITH_MODEM_MANAGER_1 */
+
 static void
 aipd_handle_event (DBusGProxy *proxy,
                    const char *event,
@@ -4034,6 +4179,23 @@ dispose (GObject *object)
        }
        g_object_unref (priv->modem_manager);
 
+#if WITH_MODEM_MANAGER_1
+       if (priv->modem_manager_1_name_owner_changed) {
+               g_source_remove (priv->modem_manager_1_name_owner_changed);
+               priv->modem_manager_1_name_owner_changed = 0;
+       }
+       if (priv->modem_object_added_id) {
+               g_source_remove (priv->modem_object_added_id);
+               priv->modem_object_added_id = 0;
+       }
+       if (priv->modem_object_removed_id) {
+               g_source_remove (priv->modem_object_removed_id);
+               priv->modem_object_removed_id = 0;
+       }
+       g_clear_object (&priv->dbus_connection);
+       g_clear_object (&priv->modem_manager_1);
+#endif
+
        /* Unregister property filter */
        bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
        if (bus) {
@@ -4341,6 +4503,43 @@ nm_manager_init (NMManager *manager)
        priv->modem_removed_id = g_signal_connect (priv->modem_manager, 
"modem-removed",
                                                   G_CALLBACK (modem_removed), 
manager);
 
+#if WITH_MODEM_MANAGER_1
+       {
+               GError *error = NULL;
+
+               priv->dbus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, 
NULL, &error);
+               if (!priv->dbus_connection) {
+                       nm_log_warn (LOGD_CORE, "error getting bus connection: 
%s", error->message);
+                       g_error_free (error);
+               } else {
+                       priv->modem_manager_1 = mm_manager_new_sync 
(priv->dbus_connection,
+                                                                    
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
+                                                                    NULL,
+                                                                    &error);
+                       if (!priv->modem_manager_1) {
+                               nm_log_warn (LOGD_MB, "error creating modem 
manager: %s", error->message);
+                               g_error_free (error);
+                       } else {
+                               priv->modem_manager_1_name_owner_changed = 
g_signal_connect (priv->modem_manager_1,
+                                                                               
             "notify::name-owner",
+                                                                               
             G_CALLBACK (modem_manager_1_name_owner_changed),
+                                                                               
             manager);
+                               priv->modem_object_added_id = g_signal_connect 
(priv->modem_manager_1,
+                                                                               
"object-added",
+                                                                               
G_CALLBACK (modem_object_added),
+                                                                               
manager);
+                               priv->modem_object_removed_id = 
g_signal_connect (priv->modem_manager_1,
+                                                                               
  "object-removed",
+                                                                               
  G_CALLBACK (modem_object_removed),
+                                                                               
  manager);
+
+                               /* Request to update initial list of modems */
+                               g_idle_add ((GSourceFunc)update_modems_list_cb, 
g_object_ref (manager));
+                       }
+               }
+       }
+#endif
+
        priv->vpn_manager = nm_vpn_manager_get ();
        priv->vpn_manager_activated_id = g_signal_connect (G_OBJECT 
(priv->vpn_manager), "connection-activated",
                                                           G_CALLBACK 
(vpn_manager_connection_activated_cb), manager);
-- 
1.7.11.7

_______________________________________________
networkmanager-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/networkmanager-list

Reply via email to