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..8a108ef5 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,52 +1131,42 @@ 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; gulong ci = 0; GError *error = NULL; gboolean success; + gboolean matched; 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); + regex = solicited ? data->solicited_creg : data->unsolicited_creg; + g_regex_match (regex, reply, 0, &info); - 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); + while (g_match_info_matches (info)) { + matched = TRUE; + success = mm_3gpp_parse_creg_response (info, NULL, &state, &lac, &ci, &access_tech, &cgreg, &cereg, &c5greg, &error); + + g_assert (success); + g_assert_no_error (error); + g_match_info_next (info, NULL); } - 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); - g_assert_no_error (error); + g_assert (matched); g_assert_cmpuint (state, ==, result->state); g_assert_cmpuint (lac, ==, result->lac); g_assert_cmpuint (ci, ==, result->ci); @@ -1472,7 +1462,7 @@ test_creg_cgreg_multi_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 5\r\n\r\n+CGREG: 0\r\n"; - const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 0, FALSE, FALSE, FALSE }; + const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 0, TRUE, FALSE, FALSE }; test_creg_match ("Multi CREG/CGREG", FALSE, reply, data, &result); } @@ -1482,11 +1472,21 @@ test_creg_cgreg_multi2_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CGREG: 0\r\n\r\n+CREG: 5\r\n"; - const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_IDLE, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 0, TRUE, FALSE, FALSE }; + const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 0, FALSE, FALSE, FALSE }; test_creg_match ("Multi CREG/CGREG #2", FALSE, reply, data, &result); } +static void +test_cereg_multi_unsolicited (void *f, gpointer d) +{ + RegTestData *data = (RegTestData *) d; + const char *reply = "\r\n+CEREG: 2\r\n\r\n+CNSMOD: 8\r\n\r\n+CEREG: 1,AAAA,01234567,7\r\n"; + const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_HOME, 0xAAAA, 0x1234567, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 5, FALSE, TRUE, FALSE }; + + test_creg_match ("Multi CEREG", FALSE, reply, data, &result); +} + static void test_cgreg2_x220_unsolicited (void *f, gpointer d) { @@ -1518,6 +1518,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 +5372,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)); @@ -5406,6 +5417,7 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi_unsolicited, reg_data)); g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi2_unsolicited, reg_data)); + g_test_suite_add (suite, TESTCASE (test_cereg_multi_unsolicited, reg_data)); g_test_suite_add (suite, TESTCASE (test_cscs_icon225_support_response, NULL)); g_test_suite_add (suite, TESTCASE (test_cscs_sierra_mercury_support_response, NULL));