From 88b26172d64c352b5dc703edce9a2bb9adc399e5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 29 May 2013 13:56:10 -0500 Subject: [PATCH] mobile: merge NMModemGsm into NMModemOld --- po/POTFILES.in | 1 - src/Makefile.am | 2 - src/devices/nm-device-modem.c | 9 +- src/modem-manager/nm-modem-gsm.c | 618 --------------------------- src/modem-manager/nm-modem-gsm.h | 60 --- src/modem-manager/nm-modem-manager.c | 10 +- src/modem-manager/nm-modem-old.c | 417 ++++++++++++++++-- 7 files changed, 396 insertions(+), 721 deletions(-) delete mode 100644 src/modem-manager/nm-modem-gsm.c delete mode 100644 src/modem-manager/nm-modem-gsm.h diff --git a/po/POTFILES.in b/po/POTFILES.in index f4fa7d06d9..bb36357a39 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -41,7 +41,6 @@ src/dhcp-manager/nm-dhcp-manager.c src/dns-manager/nm-dns-manager.c src/logging/nm-logging.c src/config/nm-config.c -src/modem-manager/nm-modem-gsm.c src/modem-manager/nm-modem-broadband.c src/modem-manager/nm-modem-old.c src/devices/nm-device-bond.c diff --git a/src/Makefile.am b/src/Makefile.am index 480e0ee00d..0b071fa011 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -125,8 +125,6 @@ nm_sources = \ modem-manager/nm-modem-old.c \ modem-manager/nm-modem-old.h \ modem-manager/nm-modem-old-types.h \ - modem-manager/nm-modem-gsm.c \ - modem-manager/nm-modem-gsm.h \ modem-manager/nm-modem-manager.c \ modem-manager/nm-modem-manager.h \ modem-manager/nm-modem.c \ diff --git a/src/devices/nm-device-modem.c b/src/devices/nm-device-modem.c index c3637a6608..d0e4d94fb8 100644 --- a/src/devices/nm-device-modem.c +++ b/src/devices/nm-device-modem.c @@ -24,7 +24,7 @@ #include "nm-device-modem.h" #include "nm-modem.h" -#include "nm-modem-gsm.h" +#include "nm-modem-old.h" #include "nm-device-private.h" #include "nm-rfkill.h" #include "nm-logging.h" @@ -343,12 +343,7 @@ nm_device_modem_new (NMModem *modem, const char *driver) g_return_val_if_fail (NM_IS_MODEM (modem), NULL); g_return_val_if_fail (driver != NULL, NULL); - if (NM_IS_MODEM_GSM (modem)) { - caps = NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS; - current_caps = caps; - type_desc = "GSM/UMTS"; - ip_iface = nm_modem_get_data_port (modem); - } else if (NM_IS_MODEM_OLD (modem)) { + if (NM_IS_MODEM_OLD (modem)) { nm_modem_old_get_capabilities (NM_MODEM_OLD (modem), &caps, ¤t_caps); type_desc = "Broadband"; ip_iface = nm_modem_get_data_port (modem); diff --git a/src/modem-manager/nm-modem-gsm.c b/src/modem-manager/nm-modem-gsm.c deleted file mode 100644 index 561724c894..0000000000 --- a/src/modem-manager/nm-modem-gsm.c +++ /dev/null @@ -1,618 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* 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. - * - * Copyright (C) 2009 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#include "config.h" - -#include -#include - -#include "nm-dbus-glib-types.h" -#include "nm-modem-gsm.h" -#include "nm-device.h" -#include "nm-device-private.h" -#include "nm-setting-connection.h" -#include "nm-setting-gsm.h" -#include "nm-setting-ppp.h" -#include "nm-modem-old-types.h" -#include "nm-enum-types.h" -#include "nm-logging.h" -#include "NetworkManagerUtils.h" - -typedef enum { - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY = 0, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA, - - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_LAST = MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA -} MMModemDeprecatedMode; - -typedef enum { - MM_MODEM_GSM_ALLOWED_MODE_ANY = 0, - MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED = 1, - MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED = 2, - MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY = 3, - MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY = 4, - MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED = 5, - MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY = 6, - - MM_MODEM_GSM_ALLOWED_MODE_LAST = MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY -} MMModemGsmAllowedMode; - -typedef enum { - MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN = 0x0000, - /* bits 0..4 order match Ericsson device bitmap */ - MM_MODEM_GSM_ALLOWED_AUTH_NONE = 0x0001, - MM_MODEM_GSM_ALLOWED_AUTH_PAP = 0x0002, - MM_MODEM_GSM_ALLOWED_AUTH_CHAP = 0x0004, - MM_MODEM_GSM_ALLOWED_AUTH_MSCHAP = 0x0008, - MM_MODEM_GSM_ALLOWED_AUTH_MSCHAPV2 = 0x0010, - MM_MODEM_GSM_ALLOWED_AUTH_EAP = 0x0020, - - MM_MODEM_GSM_ALLOWED_AUTH_LAST = MM_MODEM_GSM_ALLOWED_AUTH_EAP -} MMModemGsmAllowedAuth; - -G_DEFINE_TYPE (NMModemGsm, nm_modem_gsm, NM_TYPE_MODEM_OLD) - -#define NM_MODEM_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MODEM_GSM, NMModemGsmPrivate)) - -typedef struct { - DBusGProxyCall *call; - - GHashTable *connect_properties; - guint32 pin_tries; - - guint enable_delay_id; -} NMModemGsmPrivate; - - -#define NM_GSM_ERROR (nm_gsm_error_quark ()) - -static GQuark -nm_gsm_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("nm-gsm-error"); - return quark; -} - -NMModem * -nm_modem_gsm_new (const char *path, - const char *data_device, - guint32 ip_method, - MMOldModemState state) -{ - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (data_device != NULL, NULL); - - return (NMModem *) g_object_new (NM_TYPE_MODEM_GSM, - NM_MODEM_PATH, path, - NM_MODEM_UID, data_device, - NM_MODEM_CONTROL_PORT, NULL, - NM_MODEM_DATA_PORT, data_device, - NM_MODEM_IP_METHOD, ip_method, - NM_MODEM_CONNECTED, (state == MM_OLD_MODEM_STATE_CONNECTED), - NULL); -} - -static NMDeviceStateReason -translate_mm_error (GError *error) -{ - NMDeviceStateReason reason; - - if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_CARRIER)) - reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_DIALTONE)) - reason = NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_BUSY)) - reason = NM_DEVICE_STATE_REASON_MODEM_BUSY; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_ANSWER)) - reason = NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NETWORK_NOT_ALLOWED)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NETWORK_TIMEOUT)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NO_NETWORK)) - reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_NOT_INSERTED)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PUK)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED; - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_WRONG)) - reason = NM_DEVICE_STATE_REASON_GSM_SIM_WRONG; - else { - /* unable to map the ModemManager error to a NM_DEVICE_STATE_REASON */ - nm_log_dbg (LOGD_MB, "unmapped dbus error detected: '%s'", dbus_g_error_get_name (error)); - reason = NM_DEVICE_STATE_REASON_UNKNOWN; - } - - /* FIXME: We have only GSM error messages here, and we have no idea which - activation state failed. Reasons like: - NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, - NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, - NM_DEVICE_STATE_REASON_GSM_APN_FAILED, - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, - NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED - are not used. - */ - return reason; -} - -static void -ask_for_pin (NMModemGsm *self, gboolean always_ask) -{ - NMModemGsmPrivate *priv; - guint32 tries = 0; - - g_return_if_fail (NM_IS_MODEM_GSM (self)); - - priv = NM_MODEM_GSM_GET_PRIVATE (self); - - if (!always_ask) - tries = priv->pin_tries++; - - nm_modem_get_secrets (NM_MODEM (self), - NM_SETTING_GSM_SETTING_NAME, - (tries || always_ask) ? TRUE : FALSE, - NM_SETTING_GSM_PIN); -} - -static void -stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - NMModemGsm *self = NM_MODEM_GSM (user_data); - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - GError *error = NULL; - - priv->call = NULL; - - if (priv->connect_properties) { - g_hash_table_destroy (priv->connect_properties); - priv->connect_properties = NULL; - } - - if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); - else { - if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) - ask_for_pin (self, FALSE); - else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_WRONG)) - ask_for_pin (self, TRUE); - else { - nm_log_warn (LOGD_MB, "GSM connection failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); - } - - g_error_free (error); - } -} - -static void -do_connect (NMModemGsm *self) -{ - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - DBusGProxy *proxy; - - proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE); - priv->call = dbus_g_proxy_begin_call_with_timeout (proxy, - "Connect", stage1_prepare_done, - self, NULL, 120000, - DBUS_TYPE_G_MAP_OF_VARIANT, priv->connect_properties, - G_TYPE_INVALID); -} - -static void stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data); - -/* do_enable() is used as a GSourceFunc, hence the gboolean return */ -static gboolean -do_enable (NMModemGsm *self) -{ - DBusGProxy *proxy; - - g_return_val_if_fail (NM_IS_MODEM_GSM (self), FALSE); - - NM_MODEM_GSM_GET_PRIVATE (self)->enable_delay_id = 0; - proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM); - dbus_g_proxy_begin_call_with_timeout (proxy, - "Enable", stage1_enable_done, - self, NULL, 20000, - G_TYPE_BOOLEAN, TRUE, - G_TYPE_INVALID); - return FALSE; -} - -static void -stage1_pin_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - NMModemGsm *self = NM_MODEM_GSM (user_data); - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - NMDeviceStateReason reason; - GError *error = NULL; - - if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { - /* Success; try to enable the modem again. Wait a few seconds to ensure - * that ModemManager is ready for the enable right after the unlock. - */ - if (priv->enable_delay_id == 0) - priv->enable_delay_id = g_timeout_add_seconds (4, (GSourceFunc) do_enable, self); - } else { - nm_log_warn (LOGD_MB, "GSM PIN unlock failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - - /* try to translate the error reason */ - reason = translate_mm_error (error); - if (reason == NM_DEVICE_STATE_REASON_UNKNOWN) - reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; - - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, reason); - g_error_free (error); - } -} - -static void -handle_enable_pin_required (NMModemGsm *self) -{ - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - const char *pin = NULL; - GValue *value; - DBusGProxy *proxy; - - /* See if we have a PIN already */ - value = g_hash_table_lookup (priv->connect_properties, "pin"); - if (value && G_VALUE_HOLDS_STRING (value)) - pin = g_value_get_string (value); - - /* If we do, send it */ - if (pin) { - proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM_GSM_CARD); - dbus_g_proxy_begin_call_with_timeout (proxy, - "SendPin", stage1_pin_done, - self, NULL, 10000, - G_TYPE_STRING, pin, - G_TYPE_INVALID); - } else - ask_for_pin (self, FALSE); -} - -static void -stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) -{ - NMModemGsm *self = NM_MODEM_GSM (user_data); - NMDeviceStateReason reason; - GError *error = NULL; - - if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) - do_connect (self); - else { - nm_log_warn (LOGD_MB, "GSM modem enable failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - - if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) - handle_enable_pin_required (self); - else { - /* try to translate the error reason */ - reason = translate_mm_error (error); - if (reason == NM_DEVICE_STATE_REASON_UNKNOWN) - reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, reason); - } - - g_error_free (error); - } -} - - -static GHashTable * -create_connect_properties (NMConnection *connection) -{ - NMSettingGsm *setting; - NMSettingPPP *s_ppp; - GHashTable *properties; - const char *str; - - setting = nm_connection_get_setting_gsm (connection); - properties = value_hash_create (); - - str = nm_setting_gsm_get_number (setting); - if (str) - value_hash_add_str (properties, "number", str); - - str = nm_setting_gsm_get_apn (setting); - if (str) - value_hash_add_str (properties, "apn", str); - - str = nm_setting_gsm_get_network_id (setting); - if (str) - value_hash_add_str (properties, "network_id", str); - - str = nm_setting_gsm_get_pin (setting); - if (str) - value_hash_add_str (properties, "pin", str); - - str = nm_setting_gsm_get_username (setting); - if (str) - value_hash_add_str (properties, "username", str); - - str = nm_setting_gsm_get_password (setting); - if (str) - value_hash_add_str (properties, "password", str); - - /* Add both old and new preferred modes */ - switch (nm_setting_gsm_get_network_type (setting)) { - case NM_SETTING_GSM_NETWORK_TYPE_UMTS_HSPA: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY); - break; - case NM_SETTING_GSM_NETWORK_TYPE_GPRS_EDGE: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY); - break; - case NM_SETTING_GSM_NETWORK_TYPE_PREFER_UMTS_HSPA: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED); - break; - case NM_SETTING_GSM_NETWORK_TYPE_PREFER_GPRS_EDGE: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED); - break; - case NM_SETTING_GSM_NETWORK_TYPE_PREFER_4G: - /* deprecated modes not extended for 4G, so no need to set them here */ - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED); - break; - case NM_SETTING_GSM_NETWORK_TYPE_4G: - /* deprecated modes not extended for 4G, so no need to set them here */ - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY); - break; - default: - value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY); - value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_ANY); - break; - } - - /* Roaming */ - if (nm_setting_gsm_get_home_only (setting)) - value_hash_add_bool (properties, "home_only", TRUE); - - /* For IpMethod == STATIC or DHCP */ - s_ppp = nm_connection_get_setting_ppp (connection); - if (s_ppp) { - guint32 auth = MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN; - - if (nm_setting_ppp_get_noauth (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_NONE; - if (!nm_setting_ppp_get_refuse_pap (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_PAP; - if (!nm_setting_ppp_get_refuse_chap (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_CHAP; - if (!nm_setting_ppp_get_refuse_mschap (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_MSCHAP; - if (!nm_setting_ppp_get_refuse_mschapv2 (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_MSCHAPV2; - if (!nm_setting_ppp_get_refuse_eap (s_ppp)) - auth |= MM_MODEM_GSM_ALLOWED_AUTH_EAP; - - if (auth != MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN) - value_hash_add_uint (properties, "allowed_auth", auth); - } - - return properties; -} - -static NMActStageReturn -act_stage1_prepare (NMModem *modem, - NMActRequest *req, - GPtrArray **out_hints, - const char **out_setting_name, - NMDeviceStateReason *reason) -{ - NMModemGsm *self = NM_MODEM_GSM (modem); - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - NMConnection *connection; - - connection = nm_act_request_get_connection (req); - g_assert (connection); - - *out_setting_name = nm_connection_need_secrets (connection, out_hints); - if (!*out_setting_name) { - gboolean enabled = nm_modem_get_mm_enabled (modem); - - if (priv->connect_properties) - g_hash_table_destroy (priv->connect_properties); - priv->connect_properties = create_connect_properties (connection); - - if (enabled) - do_connect (self); - else - do_enable (self); - } else { - /* NMModem will handle requesting secrets... */ - } - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static gboolean -check_connection_compatible (NMModem *modem, - NMConnection *connection, - GError **error) -{ - NMSettingConnection *s_con; - NMSettingGsm *s_gsm; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_GSM_SETTING_NAME)) { - g_set_error (error, - NM_GSM_ERROR, NM_GSM_ERROR_CONNECTION_NOT_GSM, - "The connection was not a GSM connection."); - return FALSE; - } - - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm) { - g_set_error (error, - NM_GSM_ERROR, NM_GSM_ERROR_CONNECTION_INVALID, - "The connection was not a valid GSM connection."); - return FALSE; - } - - return TRUE; -} - -static gboolean -complete_connection (NMModem *modem, - NMConnection *connection, - const GSList *existing_connections, - GError **error) -{ - NMSettingGsm *s_gsm; - NMSettingPPP *s_ppp; - - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm || !nm_setting_gsm_get_apn (s_gsm)) { - /* Need an APN at least */ - g_set_error_literal (error, - NM_SETTING_GSM_ERROR, - NM_SETTING_GSM_ERROR_MISSING_PROPERTY, - NM_SETTING_GSM_APN); - return FALSE; - } - - if (!nm_setting_gsm_get_number (s_gsm)) - g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); - - s_ppp = nm_connection_get_setting_ppp (connection); - if (!s_ppp) { - s_ppp = (NMSettingPPP *) nm_setting_ppp_new (); - g_object_set (G_OBJECT (s_ppp), - NM_SETTING_PPP_LCP_ECHO_FAILURE, 5, - NM_SETTING_PPP_LCP_ECHO_INTERVAL, 30, - NULL); - nm_connection_add_setting (connection, NM_SETTING (s_ppp)); - } - - nm_utils_complete_generic (connection, - NM_SETTING_GSM_SETTING_NAME, - existing_connections, - _("GSM connection %d"), - NULL, - FALSE); /* No IPv6 yet by default */ - - return TRUE; -} - -static gboolean -get_user_pass (NMModem *modem, - NMConnection *connection, - const char **user, - const char **pass) -{ - NMSettingGsm *s_gsm; - - s_gsm = nm_connection_get_setting_gsm (connection); - if (!s_gsm) - return FALSE; - - if (user) - *user = nm_setting_gsm_get_username (s_gsm); - if (pass) - *pass = nm_setting_gsm_get_password (s_gsm); - - return TRUE; -} - -static void -deactivate (NMModem *modem, NMDevice *device) -{ - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (modem); - - if (priv->call) { - DBusGProxy *proxy; - - proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (modem), MM_OLD_DBUS_INTERFACE_MODEM_SIMPLE); - dbus_g_proxy_cancel_call (proxy, priv->call); - priv->call = NULL; - } - - priv->pin_tries = 0; - - if (priv->enable_delay_id) - g_source_remove (priv->enable_delay_id); - - NM_MODEM_CLASS (nm_modem_gsm_parent_class)->deactivate (modem, device); -} - - -/*****************************************************************************/ - -static void -nm_modem_gsm_init (NMModemGsm *self) -{ -} - -static void -dispose (GObject *object) -{ - NMModemGsm *self = NM_MODEM_GSM (object); - NMModemGsmPrivate *priv = NM_MODEM_GSM_GET_PRIVATE (self); - - if (priv->connect_properties) - g_hash_table_destroy (priv->connect_properties); - if (priv->enable_delay_id) - g_source_remove (priv->enable_delay_id); - - G_OBJECT_CLASS (nm_modem_gsm_parent_class)->dispose (object); -} - -static void -nm_modem_gsm_class_init (NMModemGsmClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMModemClass *modem_class = NM_MODEM_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMModemGsmPrivate)); - - /* Virtual methods */ - object_class->dispose = dispose; - modem_class->get_user_pass = get_user_pass; - modem_class->check_connection_compatible = check_connection_compatible; - modem_class->complete_connection = complete_connection; - modem_class->act_stage1_prepare = act_stage1_prepare; - modem_class->deactivate = deactivate; - - dbus_g_error_domain_register (NM_GSM_ERROR, NULL, NM_TYPE_GSM_ERROR); -} diff --git a/src/modem-manager/nm-modem-gsm.h b/src/modem-manager/nm-modem-gsm.h deleted file mode 100644 index bf974eaef5..0000000000 --- a/src/modem-manager/nm-modem-gsm.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* 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. - * - * Copyright (C) 2009 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef NM_MODEM_GSM_H -#define NM_MODEM_GSM_H - -#include "nm-modem-old.h" -#include "nm-modem-old-types.h" - -G_BEGIN_DECLS - -#define NM_TYPE_MODEM_GSM (nm_modem_gsm_get_type ()) -#define NM_MODEM_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MODEM_GSM, NMModemGsm)) -#define NM_MODEM_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MODEM_GSM, NMModemGsmClass)) -#define NM_IS_MODEM_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MODEM_GSM)) -#define NM_IS_MODEM_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MODEM_GSM)) -#define NM_MODEM_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM_GSM, NMModemGsmClass)) - -typedef enum { - NM_GSM_ERROR_CONNECTION_NOT_GSM = 0, /*< nick=ConnectionNotGsm >*/ - NM_GSM_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ - NM_GSM_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ -} NMGsmError; - -typedef struct { - NMModemOld parent; -} NMModemGsm; - -typedef struct { - NMModemOldClass parent; -} NMModemGsmClass; - -GType nm_modem_gsm_get_type (void); - -NMModem *nm_modem_gsm_new (const char *path, - const char *data_device, - guint32 ip_method, - MMOldModemState state); - -G_END_DECLS - -#endif /* NM_MODEM_GSM_H */ diff --git a/src/modem-manager/nm-modem-manager.c b/src/modem-manager/nm-modem-manager.c index b63017d1cf..86aea1b8db 100644 --- a/src/modem-manager/nm-modem-manager.c +++ b/src/modem-manager/nm-modem-manager.c @@ -25,7 +25,7 @@ #include "nm-modem-manager.h" #include "nm-logging.h" #include "nm-modem.h" -#include "nm-modem-gsm.h" +#include "nm-modem-old.h" #include "nm-dbus-manager.h" #include "nm-modem-old-types.h" #include "nm-dbus-glib-types.h" @@ -207,13 +207,7 @@ create_modem (NMModemManager *self, const char *path) return; } - if (modem_type == MM_OLD_MODEM_TYPE_GSM) - modem = nm_modem_gsm_new (path, data_device, ip_method, state); - else if (modem_type == MM_OLD_MODEM_TYPE_CDMA) - modem = nm_modem_old_new (path, data_device, ip_method, MM_OLD_MODEM_TYPE_CDMA, state); - else - nm_log_warn (LOGD_MB, "unknown modem type '%d'", modem_type); - + modem = nm_modem_old_new (path, data_device, ip_method, modem_type, state); g_free (data_device); if (modem) { diff --git a/src/modem-manager/nm-modem-old.c b/src/modem-manager/nm-modem-old.c index 3acc5117fb..9ab3fd7404 100644 --- a/src/modem-manager/nm-modem-old.c +++ b/src/modem-manager/nm-modem-old.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2009 - 2011 Red Hat, Inc. + * Copyright (C) 2009 - 2013 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. */ @@ -47,8 +47,101 @@ typedef struct { DBusGProxyCall *call; GHashTable *connect_properties; + + guint32 pin_tries; + guint enable_delay_id; } NMModemOldPrivate; +#define CAPS_3GPP (NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS | NM_DEVICE_MODEM_CAPABILITY_LTE) + +/*****************************************************************************/ + +typedef enum { + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY = 0, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA, + + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_LAST = MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA +} MMModemDeprecatedMode; + +typedef enum { + MM_MODEM_GSM_ALLOWED_MODE_ANY = 0, + MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED = 1, + MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED = 2, + MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY = 3, + MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY = 4, + MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED = 5, + MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY = 6, + + MM_MODEM_GSM_ALLOWED_MODE_LAST = MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY +} MMModemGsmAllowedMode; + +typedef enum { + MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN = 0x0000, + /* bits 0..4 order match Ericsson device bitmap */ + MM_MODEM_GSM_ALLOWED_AUTH_NONE = 0x0001, + MM_MODEM_GSM_ALLOWED_AUTH_PAP = 0x0002, + MM_MODEM_GSM_ALLOWED_AUTH_CHAP = 0x0004, + MM_MODEM_GSM_ALLOWED_AUTH_MSCHAP = 0x0008, + MM_MODEM_GSM_ALLOWED_AUTH_MSCHAPV2 = 0x0010, + MM_MODEM_GSM_ALLOWED_AUTH_EAP = 0x0020, + + MM_MODEM_GSM_ALLOWED_AUTH_LAST = MM_MODEM_GSM_ALLOWED_AUTH_EAP +} MMModemGsmAllowedAuth; + +static NMDeviceStateReason +translate_mm_error (GError *error) +{ + NMDeviceStateReason reason; + + if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_CARRIER)) + reason = NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_DIALTONE)) + reason = NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_BUSY)) + reason = NM_DEVICE_STATE_REASON_MODEM_BUSY; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_CONNECT_ERROR_NO_ANSWER)) + reason = NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NETWORK_NOT_ALLOWED)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NETWORK_TIMEOUT)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_NO_NETWORK)) + reason = NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_NOT_INSERTED)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PUK)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED; + else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_WRONG)) + reason = NM_DEVICE_STATE_REASON_GSM_SIM_WRONG; + else { + /* unable to map the ModemManager error to a NM_DEVICE_STATE_REASON */ + nm_log_dbg (LOGD_MB, "unmapped dbus error detected: '%s'", dbus_g_error_get_name (error)); + reason = NM_DEVICE_STATE_REASON_UNKNOWN; + } + + /* FIXME: We have only GSM error messages here, and we have no idea which + activation state failed. Reasons like: + NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, + NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, + NM_DEVICE_STATE_REASON_GSM_APN_FAILED, + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, + NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED + are not used. + */ + return reason; +} + /*****************************************************************************/ DBusGProxy * @@ -158,12 +251,30 @@ set_mm_enabled (NMModem *self, gboolean enabled) /*****************************************************************************/ +static void +ask_for_pin (NMModemOld *self, gboolean always_ask) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + guint32 tries = 0; + + g_return_if_fail (NM_IS_MODEM_OLD (self)); + + if (!always_ask) + tries = priv->pin_tries++; + + nm_modem_get_secrets (NM_MODEM (self), + NM_SETTING_GSM_SETTING_NAME, + (tries || always_ask) ? TRUE : FALSE, + NM_SETTING_GSM_PIN); +} + static void stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) { NMModemOld *self = NM_MODEM_OLD (user_data); NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); GError *error = NULL; + gboolean asked = FALSE; priv->call = NULL; @@ -175,11 +286,23 @@ stage1_prepare_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); else { - nm_log_warn (LOGD_MB, "Modem connection failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + if (priv->caps & CAPS_3GPP) { + if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) { + ask_for_pin (self, FALSE); + asked = TRUE; + } else if (dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_WRONG)) { + ask_for_pin (self, TRUE); + asked = TRUE; + } + } + + if (!asked) { + nm_log_warn (LOGD_MB, "Mobile connection failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); + } g_error_free (error); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_NONE); } } @@ -197,20 +320,108 @@ do_connect (NMModemOld *self) G_TYPE_INVALID); } +static void stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data); + +/* do_enable() is used as a GSourceFunc, hence the gboolean return */ +static gboolean +do_enable (NMModemOld *self) +{ + DBusGProxy *proxy; + + g_return_val_if_fail (NM_IS_MODEM_OLD (self), FALSE); + + NM_MODEM_OLD_GET_PRIVATE (self)->enable_delay_id = 0; + proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM); + dbus_g_proxy_begin_call_with_timeout (proxy, + "Enable", stage1_enable_done, + self, NULL, 20000, + G_TYPE_BOOLEAN, TRUE, + G_TYPE_INVALID); + return FALSE; +} + +static void +stage1_pin_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +{ + NMModemOld *self = NM_MODEM_OLD (user_data); + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + NMDeviceStateReason reason; + GError *error = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { + /* Success; try to enable the modem again. Wait a few seconds to ensure + * that ModemManager is ready for the enable right after the unlock. + */ + if (priv->enable_delay_id == 0) + priv->enable_delay_id = g_timeout_add_seconds (4, (GSourceFunc) do_enable, self); + } else { + nm_log_warn (LOGD_MB, "GSM PIN unlock failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + /* try to translate the error reason */ + reason = translate_mm_error (error); + if (reason == NM_DEVICE_STATE_REASON_UNKNOWN) + reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; + + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, reason); + g_error_free (error); + } +} + +static void +handle_enable_pin_required (NMModemOld *self) +{ + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + const char *pin = NULL; + GValue *value; + DBusGProxy *proxy; + + g_assert (priv->caps & CAPS_3GPP); + + /* See if we have a PIN already */ + value = g_hash_table_lookup (priv->connect_properties, "pin"); + if (value && G_VALUE_HOLDS_STRING (value)) + pin = g_value_get_string (value); + + /* If we do, send it */ + if (pin) { + proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (self), MM_OLD_DBUS_INTERFACE_MODEM_GSM_CARD); + dbus_g_proxy_begin_call_with_timeout (proxy, + "SendPin", stage1_pin_done, + self, NULL, 10000, + G_TYPE_STRING, pin, + G_TYPE_INVALID); + } else + ask_for_pin (self, FALSE); +} + static void stage1_enable_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { NMModemOld *self = NM_MODEM_OLD (user_data); + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); + NMDeviceStateReason reason; GError *error = NULL; if (dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) do_connect (self); else { - nm_log_warn (LOGD_MB, "Modem enable failed: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); + if ((priv->caps & CAPS_3GPP) && dbus_g_error_has_name (error, MM_OLD_MODEM_ERROR_SIM_PIN)) + handle_enable_pin_required (self); + else { + nm_log_warn (LOGD_MB, "Modem enable failed: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + + /* try to translate the error reason */ + reason = translate_mm_error (error); + if (reason == NM_DEVICE_STATE_REASON_UNKNOWN) + reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, reason); + } + g_error_free (error); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); } } @@ -218,6 +429,8 @@ static GHashTable * create_connect_properties (NMConnection *connection) { NMSettingCdma *s_cdma; + NMSettingGsm *s_gsm; + NMSettingPPP *s_ppp; GHashTable *properties; const char *str; @@ -231,6 +444,93 @@ create_connect_properties (NMConnection *connection) return properties; } + s_gsm = nm_connection_get_setting_gsm (connection); + if (s_gsm) { + str = nm_setting_gsm_get_number (s_gsm); + if (str) + value_hash_add_str (properties, "number", str); + + str = nm_setting_gsm_get_apn (s_gsm); + if (str) + value_hash_add_str (properties, "apn", str); + + str = nm_setting_gsm_get_network_id (s_gsm); + if (str) + value_hash_add_str (properties, "network_id", str); + + str = nm_setting_gsm_get_pin (s_gsm); + if (str) + value_hash_add_str (properties, "pin", str); + + str = nm_setting_gsm_get_username (s_gsm); + if (str) + value_hash_add_str (properties, "username", str); + + str = nm_setting_gsm_get_password (s_gsm); + if (str) + value_hash_add_str (properties, "password", str); + + /* Add both old and new preferred modes */ + switch (nm_setting_gsm_get_network_type (s_gsm)) { + case NM_SETTING_GSM_NETWORK_TYPE_UMTS_HSPA: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY); + break; + case NM_SETTING_GSM_NETWORK_TYPE_GPRS_EDGE: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY); + break; + case NM_SETTING_GSM_NETWORK_TYPE_PREFER_UMTS_HSPA: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED); + break; + case NM_SETTING_GSM_NETWORK_TYPE_PREFER_GPRS_EDGE: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED); + break; + case NM_SETTING_GSM_NETWORK_TYPE_PREFER_4G: + /* deprecated modes not extended for 4G, so no need to set them here */ + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_4G_PREFERRED); + break; + case NM_SETTING_GSM_NETWORK_TYPE_4G: + /* deprecated modes not extended for 4G, so no need to set them here */ + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_4G_ONLY); + break; + default: + value_hash_add_uint (properties, "network_mode", MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY); + value_hash_add_uint (properties, "allowed_mode", MM_MODEM_GSM_ALLOWED_MODE_ANY); + break; + } + + /* Roaming */ + if (nm_setting_gsm_get_home_only (s_gsm)) + value_hash_add_bool (properties, "home_only", TRUE); + + /* For IpMethod == STATIC or DHCP */ + s_ppp = nm_connection_get_setting_ppp (connection); + if (s_ppp) { + guint32 auth = MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN; + + if (nm_setting_ppp_get_noauth (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_NONE; + if (!nm_setting_ppp_get_refuse_pap (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_PAP; + if (!nm_setting_ppp_get_refuse_chap (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_CHAP; + if (!nm_setting_ppp_get_refuse_mschap (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_MSCHAP; + if (!nm_setting_ppp_get_refuse_mschapv2 (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_MSCHAPV2; + if (!nm_setting_ppp_get_refuse_eap (s_ppp)) + auth |= MM_MODEM_GSM_ALLOWED_AUTH_EAP; + + if (auth != MM_MODEM_GSM_ALLOWED_AUTH_UNKNOWN) + value_hash_add_uint (properties, "allowed_auth", auth); + } + + return properties; + } + g_hash_table_destroy (properties); return NULL; } @@ -252,7 +552,6 @@ act_stage1_prepare (NMModem *modem, *out_setting_name = nm_connection_need_secrets (connection, out_hints); if (!*out_setting_name) { gboolean enabled = nm_modem_get_mm_enabled (modem); - DBusGProxy *proxy; if (priv->connect_properties) g_hash_table_destroy (priv->connect_properties); @@ -260,14 +559,8 @@ act_stage1_prepare (NMModem *modem, if (enabled) do_connect (self); - else { - proxy = nm_modem_old_get_proxy (NM_MODEM_OLD (modem), MM_OLD_DBUS_INTERFACE_MODEM); - dbus_g_proxy_begin_call_with_timeout (proxy, - "Enable", stage1_enable_done, - modem, NULL, 20000, - G_TYPE_BOOLEAN, TRUE, - G_TYPE_INVALID); - } + else + do_enable (self); } else { /* NMModem will handle requesting secrets... */ } @@ -407,19 +700,21 @@ disconnect (NMModem *self, static void deactivate (NMModem *self, NMDevice *device) { - NMModemOldPrivate *priv; + NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (self); - g_assert (NM_IS_MODEM_OLD (self)); - g_assert (NM_IS_DEVICE (device)); - - priv = NM_MODEM_OLD_GET_PRIVATE (self); + priv->pin_tries = 0; if (priv->call) { dbus_g_proxy_cancel_call (priv->proxy, priv->call); priv->call = NULL; } - /* Chain up parent's */ + if (priv->enable_delay_id) { + g_source_remove (priv->enable_delay_id); + priv->enable_delay_id = 0; + } + + /* Chain up parent */ NM_MODEM_CLASS (nm_modem_old_parent_class)->deactivate (self, device); } @@ -479,7 +774,7 @@ check_connection_compatible (NMModem *modem, { NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (modem); NMSettingConnection *s_con; - gboolean valid_cdma = FALSE; + gboolean valid_cdma = FALSE, valid_gsm = FALSE; const char *ctype; s_con = nm_connection_get_setting_connection (connection); @@ -491,6 +786,9 @@ check_connection_compatible (NMModem *modem, if (strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME) == 0) valid_cdma = !!nm_connection_get_setting_cdma (connection); + if (strcmp (ctype, NM_SETTING_GSM_SETTING_NAME) == 0) + valid_gsm = !!nm_connection_get_setting_gsm (connection); + /* Validate CDMA */ if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) { if (valid_cdma) @@ -504,6 +802,16 @@ check_connection_compatible (NMModem *modem, } } + /* Validate 3GPP */ + if (priv->caps & CAPS_3GPP) { + if (valid_gsm) + return TRUE; + + g_set_error (error, NM_MODEM_ERROR, NM_MODEM_ERROR_CONNECTION_NOT_GSM, + "The connection was not a GSM/UMTS/LTE connection."); + return FALSE; + } + g_set_error (error, NM_MODEM_ERROR, NM_MODEM_ERROR_CONNECTION_INCOMPATIBLE, "The connection was not not compatible with this modem (caps 0x%X)", priv->caps); @@ -528,6 +836,37 @@ complete_ppp_setting (NMConnection *connection) } } +static gboolean +complete_connection_3gpp (NMConnection *connection, + const GSList *existing_connections, + GError **error) +{ + NMSettingGsm *s_gsm; + + s_gsm = nm_connection_get_setting_gsm (connection); + if (!s_gsm || !nm_setting_gsm_get_apn (s_gsm)) { + /* Need an APN at least */ + g_set_error_literal (error, + NM_SETTING_GSM_ERROR, + NM_SETTING_GSM_ERROR_MISSING_PROPERTY, + NM_SETTING_GSM_APN); + return FALSE; + } + + if (!nm_setting_gsm_get_number (s_gsm)) + g_object_set (G_OBJECT (s_gsm), NM_SETTING_GSM_NUMBER, "*99#", NULL); + + complete_ppp_setting (connection); + + nm_utils_complete_generic (connection, + NM_SETTING_GSM_SETTING_NAME, + existing_connections, + _("GSM connection %d"), + NULL, + FALSE); /* No IPv6 yet by default */ + return TRUE; +} + static gboolean complete_connection_cdma (NMConnection *connection, const GSList *existing_connections, @@ -563,9 +902,19 @@ complete_connection (NMModem *modem, { NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (modem); + /* If the modem has LTE, complete as 3GPP */ + if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_LTE) + return complete_connection_3gpp (connection, existing_connections, error); + + /* Otherwise, prefer CDMA on the theory that if the modem has CDMA/EVDO + * that's most likely what the user will be using. + */ if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) return complete_connection_cdma (connection, existing_connections, error); + if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) + return complete_connection_3gpp (connection, existing_connections, error); + g_set_error_literal (error, NM_MODEM_ERROR, NM_MODEM_ERROR_CONNECTION_INCOMPATIBLE, "Modem had no WWAN capabilities."); return FALSE; @@ -581,6 +930,7 @@ get_user_pass (NMModem *modem, { NMModemOldPrivate *priv = NM_MODEM_OLD_GET_PRIVATE (modem); NMSettingCdma *s_cdma; + NMSettingGsm *s_gsm; if (priv->caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) { s_cdma = nm_connection_get_setting_cdma (connection); @@ -593,6 +943,16 @@ get_user_pass (NMModem *modem, } } + /* Fall back to GSM; will be used for CDMA devices on LTE networks too */ + s_gsm = nm_connection_get_setting_gsm (connection); + if (s_gsm) { + if (user) + *user = nm_setting_gsm_get_username (s_gsm); + if (pass) + *pass = nm_setting_gsm_get_password (s_gsm); + return TRUE; + } + return FALSE; } @@ -633,6 +993,8 @@ nm_modem_old_new (const char *path, if (self) { if (modem_type == MM_OLD_MODEM_TYPE_CDMA) caps |= NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO; + if (modem_type == MM_OLD_MODEM_TYPE_GSM) + caps |= NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS; NM_MODEM_OLD_GET_PRIVATE (self)->caps = caps; } @@ -707,6 +1069,11 @@ dispose (GObject *object) priv->connect_properties = NULL; } + if (priv->enable_delay_id) { + g_source_remove (priv->enable_delay_id); + priv->enable_delay_id = 0; + } + G_OBJECT_CLASS (nm_modem_old_parent_class)->dispose (object); }