From d28b756e61665046ccfb83c79daab71189f56ee6 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Tue, 5 Feb 2013 18:57:26 +0100 Subject: [PATCH] network: try to guess operator name from MCCMNC or SID When the network doesn't provide a valid text string with the current operator name, try to guess it using either the 3GPP MCCMNC pair or with the CDMA SID. Guessing is based on the Mobile Providers Database for which there is an API in libnm-gtk (>= 0.9.7.995). The same logic to guess operator name is used in gnome-shell. --- panels/network/net-device-mobile.c | 197 +++++++++++++++++++++++++++-- 1 file changed, 185 insertions(+), 12 deletions(-) diff --git a/panels/network/net-device-mobile.c b/panels/network/net-device-mobile.c index 1f98278f9..aafdc79e7 100644 --- a/panels/network/net-device-mobile.c +++ b/panels/network/net-device-mobile.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "panel-common.h" #include "network-dialogs.h" @@ -48,10 +49,13 @@ struct _NetDeviceMobilePrivate /* Old MM < 0.7 support */ GDBusProxy *gsm_proxy; + GDBusProxy *cdma_proxy; /* New MM >= 0.7 support */ MMObject *mm_object; guint operator_name_updated; + + NMAMobileProvidersDatabase *mpd; }; enum { @@ -265,14 +269,57 @@ device_mobile_refresh_equipment_id (NetDeviceMobile *device_mobile) panel_set_device_widget_details (device_mobile->priv->builder, "imei", equipment_id); } +static gchar * +device_mobile_find_provider (NetDeviceMobile *device_mobile, + const gchar *mccmnc, + guint32 sid) +{ + NMAMobileProvider *provider; + GString *name = NULL; + + if (device_mobile->priv->mpd == NULL) { + GError *error = NULL; + + /* Use defaults */ + device_mobile->priv->mpd = nma_mobile_providers_database_new_sync (NULL, NULL, NULL, &error); + if (device_mobile->priv->mpd == NULL) { + g_debug ("Couldn't load mobile providers database: %s", + error ? error->message : ""); + g_clear_error (&error); + return NULL; + } + } + + if (mccmnc != NULL) { + provider = nma_mobile_providers_database_lookup_3gpp_mcc_mnc (device_mobile->priv->mpd, mccmnc); + if (provider != NULL) + name = g_string_new (nma_mobile_provider_get_name (provider)); + } + + if (sid != 0) { + provider = nma_mobile_providers_database_lookup_cdma_sid (device_mobile->priv->mpd, sid); + if (provider != NULL) { + if (name == NULL) + name = g_string_new (nma_mobile_provider_get_name (provider)); + else + g_string_append_printf (name, ", %s", nma_mobile_provider_get_name (provider)); + } + } + + return (name != NULL ? g_string_free (name, FALSE) : NULL); +} + static void device_mobile_refresh_operator_name (NetDeviceMobile *device_mobile) { if (device_mobile->priv->mm_object != NULL) { gchar *operator_name = NULL; MMModem3gpp *modem_3gpp; + MMModemCdma *modem_cdma; modem_3gpp = mm_object_peek_modem_3gpp (device_mobile->priv->mm_object); + modem_cdma = mm_object_peek_modem_cdma (device_mobile->priv->mm_object); + if (modem_3gpp != NULL) { const gchar *operator_name_unsafe; @@ -281,6 +328,19 @@ device_mobile_refresh_operator_name (NetDeviceMobile *device_mobile) operator_name = g_strescape (operator_name_unsafe, NULL); } + /* If not directly given in the 3GPP interface, try to guess from + * MCCMNC/SID */ + if (operator_name == NULL) { + const gchar *mccmnc = NULL; + guint32 sid = 0; + + if (modem_3gpp != NULL) + mccmnc = mm_modem_3gpp_get_operator_code (modem_3gpp); + if (modem_cdma != NULL) + sid = mm_modem_cdma_get_sid (modem_cdma); + operator_name = device_mobile_find_provider (device_mobile, mccmnc, sid); + } + /* Set operator name */ if (operator_name != NULL) { g_debug ("[%s] Operator name set to '%s'", @@ -291,12 +351,28 @@ device_mobile_refresh_operator_name (NetDeviceMobile *device_mobile) panel_set_device_widget_details (device_mobile->priv->builder, "provider", operator_name); g_free (operator_name); } else { - const char *str; + const gchar *gsm; + const gchar *cdma; /* Assume old MM handling */ - str = g_object_get_data (G_OBJECT (device_mobile), - "ControlCenter::OperatorName"); - panel_set_device_widget_details (device_mobile->priv->builder, "provider", str); + gsm = g_object_get_data (G_OBJECT (device_mobile), + "ControlCenter::OperatorNameGsm"); + cdma = g_object_get_data (G_OBJECT (device_mobile), + "ControlCenter::OperatorNameCdma"); + + if (gsm != NULL && cdma != NULL) { + gchar *both; + + both = g_strdup_printf ("%s, %s", gsm, cdma); + panel_set_device_widget_details (device_mobile->priv->builder, "provider", both); + g_free (both); + } else if (gsm != NULL) { + panel_set_device_widget_details (device_mobile->priv->builder, "provider", gsm); + } else if (cdma != NULL) { + panel_set_device_widget_details (device_mobile->priv->builder, "provider", cdma); + } else { + panel_set_device_widget_details (device_mobile->priv->builder, "provider", NULL); + } } } @@ -446,7 +522,8 @@ device_mobile_device_got_modem_manager_cb (GObject *source_object, static void device_mobile_save_operator_name (NetDeviceMobile *device_mobile, - const gchar *operator_name) + const gchar *field, + const gchar *operator_name) { gchar *operator_name_safe = NULL; @@ -455,7 +532,7 @@ device_mobile_save_operator_name (NetDeviceMobile *device_mobile, /* save */ g_object_set_data_full (G_OBJECT (device_mobile), - "ControlCenter::OperatorName", + field, operator_name_safe, g_free); /* refresh */ @@ -463,9 +540,9 @@ device_mobile_save_operator_name (NetDeviceMobile *device_mobile, } static void -device_mobile_get_registration_info_cb (GObject *source_object, +device_mobile_get_registration_info_cb (GObject *source_object, GAsyncResult *res, - gpointer user_data) + gpointer user_data) { gchar *operator_code = NULL; GError *error = NULL; @@ -488,8 +565,16 @@ device_mobile_get_registration_info_cb (GObject *source_object, &operator_code, &operator_name); + /* If none give, try to guess it */ + if (operator_name == NULL || operator_name[0] == '\0') { + g_free (operator_name); + operator_name = device_mobile_find_provider (device_mobile, operator_code, 0); + } + /* save and refresh */ - device_mobile_save_operator_name (device_mobile, operator_name); + device_mobile_save_operator_name (device_mobile, + "ControlCenter::OperatorNameGsm", + operator_name); g_free (operator_name); g_free (operator_code); @@ -517,17 +602,25 @@ device_mobile_gsm_signal_cb (GDBusProxy *proxy, &operator_code, &operator_name); + /* If none given, try to guess it */ + if (operator_name == NULL || operator_name[0] == '\0') { + g_free (operator_name); + operator_name = device_mobile_find_provider (device_mobile, operator_code, 0); + } + /* save and refresh */ - device_mobile_save_operator_name (device_mobile, operator_name); + device_mobile_save_operator_name (device_mobile, + "ControlCenter::OperatorNameGsm", + operator_name); g_free (operator_code); g_free (operator_name); } static void -device_mobile_device_got_modem_manager_gsm_cb (GObject *source_object, +device_mobile_device_got_modem_manager_gsm_cb (GObject *source_object, GAsyncResult *res, - gpointer user_data) + gpointer user_data) { GError *error = NULL; NetDeviceMobile *device_mobile = (NetDeviceMobile *)user_data; @@ -557,6 +650,72 @@ device_mobile_device_got_modem_manager_gsm_cb (GObject *source_object, device_mobile); } +static void +device_mobile_get_serving_system_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NetDeviceMobile *device_mobile = (NetDeviceMobile *)user_data; + GVariant *result = NULL; + GError *error = NULL; + + guint32 band_class; + gchar *band; + guint32 sid; + gchar *operator_name; + + result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); + if (result == NULL) { + g_warning ("Error getting serving system: %s\n", + error->message); + g_error_free (error); + return; + } + + /* get values */ + g_variant_get (result, "((usu))", + &band_class, + &band, + &sid); + + operator_name = device_mobile_find_provider (device_mobile, NULL, sid); + + /* save and refresh */ + device_mobile_save_operator_name (device_mobile, + "ControlCenter::OperatorNameCdma", + operator_name); + + g_free (band); + g_variant_unref (result); +} + +static void +device_mobile_device_got_modem_manager_cdma_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + NetDeviceMobile *device_mobile = (NetDeviceMobile *)user_data; + + device_mobile->priv->cdma_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + if (device_mobile->priv->cdma_proxy == NULL) { + g_warning ("Error creating ModemManager CDMA proxy: %s\n", + error->message); + g_error_free (error); + return; + } + + /* Load initial value */ + g_dbus_proxy_call (device_mobile->priv->cdma_proxy, + "GetServingSystem", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + device_mobile_get_serving_system_cb, + device_mobile); +} + static void net_device_mobile_constructed (GObject *object) { @@ -600,6 +759,18 @@ net_device_mobile_constructed (GObject *object) device_mobile_device_got_modem_manager_gsm_cb, device_mobile); } + + if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) { + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.ModemManager", + nm_device_get_udi (device), + "org.freedesktop.ModemManager.Modem.Cdma", + cancellable, + device_mobile_device_got_modem_manager_cdma_cb, + device_mobile); + } } client = net_object_get_client (NET_OBJECT (device_mobile)); @@ -686,6 +857,7 @@ net_device_mobile_dispose (GObject *object) g_clear_object (&priv->builder); g_clear_object (&priv->gsm_proxy); + g_clear_object (&priv->cdma_proxy); if (priv->operator_name_updated) { g_assert (priv->mm_object != NULL); @@ -693,6 +865,7 @@ net_device_mobile_dispose (GObject *object) priv->operator_name_updated = 0; } g_clear_object (&priv->mm_object); + g_clear_object (&priv->mpd); G_OBJECT_CLASS (net_device_mobile_parent_class)->dispose (object); }