[PATCH1 1/4 v3] helpers: new 'AT+CMER=?' parser
Aleksander Morgado
aleksander at aleksander.es
Mon May 29 13:02:26 UTC 2017
On 22/05/17 14:43, Aleksander Morgado wrote:
> ---
>
> Hey Colin,
>
> Please try now with this v3 patch. I modified the helper method to allow the comma-separated number sequence you get in your EHS5 for the modes, i.e.: "(1,2)". The regex wasn't catching that logic, so instead of complicating it too much, I switched to splitting the response into groups and then parsing the groups we want independently.
>
> See if you get +CMER setting correctly run now.
>
> Cheers!
>
This has been merged to git master.
> ---
> src/mm-modem-helpers.c | 123 +++++++++++++++++++++++++++++++++++++++++
> src/mm-modem-helpers.h | 25 +++++++++
> src/tests/test-modem-helpers.c | 68 +++++++++++++++++++++++
> 3 files changed, 216 insertions(+)
>
> diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
> index 679f9252..ddf69406 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,119 @@ 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)
> +{
> + gchar **split;
> + GError *inner_error = 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)
> + *
> + * AT+CMER=?
> + * +CMER: (1,2),0,0,(0-1),0
> + */
> +
> + split = mm_split_string_groups (mm_strip_tag (response, "+CMER:"));
> + if (!split) {
> + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't split +CMER test response in groups");
> + goto out;
> + }
> +
> + /* We want 1st and 4th groups */
> + if (g_strv_length (split) < 4) {
> + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing groups in +CMER test response (%u < 4)", g_strv_length (split));
> + goto out;
> + }
> +
> + /* Modes in 1st group */
> + if (!(array_supported_modes = mm_parse_uint_list (split[0], &inner_error)))
> + goto out;
> + g_clear_pointer (&aux, g_free);
> +
> + /* Ind settings in 4th group */
> + if (!(array_supported_inds = mm_parse_uint_list (split[3], &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_strfreev (split);
> +
> + 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..ab566539 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 { /*< underscore_name=mm_3gpp_cmer_mode >*/
> + 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 { /*< underscore_name=mm_3gpp_cmer_ind >*/
> + 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..d6984d2d 100644
> --- a/src/tests/test-modem-helpers.c
> +++ b/src/tests/test-modem-helpers.c
> @@ -1867,6 +1867,70 @@ 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);
> +}
> +
> +static void
> +test_cmer_response_cinterion_ehs5 (void)
> +{
> + static const gchar *str = "+CMER: (1,2),0,0,(0-1),0";
> + static const MM3gppCmerMode expected_modes = ( \
> + MM_3GPP_CMER_MODE_DISCARD_URCS_IF_LINK_RESERVED | \
> + MM_3GPP_CMER_MODE_BUFFER_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 +3790,10 @@ 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_cmer_response_cinterion_ehs5, 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
>
--
Aleksander
https://aleksander.es
More information about the ModemManager-devel
mailing list