3gpp: update registration state enumeration with CSFB related states
Introduce "sms only" and "CSFB not preferred" home/roaming states to be reported for the CS context, while already registered on LTE. Based on 3GPP TS 27.007 v13.5.0.
This commit is contained in:
@@ -246,10 +246,13 @@ status_process_reply (MMSimpleStatus *result,
|
||||
VALIDATE_UNKNOWN (bands_str),
|
||||
VALIDATE_UNKNOWN (access_tech_str));
|
||||
|
||||
if ((mm_simple_status_get_3gpp_registration_state (result) ==
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_HOME) ||
|
||||
(mm_simple_status_get_3gpp_registration_state (result) ==
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)) {
|
||||
switch (mm_simple_status_get_3gpp_registration_state (result)) {
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED:
|
||||
g_print (" -------------------------\n"
|
||||
" 3GPP | registration: '%s'\n"
|
||||
" | operator code: '%s'\n"
|
||||
@@ -261,6 +264,9 @@ status_process_reply (MMSimpleStatus *result,
|
||||
VALIDATE_UNKNOWN (mm_simple_status_get_3gpp_operator_name (result)),
|
||||
mm_modem_3gpp_subscription_state_get_string (
|
||||
mm_simple_status_get_3gpp_subscription_state (result)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mm_simple_status_get_cdma_cdma1x_registration_state (result) !=
|
||||
|
@@ -978,16 +978,26 @@ typedef enum { /*< underscore_name=mm_modem_cdma_rm_protocol >*/
|
||||
* @MM_MODEM_3GPP_REGISTRATION_STATE_DENIED: Registration denied.
|
||||
* @MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN: Unknown registration status.
|
||||
* @MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING: Registered on a roaming network.
|
||||
* @MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY: Registered for "SMS only", home network (applicable only when on LTE).
|
||||
* @MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY: Registered for "SMS only", roaming network (applicable only when on LTE).
|
||||
* @MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY: Emergency services only.
|
||||
* @MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED: Registered for "CSFB not preferred", home network (applicable only when on LTE).
|
||||
* @MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED: Registered for "CSFB not preferred", roaming network (applicable only when on LTE).
|
||||
*
|
||||
* GSM registration code as defined in 3GPP TS 27.007 section 10.1.19.
|
||||
* GSM registration code as defined in 3GPP TS 27.007.
|
||||
*/
|
||||
typedef enum { /*< underscore_name=mm_modem_3gpp_registration_state >*/
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_IDLE = 0,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_HOME = 1,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING = 2,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_DENIED = 3,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN = 4,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING = 5,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_IDLE = 0,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_HOME = 1,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING = 2,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_DENIED = 3,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN = 4,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING = 5,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY = 6,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY = 7,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY = 8,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED = 9,
|
||||
MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED = 10,
|
||||
} MMModem3gppRegistrationState;
|
||||
|
||||
/**
|
||||
|
@@ -54,6 +54,7 @@ typedef enum {
|
||||
CONNECTION_FORBIDDEN_REASON_NONE,
|
||||
CONNECTION_FORBIDDEN_REASON_UNREGISTERED,
|
||||
CONNECTION_FORBIDDEN_REASON_ROAMING,
|
||||
CONNECTION_FORBIDDEN_REASON_EMERGENCY_ONLY,
|
||||
CONNECTION_FORBIDDEN_REASON_LAST
|
||||
} ConnectionForbiddenReason;
|
||||
|
||||
@@ -120,7 +121,8 @@ struct _MMBaseBearerPrivate {
|
||||
static const gchar *connection_forbidden_reason_str [CONNECTION_FORBIDDEN_REASON_LAST] = {
|
||||
"none",
|
||||
"Not registered in the network",
|
||||
"Registered in roaming network, and roaming not allowed"
|
||||
"Registered in roaming network, and roaming not allowed",
|
||||
"Emergency services only",
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -401,15 +403,22 @@ modem_3gpp_registration_state_changed (MMIfaceModem3gpp *modem,
|
||||
self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_UNREGISTERED;
|
||||
break;
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING:
|
||||
self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_NONE;
|
||||
break;
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY:
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED:
|
||||
if (mm_bearer_properties_get_allow_roaming (mm_base_bearer_peek_config (self)))
|
||||
self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_NONE;
|
||||
else
|
||||
self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_ROAMING;
|
||||
break;
|
||||
case MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY:
|
||||
self->priv->reason_3gpp = CONNECTION_FORBIDDEN_REASON_EMERGENCY_ONLY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If no reason to disconnect, or if it's a mixed CDMA+LTE modem without a CDMA reason,
|
||||
@@ -429,6 +438,14 @@ modem_3gpp_registration_state_changed (MMIfaceModem3gpp *modem,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Modem is registered under emergency services only? */
|
||||
if (self->priv->reason_3gpp == CONNECTION_FORBIDDEN_REASON_EMERGENCY_ONLY) {
|
||||
mm_dbg ("Bearer not allowed to connect, emergency services only");
|
||||
reset_deferred_unregistration (self);
|
||||
mm_base_bearer_disconnect_force (self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Modem reports being unregistered */
|
||||
if (self->priv->reason_3gpp == CONNECTION_FORBIDDEN_REASON_UNREGISTERED) {
|
||||
/* If there is already a notification pending, just return */
|
||||
|
@@ -137,12 +137,11 @@ get_consolidated_reg_state (RegistrationStateContext *ctx)
|
||||
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;
|
||||
/* Searching? */
|
||||
if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING ||
|
||||
ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING ||
|
||||
ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING)
|
||||
return MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING;
|
||||
|
||||
/* If one state is DENIED and the others are UNKNOWN, use DENIED */
|
||||
if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_DENIED &&
|
||||
@@ -158,7 +157,41 @@ get_consolidated_reg_state (RegistrationStateContext *ctx)
|
||||
ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_DENIED)
|
||||
return ctx->eps;
|
||||
|
||||
return ctx->cs;
|
||||
/* Emergency services? */
|
||||
if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY ||
|
||||
ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY ||
|
||||
ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY)
|
||||
return MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY;
|
||||
|
||||
/* Support for additional registration states reported when on LTE.
|
||||
*
|
||||
* For example, we may see the modem registered in LTE (EPS==HOME), and we
|
||||
* may get "SMS only" reported for CS.
|
||||
*
|
||||
* We give these states a very low priority w.r.t. the other ones as they
|
||||
* are really likely never used (i.e. we would get as consolidated the LTE
|
||||
* registration state, not the CS fall back state).
|
||||
*
|
||||
* We also warn in that case, because ideally we should always report the
|
||||
* LTE registration state first, not this one.
|
||||
*/
|
||||
if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
|
||||
ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
|
||||
ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
|
||||
ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED) {
|
||||
mm_warn ("3GPP CSFB registration state is consolidated: %s",
|
||||
mm_modem_3gpp_registration_state_get_string (ctx->cs));
|
||||
return ctx->cs;
|
||||
}
|
||||
|
||||
/* Idle? */
|
||||
if (ctx->cs == MM_MODEM_3GPP_REGISTRATION_STATE_IDLE ||
|
||||
ctx->ps == MM_MODEM_3GPP_REGISTRATION_STATE_IDLE ||
|
||||
ctx->eps == MM_MODEM_3GPP_REGISTRATION_STATE_IDLE)
|
||||
return MM_MODEM_3GPP_REGISTRATION_STATE_IDLE;
|
||||
|
||||
/* Just unknown at this point */
|
||||
return MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -269,7 +302,11 @@ run_registration_checks_ready (MMIfaceModem3gpp *self,
|
||||
|
||||
/* If we got registered, end registration checks */
|
||||
if (current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
|
||||
current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
|
||||
current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
|
||||
current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
|
||||
current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
|
||||
current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
|
||||
current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED) {
|
||||
/* Request immediate access tech update */
|
||||
mm_iface_modem_refresh_access_technologies (MM_IFACE_MODEM (ctx->self));
|
||||
mm_dbg ("Modem is currently registered in a 3GPP network");
|
||||
@@ -1035,6 +1072,10 @@ mm_iface_modem_3gpp_update_access_technologies (MMIfaceModem3gpp *self,
|
||||
* but only if something valid to report */
|
||||
if (state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED ||
|
||||
ctx->reloading_registration_info) {
|
||||
if (access_tech != MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN)
|
||||
mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self),
|
||||
@@ -1070,7 +1111,11 @@ mm_iface_modem_3gpp_update_location (MMIfaceModem3gpp *self,
|
||||
* change to registered), we also allow LAC/CID updates. */
|
||||
if (ctx->reloading_registration_info ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
|
||||
state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED) {
|
||||
if (location_area_code > 0 && cell_id > 0)
|
||||
mm_iface_modem_location_3gpp_update_lac_ci (MM_IFACE_MODEM_LOCATION (self),
|
||||
location_area_code,
|
||||
@@ -1123,7 +1168,11 @@ update_non_registered_state (MMIfaceModem3gpp *self,
|
||||
* registration reject error code. If b), we want to make sure we
|
||||
* preserve the subscription state */
|
||||
if (old_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
|
||||
old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING)
|
||||
old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
|
||||
old_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
|
||||
old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
|
||||
old_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
|
||||
old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED)
|
||||
clear_subscription_state (self);
|
||||
|
||||
/* The property in the interface is bound to the property
|
||||
@@ -1161,7 +1210,11 @@ update_registration_state (MMIfaceModem3gpp *self,
|
||||
return;
|
||||
|
||||
if (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
|
||||
new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
|
||||
new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
|
||||
new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
|
||||
new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
|
||||
new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
|
||||
new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED) {
|
||||
/* If already reloading registration info, skip it */
|
||||
if (ctx->reloading_registration_info)
|
||||
return;
|
||||
|
@@ -1428,7 +1428,7 @@ mm_3gpp_parse_creg_response (GMatchInfo *info,
|
||||
|
||||
/* Status */
|
||||
str = g_match_info_fetch (info, istat);
|
||||
stat = parse_uint (str, 10, 0, 5, &success);
|
||||
stat = parse_uint (str, 10, 0, G_MAXUINT, &success);
|
||||
g_free (str);
|
||||
if (!success) {
|
||||
g_set_error_literal (error,
|
||||
@@ -1437,6 +1437,12 @@ mm_3gpp_parse_creg_response (GMatchInfo *info,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 'roaming (csfb not preferred)' is the last valid state */
|
||||
if (stat > MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED) {
|
||||
mm_warn ("Registration State '%lu' is unknown", stat);
|
||||
stat = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Location Area Code */
|
||||
if (ilac) {
|
||||
/* FIXME: some phones apparently swap the LAC bytes (LG, SonyEricsson,
|
||||
@@ -1463,12 +1469,6 @@ mm_3gpp_parse_creg_response (GMatchInfo *info,
|
||||
act = -1;
|
||||
}
|
||||
|
||||
/* 'roaming' is the last valid state */
|
||||
if (stat > MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING) {
|
||||
mm_warn ("Registration State '%lu' is unknown", stat);
|
||||
stat = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
*out_reg_state = (MMModem3gppRegistrationState) stat;
|
||||
if (stat != MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN) {
|
||||
/* Don't fill in lac/ci/act if the device's state is unknown */
|
||||
|
@@ -1026,6 +1026,28 @@ test_creg2_leading_zeros_unsolicited (void *f, gpointer d)
|
||||
test_creg_match ("unsolicited CREG=2 with leading zeros in integer fields", FALSE, reply, data, &result);
|
||||
}
|
||||
|
||||
static void
|
||||
test_creg2_ublox_solicited (void *f, gpointer d)
|
||||
{
|
||||
RegTestData *data = (RegTestData *) d;
|
||||
const gchar *reply = "\r\n+CREG: 2,6,\"8B37\",\"0A265185\",7\r\n";
|
||||
/* NOTE: '6' means registered for "SMS only", home network; we just assume UNKNOWN in this case */
|
||||
const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY, 0x8B37, 0x0A265185, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 8, FALSE, FALSE };
|
||||
|
||||
test_creg_match ("Ublox Toby-L2 solicited while on LTE", TRUE, reply, data, &result);
|
||||
}
|
||||
|
||||
static void
|
||||
test_creg2_ublox_unsolicited (void *f, gpointer d)
|
||||
{
|
||||
RegTestData *data = (RegTestData *) d;
|
||||
const gchar *reply = "\r\n+CREG: 6,\"8B37\",\"0A265185\",7\r\n";
|
||||
/* NOTE: '6' means registered for "SMS only", home network; we just assume UNKNOWN in this case */
|
||||
const CregResult result = { MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY, 0x8B37, 0x0A265185, MM_MODEM_ACCESS_TECHNOLOGY_LTE, 6, FALSE, FALSE };
|
||||
|
||||
test_creg_match ("Ublox Toby-L2 unsolicited while on LTE", FALSE, reply, data, &result);
|
||||
}
|
||||
|
||||
static void
|
||||
test_cgreg1_solicited (void *f, gpointer d)
|
||||
{
|
||||
@@ -3255,6 +3277,8 @@ int main (int argc, char **argv)
|
||||
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_ublox_solicited, reg_data));
|
||||
g_test_suite_add (suite, TESTCASE (test_creg2_ublox_unsolicited, reg_data));
|
||||
|
||||
g_test_suite_add (suite, TESTCASE (test_cgreg1_solicited, reg_data));
|
||||
g_test_suite_add (suite, TESTCASE (test_cgreg1_unsolicited, reg_data));
|
||||
|
Reference in New Issue
Block a user