diff options
-rw-r--r-- | src/mm-broadband-modem.c | 51 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.c | 161 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.h | 8 |
3 files changed, 164 insertions, 56 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 478ab1a8..e858cd5c 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -11,8 +11,8 @@ * GNU General Public License for more details: * * Copyright (C) 2008 - 2009 Novell, Inc. - * Copyright (C) 2009 - 2011 Red Hat, Inc. - * Copyright (C) 2011 Google, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. + * Copyright (C) 2011 - 2012 Google, Inc. */ #include <config.h> @@ -1982,14 +1982,15 @@ registration_state_changed (MMAtSerialPort *port, if (cgreg) mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), state, - act); + act, + lac, + cell_id); else mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), state, - act); - - /* TODO: report LAC/CI location */ - /* update_lac_ci (self, lac, cell_id, cgreg ? 1 : 0); */ + act, + lac, + cell_id); } static void @@ -2199,10 +2200,12 @@ run_all_3gpp_registration_checks_ready (MMBroadbandModem *self, mm_dbg ("3GPP registration check failed: '%s'", error->message); mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, - MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + 0, 0); mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, - MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + 0, 0); g_simple_async_result_take_error (ctx->result, error); register_in_3gpp_network_context_complete_and_free (ctx); return; @@ -2221,10 +2224,12 @@ run_all_3gpp_registration_checks_ready (MMBroadbandModem *self, mm_dbg ("3GPP registration check timed out"); mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, - MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + 0, 0); mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, - MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + 0, 0); g_simple_async_result_take_error ( ctx->result, mm_mobile_equipment_error_for_code (MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT)); @@ -2257,10 +2262,12 @@ register_in_3gpp_network_ready (MMBroadbandModem *self, /* Propagate error in COPS, if any */ mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, - MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + 0, 0); mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, - MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + 0, 0); g_simple_async_result_take_error (ctx->result, error); register_in_3gpp_network_context_complete_and_free (ctx); return; @@ -2443,14 +2450,16 @@ registration_status_check_ready (MMBroadbandModem *self, mm_iface_modem_3gpp_update_ps_registration_state ( MM_IFACE_MODEM_3GPP (self), state, - act); + act, + lac, + cid); else mm_iface_modem_3gpp_update_cs_registration_state ( MM_IFACE_MODEM_3GPP (self), state, - act); - - /* TODO: report LAC/CI location */ + act, + lac, + cid); g_simple_async_result_set_op_res_gboolean (operation_result, TRUE); } @@ -2578,12 +2587,14 @@ cleanup_registration_sequence_ready (MMBroadbandModem *self, mm_iface_modem_3gpp_update_cs_registration_state ( MM_IFACE_MODEM_3GPP (self), MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, - MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + 0, 0); else mm_iface_modem_3gpp_update_ps_registration_state ( MM_IFACE_MODEM_3GPP (self), MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, - MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); + MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, + 0, 0); /* We're done */ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); @@ -4008,7 +4019,7 @@ modem_location_load_capabilities (MMIfaceModemLocation *self, NULL); else g_simple_async_result_set_op_res_gpointer (result, - GUINT_TO_POINTER (MM_MODEM_LOCATION_SOURCE_GSM_LAC_CI), + GUINT_TO_POINTER (MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI), NULL); g_simple_async_result_complete_in_idle (result); diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c index 18f71e7d..b4885af1 100644 --- a/src/mm-iface-modem-3gpp.c +++ b/src/mm-iface-modem-3gpp.c @@ -10,13 +10,17 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * - * Copyright (C) 2011 Google, Inc. + * Copyright (C) 2011 - 2012 Google, Inc. */ +#include <stdlib.h> +#include <string.h> + #include <ModemManager.h> #include <libmm-common.h> #include "mm-iface-modem.h" +#include "mm-iface-modem-location.h" #include "mm-iface-modem-3gpp.h" #include "mm-bearer-3gpp.h" #include "mm-bearer-list.h" @@ -537,33 +541,91 @@ mm_iface_modem_3gpp_run_all_registration_checks (MMIfaceModem3gpp *self, /*****************************************************************************/ -#undef STR_REPLY_READY_FN -#define STR_REPLY_READY_FN(NAME, DISPLAY) \ - static void \ - load_##NAME##_ready (MMIfaceModem3gpp *self, \ - GAsyncResult *res) \ - { \ - GError *error = NULL; \ - MmGdbusModem3gpp *skeleton = NULL; \ - gchar *str; \ - \ - str = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_##NAME##_finish (self, res, &error); \ - if (error) { \ - mm_warn ("Couldn't load %s: '%s'", DISPLAY, error->message); \ - g_error_free (error); \ - return; \ - } \ - \ - g_object_get (self, \ - MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, \ - NULL); \ - mm_gdbus_modem3gpp_set_##NAME (skeleton, str); \ - g_free (str); \ - g_object_unref (skeleton); \ +static void +load_operator_name_ready (MMIfaceModem3gpp *self, + GAsyncResult *res) +{ + GError *error = NULL; + MmGdbusModem3gpp *skeleton = NULL; + gchar *str; + + str = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_name_finish (self, res, &error); + if (error) { + mm_warn ("Couldn't load Operator Name: '%s'", error->message); + g_error_free (error); + return; + } + + g_object_get (self, + MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, + NULL); + mm_gdbus_modem3gpp_set_operator_name (skeleton, str); + g_free (str); + g_object_unref (skeleton); +} + +static gboolean +parse_mcc_mnc (const gchar *mccmnc, + guint *mcc_out, + guint *mnc_out) +{ + guint mccmnc_len; + gchar mcc[4] = { 0, 0, 0, 0 }; + gchar mnc[4] = { 0, 0, 0, 0 }; + + mccmnc_len = strlen (mccmnc); + if (mccmnc_len != 5 && + mccmnc_len != 6) { + mm_dbg ("Unexpected MCC/MNC string '%s'", mccmnc); + return FALSE; } -STR_REPLY_READY_FN (operator_code, "Operator Code") -STR_REPLY_READY_FN (operator_name, "Operator Name") + memcpy (mcc, mccmnc, 3); + /* Not all modems report 6-digit MNCs */ + memcpy (mnc, mccmnc + 3, 2); + if (mccmnc_len == 6) + mnc[2] = mccmnc[5]; + + *mcc_out = atoi (mcc); + *mnc_out = atoi (mnc); + + return TRUE; +} + +static void +load_operator_code_ready (MMIfaceModem3gpp *self, + GAsyncResult *res) +{ + GError *error = NULL; + MmGdbusModem3gpp *skeleton = NULL; + gchar *str; + + str = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_operator_code_finish (self, res, &error); + if (error) { + mm_warn ("Couldn't load Operator Code: '%s'", error->message); + g_error_free (error); + return; + } + + g_object_get (self, + MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, + NULL); + mm_gdbus_modem3gpp_set_operator_code (skeleton, str); + + /* If we also implement the location interface, update the 3GPP location */ + if (MM_IS_IFACE_MODEM_LOCATION (self)) { + guint mcc = 0; + guint mnc = 0; + + if (parse_mcc_mnc (str, &mcc, &mnc)) + mm_iface_modem_location_3gpp_update_mcc_mnc (MM_IFACE_MODEM_LOCATION (self), + mcc, + mnc); + } + + g_free (str); + g_object_unref (skeleton); +} static void set_bearer_3gpp_connection_allowed (MMBearer *bearer, @@ -641,14 +703,19 @@ bearer_3gpp_connection_forbidden (MMIfaceModem3gpp *self) static void update_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState new_state, - MMModemAccessTechnology access_tech) + MMModemAccessTechnology access_tech, + gulong location_area_code, + gulong cell_id) { - MMModem3gppRegistrationState old_state; + MMModem3gppRegistrationState old_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; + MmGdbusModem3gpp *skeleton = NULL; /* Only set new state if different */ g_object_get (self, MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, &old_state, + MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, NULL); + if (new_state != old_state) { GEnumClass *enum_class; GEnumValue *new_value; @@ -694,8 +761,6 @@ update_registration_state (MMIfaceModem3gpp *self, (GAsyncReadyCallback)load_operator_name_ready, NULL); - /* TODO: Update signal quality */ - mm_iface_modem_update_access_tech (MM_IFACE_MODEM (self), access_tech, ALL_3GPP_ACCESS_TECHNOLOGIES_MASK); @@ -704,16 +769,30 @@ update_registration_state (MMIfaceModem3gpp *self, SUBSYSTEM_3GPP, MM_MODEM_STATE_REGISTERED, MM_MODEM_STATE_REASON_NONE); + + /* If we also implement the location interface, update the 3GPP location */ + if (MM_IS_IFACE_MODEM_LOCATION (self)) + mm_iface_modem_location_3gpp_update_lac_ci (MM_IFACE_MODEM_LOCATION (self), + location_area_code, + cell_id); break; case MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING: case MM_MODEM_3GPP_REGISTRATION_STATE_IDLE: case MM_MODEM_3GPP_REGISTRATION_STATE_DENIED: case MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN: + mm_gdbus_modem3gpp_set_operator_code (skeleton, NULL); + mm_gdbus_modem3gpp_set_operator_name (skeleton, NULL); + + if (MM_IS_IFACE_MODEM_LOCATION (self)) + mm_iface_modem_location_3gpp_clear (MM_IFACE_MODEM_LOCATION (self)); + mm_iface_modem_update_access_tech (MM_IFACE_MODEM (self), 0, ALL_3GPP_ACCESS_TECHNOLOGIES_MASK); + bearer_3gpp_connection_forbidden (self); + mm_iface_modem_update_subsystem_state ( MM_IFACE_MODEM (self), SUBSYSTEM_3GPP, @@ -724,6 +803,8 @@ update_registration_state (MMIfaceModem3gpp *self, break; } } + + g_object_unref (skeleton); } typedef struct { @@ -785,7 +866,9 @@ get_consolidated_reg_state (RegistrationStateContext *ctx) void mm_iface_modem_3gpp_update_cs_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState state, - MMModemAccessTechnology access_tech) + MMModemAccessTechnology access_tech, + gulong location_area_code, + gulong cell_id) { RegistrationStateContext *ctx; gboolean supported = FALSE; @@ -799,13 +882,19 @@ mm_iface_modem_3gpp_update_cs_registration_state (MMIfaceModem3gpp *self, ctx = get_registration_state_context (self); ctx->cs = state; - update_registration_state (self, get_consolidated_reg_state (ctx), access_tech); + update_registration_state (self, + get_consolidated_reg_state (ctx), + access_tech, + location_area_code, + cell_id); } void mm_iface_modem_3gpp_update_ps_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState state, - MMModemAccessTechnology access_tech) + MMModemAccessTechnology access_tech, + gulong location_area_code, + gulong cell_id) { RegistrationStateContext *ctx; gboolean supported = FALSE; @@ -819,7 +908,11 @@ mm_iface_modem_3gpp_update_ps_registration_state (MMIfaceModem3gpp *self, ctx = get_registration_state_context (self); ctx->ps = state; - update_registration_state (self, get_consolidated_reg_state (ctx), access_tech); + update_registration_state (self, + get_consolidated_reg_state (ctx), + access_tech, + location_area_code, + cell_id); } /*****************************************************************************/ diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h index ded5e61c..04036229 100644 --- a/src/mm-iface-modem-3gpp.h +++ b/src/mm-iface-modem-3gpp.h @@ -217,10 +217,14 @@ void mm_iface_modem_3gpp_shutdown (MMIfaceModem3gpp *self); * the interface asks to run registration state checks. */ void mm_iface_modem_3gpp_update_cs_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState state, - MMModemAccessTechnology access_tech); + MMModemAccessTechnology access_tech, + gulong location_area_code, + gulong cell_id); void mm_iface_modem_3gpp_update_ps_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState state, - MMModemAccessTechnology access_tech); + MMModemAccessTechnology access_tech, + gulong location_area_code, + gulong cell_id); /* Run all registration checks */ void mm_iface_modem_3gpp_run_all_registration_checks (MMIfaceModem3gpp *self, |