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:
<CR><LF>+CEREG:  2<CR><LF><CR><LF>+CNSMOD: 8<CR><LF><CR><LF>+CEREG: 1,AAAA,01234567,7<CR><LF>
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 <dominique.martinet@atmark-techno.com>
This commit is contained in:
Dominique Martinet
2026-09-08 18:51:58 +02:00
committed by Dan Williams
parent 76c66944cc
commit 04c9797456
4 changed files with 184 additions and 202 deletions
+25 -46
View File
@@ -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);
+129 -122
View File
@@ -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 <stat> 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: <stat> (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: <n>,<stat> (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: <stat>,<lac>,<ci> (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: <n>,<stat>,<lac>,<ci> (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: <stat>,<lac>,<ci>,<AcT> (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: <n>,<stat>,<lac>,<ci>,<AcT> (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: <n>,<stat>,<lac>,<ci>,<AcT?>,<something> (Samsung Wave S8500) */
/* '<CR><LF>+CREG: 2,1,000B,2816, B, C2816<CR><LF><CR><LF>OK<CR><LF>' */
/* [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: <stat>,<lac>,<ci>,<AcT>,<RAC> (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: <stat>,<lac>,<rac>,<ci>,<AcT> (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: <n>,<stat>,<lac>,<rac>,<ci>,<AcT> (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: <stat>,<lac>,<ci>,<AcT>,<Allowed_NSSAI_length>,<Allowed_NSSAI> (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: <n>,<stat>,<lac>,<ci>,<AcT>,<Allowed_NSSAI_length>,<Allowed_NSSAI> (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: <stat> */
istat = 2;
} else if (n_matches == 4) {
/* Solicited response: +CREG: <n>,<stat> */
istat = 3;
} else if (n_matches == 5) {
/* CREG=2 (GSM 07.07): +CREG: <stat>,<lac>,<ci> */
istat = 2;
ilac = 3;
ici = 4;
} else if (n_matches == 6) {
/* CREG=2 (ETSI 27.007): +CREG: <stat>,<lac>,<ci>,<AcT>
* CREG=2 (non-standard): +CREG: <n>,<stat>,<lac>,<ci>
*/
/* 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: <n>,<stat>,<lac>,<ci>,<AcT>
* CREG=2 (unsolicited with RAC): +CREG: <stat>,<lac>,<ci>,<AcT>,<RAC>
* CEREG=2 (solicited): +CEREG: <n>,<stat>,<lac>,<ci>,<AcT>
* CEREG=2 (unsolicited with RAC): +CEREG: <stat>,<lac>,<rac>,<ci>,<AcT>
*/
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: <n>,<stat>,<lac>,<rac>,<ci>,<AcT>
* C5GREG=2 (unsolicited): +C5GREG: <stat>,<tac>,<ci>,<AcT>,<Allowed_NSSAI_length>,<Allowed_NSSAI>
*/
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: <n>,<stat>,<tac>,<ci>,<AcT>,<Allowed_NSSAI_length>,<Allowed_NSSAI> */
istat = 3;
ilac = 4;
ici = 5;
iact = 6;
}
/* Status */
if (!mm_get_uint_from_match_info (info, istat, &stat)) {
g_set_error_literal (error,
+7 -8
View File
@@ -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,
+23 -26
View File
@@ -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));