diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2011-12-28 20:33:08 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-15 14:14:39 +0100 |
commit | e06d42c868745af69f63b8f9ca418b07b70602de (patch) | |
tree | 5395e15561a91f2a6690bd16c0e7d1e669903ff9 /src | |
parent | f0433a4dda362a5d8658c154abf356f1fc5f5c82 (diff) |
broadband-modem: implement on demand signal quality checks with AT+CSQ
Still need to implement CIND-based signal quality checks.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 13157fb2..4925ebcc 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -59,6 +59,12 @@ enum { PROP_LAST }; +typedef enum { + SIGNAL_QUALITY_METHOD_UNKNOWN, + SIGNAL_QUALITY_METHOD_CSQ, + SIGNAL_QUALITY_METHOD_CIND +} SignalQualityMethod; + struct _MMBroadbandModemPrivate { GObject *modem_dbus_skeleton; GObject *modem_3gpp_dbus_skeleton; @@ -72,6 +78,8 @@ struct _MMBroadbandModemPrivate { /* Modem helpers */ MMModemCharset current_charset; + SignalQualityMethod signal_quality_method; + guint cind_indicator_signal_quality; /* 3GPP registration helpers */ GPtrArray *reg_regex; @@ -647,6 +655,114 @@ load_unlock_required (MMIfaceModem *self, user_data); } + +/*****************************************************************************/ +/* SIGNAL QUALITY */ + +static guint +load_signal_quality_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) + return 0; + + return GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (res))); +} + +static void +load_signal_quality_csf_ready (MMBroadbandModem *self, + GAsyncResult *res, + GSimpleAsyncResult *simple) +{ + GError *error = NULL; + const gchar *result; + + result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); + if (error) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + if (result && + !strncmp (result, "+CSQ: ", 6)) { + /* Got valid reply */ + int quality; + int ber; + + if (sscanf (result + 6, "%d, %d", &quality, &ber)) { + /* 99 means unknown */ + if (quality == 99) { + g_simple_async_result_take_error ( + simple, + mm_mobile_equipment_error_for_code (MM_MOBILE_EQUIPMENT_ERROR_NO_NETWORK)); + } else { + /* Normalize the quality */ + quality = CLAMP (quality, 0, 31) * 100 / 31; + g_simple_async_result_set_op_res_gpointer (simple, + GUINT_TO_POINTER (quality), + NULL); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + } + + g_simple_async_result_set_error (simple, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Could not parse signal quality results"); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +load_signal_quality_csf (MMBroadbandModem *self, + GSimpleAsyncResult *result) +{ + mm_base_modem_at_command (MM_BASE_MODEM (self), + "+CSQ", + 3, + FALSE, + NULL, /* cancellable */ + (GAsyncReadyCallback)load_signal_quality_csf_ready, + result); +} + +static void +load_signal_quality (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + MM_BROADBAND_MODEM (self)->priv->signal_quality_method = SIGNAL_QUALITY_METHOD_CSQ; + + mm_dbg ("loading signal quality..."); + result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + load_signal_quality); + + switch (MM_BROADBAND_MODEM (self)->priv->signal_quality_method) { + case SIGNAL_QUALITY_METHOD_UNKNOWN: + /* Check if CIND supported */ + return; + case SIGNAL_QUALITY_METHOD_CSQ: + load_signal_quality_csf (MM_BROADBAND_MODEM (self), result); + return; + case SIGNAL_QUALITY_METHOD_CIND: + return; + } + + g_assert_not_reached (); +} + /*****************************************************************************/ /* SETTING MODEM CHARSET */ @@ -2661,6 +2777,7 @@ mm_broadband_modem_init (MMBroadbandModem *self) self->priv->reg_cs = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; self->priv->reg_ps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; self->priv->current_charset = MM_MODEM_CHARSET_UNKNOWN; + self->priv->signal_quality_method = SIGNAL_QUALITY_METHOD_UNKNOWN; } static void @@ -2723,6 +2840,8 @@ iface_modem_init (MMIfaceModem *iface) iface->load_device_identifier_finish = load_device_identifier_finish; iface->load_unlock_required = load_unlock_required; iface->load_unlock_required_finish = load_unlock_required_finish; + iface->load_signal_quality = load_signal_quality; + iface->load_signal_quality_finish = load_signal_quality_finish; iface->modem_init = modem_init; iface->modem_init_finish = modem_init_finish; |