aboutsummaryrefslogtreecommitdiff
path: root/plugins/xmm/mm-modem-helpers-xmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/xmm/mm-modem-helpers-xmm.c')
-rw-r--r--plugins/xmm/mm-modem-helpers-xmm.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/plugins/xmm/mm-modem-helpers-xmm.c b/plugins/xmm/mm-modem-helpers-xmm.c
index e403cb35..41e53baa 100644
--- a/plugins/xmm/mm-modem-helpers-xmm.c
+++ b/plugins/xmm/mm-modem-helpers-xmm.c
@@ -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;
+}