aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dan@ioncontrol.co>2025-05-14 15:43:04 -0500
committerDan Williams <dan@ioncontrol.co>2025-05-14 15:43:04 -0500
commita4421095f8464eaf678824a15a8e382a8b653ce5 (patch)
treeb63906663f23670582b9e9d032d7c28a8e837545
parentbee6bce2fafdcddd0cb8fbc34898550967353f1b (diff)
parent02131bf3bb1af33773ced6dff666d016f2022f6d (diff)
Merge request !1353 from 'fix-creg-regex'
modem-helpers: support multi-digit "stat" values in CREG response https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/1353 Closes #987
-rw-r--r--src/mm-modem-helpers.c28
-rw-r--r--src/tests/test-modem-helpers.c132
2 files changed, 146 insertions, 14 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 7a911248..e1450a05 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -854,28 +854,28 @@ mm_modem_3gpp_registration_state_is_registered (MMModem3gppRegistrationState sta
static const gchar *creg_regex[] = {
/* +CREG: <stat> (GSM 07.07 CREG=1 unsolicited) */
- [0] = "\\+(CREG|CGREG|CEREG|C5GREG):\\s*0*([0-9])",
+ [0] = "\\+(CREG|CGREG|CEREG|C5GREG):\\s*0*([0-9]+)",
/* +CREG: <n>,<stat> (GSM 07.07 CREG=1 solicited) */
- [1] = "\\+(CREG|CGREG|CEREG|C5GREG):\\s*0*([0-9]),\\s*0*([0-9])",
+ [1] = "\\+(CREG|CGREG|CEREG|C5GREG):\\s*0*([0-9]),\\s*0*([0-9]+)",
/* +CREG: <stat>,<lac>,<ci> (GSM 07.07 CREG=2 unsolicited) */
- [2] = "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)",
+ [2] = "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]+),\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)",
/* +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]*\")",
+ [3] = "\\+(CREG|CGREG|CEREG):\\s*([0-9]),\\s*([0-9]|[1-9][0-9]+)\\s*,\\s*([^,]*)\\s*,\\s*([^,\\s]*)",
+ [4] = "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*0*([0-9]+)\\s*,\\s*(\"[^,]*\")\\s*,\\s*(\"[^,\\s]*\")",
/* +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])",
+ [5] = "\\+(CREG|CGREG|CEREG):\\s*([0-9]|[1-9][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])",
/* +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])",
+ [7] = "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*0*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])",
/* +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]*",
+ [8] = "\\+(CREG|CGREG):\\s*0*([0-9]),\\s*0*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*[^,\\s]*",
/* +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]*)",
+ [9] = "\\+(CREG|CGREG):\\s*0*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])\\s*,\\s*([^,\\s]*)",
/* +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])",
+ [10] = "\\+(CEREG):\\s*0*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])",
/* +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])",
+ [11] = "\\+(CEREG):\\s*0*([0-9]),\\s*0*([0-9]+)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])",
/* +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]*)",
/* +C5GREG: <n>,<stat>,<lac>,<ci>,<AcT>,<Allowed_NSSAI_length>,<Allowed_NSSAI> (ETSI 27.007 solicited) */
@@ -2001,10 +2001,10 @@ item_is_lac_not_stat (GMatchInfo *info, guint32 item)
gchar *str;
gboolean is_lac = FALSE;
- /* A <stat> will always be a single digit, without quotes */
+ /* 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) > 1);
+ is_lac = (strchr (str, '"') || strlen (str) > 2);
g_free (str);
return is_lac;
}
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index a75b2647..a6755b0a 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -1207,6 +1207,16 @@ test_creg1_unsolicited (void *f, gpointer d)
}
static void
+test_creg1_multidigit_stat_unsolicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CREG: 11\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 0, FALSE, FALSE, FALSE };
+
+ test_creg_match ("CREG=1 with multidigit \"stat\" value", FALSE, reply, data, &result);
+}
+
+static void
test_creg2_mercury_solicited (void *f, gpointer d)
{
RegTestData *data = (RegTestData *) d;
@@ -1227,6 +1237,16 @@ test_creg2_mercury_unsolicited (void *f, gpointer d)
}
static void
+test_creg2_multidigit_stat_unsolicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CREG: 11,\"33FE\",\"a3fb477\"\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS, 0x33FE, 0xa3fb477, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 2, FALSE, FALSE, FALSE };
+
+ test_creg_match ("CREG=2 with multidigit \"stat\" value", FALSE, reply, data, &result);
+}
+
+static void
test_creg2_sek850i_solicited (void *f, gpointer d)
{
RegTestData *data = (RegTestData *) d;
@@ -1348,6 +1368,26 @@ test_creg2_leading_zeros_unsolicited (void *f, gpointer d)
}
static void
+test_creg2_multidigit_stat_no_leading_zeros_unsolicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CREG: 10,0001,0010,0\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED, 0x0001, 0x0010, MM_MODEM_ACCESS_TECHNOLOGY_GSM, 5, FALSE, FALSE, FALSE };
+
+ test_creg_match ("unsolicited CREG=2 with no leading zeros in integer fields and multidigit \"stat\" value", FALSE, reply, data, &result);
+}
+
+static void
+test_creg2_multidigit_stat_leading_zeros_unsolicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CREG: 0011,\"0001\",\"0010\",000\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS, 0x0001, 0x0010, MM_MODEM_ACCESS_TECHNOLOGY_GSM, 6, FALSE, FALSE, FALSE };
+
+ test_creg_match ("unsolicited CREG=2 with leading zeros in integer fields and multidigit \"stat\" value", FALSE, reply, data, &result);
+}
+
+static void
test_creg2_ublox_solicited (void *f, gpointer d)
{
RegTestData *data = (RegTestData *) d;
@@ -1469,6 +1509,16 @@ test_creg2_s8500_wave_unsolicited (void *f, gpointer d)
}
static void
+test_creg2_s8500_wave_multidigit_stat_unsolicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CREG: 2,11,003F,8FE3, B, C2816\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS, 0x003F, 0x8FE3, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 8, FALSE, FALSE, FALSE };
+
+ test_creg_match ("Samsung Wave S8500 CREG=2 with multidigit \"stat\" value", FALSE, reply, data, &result);
+}
+
+static void
test_creg2_gobi_weird_solicited (void *f, gpointer d)
{
RegTestData *data = (RegTestData *) d;
@@ -1489,6 +1539,36 @@ test_cgreg2_unsolicited_with_rac (void *f, gpointer d)
}
static void
+test_cgreg2_multidigit_stat_with_rac_unsolicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CGREG: 11,\"B092\",\"00000697\",3,\"00\"\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS, 0xB092, 0x0697, MM_MODEM_ACCESS_TECHNOLOGY_EDGE, 9, TRUE, FALSE, FALSE };
+
+ test_creg_match ("CGREG=2 with multidigit \"stat\" value and RAC", FALSE, reply, data, &result);
+}
+
+static void
+test_cgreg2_multidigit_stat_no_leading_zeros_solicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "+CGREG:2,10,ebbd,f025";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED, 0xebbd, 0xf025, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 3, TRUE, FALSE, FALSE };
+
+ test_creg_match ("solicited CGREG=2 with no leading zeros in integer fields and multidigit \"stat\" value", TRUE, reply, data, &result);
+}
+
+static void
+test_cgreg2_multidigit_stat_leading_zeros_solicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "+CGREG:002,0011,\"0f0d\",\"14c3\"";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS, 0x0f0d, 0x14c3, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 4, TRUE, FALSE, FALSE };
+
+ test_creg_match ("solicited CGREG=2 with leading zeros in integer fields and multidigit \"stat\" value", TRUE, reply, data, &result);
+}
+
+static void
test_cereg1_solicited (void *f, gpointer d)
{
RegTestData *data = (RegTestData *) d;
@@ -1529,6 +1609,36 @@ test_cereg2_unsolicited (void *f, gpointer d)
}
static void
+test_cereg2_multidigit_stat_solicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CEREG: 2,10,\"8d83\",\"671f98a\",7\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED, 0x8d83, 0x671f98a, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 7, FALSE, TRUE, FALSE };
+
+ test_creg_match ("CEREG=2 with multidigit \"stat\" value", TRUE, reply, data, &result);
+}
+
+static void
+test_cereg2_multidigit_stat_with_rac_solicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CEREG: 2,10, 2CA8, 20 ,B5583D ,7\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED, 0x2ca8, 0xB5583D, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 11, FALSE, TRUE, FALSE };
+
+ test_creg_match ("CEREG=2 with multidigit \"stat\" value and RAC", TRUE, reply, data, &result);
+}
+
+static void
+test_cereg2_multidigit_stat_with_rac_unsolicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+CEREG: 11, 78FE, 20 ,14419E ,7\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS, 0x78FE, 0x14419E, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 10, FALSE, TRUE, FALSE };
+
+ test_creg_match ("CEREG=2 with multidigit \"stat\" value and RAC", FALSE, reply, data, &result);
+}
+
+static void
test_cereg2_altair_lte_solicited (void *f, gpointer d)
{
RegTestData *data = (RegTestData *) d;
@@ -1599,6 +1709,16 @@ test_c5greg1_solicited (void *f, gpointer d)
}
static void
+test_c5greg1_multidigit_stat_solicited (void *f, gpointer d)
+{
+ RegTestData *data = (RegTestData *) d;
+ const char *reply = "\r\n+C5GREG: 1, 10\r\n";
+ const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 1, FALSE, FALSE, TRUE };
+
+ test_creg_match ("C5GREG=1 with multidigit \"stat\" value", TRUE, reply, data, &result);
+}
+
+static void
test_c5greg1_unsolicited (void *f, gpointer d)
{
RegTestData *data = (RegTestData *) d;
@@ -5001,8 +5121,10 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_creg1_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg1_unsolicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_creg1_multidigit_stat_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_mercury_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_mercury_unsolicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_creg2_multidigit_stat_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_sek850i_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_sek850i_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_e160g_solicited_unregistered, reg_data));
@@ -5012,12 +5134,15 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_creg2_xu870_unsolicited_unregistered, reg_data));
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_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));
g_test_suite_add (suite, TESTCASE (test_creg2_leading_zeros_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_no_leading_zeros_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_leading_zeros_unsolicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_creg2_multidigit_stat_no_leading_zeros_unsolicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_creg2_multidigit_stat_leading_zeros_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_ublox_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_creg2_ublox_unsolicited, reg_data));
@@ -5028,6 +5153,9 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_cgreg2_md400_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cgreg2_x220_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cgreg2_unsolicited_with_rac, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_cgreg2_multidigit_stat_with_rac_unsolicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_cgreg2_multidigit_stat_no_leading_zeros_solicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_cgreg2_multidigit_stat_leading_zeros_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cgreg2_thuraya_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cgreg2_thuraya_unsolicited, reg_data));
@@ -5035,12 +5163,16 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_cereg1_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cereg2_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cereg2_unsolicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_cereg2_multidigit_stat_solicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_cereg2_multidigit_stat_with_rac_solicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_cereg2_multidigit_stat_with_rac_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cereg2_altair_lte_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cereg2_altair_lte_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cereg2_novatel_lte_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_cereg2_novatel_lte_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_c5greg1_solicited, reg_data));
+ g_test_suite_add (suite, TESTCASE (test_c5greg1_multidigit_stat_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_c5greg1_unsolicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_c5greg2_solicited, reg_data));
g_test_suite_add (suite, TESTCASE (test_c5greg2_unsolicited, reg_data));