xmm: new common XACT? parser for Intel XMM based devices

This commit is contained in:
Aleksander Morgado
2018-08-08 14:05:24 +02:00
committed by Dan Williams
parent 142f1d0360
commit 023ba97d9c
3 changed files with 225 additions and 0 deletions

View File

@@ -338,3 +338,123 @@ out:
*bands_out = bands;
return TRUE;
}
/*****************************************************************************/
/* AT+XACT? response parser */
gboolean
mm_xmm_parse_xact_query_response (const gchar *response,
MMModemModeCombination *mode_out,
GArray **bands_out,
GError **error)
{
GRegex *r;
GMatchInfo *match_info;
GError *inner_error = NULL;
GArray *bands = NULL;
guint i;
MMModemModeCombination mode = {
.allowed = MM_MODEM_MODE_NONE,
.preferred = MM_MODEM_MODE_NONE,
};
/* At least one */
g_assert (mode_out || bands_out);
/*
* AT+XACT?
* +XACT: 4,1,2,1,2,4,5,8,101,102,103,104,105,107,108,111,...
*
* Note: the first 3 fields corresponde to allowed and preferred modes. Only the
* first one of those 3 first fields is mandatory, the other two may be empty.
*/
r = g_regex_new ("\\+XACT: (\\d+),([^,]*),([^,]*),(.*)(?:\\r\\n)?",
G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL);
g_assert (r != NULL);
g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error);
if (!inner_error && g_match_info_matches (match_info)) {
if (mode_out) {
guint xmm_mode;
/* Number at index 1 */
mm_get_uint_from_match_info (match_info, 1, &xmm_mode);
if (xmm_mode >= G_N_ELEMENTS (xmm_modes)) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Unsupported XACT AcT value: %u", xmm_mode);
goto out;
}
mode.allowed = xmm_modes[xmm_mode];
/* Number at index 2 */
if (mm_count_bits_set (mode.allowed) > 1 && mm_get_uint_from_match_info (match_info, 2, &xmm_mode)) {
if (xmm_mode >= G_N_ELEMENTS (xmm_modes)) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Unsupported XACT preferred AcT value: %u", xmm_mode);
goto out;
}
mode.preferred = xmm_modes[xmm_mode];
}
/* Number at index 3: ignored */
}
if (bands_out) {
gchar *bandstr;
GArray *nums;
/* Bands start at index 4 */
bandstr = mm_get_string_unquoted_from_match_info (match_info, 4);
nums = mm_parse_uint_list (bandstr, &inner_error);
g_free (bandstr);
if (inner_error)
goto out;
if (!nums) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Invalid XACT? response");
goto out;
}
bands = g_array_sized_new (FALSE, FALSE, sizeof (MMModemBand), nums->len);
for (i = 0; i < nums->len; i++) {
MMModemBand band;
band = xact_num_to_band (g_array_index (nums, guint, i));
if (band != MM_MODEM_BAND_UNKNOWN)
g_array_append_val (bands, band);
}
g_array_unref (nums);
if (bands->len == 0) {
inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing current band list");
goto out;
}
}
}
/* success */
out:
if (match_info)
g_match_info_free (match_info);
g_regex_unref (r);
if (inner_error) {
if (bands)
g_array_unref (bands);
g_propagate_error (error, inner_error);
return FALSE;
}
if (mode_out) {
g_assert (mode.allowed != MM_MODEM_MODE_NONE);
mode_out->allowed = mode.allowed;
mode_out->preferred = mode.preferred;
}
if (bands_out) {
g_assert (bands);
*bands_out = bands;
}
return TRUE;
}

View File

@@ -25,4 +25,10 @@ gboolean mm_xmm_parse_xact_test_response (const gchar *response,
GArray **bands_out,
GError **error);
/* AT+XACT? response parser */
gboolean mm_xmm_parse_xact_query_response (const gchar *response,
MMModemModeCombination *mode_out,
GArray **bands_out,
GError **error);
#endif /* MM_MODEM_HELPERS_XMM_H */

View File

@@ -174,6 +174,102 @@ test_xact_test_2g_3g_4g (void)
expected_bands, G_N_ELEMENTS (expected_bands));
}
/*****************************************************************************/
/* Test XACT? responses */
static void
validate_xact_query_response (const gchar *response,
const MMModemModeCombination *expected_mode,
const MMModemBand *expected_bands,
guint n_expected_bands)
{
GError *error = NULL;
GArray *bands = NULL;
gboolean ret;
guint i;
MMModemModeCombination mode = {
.allowed = MM_MODEM_MODE_NONE,
.preferred = MM_MODEM_MODE_NONE,
};
ret = mm_xmm_parse_xact_query_response (response, &mode, &bands, &error);
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpuint (mode.allowed, ==, expected_mode->allowed);
g_assert_cmpuint (mode.preferred, ==, expected_mode->preferred);
g_assert_cmpuint (bands->len, ==, n_expected_bands);
for (i = 0; i < bands->len; i++) {
MMModemBand band;
guint j;
gboolean found = FALSE;
band = g_array_index (bands, MMModemBand, i);
for (j = 0; !found && j < n_expected_bands; j++)
found = (band == expected_bands[j]);
g_assert (found);
}
g_array_unref (bands);
}
static void
test_xact_query_3g_only (void)
{
const gchar *response =
"+XACT: "
"1,1,,"
"1,2,4,5,8,"
"101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166";
static const MMModemModeCombination expected_mode = {
.allowed = MM_MODEM_MODE_3G,
.preferred = MM_MODEM_MODE_NONE
};
static const MMModemBand expected_bands[] = {
MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8,
MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5,
MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13,
MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21,
MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38,
MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66
};
validate_xact_query_response (response,
&expected_mode,
expected_bands, G_N_ELEMENTS (expected_bands));
}
static void
test_xact_query_3g_4g (void)
{
const gchar *response =
"+XACT: "
"4,1,2,"
"1,2,4,5,8,"
"101,102,103,104,105,107,108,111,112,113,117,118,119,120,121,126,128,129,130,138,139,140,141,166";
static const MMModemModeCombination expected_mode = {
.allowed = MM_MODEM_MODE_3G | MM_MODEM_MODE_4G,
.preferred = MM_MODEM_MODE_3G
};
static const MMModemBand expected_bands[] = {
MM_MODEM_BAND_UTRAN_1, MM_MODEM_BAND_UTRAN_2, MM_MODEM_BAND_UTRAN_4, MM_MODEM_BAND_UTRAN_5, MM_MODEM_BAND_UTRAN_8,
MM_MODEM_BAND_EUTRAN_1, MM_MODEM_BAND_EUTRAN_2, MM_MODEM_BAND_EUTRAN_3, MM_MODEM_BAND_EUTRAN_4, MM_MODEM_BAND_EUTRAN_5,
MM_MODEM_BAND_EUTRAN_7, MM_MODEM_BAND_EUTRAN_8, MM_MODEM_BAND_EUTRAN_11, MM_MODEM_BAND_EUTRAN_12, MM_MODEM_BAND_EUTRAN_13,
MM_MODEM_BAND_EUTRAN_17, MM_MODEM_BAND_EUTRAN_18, MM_MODEM_BAND_EUTRAN_19, MM_MODEM_BAND_EUTRAN_20, MM_MODEM_BAND_EUTRAN_21,
MM_MODEM_BAND_EUTRAN_26, MM_MODEM_BAND_EUTRAN_28, MM_MODEM_BAND_EUTRAN_29, MM_MODEM_BAND_EUTRAN_30, MM_MODEM_BAND_EUTRAN_38,
MM_MODEM_BAND_EUTRAN_39, MM_MODEM_BAND_EUTRAN_40, MM_MODEM_BAND_EUTRAN_41, MM_MODEM_BAND_EUTRAN_66
};
validate_xact_query_response (response,
&expected_mode,
expected_bands, G_N_ELEMENTS (expected_bands));
}
/*****************************************************************************/
void
@@ -206,5 +302,8 @@ int main (int argc, char **argv)
g_test_add_func ("/MM/xmm/xact/test/3g-4g", test_xact_test_3g_4g);
g_test_add_func ("/MM/xmm/xact/test/2g-3g-4g", test_xact_test_2g_3g_4g);
g_test_add_func ("/MM/xmm/xact/query/3g-only", test_xact_query_3g_only);
g_test_add_func ("/MM/xmm/xact/query/3g-4g", test_xact_query_3g_4g);
return g_test_run ();
}