helpers: new 'AT+CMER=?' parser
This commit is contained in:
@@ -240,6 +240,16 @@ mm_count_bits_set (gulong number)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
mm_find_bit_set (gulong number)
|
||||||
|
{
|
||||||
|
guint c = 0;
|
||||||
|
|
||||||
|
for (c = 0; !(number & 0x1); c++)
|
||||||
|
number >>= 1;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
gchar *
|
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 {
|
struct MM3gppCindResponse {
|
||||||
gchar *desc;
|
gchar *desc;
|
||||||
guint idx;
|
guint idx;
|
||||||
|
@@ -57,6 +57,7 @@ GArray *mm_parse_uint_list (const gchar *str,
|
|||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
guint mm_count_bits_set (gulong number);
|
guint mm_count_bits_set (gulong number);
|
||||||
|
guint mm_find_bit_set (gulong number);
|
||||||
|
|
||||||
gchar *mm_create_device_identifier (guint vid,
|
gchar *mm_create_device_identifier (guint vid,
|
||||||
guint pid,
|
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,
|
GStrv mm_3gpp_parse_cnum_exec_response (const gchar *reply,
|
||||||
GError **error);
|
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 */
|
/* AT+CIND=? (Supported indicators) response parser */
|
||||||
typedef struct MM3gppCindResponse MM3gppCindResponse;
|
typedef struct MM3gppCindResponse MM3gppCindResponse;
|
||||||
GHashTable *mm_3gpp_parse_cind_test_response (const gchar *reply,
|
GHashTable *mm_3gpp_parse_cind_test_response (const gchar *reply,
|
||||||
|
@@ -1866,6 +1866,70 @@ test_devid_item (void *f, gpointer d)
|
|||||||
g_free (devid);
|
g_free (devid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* 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 */
|
/* Test CIND responses */
|
||||||
|
|
||||||
@@ -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_buslink_support_response, NULL));
|
||||||
g_test_suite_add (suite, TESTCASE (test_cscs_blackberry_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_linktop_lw273, NULL));
|
||||||
g_test_suite_add (suite, TESTCASE (test_cind_response_moto_v3m, NULL));
|
g_test_suite_add (suite, TESTCASE (test_cind_response_moto_v3m, NULL));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user