about summary refs log tree commit diff
path: root/src/devices/wwan/nm-device-modem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/wwan/nm-device-modem.c')
-rw-r--r--src/devices/wwan/nm-device-modem.c104
1 files changed, 53 insertions, 51 deletions
diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c
index 042a6ca4..3e6ccc8f 100644
--- a/src/devices/wwan/nm-device-modem.c
+++ b/src/devices/wwan/nm-device-modem.c
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2009 - 2019 Red Hat, Inc.
  */
 
@@ -48,10 +34,11 @@ typedef struct {
 	NMModem *modem;
 	NMDeviceModemCapabilities caps;
 	NMDeviceModemCapabilities current_caps;
-	gboolean rf_enabled;
 	char *device_id;
 	char *operator_code;
 	char *apn;
+	bool rf_enabled:1;
+	NMDeviceStageState stage1_state:3;
 } NMDeviceModemPrivate;
 
 struct _NMDeviceModem {
@@ -119,16 +106,17 @@ modem_prepare_result (NMModem *modem,
                       gpointer user_data)
 {
 	NMDeviceModem *self = NM_DEVICE_MODEM (user_data);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
 	NMDevice *device = NM_DEVICE (self);
-	NMDeviceState state;
 	NMDeviceStateReason reason = i_reason;
 
-	state = nm_device_get_state (device);
-	g_return_if_fail (state == NM_DEVICE_STATE_PREPARE);
+	if (   nm_device_get_state (device) != NM_DEVICE_STATE_PREPARE
+	    || priv->stage1_state != NM_DEVICE_STAGE_STATE_PENDING) {
+		nm_assert_not_reached ();
+		success = FALSE;
+	}
 
-	if (success)
-		nm_device_activate_schedule_stage2_device_config (device);
-	else {
+	if (!success) {
 		/* There are several reasons to block autoconnection at device level:
 		 *
 		 *  - Wrong SIM-PIN: The device won't autoconnect because it doesn't make sense
@@ -164,7 +152,11 @@ modem_prepare_result (NMModem *modem,
 			break;
 		}
 		nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
+		return;
 	}
+
+	priv->stage1_state = NM_DEVICE_STAGE_STATE_COMPLETED;
+	nm_device_activate_schedule_stage1_device_prepare (device);
 }
 
 static void
@@ -187,16 +179,19 @@ static void
 modem_auth_result (NMModem *modem, GError *error, gpointer user_data)
 {
 	NMDevice *device = NM_DEVICE (user_data);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
+
+	g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
 
 	if (error) {
 		nm_device_state_changed (device,
 		                         NM_DEVICE_STATE_FAILED,
 		                         NM_DEVICE_STATE_REASON_NO_SECRETS);
-	} else {
-		/* Otherwise, on success for modem secrets we need to schedule stage1 again */
-		g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
-		nm_device_activate_schedule_stage1_device_prepare (device);
+		return;
 	}
+
+	priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT;
+	nm_device_activate_schedule_stage1_device_prepare (device);
 }
 
 static void
@@ -355,7 +350,7 @@ modem_state_cb (NMModem *modem,
 	NMModemState new_state = new_state_i;
 	NMModemState old_state = old_state_i;
 	NMDevice *device = NM_DEVICE (user_data);
-	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 	NMDeviceState dev_state = nm_device_get_state (device);
 
 	if (new_state <= NM_MODEM_STATE_DISABLING &&
@@ -409,7 +404,7 @@ modem_removed_cb (NMModem *modem, gpointer user_data)
 static gboolean
 owns_iface (NMDevice *device, const char *iface)
 {
-	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 
 	g_return_val_if_fail (priv->modem, FALSE);
 
@@ -447,7 +442,7 @@ get_generic_capabilities (NMDevice *device)
 static const char *
 get_type_description (NMDevice *device)
 {
-	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 
 	if (NM_FLAGS_HAS (priv->current_caps, NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS))
 		return "gsm";
@@ -464,7 +459,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection, GError
 	if (!NM_DEVICE_CLASS (nm_device_modem_parent_class)->check_connection_compatible (device, connection, error))
 		return FALSE;
 
-	if (!nm_modem_check_connection_compatible (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem,
+	if (!nm_modem_check_connection_compatible (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem,
 	                                           connection,
 	                                           error ? &local : NULL)) {
 		if (error) {
@@ -530,7 +525,7 @@ complete_connection (NMDevice *device,
                      NMConnection *const*existing_connections,
                      GError **error)
 {
-	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 
 	return nm_modem_complete_connection (priv->modem,
 	                                     nm_device_get_iface (device),
@@ -542,7 +537,10 @@ complete_connection (NMDevice *device,
 static void
 deactivate (NMDevice *device)
 {
-	nm_modem_deactivate (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, device);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
+
+	nm_modem_deactivate (priv->modem, device);
+	priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT;
 }
 
 /*****************************************************************************/
@@ -583,28 +581,32 @@ deactivate_async (NMDevice *self,
 static NMActStageReturn
 act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 {
-	NMActStageReturn ret;
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 	NMActRequest *req;
 
-	ret = NM_DEVICE_CLASS (nm_device_modem_parent_class)->act_stage1_prepare (device, out_failure_reason);
-	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
-		return ret;
-
 	req = nm_device_get_act_request (device);
 	g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE);
 
-	return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, req, out_failure_reason);
+	if (priv->stage1_state == NM_DEVICE_STAGE_STATE_INIT) {
+		priv->stage1_state = NM_DEVICE_STAGE_STATE_PENDING;
+		return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem,
+		                                    req,
+		                                    out_failure_reason);
+	}
+
+	if (priv->stage1_state == NM_DEVICE_STAGE_STATE_PENDING)
+		return NM_ACT_STAGE_RETURN_POSTPONE;
+
+	nm_assert (priv->stage1_state == NM_DEVICE_STAGE_STATE_COMPLETED);
+	return NM_ACT_STAGE_RETURN_SUCCESS;
 }
 
 static NMActStageReturn
 act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 {
-	NMActRequest *req;
-
-	req = nm_device_get_act_request (device);
-	g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE);
+	nm_modem_act_stage2_config (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem);
 
-	return nm_modem_act_stage2_config (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, req, out_failure_reason);
+	return NM_ACT_STAGE_RETURN_SUCCESS;
 }
 
 static NMActStageReturn
@@ -632,7 +634,7 @@ act_stage3_ip_config_start (NMDevice *device,
 static void
 ip4_config_pre_commit (NMDevice *device, NMIP4Config *config)
 {
-	nm_modem_ip4_pre_commit (NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device)->modem, device, config);
+	nm_modem_ip4_pre_commit (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device, config);
 }
 
 static gboolean
@@ -654,7 +656,7 @@ get_ip_iface_identifier (NMDevice *device, NMUtilsIPv6IfaceId *out_iid)
 static gboolean
 get_enabled (NMDevice *device)
 {
-	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) device);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
 	NMModemState modem_state = nm_modem_get_state (priv->modem);
 
 	return priv->rf_enabled && (modem_state >= NM_MODEM_STATE_LOCKED);
@@ -710,7 +712,7 @@ set_modem (NMDeviceModem *self, NMModem *modem)
 
 	g_return_if_fail (modem != NULL);
 
-	priv->modem = g_object_ref (modem);
+	priv->modem = nm_modem_claim (modem);
 
 	g_signal_connect (modem, NM_MODEM_PPP_FAILED, G_CALLBACK (ppp_failed), self);
 	g_signal_connect (modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK (modem_prepare_result), self);
@@ -745,7 +747,7 @@ static void
 get_property (GObject *object, guint prop_id,
               GValue *value, GParamSpec *pspec)
 {
-	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object);
 
 	switch (prop_id) {
 	case PROP_MODEM:
@@ -776,7 +778,7 @@ static void
 set_property (GObject *object, guint prop_id,
               const GValue *value, GParamSpec *pspec)
 {
-	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object);
 
 	switch (prop_id) {
 	case PROP_MODEM:
@@ -834,11 +836,11 @@ nm_device_modem_new (NMModem *modem)
 static void
 dispose (GObject *object)
 {
-	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE ((NMDeviceModem *) object);
+	NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object);
 
 	if (priv->modem) {
 		g_signal_handlers_disconnect_by_data (priv->modem, NM_DEVICE_MODEM (object));
-		g_clear_object (&priv->modem);
+		nm_clear_pointer (&priv->modem, nm_modem_unclaim);
 	}
 
 	g_clear_pointer (&priv->device_id, g_free);