aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2011-12-28 20:33:08 +0100
committerAleksander Morgado <aleksander@lanedo.com>2012-03-15 14:14:39 +0100
commite06d42c868745af69f63b8f9ca418b07b70602de (patch)
tree5395e15561a91f2a6690bd16c0e7d1e669903ff9 /src
parentf0433a4dda362a5d8658c154abf356f1fc5f5c82 (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.c119
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;