---
 src/mm-modem-helpers.c         | 136 +++++++++++++++++++++++++++++++++++++++++
 src/mm-modem-helpers.h         |  25 ++++++++
 src/tests/test-modem-helpers.c |  53 ++++++++++++++++
 3 files changed, 214 insertions(+)

diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 679f9252..f092d223 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -240,6 +240,16 @@ mm_count_bits_set (gulong number)
     return c;
 }
 
+guint
+mm_find_bit_set (gulong number)
+{
+    guint c = 0;
+
+    for (c = 0; !(number & 0x1); c++)
+        number >>= 1;
+    return c;
+}
+
 /*****************************************************************************/
 
 gchar *
@@ -2847,6 +2857,132 @@ mm_3gpp_parse_cnum_exec_response (const gchar *reply,
 
 /*************************************************************************/
 
+gchar *
+mm_3gpp_build_cmer_set_request (MM3gppCmerMode mode,
+                                MM3gppCmerInd  ind)
+{
+    guint mode_val;
+    guint ind_val;
+
+    if (mode == MM_3GPP_CMER_MODE_DISCARD_URCS)
+        return g_strdup ("+CMER=0");
+    if (mode < MM_3GPP_CMER_MODE_DISCARD_URCS || mode > 
MM_3GPP_CMER_MODE_FORWARD_URCS)
+        return NULL;
+    mode_val = mm_find_bit_set (mode);
+
+    if (ind < MM_3GPP_CMER_IND_DISABLE || ind > MM_3GPP_CMER_IND_ENABLE_ALL)
+        return NULL;
+    ind_val = mm_find_bit_set (ind);
+
+    return g_strdup_printf ("+CMER=%u,0,0,%u", mode_val, ind_val);
+}
+
+gboolean
+mm_3gpp_parse_cmer_test_response (const gchar     *response,
+                                  MM3gppCmerMode  *out_supported_modes,
+                                  MM3gppCmerInd   *out_supported_inds,
+                                  GError         **error)
+{
+    GRegex         *r;
+    GError         *inner_error = NULL;
+    GMatchInfo     *match_info  = NULL;
+    GArray         *array_supported_modes = NULL;
+    GArray         *array_supported_inds = NULL;
+    gchar          *aux   = NULL;
+    gboolean        ret = FALSE;
+    MM3gppCmerMode  supported_modes = 0;
+    MM3gppCmerInd   supported_inds = 0;
+    guint           i;
+
+    /*
+     * AT+CMER=?
+     *  +CMER: 1,0,0,(0-1),0
+     *
+     * AT+CMER=?
+     *  +CMER: (0-3),(0),(0),(0-1),(0-1)
+     */
+
+    r = g_regex_new ("\\+CMER:\\s*"
+                     "\\(?([0-9-]+)\\)?,"
+                     "\\(?(?:[0-9-]+)\\)?,"
+                     "\\(?(?:[0-9-]+)\\)?,"
+                     "\\(?([0-9-]+)\\)?,"
+                     "\\(?(?:[0-9-]+)\\)?"
+                     "(?:\\r\\n)?", 0, 0, NULL);
+    g_assert (r != NULL);
+
+    g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, 
&inner_error);
+    if (inner_error)
+        goto out;
+
+    if (!g_match_info_matches (match_info)) {
+        inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, 
"Couldn't match response");
+        goto out;
+    }
+
+    if (!(aux = mm_get_string_unquoted_from_match_info (match_info, 1))) {
+        inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                   "Error retrieving list of supported +CMER 
modes");
+        goto out;
+    }
+
+    if (!(array_supported_modes = mm_parse_uint_list (aux, &inner_error)))
+        goto out;
+    g_clear_pointer (&aux, g_free);
+
+    if (!(aux = mm_get_string_unquoted_from_match_info (match_info, 2))) {
+        inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                   "Error retrieving list of supported +CMER 
inds");
+        goto out;
+    }
+
+    if (!(array_supported_inds = mm_parse_uint_list (aux, &inner_error)))
+        goto out;
+    g_clear_pointer (&aux, g_free);
+
+    for (i = 0; i < array_supported_modes->len; i++) {
+        guint mode_val;
+
+        mode_val = g_array_index (array_supported_modes, guint, i);
+        if (mode_val >= 0 && mode_val <= 3)
+            supported_modes |= (MM3gppCmerMode) (1 << mode_val);
+        else
+            mm_dbg ("Unknown +CMER mode reported: %u", mode_val);
+    }
+
+    for (i = 0; i < array_supported_inds->len; i++) {
+        guint ind_val;
+
+        ind_val = g_array_index (array_supported_inds, guint, i);
+        if (ind_val >= 0 && ind_val <= 2)
+            supported_inds |= (MM3gppCmerInd) (1 << ind_val);
+        else
+            mm_dbg ("Unknown +CMER ind reported: %u", ind_val);
+    }
+
+    if (out_supported_modes)
+        *out_supported_modes = supported_modes;
+    if (out_supported_inds)
+        *out_supported_inds = supported_inds;
+    ret = TRUE;
+
+out:
+    if (array_supported_modes)
+        g_array_unref (array_supported_modes);
+    if (array_supported_inds)
+        g_array_unref (array_supported_inds);
+    g_clear_pointer (&aux, g_free);
+    g_clear_pointer (&match_info, g_match_info_free);
+    g_regex_unref (r);
+
+    if (inner_error)
+        g_propagate_error (error, inner_error);
+
+    return ret;
+}
+
+/*************************************************************************/
+
 struct MM3gppCindResponse {
     gchar *desc;
     guint idx;
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 297e15df..309592f8 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -57,6 +57,7 @@ GArray *mm_parse_uint_list (const gchar  *str,
                             GError      **error);
 
 guint mm_count_bits_set (gulong number);
+guint mm_find_bit_set   (gulong number);
 
 gchar *mm_create_device_identifier (guint vid,
                                     guint pid,
@@ -228,6 +229,30 @@ gboolean mm_3gpp_parse_clck_write_response (const gchar 
*reply,
 GStrv mm_3gpp_parse_cnum_exec_response (const gchar *reply,
                                         GError **error);
 
+/* AT+CMER=? (Mobile Equipment Event Reporting) response parser */
+typedef enum {
+    MM_3GPP_CMER_MODE_NONE                          = 0,
+    MM_3GPP_CMER_MODE_DISCARD_URCS                  = 1 << 0,
+    MM_3GPP_CMER_MODE_DISCARD_URCS_IF_LINK_RESERVED = 1 << 1,
+    MM_3GPP_CMER_MODE_BUFFER_URCS_IF_LINK_RESERVED  = 1 << 2,
+    MM_3GPP_CMER_MODE_FORWARD_URCS                  = 1 << 3,
+} MM3gppCmerMode;
+typedef enum {
+    MM_3GPP_CMER_IND_NONE = 0,
+    /* no indicator event reporting */
+    MM_3GPP_CMER_IND_DISABLE = 1 << 0,
+    /* Only indicator events that are not caused by +CIND */
+    MM_3GPP_CMER_IND_ENABLE_NOT_CAUSED_BY_CIND = 1 << 1,
+    /* All indicator events */
+    MM_3GPP_CMER_IND_ENABLE_ALL = 1 << 2,
+} MM3gppCmerInd;
+gchar    *mm_3gpp_build_cmer_set_request   (MM3gppCmerMode   mode,
+                                            MM3gppCmerInd    ind);
+gboolean  mm_3gpp_parse_cmer_test_response (const gchar     *reply,
+                                            MM3gppCmerMode  *supported_modes,
+                                            MM3gppCmerInd   *supported_inds,
+                                            GError         **error);
+
 /* AT+CIND=? (Supported indicators) response parser */
 typedef struct MM3gppCindResponse MM3gppCindResponse;
 GHashTable  *mm_3gpp_parse_cind_test_response    (const gchar *reply,
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index b59c5900..3c058951 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -1867,6 +1867,56 @@ test_devid_item (void *f, gpointer d)
 }
 
 /*****************************************************************************/
+/* Test CMER test responses */
+
+static void
+test_cmer_response (const gchar    *str,
+                    MM3gppCmerMode  expected_modes,
+                    MM3gppCmerInd   expected_inds)
+{
+    gboolean        ret;
+    MM3gppCmerMode  modes = MM_3GPP_CMER_MODE_NONE;
+    MM3gppCmerInd   inds = MM_3GPP_CMER_IND_NONE;
+    GError         *error = NULL;
+
+    ret = mm_3gpp_parse_cmer_test_response (str, &modes, &inds, &error);
+    g_assert_no_error (error);
+    g_assert (ret);
+
+    g_assert_cmpuint (modes, ==, expected_modes);
+    g_assert_cmpuint (inds,  ==, expected_inds);
+}
+
+static void
+test_cmer_response_cinterion_pls8 (void)
+{
+    static const gchar *str = "+CMER: (0-3),(0),(0),(0-1),(0-1)";
+    static const MM3gppCmerMode expected_modes = (        \
+        MM_3GPP_CMER_MODE_DISCARD_URCS |                  \
+        MM_3GPP_CMER_MODE_DISCARD_URCS_IF_LINK_RESERVED | \
+        MM_3GPP_CMER_MODE_BUFFER_URCS_IF_LINK_RESERVED |  \
+        MM_3GPP_CMER_MODE_FORWARD_URCS);
+    static const MM3gppCmerInd expected_inds = (        \
+        MM_3GPP_CMER_IND_DISABLE |                      \
+        MM_3GPP_CMER_IND_ENABLE_NOT_CAUSED_BY_CIND);
+
+    test_cmer_response (str, expected_modes, expected_inds);
+}
+
+static void
+test_cmer_response_sierra_em7345 (void)
+{
+    static const gchar *str = "+CMER: 1,0,0,(0-1),0";
+    static const MM3gppCmerMode expected_modes = (          \
+        MM_3GPP_CMER_MODE_DISCARD_URCS_IF_LINK_RESERVED);
+    static const MM3gppCmerInd expected_inds = (        \
+        MM_3GPP_CMER_IND_DISABLE |                      \
+        MM_3GPP_CMER_IND_ENABLE_NOT_CAUSED_BY_CIND);
+
+    test_cmer_response (str, expected_modes, expected_inds);
+}
+
+/*****************************************************************************/
 /* Test CIND responses */
 
 typedef struct {
@@ -3726,6 +3776,9 @@ int main (int argc, char **argv)
     g_test_suite_add (suite, TESTCASE (test_cscs_buslink_support_response, 
NULL));
     g_test_suite_add (suite, TESTCASE (test_cscs_blackberry_support_response, 
NULL));
 
+    g_test_suite_add (suite, TESTCASE (test_cmer_response_cinterion_pls8, 
NULL));
+    g_test_suite_add (suite, TESTCASE (test_cmer_response_sierra_em7345, 
NULL));
+
     g_test_suite_add (suite, TESTCASE (test_cind_response_linktop_lw273, 
NULL));
     g_test_suite_add (suite, TESTCASE (test_cind_response_moto_v3m, NULL));
 
-- 
2.12.2

_______________________________________________
ModemManager-devel mailing list
ModemManager-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/modemmanager-devel

Reply via email to