summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2016-10-05 13:51:35 +0200
committerDan Williams <dcbw@redhat.com>2016-12-06 11:50:42 -0600
commitf7e7ea5b6fb26201268b362062774ba4664706d3 (patch)
treef08cb421cca6e7107a0b261012754ead481a3192
parent396413eb94b995de8a3bb6bf0a82b35081ceabdb (diff)
downloadModemManager-f7e7ea5b6fb26201268b362062774ba4664706d3.tar.gz
modem-helpers: new helper to parse +CESQ response into MMSignal objects
(cherry picked from commit 7ab3d3e727cdc03fa7e058416e57c7d6c83aeab7)
-rw-r--r--src/mm-modem-helpers.c149
-rw-r--r--src/mm-modem-helpers.h6
-rw-r--r--src/tests/test-modem-helpers.c116
3 files changed, 238 insertions, 33 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 46274fd21..7b6b5c8ff 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -1484,6 +1484,155 @@ out:
return TRUE;
}
+static gboolean
+rxlev_to_rssi (guint rxlev,
+ gdouble *out_rssi)
+{
+ if (rxlev <= 63) {
+ *out_rssi = -111.0 + rxlev;
+ return TRUE;
+ }
+
+ if (rxlev != 99)
+ mm_warn ("unexpected rxlev: %u", rxlev);
+ return FALSE;
+}
+
+static gboolean
+rscp_level_to_rscp (guint rscp_level,
+ gdouble *out_rscp)
+{
+ if (rscp_level <= 96) {
+ *out_rscp = -121.0 + rscp_level;
+ return TRUE;
+ }
+
+ if (rscp_level != 255)
+ mm_warn ("unexpected rscp level: %u", rscp_level);
+ return FALSE;
+}
+
+static gboolean
+ecn0_level_to_ecio (guint ecn0_level,
+ gdouble *out_ecio)
+{
+ if (ecn0_level <= 49) {
+ *out_ecio = -24.5 + (((gdouble) ecn0_level) * 0.5);
+ return TRUE;
+ }
+
+ if (ecn0_level != 255)
+ mm_warn ("unexpected Ec/N0 level: %u", ecn0_level);
+ return FALSE;
+}
+
+static gboolean
+rsrq_level_to_rsrq (guint rsrq_level,
+ gdouble *out_rsrq)
+{
+ if (rsrq_level <= 34) {
+ *out_rsrq = -20.0 + (((gdouble) rsrq_level) * 0.5);
+ return TRUE;
+ }
+
+ if (rsrq_level != 255)
+ mm_warn ("unexpected RSRQ level: %u", rsrq_level);
+ return FALSE;
+}
+
+static gboolean
+rsrp_level_to_rsrp (guint rsrp_level,
+ gdouble *out_rsrp)
+{
+ if (rsrp_level <= 97) {
+ *out_rsrp = -141.0 + rsrp_level;
+ return TRUE;
+ }
+
+ if (rsrp_level != 255)
+ mm_warn ("unexpected RSRP level: %u", rsrp_level);
+ return FALSE;
+}
+
+gboolean
+mm_3gpp_cesq_response_to_signal_info (const gchar *response,
+ MMSignal **out_gsm,
+ MMSignal **out_umts,
+ MMSignal **out_lte,
+ GError **error)
+{
+ guint rxlev = 0;
+ guint ber = 0;
+ guint rscp_level = 0;
+ guint ecn0_level = 0;
+ guint rsrq_level = 0;
+ guint rsrp_level = 0;
+ gdouble rssi = -G_MAXDOUBLE;
+ gdouble rscp = -G_MAXDOUBLE;
+ gdouble ecio = -G_MAXDOUBLE;
+ gdouble rsrq = -G_MAXDOUBLE;
+ gdouble rsrp = -G_MAXDOUBLE;
+ MMSignal *gsm = NULL;
+ MMSignal *umts = NULL;
+ MMSignal *lte = NULL;
+
+ if (!mm_3gpp_parse_cesq_response (response,
+ &rxlev, &ber,
+ &rscp_level, &ecn0_level,
+ &rsrq_level, &rsrp_level,
+ error))
+ return FALSE;
+
+ /* GERAN RSSI */
+ if (rxlev_to_rssi (rxlev, &rssi)) {
+ gsm = mm_signal_new ();
+ mm_signal_set_rssi (gsm, rssi);
+ }
+
+ /* ignore BER */
+
+ /* UMTS RSCP */
+ if (rscp_level_to_rscp (rscp_level, &rscp)) {
+ umts = mm_signal_new ();
+ mm_signal_set_rscp (umts, rscp);
+ }
+
+ /* UMTS EcIo (assumed EcN0) */
+ if (ecn0_level_to_ecio (ecn0_level, &ecio)) {
+ if (!umts)
+ umts = mm_signal_new ();
+ mm_signal_set_ecio (umts, ecio);
+ }
+
+ /* LTE RSRQ */
+ if (rsrq_level_to_rsrq (rsrq_level, &rsrq)) {
+ lte = mm_signal_new ();
+ mm_signal_set_rsrq (lte, rsrq);
+ }
+
+ /* LTE RSRP */
+ if (rsrp_level_to_rsrp (rsrp_level, &rsrp)) {
+ if (!lte)
+ lte = mm_signal_new ();
+ mm_signal_set_rsrp (lte, rsrp);
+ }
+
+ if (!gsm && !umts && !lte) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Couldn't build detailed signal info");
+ return FALSE;
+ }
+
+ if (gsm)
+ *out_gsm = gsm;
+ if (umts)
+ *out_umts = umts;
+ if (lte)
+ *out_lte = lte;
+
+ return TRUE;
+}
+
/*************************************************************************/
static MMSmsStorage
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index af0520415..2ac6c7d1a 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -231,6 +231,12 @@ gboolean mm_3gpp_parse_cesq_response (const gchar *response,
guint *out_rsrp,
GError **error);
+gboolean mm_3gpp_cesq_response_to_signal_info (const gchar *response,
+ MMSignal **out_gsm,
+ MMSignal **out_umts,
+ MMSignal **out_lte,
+ GError **error);
+
/* Additional 3GPP-specific helpers */
MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index 84bc07f93..32d01583a 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -17,6 +17,7 @@
#include <glib-object.h>
#include <string.h>
#include <stdlib.h>
+#include <math.h>
#include <libmm-glib.h>
#include "mm-modem-helpers.h"
@@ -28,6 +29,9 @@
#define trace(...)
#endif
+#define g_assert_cmpfloat_tolerance(val1, val2, tolerance) \
+ g_assert_cmpfloat (fabs (val1 - val2), <, tolerance)
+
/*****************************************************************************/
/* Test CMGL responses */
@@ -2737,41 +2741,43 @@ test_crsm_response (void)
typedef struct {
const gchar *str;
- guint rxlev;
- guint ber;
- guint rscp;
- guint ecn0;
- guint rsrq;
- guint rsrp;
+
+ gboolean gsm_info;
+ guint rxlev;
+ gdouble rssi;
+ guint ber;
+
+ gboolean umts_info;
+ guint rscp_level;
+ gdouble rscp;
+ guint ecn0_level;
+ gdouble ecio;
+
+ gboolean lte_info;
+ guint rsrq_level;
+ gdouble rsrq;
+ guint rsrp_level;
+ gdouble rsrp;
} CesqResponseTest;
static const CesqResponseTest cesq_response_tests[] = {
{
- .str = "+CESQ: 99,99,255,255,20,80",
- .rxlev = 99,
- .ber = 99,
- .rscp = 255,
- .ecn0 = 255,
- .rsrq = 20,
- .rsrp = 80
+ .str = "+CESQ: 99,99,255,255,20,80",
+ .gsm_info = FALSE, .rxlev = 99, .ber = 99,
+ .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255,
+ .lte_info = TRUE, .rsrq_level = 20, .rsrq = -10.0, .rsrp_level = 80, .rsrp = -61.0,
},
{
- .str = "+CESQ: 99,99,95,40,255,255",
- .rxlev = 99,
- .ber = 99,
- .rscp = 95,
- .ecn0 = 40,
- .rsrq = 255,
- .rsrp = 255
+ .str = "+CESQ: 99,99,95,40,255,255",
+ .gsm_info = FALSE, .rxlev = 99, .ber = 99,
+ .umts_info = TRUE, .rscp_level = 95, .rscp = -26.0, .ecn0_level = 40, .ecio = -4.5,
+ .lte_info = FALSE, .rsrq_level = 255, .rsrp_level = 255,
},
{
- .str = "+CESQ: 10,6,255,255,255,255",
- .rxlev = 10,
- .ber = 6,
- .rscp = 255,
- .ecn0 = 255,
- .rsrq = 255,
- .rsrp = 255
+ .str = "+CESQ: 10,6,255,255,255,255",
+ .gsm_info = TRUE, .rxlev = 10, .rssi = -101.0, .ber = 6,
+ .umts_info = FALSE, .rscp_level = 255, .ecn0_level = 255,
+ .lte_info = FALSE, .rsrq_level = 255, .rsrp_level = 255,
}
};
@@ -2798,12 +2804,55 @@ test_cesq_response (void)
g_assert_no_error (error);
g_assert (success);
- g_assert_cmpuint (cesq_response_tests[i].rxlev, ==, rxlev);
- g_assert_cmpuint (cesq_response_tests[i].ber, ==, ber);
- g_assert_cmpuint (cesq_response_tests[i].rscp, ==, rscp);
- g_assert_cmpuint (cesq_response_tests[i].ecn0, ==, ecn0);
- g_assert_cmpuint (cesq_response_tests[i].rsrq, ==, rsrq);
- g_assert_cmpuint (cesq_response_tests[i].rsrp, ==, rsrp);
+ g_assert_cmpuint (cesq_response_tests[i].rxlev, ==, rxlev);
+ g_assert_cmpuint (cesq_response_tests[i].ber, ==, ber);
+ g_assert_cmpuint (cesq_response_tests[i].rscp_level, ==, rscp);
+ g_assert_cmpuint (cesq_response_tests[i].ecn0_level, ==, ecn0);
+ g_assert_cmpuint (cesq_response_tests[i].rsrq_level, ==, rsrq);
+ g_assert_cmpuint (cesq_response_tests[i].rsrp_level, ==, rsrp);
+ }
+}
+
+static void
+test_cesq_response_to_signal (void)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (cesq_response_tests); i++) {
+ GError *error = NULL;
+ gboolean success;
+ MMSignal *gsm = NULL;
+ MMSignal *umts = NULL;
+ MMSignal *lte = NULL;
+
+ success = mm_3gpp_cesq_response_to_signal_info (cesq_response_tests[i].str,
+ &gsm, &umts, &lte,
+ &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ if (cesq_response_tests[i].gsm_info) {
+ g_assert (gsm);
+ g_assert_cmpfloat_tolerance (mm_signal_get_rssi (gsm), cesq_response_tests[i].rssi, 0.1);
+ g_object_unref (gsm);
+ } else
+ g_assert (!gsm);
+
+ if (cesq_response_tests[i].umts_info) {
+ g_assert (umts);
+ g_assert_cmpfloat_tolerance (mm_signal_get_rscp (umts), cesq_response_tests[i].rscp, 0.1);
+ g_assert_cmpfloat_tolerance (mm_signal_get_ecio (umts), cesq_response_tests[i].ecio, 0.1);
+ g_object_unref (umts);
+ } else
+ g_assert (!umts);
+
+ if (cesq_response_tests[i].lte_info) {
+ g_assert (lte);
+ g_assert_cmpfloat_tolerance (mm_signal_get_rsrq (lte), cesq_response_tests[i].rsrq, 0.1);
+ g_assert_cmpfloat_tolerance (mm_signal_get_rsrp (lte), cesq_response_tests[i].rsrp, 0.1);
+ g_object_unref (lte);
+ } else
+ g_assert (!lte);
}
}
@@ -2986,6 +3035,7 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_crsm_response, NULL));
g_test_suite_add (suite, TESTCASE (test_cesq_response, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cesq_response_to_signal, NULL));
result = g_test_run ();