diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 3 | ||||
-rw-r--r-- | src/mm-broadband-modem.c | 165 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.c | 51 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.h | 10 | ||||
-rw-r--r-- | src/mm-modem-helpers.c | 82 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 1 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 121 |
7 files changed, 365 insertions, 68 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 464da87e..f8b84d43 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -3984,6 +3984,7 @@ static void modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data) { @@ -4138,6 +4139,7 @@ static void modem_3gpp_disable_unsolicited_registration_events (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data) { @@ -4183,6 +4185,7 @@ static void modem_3gpp_enable_unsolicited_registration_events (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data) { diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index ba4ca9cf..12ed91b6 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -86,6 +86,7 @@ enum { PROP_MODEM_3GPP_REGISTRATION_STATE, PROP_MODEM_3GPP_CS_NETWORK_SUPPORTED, PROP_MODEM_3GPP_PS_NETWORK_SUPPORTED, + PROP_MODEM_3GPP_EPS_NETWORK_SUPPORTED, PROP_MODEM_CDMA_CDMA1X_REGISTRATION_STATE, PROP_MODEM_CDMA_EVDO_REGISTRATION_STATE, PROP_MODEM_CDMA_CDMA1X_NETWORK_SUPPORTED, @@ -129,6 +130,7 @@ struct _MMBroadbandModemPrivate { MMModem3gppRegistrationState modem_3gpp_registration_state; gboolean modem_3gpp_cs_network_supported; gboolean modem_3gpp_ps_network_supported; + gboolean modem_3gpp_eps_network_supported; /* Implementation helpers */ GPtrArray *modem_3gpp_registration_regex; @@ -3285,6 +3287,7 @@ registration_state_changed (MMAtSerialPort *port, gulong lac = 0, cell_id = 0; MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; gboolean cgreg = FALSE; + gboolean cereg = FALSE; GError *error = NULL; if (!mm_3gpp_parse_creg_response (match_info, @@ -3293,6 +3296,7 @@ registration_state_changed (MMAtSerialPort *port, &cell_id, &act, &cgreg, + &cereg, &error)) { mm_warn ("error parsing unsolicited registration: %s", error && error->message ? error->message : "(unknown)"); @@ -3303,6 +3307,8 @@ registration_state_changed (MMAtSerialPort *port, /* Report new registration state */ if (cgreg) mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), state); + else if (cereg) + mm_iface_modem_3gpp_update_eps_registration_state (MM_IFACE_MODEM_3GPP (self), state); else mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), state); @@ -3489,12 +3495,16 @@ typedef struct { GSimpleAsyncResult *result; gboolean cs_supported; gboolean ps_supported; + gboolean eps_supported; gboolean run_cs; gboolean run_ps; + gboolean run_eps; gboolean running_cs; gboolean running_ps; + gboolean running_eps; GError *cs_error; GError *ps_error; + GError *eps_error; } RunRegistrationChecksContext; static void @@ -3505,6 +3515,8 @@ run_registration_checks_context_complete_and_free (RunRegistrationChecksContext g_error_free (ctx->cs_error); if (ctx->ps_error) g_error_free (ctx->ps_error); + if (ctx->eps_error) + g_error_free (ctx->eps_error); g_object_unref (ctx->result); g_object_unref (ctx->self); g_free (ctx); @@ -3531,22 +3543,26 @@ registration_status_check_ready (MMBroadbandModem *self, guint i; gboolean parsed; gboolean cgreg; + gboolean cereg; MMModem3gppRegistrationState state; MMModemAccessTechnology act; gulong lac; gulong cid; /* Only one must be running */ - g_assert (!(ctx->running_ps && ctx->running_cs) && - (ctx->running_cs || ctx->running_ps)); + g_assert ((ctx->running_cs ? 1 : 0) + + (ctx->running_ps ? 1 : 0) + + (ctx->running_eps ? 1 : 0) == 1); response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (!response) { g_assert (error != NULL); if (ctx->running_cs) ctx->cs_error = error; - else + else if (ctx->running_ps) ctx->ps_error = error; + else + ctx->eps_error = error; run_registration_checks_context_step (ctx); return; @@ -3582,14 +3598,17 @@ registration_status_check_ready (MMBroadbandModem *self, response); if (ctx->running_cs) ctx->cs_error = error; - else + else if (ctx->running_ps) ctx->ps_error = error; + else + ctx->eps_error = error; run_registration_checks_context_step (ctx); return; } cgreg = FALSE; + cereg = FALSE; state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; lac = 0; @@ -3600,6 +3619,7 @@ registration_status_check_ready (MMBroadbandModem *self, &cid, &act, &cgreg, + &cereg, &error); g_match_info_free (match_info); @@ -3611,8 +3631,10 @@ registration_status_check_ready (MMBroadbandModem *self, response); if (ctx->running_cs) ctx->cs_error = error; - else + else if (ctx->running_ps) ctx->ps_error = error; + else + ctx->eps_error = error; run_registration_checks_context_step (ctx); return; } @@ -3621,10 +3643,20 @@ registration_status_check_ready (MMBroadbandModem *self, if (cgreg) { if (ctx->running_cs) mm_dbg ("Got PS registration state when checking CS registration state"); + else if (ctx->running_eps) + mm_dbg ("Got PS registration state when checking EPS registration state"); mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), state); + } else if (cereg) { + if (ctx->running_cs) + mm_dbg ("Got EPS registration state when checking CS registration state"); + else if (ctx->running_ps) + mm_dbg ("Got EPS registration state when checking PS registration state"); + mm_iface_modem_3gpp_update_eps_registration_state (MM_IFACE_MODEM_3GPP (self), state); } else { if (ctx->running_ps) mm_dbg ("Got CS registration state when checking PS registration state"); + else if (ctx->running_eps) + mm_dbg ("Got CS registration state when checking EPS registration state"); mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), state); } @@ -3639,6 +3671,7 @@ run_registration_checks_context_step (RunRegistrationChecksContext *ctx) { ctx->running_cs = FALSE; ctx->running_ps = FALSE; + ctx->running_eps = FALSE; if (ctx->run_cs) { ctx->running_cs = TRUE; @@ -3666,12 +3699,29 @@ run_registration_checks_context_step (RunRegistrationChecksContext *ctx) return; } + if (ctx->run_eps) { + ctx->running_eps = TRUE; + ctx->run_eps = FALSE; + /* Check current EPS-registration state. */ + mm_base_modem_at_command (MM_BASE_MODEM (ctx->self), + "+CEREG?", + 10, + FALSE, + (GAsyncReadyCallback)registration_status_check_ready, + ctx); + return; + } + /* If all run checks returned errors we fail */ - if ((ctx->ps_supported && ctx->ps_error && ctx->cs_supported && ctx->cs_error) || - (ctx->ps_supported && ctx->ps_error && !ctx->cs_supported) || - (ctx->cs_supported && ctx->cs_error && !ctx->ps_supported)) { - /* Prefer the PS error if any */ - if (ctx->ps_error) { + if ((ctx->cs_supported || ctx->ps_supported || ctx->eps_supported) && + (!ctx->cs_supported || ctx->cs_error) && + (!ctx->ps_supported || ctx->ps_error) && + (!ctx->eps_supported || ctx->eps_error)) { + /* Prefer the EPS, and then PS error if any */ + if (ctx->eps_error) { + g_simple_async_result_set_from_error (ctx->result, ctx->eps_error); + ctx->eps_error = NULL; + } else if (ctx->ps_error) { g_simple_async_result_set_from_error (ctx->result, ctx->ps_error); ctx->ps_error = NULL; } else if (ctx->cs_error) { @@ -3689,6 +3739,7 @@ static void modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data) { @@ -3702,8 +3753,10 @@ modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, modem_3gpp_run_registration_checks); ctx->cs_supported = cs_supported; ctx->ps_supported = ps_supported; + ctx->eps_supported = eps_supported; ctx->run_cs = cs_supported; ctx->run_ps = ps_supported; + ctx->run_eps = eps_supported; run_registration_checks_context_step (ctx); } @@ -3717,10 +3770,13 @@ typedef struct { gboolean enable; /* TRUE for enabling, FALSE for disabling */ gboolean run_cs; gboolean run_ps; + gboolean run_eps; gboolean running_cs; gboolean running_ps; + gboolean running_eps; GError *cs_error; GError *ps_error; + GError *eps_error; gboolean secondary_sequence; gboolean secondary_done; } UnsolicitedRegistrationEventsContext; @@ -3733,6 +3789,8 @@ unsolicited_registration_events_context_complete_and_free (UnsolicitedRegistrati g_error_free (ctx->cs_error); if (ctx->ps_error) g_error_free (ctx->ps_error); + if (ctx->eps_error) + g_error_free (ctx->eps_error); g_object_unref (ctx->result); g_object_unref (ctx->self); g_free (ctx); @@ -3743,6 +3801,7 @@ unsolicited_registration_events_context_new (MMBroadbandModem *self, gboolean enable, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data) { @@ -3757,6 +3816,7 @@ unsolicited_registration_events_context_new (MMBroadbandModem *self, ctx->enable = FALSE; ctx->run_cs = cs_supported; ctx->run_ps = ps_supported; + ctx->run_eps = eps_supported; return ctx; } @@ -3816,6 +3876,20 @@ static const MMBaseModemAtCommand ps_unregistration_sequence[] = { { NULL } }; +static const MMBaseModemAtCommand eps_registration_sequence[] = { + /* Enable unsolicited registration notifications in EPS network, with location */ + { "+CEREG=2", 3, FALSE, parse_registration_setup_reply }, + /* Enable unsolicited registration notifications in EPS network, without location */ + { "+CEREG=1", 3, FALSE, parse_registration_setup_reply }, + { NULL } +}; + +static const MMBaseModemAtCommand eps_unregistration_sequence[] = { + /* Disable unsolicited registration notifications in PS network */ + { "+CEREG=0", 3, FALSE, parse_registration_setup_reply }, + { NULL } +}; + static void unsolicited_registration_events_context_step (UnsolicitedRegistrationEventsContext *ctx); static void @@ -3828,8 +3902,9 @@ unsolicited_registration_events_sequence_ready (MMBroadbandModem *self, MMAtSerialPort *secondary; /* Only one must be running */ - g_assert (!(ctx->running_ps && ctx->running_cs) && - (ctx->running_cs || ctx->running_ps)); + g_assert ((ctx->running_cs ? 1 : 0) + + (ctx->running_ps ? 1 : 0) + + (ctx->running_eps ? 1 : 0) == 1); if (ctx->secondary_done) { if (ctx->secondary_sequence) @@ -3846,6 +3921,8 @@ unsolicited_registration_events_sequence_ready (MMBroadbandModem *self, ctx->cs_error = error; else if (ctx->running_ps && !ctx->ps_error) ctx->ps_error = error; + else if (ctx->running_eps && !ctx->eps_error) + ctx->eps_error = error; else g_error_free (error); } else { @@ -3858,6 +3935,10 @@ unsolicited_registration_events_sequence_ready (MMBroadbandModem *self, g_error_free (ctx->ps_error); ctx->ps_error = NULL; } + else if (ctx->running_eps && ctx->eps_error) { + g_error_free (ctx->eps_error); + ctx->eps_error = NULL; + } } /* Done with primary and secondary, keep on */ @@ -3878,13 +3959,17 @@ unsolicited_registration_events_sequence_ready (MMBroadbandModem *self, /* Keep errors reported */ if (ctx->running_cs) ctx->cs_error = error; - else + else if (ctx->running_ps) ctx->ps_error = error; + else + ctx->eps_error = error; /* Even if primary failed, go on and try to enable in secondary port */ } secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self)); if (secondary) { + const MMBaseModemAtCommand *registration_sequence = NULL; + ctx->secondary_done = TRUE; /* Now use the same registration setup in secondary port, if any */ @@ -3904,12 +3989,16 @@ unsolicited_registration_events_sequence_ready (MMBroadbandModem *self, /* If primary failed, run the whole sequence in secondary */ ctx->secondary_sequence = TRUE; + if (ctx->running_cs) + registration_sequence = ctx->enable ? cs_registration_sequence : cs_unregistration_sequence; + else if (ctx->running_ps) + registration_sequence = ctx->enable ? ps_registration_sequence : ps_unregistration_sequence; + else + registration_sequence = ctx->enable ? eps_registration_sequence : eps_unregistration_sequence; mm_base_modem_at_sequence_full ( MM_BASE_MODEM (self), secondary, - (ctx->running_cs ? - (ctx->enable ? cs_registration_sequence : cs_unregistration_sequence) : - (ctx->enable ? ps_registration_sequence : ps_unregistration_sequence)), + registration_sequence, NULL, /* response processor context */ NULL, /* response processor context free */ NULL, /* cancellable */ @@ -3927,6 +4016,7 @@ unsolicited_registration_events_context_step (UnsolicitedRegistrationEventsConte { ctx->running_cs = FALSE; ctx->running_ps = FALSE; + ctx->running_eps = FALSE; ctx->secondary_done = FALSE; if (ctx->run_cs) { @@ -3938,7 +4028,7 @@ unsolicited_registration_events_context_step (UnsolicitedRegistrationEventsConte cs_registration_sequence, NULL, /* response processor context */ NULL, /* response processor context free */ - NULL, /* cancellable */ + NULL, /* cancellable */ (GAsyncReadyCallback)unsolicited_registration_events_sequence_ready, ctx); return; @@ -3953,16 +4043,34 @@ unsolicited_registration_events_context_step (UnsolicitedRegistrationEventsConte ps_registration_sequence, NULL, /* response processor context */ NULL, /* response processor context free */ - NULL, /* cancellable */ + NULL, /* cancellable */ + (GAsyncReadyCallback)unsolicited_registration_events_sequence_ready, + ctx); + return; + } + + if (ctx->run_eps) { + ctx->running_eps = TRUE; + ctx->run_eps = FALSE; + mm_base_modem_at_sequence_full ( + MM_BASE_MODEM (ctx->self), + mm_base_modem_peek_port_primary (MM_BASE_MODEM (ctx->self)), + eps_registration_sequence, + NULL, /* response processor context */ + NULL, /* response processor context free */ + NULL, /* cancellable */ (GAsyncReadyCallback)unsolicited_registration_events_sequence_ready, ctx); return; } /* All done! - * If we have any error reported, we'll propagate it. PS errors take - * precendence over CS errors. */ - if (ctx->ps_error) { + * If we have any error reported, we'll propagate it. EPS errors take + * precendence over PS errors and PS errors take precendence over CS errors. */ + if (ctx->eps_error) { + g_simple_async_result_take_error (ctx->result, ctx->eps_error); + ctx->eps_error = NULL; + } else if (ctx->ps_error) { g_simple_async_result_take_error (ctx->result, ctx->ps_error); ctx->ps_error = NULL; } else if (ctx->cs_error) { @@ -3977,6 +4085,7 @@ static void modem_3gpp_disable_unsolicited_registration_events (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data) { @@ -3985,6 +4094,7 @@ modem_3gpp_disable_unsolicited_registration_events (MMIfaceModem3gpp *self, FALSE, cs_supported, ps_supported, + eps_supported, callback, user_data)); } @@ -3993,6 +4103,7 @@ static void modem_3gpp_enable_unsolicited_registration_events (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data) { @@ -4001,6 +4112,7 @@ modem_3gpp_enable_unsolicited_registration_events (MMIfaceModem3gpp *self, TRUE, cs_supported, ps_supported, + eps_supported, callback, user_data)); } @@ -8740,6 +8852,9 @@ set_property (GObject *object, case PROP_MODEM_3GPP_PS_NETWORK_SUPPORTED: self->priv->modem_3gpp_ps_network_supported = g_value_get_boolean (value); break; + case PROP_MODEM_3GPP_EPS_NETWORK_SUPPORTED: + self->priv->modem_3gpp_eps_network_supported = g_value_get_boolean (value); + break; case PROP_MODEM_CDMA_CDMA1X_REGISTRATION_STATE: self->priv->modem_cdma_cdma1x_registration_state = g_value_get_enum (value); break; @@ -8826,6 +8941,9 @@ get_property (GObject *object, case PROP_MODEM_3GPP_PS_NETWORK_SUPPORTED: g_value_set_boolean (value, self->priv->modem_3gpp_ps_network_supported); break; + case PROP_MODEM_3GPP_EPS_NETWORK_SUPPORTED: + g_value_set_boolean (value, self->priv->modem_3gpp_eps_network_supported); + break; case PROP_MODEM_CDMA_CDMA1X_REGISTRATION_STATE: g_value_set_enum (value, self->priv->modem_cdma_cdma1x_registration_state); break; @@ -8869,6 +8987,7 @@ mm_broadband_modem_init (MMBroadbandModem *self) self->priv->modem_3gpp_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; self->priv->modem_3gpp_cs_network_supported = TRUE; self->priv->modem_3gpp_ps_network_supported = TRUE; + self->priv->modem_3gpp_eps_network_supported = FALSE; self->priv->modem_cdma_cdma1x_registration_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; self->priv->modem_cdma_evdo_registration_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; self->priv->modem_cdma_cdma1x_network_supported = TRUE; @@ -9228,6 +9347,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass) MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED); g_object_class_override_property (object_class, + PROP_MODEM_3GPP_EPS_NETWORK_SUPPORTED, + MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED); + + g_object_class_override_property (object_class, PROP_MODEM_CDMA_CDMA1X_REGISTRATION_STATE, MM_IFACE_MODEM_CDMA_CDMA1X_REGISTRATION_STATE); diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c index 7a88b2fd..7117e9c3 100644 --- a/src/mm-iface-modem-3gpp.c +++ b/src/mm-iface-modem-3gpp.c @@ -72,6 +72,7 @@ mm_iface_modem_3gpp_bind_simple_status (MMIfaceModem3gpp *self, typedef struct { MMModem3gppRegistrationState cs; MMModem3gppRegistrationState ps; + MMModem3gppRegistrationState eps; gboolean manual_registration; GCancellable *pending_registration_cancellable; gboolean reloading_operator; @@ -102,6 +103,7 @@ get_registration_state_context (MMIfaceModem3gpp *self) ctx = g_slice_new0 (RegistrationStateContext); ctx->cs = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; ctx->ps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; + ctx->eps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN; g_object_set_qdata_full ( G_OBJECT (self), @@ -129,12 +131,19 @@ get_consolidated_reg_state (RegistrationStateContext *ctx) ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) return ctx->ps; + if (ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_HOME || + ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) + return ctx->eps; + if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING) return ctx->cs; if (ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING) return ctx->ps; + if (ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING) + return ctx->eps; + return ctx->cs; } @@ -183,6 +192,7 @@ register_in_network_context_failed (RegisterInNetworkContext *ctx, { mm_iface_modem_3gpp_update_cs_registration_state (ctx->self, MM_MODEM_3GPP_REGISTRATION_STATE_IDLE); mm_iface_modem_3gpp_update_ps_registration_state (ctx->self, MM_MODEM_3GPP_REGISTRATION_STATE_IDLE); + mm_iface_modem_3gpp_update_eps_registration_state (ctx->self, MM_MODEM_3GPP_REGISTRATION_STATE_IDLE); mm_iface_modem_3gpp_update_access_technologies (ctx->self, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN); mm_iface_modem_3gpp_update_location (ctx->self, 0, 0); @@ -719,21 +729,25 @@ mm_iface_modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, { gboolean cs_supported = FALSE; gboolean ps_supported = FALSE; + gboolean eps_supported = FALSE; g_assert (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_registration_checks != NULL); g_object_get (self, MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, &cs_supported, MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, &ps_supported, + MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, &eps_supported, NULL); - mm_dbg ("Running registration checks (CS: '%s', PS: '%s')", + mm_dbg ("Running registration checks (CS: '%s', PS: '%s', EPS: '%s')", cs_supported ? "yes" : "no", - ps_supported ? "yes" : "no"); + ps_supported ? "yes" : "no", + eps_supported ? "yes" : "no"); MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->run_registration_checks (self, cs_supported, ps_supported, + eps_supported, callback, user_data); } @@ -1117,6 +1131,25 @@ mm_iface_modem_3gpp_update_ps_registration_state (MMIfaceModem3gpp *self, update_registration_state (self, get_consolidated_reg_state (ctx)); } +void +mm_iface_modem_3gpp_update_eps_registration_state (MMIfaceModem3gpp *self, + MMModem3gppRegistrationState state) +{ + RegistrationStateContext *ctx; + gboolean supported = FALSE; + + g_object_get (self, + MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, &supported, + NULL); + + if (!supported) + return; + + ctx = get_registration_state_context (self); + ctx->eps = state; + update_registration_state (self, get_consolidated_reg_state (ctx)); +} + /*****************************************************************************/ typedef struct { @@ -1297,10 +1330,12 @@ interface_disabling_step (DisablingContext *ctx) case DISABLING_STEP_DISABLE_UNSOLICITED_REGISTRATION_EVENTS: { gboolean cs_supported = FALSE; gboolean ps_supported = FALSE; + gboolean eps_supported = FALSE; g_object_get (ctx->self, MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, &cs_supported, MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, &ps_supported, + MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, &eps_supported, NULL); if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->disable_unsolicited_registration_events && @@ -1309,6 +1344,7 @@ interface_disabling_step (DisablingContext *ctx) ctx->self, cs_supported, ps_supported, + eps_supported, (GAsyncReadyCallback)disable_unsolicited_registration_events_ready, ctx); return; @@ -1618,10 +1654,12 @@ interface_enabling_step (EnablingContext *ctx) case ENABLING_STEP_ENABLE_UNSOLICITED_REGISTRATION_EVENTS: { gboolean cs_supported = FALSE; gboolean ps_supported = FALSE; + gboolean eps_supported = FALSE; g_object_get (ctx->self, MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED, &cs_supported, MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED, &ps_supported, + MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, &eps_supported, NULL); if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (ctx->self)->enable_unsolicited_registration_events && @@ -1630,6 +1668,7 @@ interface_enabling_step (EnablingContext *ctx) ctx->self, cs_supported, ps_supported, + eps_supported, (GAsyncReadyCallback)enable_unsolicited_registration_events_ready, ctx); return; @@ -1996,6 +2035,14 @@ iface_modem_3gpp_init (gpointer g_iface) TRUE, G_PARAM_READWRITE)); + g_object_interface_install_property + (g_iface, + g_param_spec_boolean (MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, + "EPS network supported", + "Whether the modem works in the EPS network", + FALSE, + G_PARAM_READWRITE)); + initialized = TRUE; } diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h index d706f1aa..caf2575d 100644 --- a/src/mm-iface-modem-3gpp.h +++ b/src/mm-iface-modem-3gpp.h @@ -30,8 +30,9 @@ #define MM_IFACE_MODEM_3GPP_DBUS_SKELETON "iface-modem-3gpp-dbus-skeleton" #define MM_IFACE_MODEM_3GPP_REGISTRATION_STATE "iface-modem-3gpp-registration-state" -#define MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED "iface-modem-3gpp-ps-network-supported" #define MM_IFACE_MODEM_3GPP_CS_NETWORK_SUPPORTED "iface-modem-3gpp-cs-network-supported" +#define MM_IFACE_MODEM_3GPP_PS_NETWORK_SUPPORTED "iface-modem-3gpp-ps-network-supported" +#define MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED "iface-modem-3gpp-eps-network-supported" #define MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK \ (MM_MODEM_ACCESS_TECHNOLOGY_GSM | \ @@ -110,6 +111,7 @@ struct _MMIfaceModem3gpp { void (*enable_unsolicited_registration_events) (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data); gboolean (*enable_unsolicited_registration_events_finish) (MMIfaceModem3gpp *self, @@ -127,18 +129,20 @@ struct _MMIfaceModem3gpp { void (*disable_unsolicited_registration_events) (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data); gboolean (*disable_unsolicited_registration_events_finish) (MMIfaceModem3gpp *self, GAsyncResult *res, GError **error); - /* Run CS/PS registration state checks.. + /* Run CS/PS/EPS registration state checks.. * Note that no registration state is returned, implementations should call * mm_iface_modem_3gpp_update_registration_state(). */ void (* run_registration_checks) (MMIfaceModem3gpp *self, gboolean cs_supported, gboolean ps_supported, + gboolean eps_supported, GAsyncReadyCallback callback, gpointer user_data); gboolean (*run_registration_checks_finish) (MMIfaceModem3gpp *self, @@ -219,6 +223,8 @@ void mm_iface_modem_3gpp_update_cs_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState state); void mm_iface_modem_3gpp_update_ps_registration_state (MMIfaceModem3gpp *self, MMModem3gppRegistrationState state); +void mm_iface_modem_3gpp_update_eps_registration_state (MMIfaceModem3gpp *self, + MMModem3gppRegistrationState state); void mm_iface_modem_3gpp_update_access_technologies (MMIfaceModem3gpp *self, MMModemAccessTechnology access_tech); void mm_iface_modem_3gpp_update_location (MMIfaceModem3gpp *self, diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index e8c8f887..cedd2b7f 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -216,22 +216,22 @@ mm_filter_current_bands (const GArray *supported_bands, /*****************************************************************************/ /* +CREG: <stat> (GSM 07.07 CREG=1 unsolicited) */ -#define CREG1 "\\+(CREG|CGREG):\\s*0*([0-9])" +#define CREG1 "\\+(CREG|CGREG|CEREG):\\s*0*([0-9])" /* +CREG: <n>,<stat> (GSM 07.07 CREG=1 solicited) */ -#define CREG2 "\\+(CREG|CGREG):\\s*0*([0-9]),\\s*0*([0-9])" +#define CREG2 "\\+(CREG|CGREG|CEREG):\\s*0*([0-9]),\\s*0*([0-9])" /* +CREG: <stat>,<lac>,<ci> (GSM 07.07 CREG=2 unsolicited) */ -#define CREG3 "\\+(CREG|CGREG):\\s*0*([0-9]),\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)" +#define CREG3 "\\+(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) */ -#define CREG4 "\\+(CREG|CGREG):\\s*0*([0-9]),\\s*0*([0-9])\\s*,\\s*([^,]*)\\s*,\\s*([^,\\s]*)" +#define CREG4 "\\+(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) */ -#define CREG5 "\\+(CREG|CGREG):\\s*0*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])" +#define CREG5 "\\+(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) */ -#define CREG6 "\\+(CREG|CGREG):\\s*0*([0-9]),\\s*0*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])" +#define CREG6 "\\+(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>' */ @@ -240,10 +240,16 @@ mm_filter_current_bands (const GArray *supported_bands, /* +CREG: <stat>,<lac>,<ci>,<AcT>,<RAC> (ETSI 27.007 v9.20 CREG=2 unsolicited with RAC) */ #define CREG8 "\\+(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) */ +#define CEREG1 "\\+(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) */ +#define CEREG2 "\\+(CEREG):\\s*0*([0-9]),\\s*0*([0-9])\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*0*([0-9])" + GPtrArray * mm_3gpp_creg_regex_get (gboolean solicited) { - GPtrArray *array = g_ptr_array_sized_new (7); + GPtrArray *array = g_ptr_array_sized_new (10); GRegex *regex; /* #1 */ @@ -310,6 +316,22 @@ mm_3gpp_creg_regex_get (gboolean solicited) g_assert (regex); g_ptr_array_add (array, regex); + /* CEREG #1 */ + if (solicited) + regex = g_regex_new (CEREG1 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + else + regex = g_regex_new ("\\r\\n" CEREG1 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_assert (regex); + g_ptr_array_add (array, regex); + + /* CEREG #2 */ + if (solicited) + regex = g_regex_new (CEREG2 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + else + regex = g_regex_new ("\\r\\n" CEREG2 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_assert (regex); + g_ptr_array_add (array, regex); + return array; } @@ -723,6 +745,7 @@ mm_3gpp_parse_creg_response (GMatchInfo *info, gulong *out_ci, MMModemAccessTechnology *out_act, gboolean *out_cgreg, + gboolean *out_cereg, GError **error) { gboolean success = FALSE, foo; @@ -737,10 +760,11 @@ mm_3gpp_parse_creg_response (GMatchInfo *info, g_return_val_if_fail (out_ci != NULL, FALSE); g_return_val_if_fail (out_act != NULL, FALSE); g_return_val_if_fail (out_cgreg != NULL, FALSE); + g_return_val_if_fail (out_cereg != NULL, FALSE); str = g_match_info_fetch (info, 1); - if (str && strstr (str, "CGREG")) - *out_cgreg = TRUE; + *out_cgreg = (str && strstr (str, "CGREG")) ? TRUE : FALSE; + *out_cereg = (str && strstr (str, "CEREG")) ? TRUE : FALSE; g_free (str); /* Normally the number of matches could be used to determine what each @@ -777,19 +801,43 @@ mm_3gpp_parse_creg_response (GMatchInfo *info, } 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> */ - /* 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; + 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> + */ + if (*out_cereg) { istat = 3; ilac = 4; - ici = 5; - iact = 6; + ici = 6; + iact = 7; } } diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index e66f259a..63e53a74 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -106,6 +106,7 @@ gboolean mm_3gpp_parse_creg_response (GMatchInfo *info, gulong *out_ci, MMModemAccessTechnology *out_act, gboolean *out_cgreg, + gboolean *out_cereg, GError **error); /* AT+CMGF=? (SMS message format) response parser */ diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index fdd336c7..6cfac3db 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -473,6 +473,7 @@ typedef struct { guint regex_num; gboolean cgreg; + gboolean cereg; } CregResult; static void @@ -488,7 +489,7 @@ test_creg_match (const char *test, MMModemAccessTechnology access_tech = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; gulong lac = 0, ci = 0; GError *error = NULL; - gboolean success, cgreg = FALSE; + gboolean success, cgreg = FALSE, cereg = FALSE; guint regex_num = 0; GPtrArray *array; @@ -522,7 +523,7 @@ test_creg_match (const char *test, g_assert (info != NULL); g_assert_cmpuint (regex_num, ==, result->regex_num); - success = mm_3gpp_parse_creg_response (info, &state, &lac, &ci, &access_tech, &cgreg, &error); + success = mm_3gpp_parse_creg_response (info, &state, &lac, &ci, &access_tech, &cgreg, &cereg, &error); g_assert (success); g_assert_no_error (error); g_assert_cmpuint (state, ==, result->state); @@ -533,6 +534,7 @@ test_creg_match (const char *test, access_tech, result->act); g_assert_cmpuint (access_tech, ==, result->act); g_assert_cmpuint (cgreg, ==, result->cgreg); + g_assert_cmpuint (cereg, ==, result->cereg); } static void @@ -540,7 +542,7 @@ test_creg1_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CREG: 1,3"; - const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 2, FALSE}; + const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 2, FALSE, FALSE }; test_creg_match ("CREG=1", TRUE, reply, data, &result); } @@ -550,7 +552,7 @@ test_creg1_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 3\r\n"; - const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 1, FALSE}; + const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 1, FALSE, FALSE }; test_creg_match ("CREG=1", FALSE, reply, data, &result); } @@ -560,7 +562,7 @@ test_creg2_mercury_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CREG: 0,1,84CD,00D30173"; - const CregResult result = { 1, 0x84cd, 0xd30173, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE}; + const CregResult result = { 1, 0x84cd, 0xd30173, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE, FALSE }; test_creg_match ("Sierra Mercury CREG=2", TRUE, reply, data, &result); } @@ -570,7 +572,7 @@ test_creg2_mercury_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 1,84CD,00D30156\r\n"; - const CregResult result = { 1, 0x84cd, 0xd30156, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 3, FALSE}; + const CregResult result = { 1, 0x84cd, 0xd30156, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 3, FALSE, FALSE }; test_creg_match ("Sierra Mercury CREG=2", FALSE, reply, data, &result); } @@ -580,7 +582,7 @@ test_creg2_sek850i_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CREG: 2,1,\"CE00\",\"01CEAD8F\""; - const CregResult result = { 1, 0xce00, 0x01cead8f, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE}; + const CregResult result = { 1, 0xce00, 0x01cead8f, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE, FALSE }; test_creg_match ("Sony Ericsson K850i CREG=2", TRUE, reply, data, &result); } @@ -590,7 +592,7 @@ test_creg2_sek850i_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 1,\"CE00\",\"00005449\"\r\n"; - const CregResult result = { 1, 0xce00, 0x5449, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 3, FALSE}; + const CregResult result = { 1, 0xce00, 0x5449, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 3, FALSE, FALSE }; test_creg_match ("Sony Ericsson K850i CREG=2", FALSE, reply, data, &result); } @@ -600,7 +602,7 @@ test_creg2_e160g_solicited_unregistered (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CREG: 2,0,00,0"; - const CregResult result = { 0, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE}; + const CregResult result = { 0, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE, FALSE }; test_creg_match ("Huawei E160G unregistered CREG=2", TRUE, reply, data, &result); } @@ -610,7 +612,7 @@ test_creg2_e160g_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CREG: 2,1,8BE3,2BAF"; - const CregResult result = { 1, 0x8be3, 0x2baf, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE}; + const CregResult result = { 1, 0x8be3, 0x2baf, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE, FALSE }; test_creg_match ("Huawei E160G CREG=2", TRUE, reply, data, &result); } @@ -620,7 +622,7 @@ test_creg2_e160g_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 2,8BE3,2BAF\r\n"; - const CregResult result = { 2, 0x8be3, 0x2baf, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 3, FALSE}; + const CregResult result = { 2, 0x8be3, 0x2baf, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 3, FALSE, FALSE }; test_creg_match ("Huawei E160G CREG=2", FALSE, reply, data, &result); } @@ -630,7 +632,7 @@ test_creg2_tm506_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CREG: 2,1,\"8BE3\",\"00002BAF\""; - const CregResult result = { 1, 0x8BE3, 0x2BAF, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE}; + const CregResult result = { 1, 0x8BE3, 0x2BAF, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE, FALSE }; /* Test leading zeros in the CI */ test_creg_match ("Sony Ericsson TM-506 CREG=2", TRUE, reply, data, &result); @@ -641,7 +643,7 @@ test_creg2_xu870_unsolicited_unregistered (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 2,,\r\n"; - const CregResult result = { 2, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 3, FALSE}; + const CregResult result = { 2, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 3, FALSE, FALSE }; test_creg_match ("Novatel XU870 unregistered CREG=2", FALSE, reply, data, &result); } @@ -651,7 +653,7 @@ test_creg2_iridium_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CREG:002,001,\"18d8\",\"ffff\""; - const CregResult result = { 1, 0x18D8, 0xFFFF, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 4, FALSE}; + const CregResult result = { 1, 0x18D8, 0xFFFF, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 4, FALSE, FALSE }; test_creg_match ("Iridium, CREG=2", TRUE, reply, data, &result); } @@ -661,7 +663,7 @@ test_cgreg1_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CGREG: 1,3"; - const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 2, TRUE}; + const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 2, TRUE, FALSE }; test_creg_match ("CGREG=1", TRUE, reply, data, &result); } @@ -671,7 +673,7 @@ test_cgreg1_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CGREG: 3\r\n"; - const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 1, TRUE}; + const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 1, TRUE, FALSE }; test_creg_match ("CGREG=1", FALSE, reply, data, &result); } @@ -681,7 +683,7 @@ test_cgreg2_f3607gw_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "+CGREG: 2,1,\"8BE3\",\"00002B5D\",3"; - const CregResult result = { 1, 0x8BE3, 0x2B5D, MM_MODEM_ACCESS_TECHNOLOGY_EDGE , 6, TRUE}; + const CregResult result = { 1, 0x8BE3, 0x2B5D, MM_MODEM_ACCESS_TECHNOLOGY_EDGE , 6, TRUE, FALSE }; test_creg_match ("Ericsson F3607gw CGREG=2", TRUE, reply, data, &result); } @@ -691,7 +693,7 @@ test_cgreg2_f3607gw_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CGREG: 1,\"8BE3\",\"00002B5D\",3\r\n"; - const CregResult result = { 1, 0x8BE3, 0x2B5D, MM_MODEM_ACCESS_TECHNOLOGY_EDGE , 5, TRUE}; + const CregResult result = { 1, 0x8BE3, 0x2B5D, MM_MODEM_ACCESS_TECHNOLOGY_EDGE , 5, TRUE, FALSE }; test_creg_match ("Ericsson F3607gw CGREG=2", FALSE, reply, data, &result); } @@ -701,7 +703,7 @@ test_creg2_md400_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 2,5,\"0502\",\"0404736D\"\r\n"; - const CregResult result = { 5, 0x0502, 0x0404736D, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE}; + const CregResult result = { 5, 0x0502, 0x0404736D, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 4, FALSE, FALSE }; test_creg_match ("Sony-Ericsson MD400 CREG=2", FALSE, reply, data, &result); } @@ -711,7 +713,7 @@ test_cgreg2_md400_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CGREG: 5,\"0502\",\"0404736D\",2\r\n"; - const CregResult result = { 5, 0x0502, 0x0404736D, MM_MODEM_ACCESS_TECHNOLOGY_UMTS, 5, TRUE}; + const CregResult result = { 5, 0x0502, 0x0404736D, MM_MODEM_ACCESS_TECHNOLOGY_UMTS, 5, TRUE, FALSE }; test_creg_match ("Sony-Ericsson MD400 CGREG=2", FALSE, reply, data, &result); } @@ -721,7 +723,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 = { 5, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 1, FALSE}; + const CregResult result = { 5, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 1, FALSE, FALSE }; test_creg_match ("Multi CREG/CGREG", FALSE, reply, data, &result); } @@ -731,7 +733,7 @@ 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 = { 0, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 1, TRUE}; + const CregResult result = { 0, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 1, TRUE, FALSE }; test_creg_match ("Multi CREG/CGREG #2", FALSE, reply, data, &result); } @@ -741,7 +743,7 @@ test_cgreg2_x220_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CGREG: 2,1, 81ED, 1A9CEB\r\n"; - const CregResult result = { 1, 0x81ED, 0x1A9CEB, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 4, TRUE}; + const CregResult result = { 1, 0x81ED, 0x1A9CEB, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 4, TRUE, FALSE }; /* Tests random spaces in response */ test_creg_match ("Alcatel One-Touch X220D CGREG=2", FALSE, reply, data, &result); @@ -752,7 +754,7 @@ test_creg2_s8500_wave_unsolicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 2,1,000B,2816, B, C2816\r\n"; - const CregResult result = { 1, 0x000B, 0x2816, MM_MODEM_ACCESS_TECHNOLOGY_GSM, 7, FALSE}; + const CregResult result = { 1, 0x000B, 0x2816, MM_MODEM_ACCESS_TECHNOLOGY_GSM, 7, FALSE, FALSE }; test_creg_match ("Samsung Wave S8500 CREG=2", FALSE, reply, data, &result); } @@ -762,7 +764,7 @@ test_creg2_gobi_weird_solicited (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CREG: 2,1, 0 5, 2715\r\n"; - const CregResult result = { 1, 0x0000, 0x2715, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 4, FALSE}; + const CregResult result = { 1, 0x0000, 0x2715, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN, 4, FALSE, FALSE }; test_creg_match ("Qualcomm Gobi 1000 CREG=2", TRUE, reply, data, &result); } @@ -772,11 +774,71 @@ test_cgreg2_unsolicited_with_rac (void *f, gpointer d) { RegTestData *data = (RegTestData *) d; const char *reply = "\r\n+CGREG: 1,\"1422\",\"00000142\",3,\"00\"\r\n"; - const CregResult result = { 1, 0x1422, 0x0142, MM_MODEM_ACCESS_TECHNOLOGY_EDGE, 8, TRUE }; + const CregResult result = { 1, 0x1422, 0x0142, MM_MODEM_ACCESS_TECHNOLOGY_EDGE, 8, TRUE, FALSE }; test_creg_match ("CGREG=2 with RAC", FALSE, reply, data, &result); } +static void +test_cereg1_solicited (void *f, gpointer d) +{ + RegTestData *data = (RegTestData *) d; + const char *reply = "+CEREG: 1,3"; + const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 2, FALSE, TRUE }; + + test_creg_match ("CEREG=1", TRUE, reply, data, &result); +} + +static void +test_cereg1_unsolicited (void *f, gpointer d) +{ + RegTestData *data = (RegTestData *) d; + const char *reply = "\r\n+CEREG: 3\r\n"; + const CregResult result = { 3, 0, 0, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN , 1, FALSE, TRUE }; + + test_creg_match ("CEREG=1", FALSE, reply, data, &result); +} + +static void +test_cereg2_solicited (void *f, gpointer d) +{ + RegTestData *data = (RegTestData *) d; + const char *reply = "\r\n+CEREG: 2,1, 1F00, 79D903 ,7\r\n"; + const CregResult result = { 1, 0x1F00, 0x79D903, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 6, FALSE, TRUE }; + + test_creg_match ("CEREG=2", TRUE, reply, data, &result); +} + +static void +test_cereg2_unsolicited (void *f, gpointer d) +{ + RegTestData *data = (RegTestData *) d; + const char *reply = "\r\n+CEREG: 1, 1F00, 79D903 ,7\r\n"; + const CregResult result = { 1, 0x1F00, 0x79D903, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 5, FALSE, TRUE }; + + test_creg_match ("CEREG=2", FALSE, reply, data, &result); +} + +static void +test_cereg2_novatel_lte_solicited (void *f, gpointer d) +{ + RegTestData *data = (RegTestData *) d; + const char *reply = "\r\n+CEREG: 2,1, 1F00, 20 ,79D903 ,7\r\n"; + const CregResult result = { 1, 0x1F00, 0x79D903, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 10, FALSE, TRUE }; + + test_creg_match ("Novatel LTE E362 CEREG=2", TRUE, reply, data, &result); +} + +static void +test_cereg2_novatel_lte_unsolicited (void *f, gpointer d) +{ + RegTestData *data = (RegTestData *) d; + const char *reply = "\r\n+CEREG: 1, 1F00, 20 ,79D903 ,7\r\n"; + const CregResult result = { 1, 0x1F00, 0x79D903, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 9, FALSE, TRUE }; + + test_creg_match ("Novatel LTE E362 CEREG=2", FALSE, reply, data, &result); +} + /*****************************************************************************/ /* Test CSCS responses */ @@ -1617,6 +1679,13 @@ int main (int argc, char **argv) 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_cereg1_solicited, reg_data)); + 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_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_creg_cgreg_multi_unsolicited, reg_data)); g_test_suite_add (suite, TESTCASE (test_creg_cgreg_multi2_unsolicited, reg_data)); |