aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2011-12-28 20:59:01 +0100
committerAleksander Morgado <aleksander@lanedo.com>2012-03-15 14:14:40 +0100
commit08b7620b7ab690c2b8f63247452b18adce7ae704 (patch)
treefd6faf725379d9422f206b70cb0426a81a629df6 /src
parente06d42c868745af69f63b8f9ca418b07b70602de (diff)
broadband-modem: implement on demand signal quality checks with AT+CIND?
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem.c128
1 files changed, 120 insertions, 8 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 4925ebcc..d9c2c498 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -735,14 +735,127 @@ load_signal_quality_csf (MMBroadbandModem *self,
}
static void
+load_signal_quality_cind_ready (MMBroadbandModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ const gchar *result;
+ GByteArray *indicators;
+
+ result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
+ if (!error)
+ indicators = mm_parse_cind_query_response (result, &error);
+
+ if (error) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ if (indicators->len >= self->priv->cind_indicator_signal_quality) {
+ guint quality;
+ quality = g_array_index (indicators, guint8, self->priv->cind_indicator_signal_quality);
+ quality = CLAMP (quality, 0, 5) * 20;
+ g_simple_async_result_set_op_res_gpointer (simple,
+ GUINT_TO_POINTER (quality),
+ NULL);
+
+ g_byte_array_free (indicators, TRUE);
+ 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 CIND signal quality results "
+ "signal index (%u) outside received range (0-%u)",
+ self->priv->cind_indicator_signal_quality,
+ indicators->len);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_signal_quality_cind (MMBroadbandModem *self,
+ GSimpleAsyncResult *result)
+{
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "+CIND?",
+ 3,
+ FALSE,
+ NULL, /* cancellable */
+ (GAsyncReadyCallback)load_signal_quality_cind_ready,
+ result);
+}
+
+static void
+check_cind_supported_ready (MMBroadbandModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GHashTable *indicators = NULL;
+ GError *error = NULL;
+ const gchar *result;
+
+ result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
+ if (error)
+ g_error_free (error);
+ else
+ indicators = mm_parse_cind_test_response (result, NULL);
+
+ if (indicators) {
+ CindResponse *r;
+
+ r = g_hash_table_lookup (indicators, "signal");
+ if (r) {
+ self->priv->cind_indicator_signal_quality = cind_response_get_index (r);
+ self->priv->signal_quality_method = SIGNAL_QUALITY_METHOD_CSQ;
+ load_signal_quality_cind (self, simple);
+ }
+
+ /* TODO: also handle roam/service indicators */
+ /* r = g_hash_table_lookup (indicators, "roam"); */
+ /* if (r) */
+ /* priv->roam_ind = cind_response_get_index (r); */
+ /* r = g_hash_table_lookup (indicators, "service"); */
+ /* if (r) */
+ /* priv->service_ind = cind_response_get_index (r); */
+
+ /* TODO: Enable CMER in the primary and secondary ports */
+ g_hash_table_destroy (indicators);
+ return;
+ }
+
+ /* CIND won't be supported, default to CSQ */
+ self->priv->signal_quality_method = SIGNAL_QUALITY_METHOD_CSQ;
+ load_signal_quality_csf (self, simple);
+}
+
+static void
+check_cind_supported (MMBroadbandModem *self,
+ GSimpleAsyncResult *result)
+{
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "+CIND=?",
+ 3,
+ TRUE,
+ NULL, /* cancellable */
+ (GAsyncReadyCallback)check_cind_supported_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,
@@ -751,16 +864,15 @@ load_signal_quality (MMIfaceModem *self,
switch (MM_BROADBAND_MODEM (self)->priv->signal_quality_method) {
case SIGNAL_QUALITY_METHOD_UNKNOWN:
- /* Check if CIND supported */
- return;
+ check_cind_supported (MM_BROADBAND_MODEM (self), result);
+ break;
case SIGNAL_QUALITY_METHOD_CSQ:
load_signal_quality_csf (MM_BROADBAND_MODEM (self), result);
- return;
+ break;
case SIGNAL_QUALITY_METHOD_CIND:
- return;
+ load_signal_quality_cind (MM_BROADBAND_MODEM (self), result);
+ break;
}
-
- g_assert_not_reached ();
}
/*****************************************************************************/