summary refs log tree commit diff
path: root/src/nm-device-modem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-device-modem.c')
-rw-r--r--src/nm-device-modem.c168
1 files changed, 112 insertions, 56 deletions
diff --git a/src/nm-device-modem.c b/src/nm-device-modem.c
index e7cd9259..57f0bf8e 100644
--- a/src/nm-device-modem.c
+++ b/src/nm-device-modem.c
@@ -18,6 +18,8 @@
  * Copyright (C) 2009 - 2011 Red Hat, Inc.
  */
 
+#include "config.h"
+
 #include <glib.h>
 
 #include "nm-device-modem.h"
@@ -29,6 +31,11 @@
 #include "nm-rfkill.h"
 #include "nm-marshal.h"
 #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)
 
@@ -56,7 +63,7 @@ enum {
 };
 static guint signals[LAST_SIGNAL] = { 0 };
 
-static void real_set_enabled (NMDevice *device, gboolean enabled);
+static void set_enabled (NMDevice *device, gboolean enabled);
 
 /*****************************************************************************/
 
@@ -132,7 +139,6 @@ modem_auth_result (NMModem *modem, GError *error, gpointer user_data)
 
 static void
 modem_ip4_config_result (NMModem *self,
-                         const char *iface,
                          NMIP4Config *config,
                          GError *error,
                          gpointer user_data)
@@ -147,12 +153,18 @@ modem_ip4_config_result (NMModem *self,
 		             error && error->message ? error->message : "(unknown)");
 
 		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
-	} else {
-		if (iface)
-			nm_device_set_ip_iface (device, iface);
-
+	} else
 		nm_device_activate_schedule_ip4_config_result (device, config);
-	}
+}
+
+static void
+data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
+{
+	NMDevice *self = NM_DEVICE (user_data);
+
+	/* We set the IP iface in the device as soon as we know it, so that we
+	 * properly ifup it if needed */
+	nm_device_set_ip_iface (self, nm_modem_get_data_port (modem));
 }
 
 static void
@@ -161,11 +173,24 @@ modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
 	NMDeviceModem *self = NM_DEVICE_MODEM (user_data);
 	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
 
-	real_set_enabled (NM_DEVICE (self), nm_modem_get_mm_enabled (priv->modem));
+	set_enabled (NM_DEVICE (self), nm_modem_get_mm_enabled (priv->modem));
 
 	g_signal_emit (G_OBJECT (self), signals[ENABLE_CHANGED], 0);
 }
 
+static void
+modem_connected_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data)
+{
+	NMDeviceModem *self = NM_DEVICE_MODEM (user_data);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
+
+	if (   nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED
+	    && !nm_modem_get_mm_connected (priv->modem)) {
+		/* Fail the device if the modem disconnects unexpectedly */
+		nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER);
+	}
+}
+
 /*****************************************************************************/
 
 NMModem *
@@ -183,8 +208,7 @@ static void
 device_state_changed (NMDevice *device,
                       NMDeviceState new_state,
                       NMDeviceState old_state,
-                      NMDeviceStateReason reason,
-                      gpointer user_data)
+                      NMDeviceStateReason reason)
 {
 	nm_modem_device_state_changed (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem,
 	                               new_state,
@@ -193,15 +217,15 @@ device_state_changed (NMDevice *device,
 }
 
 static guint32
-real_get_generic_capabilities (NMDevice *device)
+get_generic_capabilities (NMDevice *device)
 {
 	return NM_DEVICE_CAP_NM_SUPPORTED;
 }
 
 static NMConnection *
-real_get_best_auto_connection (NMDevice *device,
-							   GSList *connections,
-							   char **specific_object)
+get_best_auto_connection (NMDevice *device,
+                          GSList *connections,
+                          char **specific_object)
 {
 	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 
@@ -209,9 +233,9 @@ real_get_best_auto_connection (NMDevice *device,
 }
 
 static gboolean
-real_check_connection_compatible (NMDevice *device,
-                                  NMConnection *connection,
-                                  GError **error)
+check_connection_compatible (NMDevice *device,
+                             NMConnection *connection,
+                             GError **error)
 {
 	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 
@@ -219,11 +243,11 @@ real_check_connection_compatible (NMDevice *device,
 }
 
 static gboolean
-real_complete_connection (NMDevice *device,
-                          NMConnection *connection,
-                          const char *specific_object,
-                          const GSList *existing_connections,
-                          GError **error)
+complete_connection (NMDevice *device,
+                     NMConnection *connection,
+                     const char *specific_object,
+                     const GSList *existing_connections,
+                     GError **error)
 {
 	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 
@@ -231,25 +255,29 @@ real_complete_connection (NMDevice *device,
 }
 
 static gboolean
-real_hw_is_up (NMDevice *device)
+hw_is_up (NMDevice *device)
 {
-	return nm_modem_hw_is_up (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device);
+	int ifindex = nm_device_get_ip_ifindex (device);
+
+	return ifindex > 0 ? nm_system_iface_is_up (ifindex) : TRUE;
 }
 
 static gboolean
-real_hw_bring_up (NMDevice *device, gboolean *no_firmware)
+hw_bring_up (NMDevice *device, gboolean *no_firmware)
 {
-	return nm_modem_hw_bring_up (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device, no_firmware);
+	int ifindex = nm_device_get_ip_ifindex (device);
+
+	return ifindex > 0 ? nm_system_iface_set_up (ifindex, TRUE, no_firmware) : TRUE;
 }
 
 static void
-real_deactivate (NMDevice *device)
+deactivate (NMDevice *device)
 {
 	nm_modem_deactivate (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device);
 }
 
 static NMActStageReturn
-real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
+act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 {
 	NMActRequest *req;
 
@@ -260,7 +288,7 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
 }
 
 static NMActStageReturn
-real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
+act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 {
 	NMActRequest *req;
 
@@ -271,9 +299,9 @@ real_act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
 }
 
 static NMActStageReturn
-real_act_stage3_ip4_config_start (NMDevice *device,
-                                  NMIP4Config **out_config,
-                                  NMDeviceStateReason *reason)
+act_stage3_ip4_config_start (NMDevice *device,
+                             NMIP4Config **out_config,
+                             NMDeviceStateReason *reason)
 {
 	return nm_modem_stage3_ip4_config_start (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem,
 	                                         device,
@@ -281,10 +309,16 @@ real_act_stage3_ip4_config_start (NMDevice *device,
 	                                         reason);
 }
 
+static void
+ip4_config_pre_commit (NMDevice *device, NMIP4Config *config)
+{
+	nm_modem_ip4_pre_commit (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device, config);
+}
+
 static NMActStageReturn
-real_act_stage3_ip6_config_start (NMDevice *device,
-                                  NMIP6Config **out_config,
-                                  NMDeviceStateReason *reason)
+act_stage3_ip6_config_start (NMDevice *device,
+                             NMIP6Config **out_config,
+                             NMDeviceStateReason *reason)
 {
 	return nm_modem_stage3_ip6_config_start (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem,
 	                                         device,
@@ -295,13 +329,13 @@ real_act_stage3_ip6_config_start (NMDevice *device,
 /*****************************************************************************/
 
 static gboolean
-real_get_enabled (NMDevice *device)
+get_enabled (NMDevice *device)
 {
 	return nm_modem_get_mm_enabled (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem);
 }
 
 static void
-real_set_enabled (NMDevice *device, gboolean enabled)
+set_enabled (NMDevice *device, gboolean enabled)
 {
 	NMDeviceModem *self = NM_DEVICE_MODEM (device);
 	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
@@ -328,7 +362,9 @@ NMDevice *
 nm_device_modem_new (NMModem *modem, const char *driver)
 {
 	NMDeviceModemCapabilities caps = NM_DEVICE_MODEM_CAPABILITY_NONE;
-	const char *type_desc = NULL;
+	NMDeviceModemCapabilities current_caps = NM_DEVICE_MODEM_CAPABILITY_NONE;
+	const gchar *type_desc = NULL;
+	const gchar *ip_iface = NULL;
 
 	g_return_val_if_fail (modem != NULL, NULL);
 	g_return_val_if_fail (NM_IS_MODEM (modem), NULL);
@@ -336,18 +372,31 @@ nm_device_modem_new (NMModem *modem, const char *driver)
 
 	if (NM_IS_MODEM_CDMA (modem)) {
 		caps = NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO;
+		current_caps = caps;
 		type_desc = "CDMA/EVDO";
+		ip_iface = nm_modem_get_data_port (modem);
 	} else if (NM_IS_MODEM_GSM (modem)) {
 		caps = NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS;
+		current_caps = caps;
 		type_desc = "GSM/UMTS";
-	} else {
+		ip_iface = nm_modem_get_data_port (modem);
+	}
+#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;
 	}
 
 	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_MODEM,
 	                                  NM_DEVICE_UDI, nm_modem_get_path (modem),
-	                                  NM_DEVICE_IFACE, nm_modem_get_iface (modem),
+	                                  NM_DEVICE_IFACE, nm_modem_get_uid (modem),
+	                                  NM_DEVICE_IP_IFACE, ip_iface,
 	                                  NM_DEVICE_DRIVER, driver,
 	                                  NM_DEVICE_TYPE_DESC, type_desc,
 	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MODEM,
@@ -361,7 +410,6 @@ nm_device_modem_new (NMModem *modem, const char *driver)
 static void
 nm_device_modem_init (NMDeviceModem *self)
 {
-	g_signal_connect (self, "state-changed", G_CALLBACK (device_state_changed), self);
 }
 
 static void
@@ -379,6 +427,12 @@ set_modem (NMDeviceModem *self, NMModem *modem)
 	g_signal_connect (modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK (modem_auth_requested), self);
 	g_signal_connect (modem, NM_MODEM_AUTH_RESULT, G_CALLBACK (modem_auth_result), self);
 	g_signal_connect (modem, "notify::" NM_MODEM_ENABLED, G_CALLBACK (modem_enabled_cb), self);
+	g_signal_connect (modem, "notify::" NM_MODEM_CONNECTED, G_CALLBACK (modem_connected_cb), self);
+
+	/* In the old ModemManager the data port is known from the very beginning;
+	 * while in the new ModemManager the data port is set afterwards when the bearer gets
+	 * created */
+	g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self);
 }
 
 static void
@@ -450,19 +504,22 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass)
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 
-	device_class->get_generic_capabilities = real_get_generic_capabilities;
-	device_class->get_best_auto_connection = real_get_best_auto_connection;
-	device_class->check_connection_compatible = real_check_connection_compatible;
-	device_class->complete_connection = real_complete_connection;
-	device_class->hw_is_up = real_hw_is_up;
-	device_class->hw_bring_up = real_hw_bring_up;
-	device_class->deactivate = real_deactivate;
-	device_class->act_stage1_prepare = real_act_stage1_prepare;
-	device_class->act_stage2_config = real_act_stage2_config;
-	device_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start;
-	device_class->act_stage3_ip6_config_start = real_act_stage3_ip6_config_start;
-	device_class->get_enabled = real_get_enabled;
-    device_class->set_enabled = real_set_enabled;
+	device_class->get_generic_capabilities = get_generic_capabilities;
+	device_class->get_best_auto_connection = get_best_auto_connection;
+	device_class->check_connection_compatible = check_connection_compatible;
+	device_class->complete_connection = complete_connection;
+	device_class->hw_is_up = hw_is_up;
+	device_class->hw_bring_up = hw_bring_up;
+	device_class->deactivate = deactivate;
+	device_class->act_stage1_prepare = act_stage1_prepare;
+	device_class->act_stage2_config = act_stage2_config;
+	device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
+	device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
+	device_class->ip4_config_pre_commit = ip4_config_pre_commit;
+	device_class->get_enabled = get_enabled;
+	device_class->set_enabled = set_enabled;
+
+	device_class->state_changed = device_state_changed;
 
 	/* Properties */
 	g_object_class_install_property
@@ -488,7 +545,7 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass)
 		                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
 	/* Signals */
-	signals[PROPERTIES_CHANGED] = 
+	signals[PROPERTIES_CHANGED] =
 		nm_properties_changed_signal_new (object_class,
 		                                  G_STRUCT_OFFSET (NMDeviceModemClass, properties_changed));
 
@@ -503,4 +560,3 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass)
 	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (mclass),
 	                                 &dbus_glib_nm_device_modem_object_info);
 }
-