From 7b10ec29a2de9b7165dec6ac232dedf21a8360c3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Dec 2009 11:52:15 -0800 Subject: [PATCH] modem: fix enable/disable/disconnect flow NM shouldn't really be calling Enable(False) except in response to direct user requests to turn off WWAN, much like rfkill, since Enable(False) /is/ essentially rfkill for 3G. Instead, we should be powering up the modem before trying to use it, and only disconnecting after we're done. Let the user do enable/disable when they want to. This also fixes issues with other devices like GPS potentially using the modem-manager at the same time as NM and ensures that NM won't punch the modem in the face while GPS is using it. --- src/modem-manager/nm-modem-cdma.c | 27 +++++++++++++++++++-- src/modem-manager/nm-modem-gsm.c | 39 ++++++++++++++++++++++++++----- src/modem-manager/nm-modem.c | 13 +++++++---- 3 files changed, 67 insertions(+), 12 deletions(-) diff --git a/src/modem-manager/nm-modem-cdma.c b/src/modem-manager/nm-modem-cdma.c index 30feb28a7..ee524aa1d 100644 --- a/src/modem-manager/nm-modem-cdma.c +++ b/src/modem-manager/nm-modem-cdma.c @@ -115,12 +115,22 @@ create_connect_properties (NMConnection *connection) return properties; } -static NMActStageReturn -real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +static void +stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { + NMDevice *device = NM_DEVICE (user_data); + GError *error = NULL; NMConnection *connection; GHashTable *properties; + dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); + if (error) { + nm_warning ("CDMA modem connection failed: %s", error->message); + g_error_free (error); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + return; + } + connection = nm_act_request_get_connection (nm_device_get_act_request (device)); g_assert (connection); @@ -130,6 +140,19 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) device, NULL, 120000, DBUS_TYPE_G_MAP_OF_VARIANT, properties, G_TYPE_INVALID); + g_hash_table_destroy (properties); +} + +static NMActStageReturn +real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + gboolean enable = TRUE; + + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), + "Enable", stage1_enable_done, + device, NULL, 20000, + G_TYPE_BOOLEAN, enable, + G_TYPE_INVALID); return NM_ACT_STAGE_RETURN_POSTPONE; } diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c index 2bd8b231a..d1e97dcbf 100644 --- a/src/modem-manager/nm-modem-gsm.c +++ b/src/modem-manager/nm-modem-gsm.c @@ -247,6 +247,34 @@ create_connect_properties (NMConnection *connection) return properties; } +static void +stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + GError *error = NULL; + NMConnection *connection; + GHashTable *properties; + + dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID); + if (error) { + nm_warning ("GSM modem connection failed: %s", error->message); + g_error_free (error); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NONE); + return; + } + + connection = nm_act_request_get_connection (nm_device_get_act_request (device)); + g_assert (connection); + + properties = create_connect_properties (connection); + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), + "Connect", stage1_prepare_done, + device, NULL, 120000, + DBUS_TYPE_G_MAP_OF_VARIANT, properties, + G_TYPE_INVALID); + g_hash_table_destroy (properties); +} + static NMActStageReturn real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { @@ -264,13 +292,12 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) setting_name = nm_connection_need_secrets (connection, &hints); if (!setting_name) { - GHashTable *properties; + gboolean enable = TRUE; - properties = create_connect_properties (connection); - dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM_SIMPLE), - "Connect", stage1_prepare_done, - device, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, properties, + dbus_g_proxy_begin_call_with_timeout (nm_modem_get_proxy (NM_MODEM (device), MM_DBUS_INTERFACE_MODEM), + "Enable", stage1_enable_done, + device, NULL, 20000, + G_TYPE_BOOLEAN, enable, G_TYPE_INVALID); return NM_ACT_STAGE_RETURN_POSTPONE; diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 3895a7d83..3bc7bab4a 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -425,6 +425,10 @@ device_state_changed (NMDeviceInterface *device, { NMModem *self = NM_MODEM (user_data); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + gboolean was_connected = FALSE; + + if (IS_ACTIVATING_STATE (old_state) || (old_state == NM_DEVICE_STATE_ACTIVATED)) + was_connected = TRUE; /* Make sure we don't leave the serial device open */ switch (new_state) { @@ -436,10 +440,11 @@ device_state_changed (NMDeviceInterface *device, case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_DISCONNECTED: - dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, NULL), - "Enable", - G_TYPE_BOOLEAN, FALSE, - G_TYPE_INVALID); + if (was_connected) { + dbus_g_proxy_call_no_reply (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM), + "Disconnect", + G_TYPE_INVALID); + } break; default: break;