From 04c97974566e476dce397c94a037e311e3dba280 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Wed, 12 Aug 2026 09:02:15 +0000 Subject: [PATCH] modem-helpers: fix multiple C*REG events in single URC When receiving a message from modem containing multiple CREG events that have different format, the parsing happens in the order CREG regexes are registered, and not in the order the modem sent the events. That means that when receiving the following URC: +CEREG: 2+CNSMOD: 8+CEREG: 1,AAAA,01234567,7 we'd incorrectly parse the `CEREG: 1` before `CEREG: 2`, and remember the state as searching (2) instead of home (1), which can cause trouble connecting because of waiting for state to go home which would never happen again. This fixes that problem by merging all the regexes together, so the parsing should properly process the events in matching order in parse_unsolicited() Unfortunately changing the regex like this means that mm_3gpp_parse_creg_response() match info handling also needs to be reworked: matches number are increased for each regex, so we can reliably know which regex was matched based on match count. This is actually cleaner than the old approach that just guessed if nth field with "item_is_lac_not_stat()", but requires careful testing. This was validated checking that tests fail if any of the indices is changed by iterating over them all and running the test: grep -n 'n_matches -' src/mm-modem-helpers.c | sed -e 's/:.*//' \ | while read lineno; do echo $lineno git show HEAD:src/mm-modem-helpers.c \ | awk -v l=$lineno '{ if (NR == l) { print $1,$2,$3,$4,$5 - 1,";" } else { print }}' > src/mm-modem-helpers.c ninja -C build src/tests/test-modem-helpers || break build/src/tests/test-modem-helpers && break done A test case was added to make this work, as the Samsung Wave S8500 sample 'act' doesn't seem to actually be a technology value? (case 36/42 could actually be merged but were kept separate on purpose for easier maintenance/testing) Fixes: #1087 Signed-off-by: Dominique Martinet --- src/mm-broadband-modem.c | 71 ++++------ src/mm-modem-helpers.c | 251 +++++++++++++++++---------------- src/mm-modem-helpers.h | 15 +- src/tests/test-modem-helpers.c | 49 +++---- 4 files changed, 184 insertions(+), 202 deletions(-) diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index b8d9c84e..276a715b 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -218,7 +218,7 @@ struct _MMBroadbandModemPrivate { gboolean modem_3gpp_eps_network_supported; gboolean modem_3gpp_5gs_network_supported; /* Implementation helpers */ - GPtrArray *modem_3gpp_registration_regex; + GRegex *modem_3gpp_registration_regex; MMModem3gppFacility modem_3gpp_ignored_facility_locks; MMBaseBearer *modem_3gpp_initial_eps_bearer; MMModem3gppPacketServiceState modem_3gpp_packet_service_state; @@ -5267,32 +5267,28 @@ modem_3gpp_setup_unsolicited_registration_events (MMIfaceModem3gpp *self, gpointer user_data) { MMPortSerialAt *ports[2]; - GPtrArray *array; + g_autoptr(GRegex) regex = NULL; guint i; - guint j; GTask *task; ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); /* Set up CREG unsolicited message handlers in both ports */ - array = mm_3gpp_creg_regex_get (FALSE); + regex = mm_3gpp_creg_regex_get (FALSE); for (i = 0; i < 2; i++) { if (!ports[i]) continue; mm_obj_dbg (self, "setting up 3GPP unsolicited registration messages handlers in %s", mm_port_get_device (MM_PORT (ports[i]))); - for (j = 0; j < array->len; j++) { - mm_port_serial_at_add_unsolicited_msg_handler ( - MM_PORT_SERIAL_AT (ports[i]), - (GRegex *) g_ptr_array_index (array, j), - (MMPortSerialAtUnsolicitedMsgFn)registration_state_changed, - self, - NULL); - } + mm_port_serial_at_add_unsolicited_msg_handler ( + MM_PORT_SERIAL_AT (ports[i]), + regex, + (MMPortSerialAtUnsolicitedMsgFn)registration_state_changed, + self, + NULL); } - mm_3gpp_creg_regex_destroy (array); task = g_task_new (self, NULL, callback, user_data); g_task_return_boolean (task, TRUE); @@ -5316,32 +5312,28 @@ modem_3gpp_cleanup_unsolicited_registration_events (MMIfaceModem3gpp *self, gpointer user_data) { MMPortSerialAt *ports[2]; - GPtrArray *array; + g_autoptr(GRegex) regex = NULL; guint i; - guint j; GTask *task; ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); /* Set up CREG unsolicited message handlers in both ports */ - array = mm_3gpp_creg_regex_get (FALSE); + regex = mm_3gpp_creg_regex_get (FALSE); for (i = 0; i < 2; i++) { if (!ports[i]) continue; mm_obj_dbg (self, "cleaning up unsolicited registration messages handlers in %s", mm_port_get_device (MM_PORT (ports[i]))); - for (j = 0; j < array->len; j++) { - mm_port_serial_at_add_unsolicited_msg_handler ( - MM_PORT_SERIAL_AT (ports[i]), - (GRegex *) g_ptr_array_index (array, j), - NULL, - NULL, - NULL); - } + mm_port_serial_at_add_unsolicited_msg_handler ( + MM_PORT_SERIAL_AT (ports[i]), + regex, + NULL, + NULL, + NULL); } - mm_3gpp_creg_regex_destroy (array); task = g_task_new (self, NULL, callback, user_data); g_task_return_boolean (task, TRUE); @@ -5608,7 +5600,6 @@ registration_status_check_ready (MMBroadbandModem *self, RunRegistrationChecksContext *ctx; const gchar *response; GError *error = NULL; - guint i; gboolean parsed; gboolean cgreg = FALSE; gboolean cereg = FALSE; @@ -5641,18 +5632,10 @@ registration_status_check_ready (MMBroadbandModem *self, } /* Try to match the response */ - for (i = 0; - i < self->priv->modem_3gpp_registration_regex->len; - i++) { - if (g_regex_match ((GRegex *)g_ptr_array_index (self->priv->modem_3gpp_registration_regex, i), - response, - 0, - &match_info)) - break; - g_clear_pointer (&match_info, g_match_info_free); - } - - if (!match_info) { + if (!g_regex_match (self->priv->modem_3gpp_registration_regex, + response, + 0, + &match_info)) { error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Unknown registration status response: '%s'", @@ -11704,9 +11687,8 @@ setup_ports (MMBroadbandModem *self) g_autoptr(GRegex) ciev_regex = NULL; g_autoptr(GRegex) cmti_regex = NULL; g_autoptr(GRegex) cusd_regex = NULL; - GPtrArray *array; + g_autoptr(GRegex) creg_regex = NULL; guint i; - guint j; ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); @@ -11722,7 +11704,7 @@ setup_ports (MMBroadbandModem *self) NULL); /* Cleanup all unsolicited message handlers in all AT ports */ - array = mm_3gpp_creg_regex_get (FALSE); + creg_regex = mm_3gpp_creg_regex_get (FALSE); ciev_regex = mm_3gpp_ciev_regex_get (); cmti_regex = mm_3gpp_cmti_regex_get (); cusd_regex = mm_3gpp_cusd_regex_get (); @@ -11731,14 +11713,11 @@ setup_ports (MMBroadbandModem *self) if (!ports[i]) continue; - for (j = 0; j < array->len; j++) - mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), (GRegex *)g_ptr_array_index (array, j), NULL, NULL, NULL); + mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), creg_regex, NULL, NULL, NULL); mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), ciev_regex, NULL, NULL, NULL); mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), cmti_regex, NULL, NULL, NULL); mm_port_serial_at_add_unsolicited_msg_handler (MM_PORT_SERIAL_AT (ports[i]), cusd_regex, NULL, NULL, NULL); } - - mm_3gpp_creg_regex_destroy (array); } /*****************************************************************************/ @@ -14284,7 +14263,7 @@ finalize (GObject *object) ports_context_unref (self->priv->in_call_ports_ctx); if (self->priv->modem_3gpp_registration_regex) - mm_3gpp_creg_regex_destroy (self->priv->modem_3gpp_registration_regex); + g_regex_unref (self->priv->modem_3gpp_registration_regex); g_free (self->priv->carrier_config_mapping); diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index de2dc247..8686aee4 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -900,35 +900,24 @@ static const gchar *creg_regex[] = { [13] = "\\+(C5GREG):\\s*([0-9]+)\\s*,\\s*([0-9+])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)", }; -GPtrArray * +GRegex * mm_3gpp_creg_regex_get (gboolean solicited) { - GPtrArray *array; + g_autoptr(GString) pattern = NULL; guint i; - array = g_ptr_array_sized_new (G_N_ELEMENTS (creg_regex)); + pattern = g_string_sized_new(4096); + for (i = 0; i < G_N_ELEMENTS (creg_regex); i++) { - GRegex *regex; - g_autofree gchar *pattern = NULL; - if (solicited) { - pattern = g_strdup_printf ("%s$", creg_regex[i]); - regex = g_regex_new (pattern, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_string_append_printf (pattern, "%s$|", creg_regex[i]); } else { - pattern = g_strdup_printf ("\\r\\n%s\\r\\n", creg_regex[i]); - regex = g_regex_new (pattern, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_string_append_printf (pattern, "\\r\\n%s\\r\\n|", creg_regex[i]); } - g_assert (regex); - g_ptr_array_add (array, regex); } - return array; -} - -void -mm_3gpp_creg_regex_destroy (GPtrArray *array) -{ - g_ptr_array_foreach (array, (GFunc) g_regex_unref, NULL); - g_ptr_array_free (array, TRUE); + /* truncate last | char */ + g_string_truncate (pattern, pattern->len - 1); + return g_regex_new (pattern->str, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); } /*************************************************************************/ @@ -2013,20 +2002,6 @@ mm_3gpp_parse_cgact_read_response (const gchar *reply, /*************************************************************************/ -static gboolean -item_is_lac_not_stat (GMatchInfo *info, guint32 item) -{ - gchar *str; - gboolean is_lac = FALSE; - - /* A will always be a digit < 100, without quotes */ - str = g_match_info_fetch (info, item); - g_assert (str); - is_lac = (strchr (str, '"') || strlen (str) > 2); - g_free (str); - return is_lac; -} - gboolean mm_3gpp_parse_creg_response (GMatchInfo *info, gpointer log_object, @@ -2042,7 +2017,7 @@ mm_3gpp_parse_creg_response (GMatchInfo *info, gint n_matches, act = -1; guint stat = 0; guint64 lac = 0, ci = 0; - guint istat = 0, ilac = 0, ici = 0, iact = 0; + guint ireg = 0, istat = 0, ilac = 0, ici = 0, iact = 0; gchar *str; g_assert (info != NULL); @@ -2054,98 +2029,130 @@ mm_3gpp_parse_creg_response (GMatchInfo *info, g_assert (out_cereg != NULL); g_assert (out_c5greg != NULL); - str = g_match_info_fetch (info, 1); + /* Each regex in the array adds to the number of matches (e.g. first regex + * will match in indices 1 and 2, but second regex will use indices 3/4/5 + * etc), so we "just" need to process each regex in order */ + n_matches = g_match_info_get_match_count (info); + switch (n_matches) { + case 3: + /* +CREG: (GSM 07.07 CREG=1 unsolicited) */ + /* [0] = "\\+(CREG|CGREG|CEREG|C5GREG):\\s*0*([0-9])", */ + ireg = n_matches - 2; + istat = n_matches - 1; + break; + case 6: + /* +CREG: , (GSM 07.07 CREG=1 solicited) */ + /* [1] = "\\+(CREG|CGREG|CEREG|C5GREG):\\s*0*([0-9]),\\s*0*([0-9])", */ + ireg = n_matches - 3; + istat = n_matches - 1; + break; + case 10: + /* +CREG: ,, (GSM 07.07 CREG=2 unsolicited) */ + /* [2] = "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)", */ + ireg = n_matches - 4; + istat = n_matches - 3; + ilac = n_matches - 2; + ici = n_matches - 1; + break; + case 15: + case 20: + /* +CREG: ,,, (GSM 07.07 solicited and some CREG=2 unsolicited) */ + /* [3] = "\\+(CREG|CGREG|CEREG):\\s*([0-9]),\\s*([0-9])\\s*,\\s*([^,]*)\\s*,\\s*([^,\\s]*)", */ + /* [4] = "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*0*([0-9])\\s*,\\s*(\"[^,]*\")\\s*,\\s*(\"[^,\\s]*\")", */ + ireg = n_matches - 5; + istat = n_matches - 3; + ilac = n_matches - 2; + ici = n_matches - 1; + break; + case 25: + case 30: + /* +CREG: ,,, (ETSI 27.007 CREG=2 unsolicited) */ + /* [5] = "\\+(CREG|CGREG|CEREG):\\s*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([0-9])", */ + /* [6] = "\\+(CREG|CGREG|CEREG):\\s*0*([0-9])\\s*,\\s*(\"[^,\\s]*\")\\s*,\\s*(\"[^,\\s]*\")\\s*,\\s*0*([0-9])", */ + ireg = n_matches - 5; + istat = n_matches - 4; + ilac = n_matches - 3; + ici = n_matches - 2; + iact = n_matches - 1; + break; + case 36: + /* +CREG: ,,,, (ETSI 27.007 solicited and some CREG=2 unsolicited) */ + /* [7] = "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*0*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])", */ + ireg = n_matches - 6; + istat = n_matches - 4; + ilac = n_matches - 3; + ici = n_matches - 2; + iact = n_matches - 1; + break; + case 42: + /* +CREG: ,,,,, (Samsung Wave S8500) */ + /* '+CREG: 2,1,000B,2816, B, C2816OK' */ + /* [8] = "\\+(CREG|CGREG):\\s*0*([0-9]),\\s*0*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*[^,\\s]*", */ + ireg = n_matches - 6; + istat = n_matches - 4; + ilac = n_matches - 3; + ici = n_matches - 2; + iact = n_matches - 1; + break; + case 48: + /* +CREG: ,,,, (ETSI 27.007 v9.20 CREG=2 unsolicited with RAC) */ + /* [9] = "\\+(CREG|CGREG):\\s*0*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])\\s*,\\s*([^,\\s]*)", */ + ireg = n_matches - 6; + istat = n_matches - 5; + ilac = n_matches - 4; + ici = n_matches - 3; + iact = n_matches - 2; + break; + case 54: + /* +CEREG: ,,,, (ETSI 27.007 v8.6 CREG=2 unsolicited with RAC) */ + /* [10] = "\\+(CEREG):\\s*0*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])", */ + ireg = n_matches - 6; + istat = n_matches - 5; + ilac = n_matches - 4; + ici = n_matches - 2; + iact = n_matches - 1; + break; + case 61: + /* +CEREG: ,,,,, (ETSI 27.007 v8.6 CREG=2 solicited with RAC) */ + /* [11] = "\\+(CEREG):\\s*0*([0-9]),\\s*0*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])", */ + ireg = n_matches - 7; + istat = n_matches - 5; + ilac = n_matches - 4; + ici = n_matches - 2; + iact = n_matches - 1; + break; + case 68: + /* +C5GREG: ,,,,, (ETSI 27.007 CREG=2 unsolicited) */ + /* [12] = "\\+(C5GREG):\\s*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)", */ + ireg = n_matches - 7; + istat = n_matches - 6; + ilac = n_matches - 5; + ici = n_matches - 4; + iact = n_matches - 3; + break; + case 76: + /* +C5GREG: ,,,,,, (ETSI 27.007 solicited) */ + /* [13] = "\\+(C5GREG):\\s*([0-9]+)\\s*,\\s*([0-9+])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)", */ + ireg = n_matches - 8; + istat = n_matches - 6; + ilac = n_matches - 5; + ici = n_matches - 4; + iact = n_matches - 3; + break; + default: + g_set_error_literal (error, + MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Could not parse the registration status response (invalid match count)"); + return FALSE; + } + + /* Reg type */ + str = g_match_info_fetch (info, ireg); *out_cgreg = (str && strstr (str, "CGREG")) ? TRUE : FALSE; *out_cereg = (str && strstr (str, "CEREG")) ? TRUE : FALSE; *out_c5greg = (str && strstr (str, "C5GREG")) ? TRUE : FALSE; g_free (str); - /* Normally the number of matches could be used to determine what each - * item is, but we have overlap in one case. - */ - n_matches = g_match_info_get_match_count (info); - if (n_matches == 3) { - /* CREG=1: +CREG: */ - istat = 2; - } else if (n_matches == 4) { - /* Solicited response: +CREG: , */ - istat = 3; - } else if (n_matches == 5) { - /* CREG=2 (GSM 07.07): +CREG: ,, */ - istat = 2; - ilac = 3; - ici = 4; - } else if (n_matches == 6) { - /* CREG=2 (ETSI 27.007): +CREG: ,,, - * CREG=2 (non-standard): +CREG: ,,, - */ - - /* Check if the third item is the LAC to distinguish the two cases */ - if (item_is_lac_not_stat (info, 3)) { - istat = 2; - ilac = 3; - ici = 4; - iact = 5; - } else { - istat = 3; - ilac = 4; - ici = 5; - } - } else if (n_matches == 7) { - /* CREG=2 (solicited): +CREG: ,,,, - * CREG=2 (unsolicited with RAC): +CREG: ,,,, - * CEREG=2 (solicited): +CEREG: ,,,, - * CEREG=2 (unsolicited with RAC): +CEREG: ,,,, - */ - - if (*out_cereg) { - /* Check if the third item is the LAC to distinguish the two cases */ - if (item_is_lac_not_stat (info, 3)) { - istat = 2; - ilac = 3; - } else { - istat = 3; - ilac = 4; - } - ici = 5; - iact = 6; - } else { - /* Check if the third item is the LAC to distinguish the two cases */ - if (item_is_lac_not_stat (info, 3)) { - istat = 2; - ilac = 3; - ici = 4; - iact = 5; - } else { - istat = 3; - ilac = 4; - ici = 5; - iact = 6; - } - } - } else if (n_matches == 8) { - /* CEREG=2 (solicited with RAC): +CEREG: ,,,,, - * C5GREG=2 (unsolicited): +C5GREG: ,,,,, - */ - if (*out_cereg) { - istat = 3; - ilac = 4; - ici = 6; - iact = 7; - } else if (*out_c5greg) { - istat = 2; - ilac = 3; - ici = 4; - iact = 5; - } - } else if (n_matches == 9) { - /* C5GREG=2 (solicited): +C5GREG: ,,,,,, */ - istat = 3; - ilac = 4; - ici = 5; - iact = 6; - } - /* Status */ if (!mm_get_uint_from_match_info (info, istat, &stat)) { g_set_error_literal (error, diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index 482809e2..dd9ca969 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -141,14 +141,13 @@ MMFlowControl mm_flow_control_from_string (const gchar *str, gboolean mm_modem_3gpp_registration_state_is_registered (MMModem3gppRegistrationState state); /* Common Regex getters */ -GPtrArray *mm_3gpp_creg_regex_get (gboolean solicited); -void mm_3gpp_creg_regex_destroy (GPtrArray *array); -GRegex *mm_3gpp_ciev_regex_get (void); -GRegex *mm_3gpp_cgev_regex_get (void); -GRegex *mm_3gpp_cusd_regex_get (void); -GRegex *mm_3gpp_cmti_regex_get (void); -GRegex *mm_3gpp_cds_regex_get (void); -GRegex *mm_3gpp_cbm_regex_get (void); +GRegex *mm_3gpp_creg_regex_get (gboolean solicited); +GRegex *mm_3gpp_ciev_regex_get (void); +GRegex *mm_3gpp_cgev_regex_get (void); +GRegex *mm_3gpp_cusd_regex_get (void); +GRegex *mm_3gpp_cmti_regex_get (void); +GRegex *mm_3gpp_cds_regex_get (void); +GRegex *mm_3gpp_cbm_regex_get (void); /* AT+WS46=? response parser: returns array of MMModemMode values */ GArray *mm_3gpp_parse_ws46_test_response (const gchar *response, diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index c8583c63..c4b0ab45 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -1088,8 +1088,8 @@ test_normalize_operator (void) /* Test CREG/CGREG responses and unsolicited messages */ typedef struct { - GPtrArray *solicited_creg; - GPtrArray *unsolicited_creg; + GRegex *solicited_creg; + GRegex *unsolicited_creg; } RegTestData; static RegTestData * @@ -1106,8 +1106,8 @@ reg_test_data_new (void) static void reg_test_data_free (RegTestData *data) { - mm_3gpp_creg_regex_destroy (data->solicited_creg); - mm_3gpp_creg_regex_destroy (data->unsolicited_creg); + g_regex_unref (data->solicited_creg); + g_regex_unref (data->unsolicited_creg); g_free (data); } @@ -1131,7 +1131,6 @@ test_creg_match (const char *test, const CregResult *result) { g_autoptr(GMatchInfo) info = NULL; - guint i; MMModem3gppRegistrationState state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; MMModemAccessTechnology access_tech = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; gulong lac = 0; @@ -1141,38 +1140,25 @@ test_creg_match (const char *test, gboolean cgreg = FALSE; gboolean cereg = FALSE; gboolean c5greg = FALSE; - guint regex_num = 0; - GPtrArray *array; + GRegex *regex; g_assert (reply); g_assert (test); g_assert (data); g_assert (result); - g_debug ("Testing '%s' +C%sREG %s response...", + g_debug ("Testing '%s' +C%sREG %s response '%s'...", test, result->cgreg ? "G" : "", - solicited ? "solicited" : "unsolicited"); + solicited ? "solicited" : "unsolicited", + reply); - array = solicited ? data->solicited_creg : data->unsolicited_creg; - for (i = 0; i < array->len; i++) { - GRegex *r = g_ptr_array_index (array, i); - - if (g_regex_match (r, reply, 0, &info)) { - g_debug (" matched with %d", i); - regex_num = i; - break; - } - g_clear_pointer (&info, g_match_info_free); + regex = solicited ? data->solicited_creg : data->unsolicited_creg; + if (!g_regex_match (regex, reply, 0, &info)) { + g_debug ("not matched"); + g_assert (FALSE); } - g_debug (" regex_num (%u) == result->regex_num (%u)", - regex_num, - result->regex_num); - - g_assert (info != NULL); - g_assert_cmpuint (regex_num, ==, result->regex_num); - success = mm_3gpp_parse_creg_response (info, NULL, &state, &lac, &ci, &access_tech, &cgreg, &cereg, &c5greg, &error); g_assert (success); @@ -1518,6 +1504,16 @@ test_creg2_s8500_wave_multidigit_stat_unsolicited (void *f, gpointer d) test_creg_match ("Samsung Wave S8500 CREG=2 with multidigit \"stat\" value", FALSE, reply, data, &result); } +static void +test_creg2_s8500_wave_act_unsolicited (void *f, gpointer d) +{ + RegTestData *data = (RegTestData *) d; + const char *reply = "\r\n+CGREG: 2,11,003F,8FE3, 10, C2816\r\n"; + const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS, 0x003F, 0x8FE3, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 8, TRUE, FALSE, FALSE }; + + test_creg_match ("Samsung Wave S8500 CREG=2 with act value", FALSE, reply, data, &result); +} + static void test_creg2_gobi_weird_solicited (void *f, gpointer d) { @@ -5362,6 +5358,7 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_creg2_md400_unsolicited, reg_data)); g_test_suite_add (suite, TESTCASE (test_creg2_s8500_wave_unsolicited, reg_data)); g_test_suite_add (suite, TESTCASE (test_creg2_s8500_wave_multidigit_stat_unsolicited, reg_data)); + g_test_suite_add (suite, TESTCASE (test_creg2_s8500_wave_act_unsolicited, reg_data)); g_test_suite_add (suite, TESTCASE (test_creg2_gobi_weird_solicited, reg_data)); g_test_suite_add (suite, TESTCASE (test_creg2_iridium_solicited, reg_data)); g_test_suite_add (suite, TESTCASE (test_creg2_no_leading_zeros_solicited, reg_data));