diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-generic-gsm.c | 144 | ||||
-rw-r--r-- | src/mm-generic-gsm.h | 19 | ||||
-rw-r--r-- | src/mm-modem-gsm-network.c | 85 | ||||
-rw-r--r-- | src/mm-modem-gsm-network.h | 16 | ||||
-rw-r--r-- | src/mm-modem-gsm.h | 15 |
5 files changed, 253 insertions, 26 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 9e35b339..b28000c6 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -29,6 +29,7 @@ #include "mm-serial-parsers.h" #include "mm-modem-helpers.h" #include "mm-options.h" +#include "mm-properties-changed-signal.h" static void modem_init (MMModem *modem_class); static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class); @@ -69,7 +70,7 @@ typedef struct { /* Index 0 for CREG, index 1 for CGREG */ gulong lac[2]; gulong cell_id[2]; - gint access_tech[2]; + MMModemGsmMode access_tech; MMModemGsmNetworkRegStatus reg_status; guint pending_reg_id; @@ -107,6 +108,8 @@ static gboolean handle_reg_status_response (MMGenericGsm *self, GString *response, GError **error); +static MMModemGsmMode etsi_act_to_mm_mode (gint act); + MMModem * mm_generic_gsm_new (const char *device, const char *driver, @@ -864,7 +867,8 @@ disable (MMModem *modem, MMModemFn callback, gpointer user_data) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + MMGenericGsm *self = MM_GENERIC_GSM (modem); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); MMCallbackInfo *info; MMModemState state; @@ -881,8 +885,7 @@ disable (MMModem *modem, priv->lac[1] = 0; priv->cell_id[0] = 0; priv->cell_id[1] = 0; - priv->access_tech[0] = -1; - priv->access_tech[1] = -1; + mm_generic_gsm_update_access_technology (self, MM_MODEM_GSM_MODE_UNKNOWN); /* Close the secondary port if its open */ if (priv->secondary && mm_serial_port_is_open (priv->secondary)) @@ -1465,7 +1468,10 @@ reg_state_changed (MMSerialPort *port, idx = cgreg ? 1 : 0; priv->lac[idx] = lac; priv->cell_id[idx] = cell_id; - priv->access_tech[idx] = access_tech; + + /* Only update access technology if it appeared in the CREG/CGREG response */ + if (access_tech != -1) + mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_mode (access_tech)); } static gboolean @@ -1531,8 +1537,10 @@ handle_reg_status_response (MMGenericGsm *self, idx = cgreg ? 1 : 0; priv->lac[idx] = lac; priv->cell_id[idx] = ci; - if (act >= 0) /* Let subclasses handle if they want */ - priv->access_tech[idx] = act; + + /* Only update access technology if it appeared in the CREG/CGREG response */ + if (act != -1) + mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_mode (act)); if ((cgreg == FALSE) && status >= 0) { /* Update cached registration status */ @@ -2161,6 +2169,84 @@ get_signal_quality (MMModemGsmNetwork *modem, } /*****************************************************************************/ + +typedef struct { + MMModemGsmMode mode; + gint etsi_act; +} ModeEtsi; + +static ModeEtsi modes_table[] = { + { MM_MODEM_GSM_MODE_GSM, 0 }, + { MM_MODEM_GSM_MODE_GSM_COMPACT, 1 }, + { MM_MODEM_GSM_MODE_UMTS, 2 }, + { MM_MODEM_GSM_MODE_EDGE, 3 }, + { MM_MODEM_GSM_MODE_HSDPA, 4 }, + { MM_MODEM_GSM_MODE_HSUPA, 5 }, + { MM_MODEM_GSM_MODE_HSDPA | + MM_MODEM_GSM_MODE_HSUPA, 6 }, + { MM_MODEM_GSM_MODE_HSDPA | + MM_MODEM_GSM_MODE_HSUPA, 7 }, /* E-UTRAN/LTE */ + { MM_MODEM_GSM_MODE_UNKNOWN, -1 }, +}; + +static MMModemGsmMode +etsi_act_to_mm_mode (gint act) +{ + ModeEtsi *iter = &modes_table[0]; + + while (iter->mode != MM_MODEM_GSM_MODE_UNKNOWN) { + if (iter->etsi_act == act) + return iter->mode; + } + return MM_MODEM_GSM_MODE_UNKNOWN; +} + +static gboolean +check_for_single_value (guint32 value) +{ + gboolean found = FALSE; + guint32 i; + + for (i = 1; i <= 32; i++) { + if (value & 0x1) { + if (found) + return FALSE; /* More than one bit set */ + found = TRUE; + } + value >>= 1; + } + + return TRUE; +} + +void +mm_generic_gsm_update_access_technology (MMGenericGsm *modem, + MMModemGsmMode mode) +{ + MMGenericGsmPrivate *priv; + + g_return_if_fail (modem != NULL); + g_return_if_fail (MM_IS_GENERIC_GSM (modem)); + + g_return_if_fail (check_for_single_value (mode) || (mode == MM_MODEM_GSM_MODE_HSPA)); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_ANY) == 0); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_2G_PREFERRED) == 0); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_3G_PREFERRED) == 0); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_2G_ONLY) == 0); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_3G_ONLY) == 0); + + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + + if (mode != priv->access_tech) { + priv->access_tech = mode; + g_object_notify (G_OBJECT (modem), MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY); + + /* Deprecated value */ + g_signal_emit_by_name (G_OBJECT (modem), "NetworkMode", mode); + } +} + +/*****************************************************************************/ /* MMModemGsmSms interface */ static void @@ -2410,17 +2496,6 @@ simple_status_got_band (MMModem *modem, } static void -simple_status_got_mode (MMModem *modem, - guint32 result, - GError *error, - gpointer user_data) -{ - /* Ignore network mode errors since there's no generic implementation for it */ - if (!error) - g_hash_table_insert ((GHashTable *) user_data, "network_mode", simple_uint_value (result)); -} - -static void simple_status_got_reg_info (MMModemGsmNetwork *modem, MMModemGsmNetworkRegStatus status, const char *oper_code, @@ -2459,9 +2534,11 @@ simple_get_status (MMModemSimple *simple, MMModemSimpleGetStatusFn callback, gpointer user_data) { - MMModemGsmNetwork *gsm; + MMModemGsmNetwork *gsm = MM_MODEM_GSM_NETWORK (simple); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (simple); GHashTable *properties; MMCallbackInfo *info; + MMModemDeprecatedMode old_mode; info = mm_callback_info_new_full (MM_MODEM (simple), simple_get_status_invoke, @@ -2471,11 +2548,18 @@ simple_get_status (MMModemSimple *simple, properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, simple_free_gvalue); mm_callback_info_set_data (info, "simple-get-status", properties, (GDestroyNotify) g_hash_table_unref); - gsm = MM_MODEM_GSM_NETWORK (simple); mm_modem_gsm_network_get_signal_quality (gsm, simple_status_got_signal_quality, properties); mm_modem_gsm_network_get_band (gsm, simple_status_got_band, properties); - mm_modem_gsm_network_get_mode (gsm, simple_status_got_mode, properties); mm_modem_gsm_network_get_registration_info (gsm, simple_status_got_reg_info, properties); + + if (priv->access_tech > -1) { + /* Deprecated key */ + old_mode = mm_modem_gsm_network_new_mode_to_old (priv->access_tech); + g_hash_table_insert (properties, "network_mode", simple_uint_value (old_mode)); + + /* New key */ + g_hash_table_insert (properties, "access_technology", simple_uint_value (priv->access_tech)); + } } /*****************************************************************************/ @@ -2532,9 +2616,12 @@ mm_generic_gsm_init (MMGenericGsm *self) { MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - priv->access_tech[0] = -1; - priv->access_tech[1] = -1; + priv->access_tech = MM_MODEM_GSM_MODE_UNKNOWN; priv->reg_regex = mm_gsm_creg_regex_get (TRUE); + + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, + MM_MODEM_GSM_NETWORK_DBUS_INTERFACE); } static void @@ -2549,6 +2636,7 @@ set_property (GObject *object, guint prop_id, case MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL: case MM_GENERIC_GSM_PROP_SUPPORTED_BANDS: case MM_GENERIC_GSM_PROP_SUPPORTED_MODES: + case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY: break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -2597,6 +2685,12 @@ get_property (GObject *object, guint prop_id, case MM_GENERIC_GSM_PROP_SUPPORTED_MODES: g_value_set_uint (value, 0); break; + case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY: + if (mm_modem_get_state (MM_MODEM (object)) >= MM_MODEM_STATE_ENABLED) + g_value_set_uint (value, priv->access_tech); + else + g_value_set_uint (value, MM_MODEM_GSM_MODE_UNKNOWN); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2659,6 +2753,10 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) MM_GENERIC_GSM_PROP_SUPPORTED_MODES, MM_MODEM_GSM_CARD_SUPPORTED_MODES); + g_object_class_override_property (object_class, + MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY, + MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY); + g_object_class_install_property (object_class, MM_GENERIC_GSM_PROP_POWER_UP_CMD, g_param_spec_string (MM_GENERIC_GSM_POWER_UP_CMD, diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 5e07b77d..477ec6b7 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -11,7 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2008 - 2009 Novell, Inc. - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #ifndef MM_GENERIC_GSM_H @@ -43,7 +43,8 @@ typedef enum { MM_GENERIC_GSM_PROP_INIT_CMD, MM_GENERIC_GSM_PROP_SUPPORTED_BANDS, MM_GENERIC_GSM_PROP_SUPPORTED_MODES, - MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL + MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL, + MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY } MMGenericGsmProp; @@ -76,6 +77,13 @@ typedef struct { GString *response, GError *error, MMCallbackInfo *info); + + /* Called by the generic class to the current radio access technology the + * device is using while communicating with the base station. + */ + void (*get_access_technology) (MMGenericGsm *self, + MMModemUIntFn callback, + gpointer user_data); } MMGenericGsmClass; GType mm_generic_gsm_get_type (void); @@ -97,6 +105,13 @@ guint32 mm_generic_gsm_get_cid (MMGenericGsm *modem); void mm_generic_gsm_set_reg_status (MMGenericGsm *modem, MMModemGsmNetworkRegStatus status); +/* Called to asynchronously update the current access technology of the device; + * this is NOT the 2G/3G mode preference, but the current radio access + * technology being used to communicate with the base station. + */ +void mm_generic_gsm_update_access_technology (MMGenericGsm *modem, + MMModemGsmMode mode); + void mm_generic_gsm_check_pin (MMGenericGsm *modem, MMModemFn callback, gpointer user_data); diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index f332f580..ca00decc 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -11,6 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2008 Novell, Inc. + * Copyright (C) 2010 Red Hat, Inc. */ #include <string.h> @@ -42,6 +43,10 @@ static void impl_gsm_modem_set_band (MMModemGsmNetwork *modem, static void impl_gsm_modem_get_band (MMModemGsmNetwork *modem, DBusGMethodInvocation *context); +static void impl_gsm_modem_set_allowed_modes (MMModemGsmNetwork *modem, + MMModemGsmMode mode, + DBusGMethodInvocation *context); + static void impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, MMModemGsmMode mode, DBusGMethodInvocation *context); @@ -68,6 +73,67 @@ static guint signals[LAST_SIGNAL] = { 0 }; /*****************************************************************************/ +MMModemGsmMode +mm_modem_gsm_network_old_mode_to_new (MMModemDeprecatedMode old_mode) +{ + /* Translate deprecated mode into new mode */ + switch (old_mode) { + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS: + return MM_MODEM_GSM_MODE_GPRS; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE: + return MM_MODEM_GSM_MODE_EDGE; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS: + return MM_MODEM_GSM_MODE_UMTS; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA: + return MM_MODEM_GSM_MODE_HSDPA; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED: + return MM_MODEM_GSM_MODE_2G_PREFERRED; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED: + return MM_MODEM_GSM_MODE_3G_PREFERRED; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY: + return MM_MODEM_GSM_MODE_2G_ONLY; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY: + return MM_MODEM_GSM_MODE_3G_ONLY; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA: + return MM_MODEM_GSM_MODE_HSUPA; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA: + return MM_MODEM_GSM_MODE_HSDPA | MM_MODEM_GSM_MODE_HSUPA; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY: + default: + break; + } + + return MM_MODEM_GSM_MODE_ANY; +} + +MMModemDeprecatedMode +mm_modem_gsm_network_new_mode_to_old (MMModemGsmMode new_mode) +{ + /* Translate new mode into old deprecated mode */ + if (new_mode & MM_MODEM_GSM_MODE_GPRS) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS; + else if (new_mode & MM_MODEM_GSM_MODE_EDGE) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE; + else if (new_mode & MM_MODEM_GSM_MODE_UMTS) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS; + else if (new_mode & MM_MODEM_GSM_MODE_HSDPA) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA; + else if (new_mode & MM_MODEM_GSM_MODE_2G_PREFERRED) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED; + else if (new_mode & MM_MODEM_GSM_MODE_3G_PREFERRED) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED; + else if (new_mode & MM_MODEM_GSM_MODE_2G_ONLY) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY; + else if (new_mode & MM_MODEM_GSM_MODE_3G_ONLY) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY; + else if (new_mode & MM_MODEM_GSM_MODE_HSUPA) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA; + + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY; +} + +/*****************************************************************************/ + static void async_call_done (MMModem *modem, GError *error, gpointer user_data) { @@ -492,6 +558,14 @@ impl_gsm_modem_get_band (MMModemGsmNetwork *modem, } static void +impl_gsm_modem_set_allowed_modes (MMModemGsmNetwork *modem, + MMModemGsmMode mode, + DBusGMethodInvocation *context) +{ + dbus_g_method_return (context); +} + +static void impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, MMModemGsmMode mode, DBusGMethodInvocation *context) @@ -534,6 +608,17 @@ mm_modem_gsm_network_init (gpointer g_iface) if (initialized) return; + g_object_interface_install_property + (g_iface, + g_param_spec_uint (MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, + "Access Technology", + "Current access technology in use when connected to " + "a mobile network.", + MM_MODEM_GSM_MODE_UNKNOWN, + MM_MODEM_GSM_MODE_LAST, + MM_MODEM_GSM_MODE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /* Signals */ signals[SIGNAL_QUALITY] = g_signal_new ("signal-quality", diff --git a/src/mm-modem-gsm-network.h b/src/mm-modem-gsm-network.h index 493baec7..3aa6ce30 100644 --- a/src/mm-modem-gsm-network.h +++ b/src/mm-modem-gsm-network.h @@ -11,7 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #ifndef MM_MODEM_GSM_NETWORK_H @@ -20,11 +20,21 @@ #include <mm-modem.h> #include <mm-modem-gsm.h> +#define MM_MODEM_GSM_NETWORK_DBUS_INTERFACE "org.freedesktop.ModemManager.Modem.Gsm.Network" + #define MM_TYPE_MODEM_GSM_NETWORK (mm_modem_gsm_network_get_type ()) #define MM_MODEM_GSM_NETWORK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_GSM_NETWORK, MMModemGsmNetwork)) #define MM_IS_MODEM_GSM_NETWORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_GSM_NETWORK)) #define MM_MODEM_GSM_NETWORK_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_MODEM_GSM_NETWORK, MMModemGsmNetwork)) +#define MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY "access-technology" + +typedef enum { + MM_MODEM_GSM_NETWORK_PROP_FIRST = 0x1200, + + MM_MODEM_GSM_NETWORK_PROP_ACCESS_TECHNOLOGY = MM_MODEM_GSM_NETWORK_PROP_FIRST, +} MMModemGsmNetworkProp; + typedef enum { MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE = 0, MM_MODEM_GSM_NETWORK_REG_STATUS_HOME = 1, @@ -161,4 +171,8 @@ void mm_modem_gsm_network_registration_info (MMModemGsmNetwork *self, void mm_modem_gsm_network_mode (MMModemGsmNetwork *self, MMModemGsmMode mode); +MMModemDeprecatedMode mm_modem_gsm_network_new_mode_to_old (MMModemGsmMode new_mode); + +MMModemGsmMode mm_modem_gsm_network_old_mode_to_new (MMModemDeprecatedMode old_mode); + #endif /* MM_MODEM_GSM_NETWORK_H */ diff --git a/src/mm-modem-gsm.h b/src/mm-modem-gsm.h index b10baf04..cac7c65f 100644 --- a/src/mm-modem-gsm.h +++ b/src/mm-modem-gsm.h @@ -29,6 +29,7 @@ typedef enum { MM_MODEM_GSM_MODE_2G_ONLY = 0x00000080, MM_MODEM_GSM_MODE_3G_ONLY = 0x00000100, MM_MODEM_GSM_MODE_HSUPA = 0x00000200, + MM_MODEM_GSM_MODE_HSPA = 0x00000210, /* HSDPA + HSUPA */ MM_MODEM_GSM_MODE_GSM = 0x00000400, MM_MODEM_GSM_MODE_GSM_COMPACT = 0x00000800, @@ -36,6 +37,20 @@ typedef enum { } MMModemGsmMode; 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 +} MMModemDeprecatedMode; + +typedef enum { MM_MODEM_GSM_BAND_UNKNOWN = 0x00000000, MM_MODEM_GSM_BAND_ANY = 0x00000001, MM_MODEM_GSM_BAND_EGSM = 0x00000002, /* 900 MHz */ |