From bb1fece6e6bdae53bc8383d300fa866150032ebc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 31 May 2013 15:22:07 -0500 Subject: [PATCH] wwan: make device available whenever it's not rfkilled Since the ModemManager enabled/disabled state is a user-changable one, and since NM can enable the modem when starting a connection, allow modems to be available for activation whenever they are not in airplane mode. This makes WWAN autoconnect=true connections actually autoconnect. If the first connection fails during ModemManager setup for fatal reasons (missing SIM, bad PIN, not registered), autoconnect will be blocked for that connection until activation is manually requested and succeeds. --- src/devices/wwan/nm-device-modem.c | 65 ++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index 5cadbf101..68619fde3 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -44,6 +44,7 @@ typedef struct { NMModem *modem; NMDeviceModemCapabilities caps; NMDeviceModemCapabilities current_caps; + gboolean rf_enabled; } NMDeviceModemPrivate; enum { @@ -53,8 +54,6 @@ enum { PROP_CURRENT_CAPABILITIES, }; -static void set_enabled (NMDevice *device, gboolean enabled); - /*****************************************************************************/ static void @@ -168,8 +167,24 @@ data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) static void modem_enabled_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) { - set_enabled (NM_DEVICE (user_data), nm_modem_get_mm_enabled (modem)); - nm_device_emit_recheck_auto_activate (NM_DEVICE (user_data)); + NMDevice *device = NM_DEVICE (user_data); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + NMDeviceState state; + + /* Called when the ModemManager modem enabled state is changed externally + * to NetworkManager (eg something using MM's D-Bus API directly). + */ + + if (priv->rf_enabled && nm_modem_get_mm_enabled (modem) == FALSE) { + state = nm_device_get_state (device); + if (nm_device_is_activating (device) || state == NM_DEVICE_STATE_ACTIVATED) { + /* user-initiated action, hence DISCONNECTED not FAILED */ + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + } + } + nm_device_emit_recheck_auto_activate (device); } static void @@ -321,7 +336,9 @@ act_stage3_ip6_config_start (NMDevice *device, static gboolean get_enabled (NMDevice *device) { - return nm_modem_get_mm_enabled (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem); + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); + + return priv->rf_enabled && nm_modem_get_mm_enabled (priv->modem); } static void @@ -329,21 +346,36 @@ set_enabled (NMDevice *device, gboolean enabled) { NMDeviceModem *self = NM_DEVICE_MODEM (device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self); - NMDeviceState state; + + /* Called only by the Manager in response to rfkill switch changes or + * global user WWAN enable/disable preference changes. + */ + priv->rf_enabled = enabled; if (priv->modem) { + /* Sync the ModemManager modem enabled/disabled with rfkill/user preference */ nm_modem_set_mm_enabled (priv->modem, enabled); - - if (enabled == FALSE) { - state = nm_device_get_state (device); - if (nm_device_is_activating (device) || state == NM_DEVICE_STATE_ACTIVATED) { - /* user-initiated action, hence DISCONNECTED not FAILED */ - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - } - } } + + if (enabled == FALSE) { + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_NONE); + } +} + +static gboolean +is_available (NMDevice *dev) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (dev); + + /* The device is available whenever it's not rfkilled */ + if (!priv->rf_enabled) { + nm_log_dbg (LOGD_MB, "(%s): not available because WWAN airplane mode is on", + nm_device_get_iface (dev)); + } + + return priv->rf_enabled; } /*****************************************************************************/ @@ -492,6 +524,7 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass) device_class->get_enabled = get_enabled; device_class->set_enabled = set_enabled; device_class->owns_iface = owns_iface; + device_class->is_available = is_available; device_class->state_changed = device_state_changed;