diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2018-11-13 12:31:47 +0100 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2018-12-07 16:20:53 +0000 |
commit | 9c3ac2fb6023b87d065221f845969b0f06e26363 (patch) | |
tree | 7fa54627a1848d38bb04f13aeb762c9a0cd1e996 /src | |
parent | dc154cf005bbcb2f0bd1123093f6ac3c402c4de8 (diff) |
api,modem-3gpp: new 'InitialEpsBearer' property
This property contains the DBus path of a Bearer object of type
MM_BEARER_TYPE_DEFAULT_ATTACH, which is automatically exposed by the
modem when registered in the LTE network.
Unlike standard bearer objects created by the user, this bearer won't
allow any connection/disconnection request, as its status is bound to
the LTE registration exclusively.
The bearer settings exposed by the object include the APN details that
have been used during the initial packet network attach, which may be
defined by modem settings (e.g. if previously configured in the
firmware which APN to use for the given SIM card operator) or by the
network itself (e.g. if none configured, or if a network override is
required as when roaming).
The bearer object will be created as soon as the LTE attach status
details are known, and only while the modem is enabled. The
implementation allows modems to update the LTE attach status details
during runtime, so the bearer object with the settings may be
recreated during runtime as well.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-base-bearer.c | 28 | ||||
-rw-r--r-- | src/mm-broadband-modem.c | 37 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.c | 107 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.h | 16 |
4 files changed, 183 insertions, 5 deletions
diff --git a/src/mm-base-bearer.c b/src/mm-base-bearer.c index b2e07e19..6b7e1e5d 100644 --- a/src/mm-base-bearer.c +++ b/src/mm-base-bearer.c @@ -764,8 +764,18 @@ mm_base_bearer_connect (MMBaseBearer *self, { GTask *task; - g_assert (MM_BASE_BEARER_GET_CLASS (self)->connect != NULL); - g_assert (MM_BASE_BEARER_GET_CLASS (self)->connect_finish != NULL); + if (!MM_BASE_BEARER_GET_CLASS (self)->connect) { + g_assert (!MM_BASE_BEARER_GET_CLASS (self)->connect_finish); + g_task_report_new_error ( + self, + callback, + user_data, + mm_base_bearer_connect, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Bearer doesn't allow explicit connection requests"); + return; + } /* If already connecting, return error, don't allow a second request. */ if (self->priv->status == MM_BEARER_STATUS_CONNECTING) { @@ -975,11 +985,19 @@ mm_base_bearer_disconnect (MMBaseBearer *self, { GTask *task; - g_assert (MM_BASE_BEARER_GET_CLASS (self)->disconnect != NULL); - g_assert (MM_BASE_BEARER_GET_CLASS (self)->disconnect_finish != NULL); - task = g_task_new (self, NULL, callback, user_data); + if (!MM_BASE_BEARER_GET_CLASS (self)->disconnect) { + g_assert (!MM_BASE_BEARER_GET_CLASS (self)->disconnect_finish); + g_task_return_new_error ( + task, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Bearer doesn't allow explicit disconnection requests"); + g_object_unref (task); + return; + } + /* If already disconnected, done */ if (self->priv->status == MM_BEARER_STATUS_DISCONNECTED) { g_task_return_boolean (task, TRUE); diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 7c7250e6..952bc30a 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -106,6 +106,7 @@ enum { PROP_MODEM_3GPP_PS_NETWORK_SUPPORTED, PROP_MODEM_3GPP_EPS_NETWORK_SUPPORTED, PROP_MODEM_3GPP_IGNORED_FACILITY_LOCKS, + PROP_MODEM_3GPP_INITIAL_EPS_BEARER, PROP_MODEM_CDMA_CDMA1X_REGISTRATION_STATE, PROP_MODEM_CDMA_EVDO_REGISTRATION_STATE, PROP_MODEM_CDMA_CDMA1X_NETWORK_SUPPORTED, @@ -171,6 +172,7 @@ struct _MMBroadbandModemPrivate { /* Implementation helpers */ GPtrArray *modem_3gpp_registration_regex; MMModem3gppFacility modem_3gpp_ignored_facility_locks; + MMBaseBearer *modem_3gpp_initial_eps_bearer; /*<--- Modem 3GPP USSD interface --->*/ /* Properties */ @@ -4870,6 +4872,28 @@ modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, } /*****************************************************************************/ +/* Create initial EPS bearer object */ + +static MMBaseBearer * +modem_3gpp_create_initial_eps_bearer (MMIfaceModem3gpp *self, + MMBearerProperties *config) +{ + MMBaseBearer *bearer; + + /* NOTE: by default we create a bearer object that is CONNECTED but which doesn't + * have an associated data interface already set. This is so that upper layers don't + * attempt connection through this bearer object. */ + bearer = g_object_new (MM_TYPE_BASE_BEARER, + MM_BASE_BEARER_MODEM, MM_BASE_MODEM (self), + MM_BASE_BEARER_CONFIG, config, + "bearer-type", MM_BEARER_TYPE_DEFAULT_ATTACH, + "connected", TRUE, + NULL); + mm_base_bearer_export (bearer); + return bearer; +} + +/*****************************************************************************/ /* Enable/Disable unsolicited registration events (3GPP interface) */ typedef struct { @@ -11117,6 +11141,10 @@ set_property (GObject *object, case PROP_MODEM_3GPP_IGNORED_FACILITY_LOCKS: self->priv->modem_3gpp_ignored_facility_locks = g_value_get_flags (value); break; + case PROP_MODEM_3GPP_INITIAL_EPS_BEARER: + g_clear_object (&self->priv->modem_3gpp_initial_eps_bearer); + self->priv->modem_3gpp_initial_eps_bearer = g_value_dup_object (value); + break; case PROP_MODEM_CDMA_CDMA1X_REGISTRATION_STATE: self->priv->modem_cdma_cdma1x_registration_state = g_value_get_enum (value); break; @@ -11234,6 +11262,9 @@ get_property (GObject *object, case PROP_MODEM_3GPP_IGNORED_FACILITY_LOCKS: g_value_set_flags (value, self->priv->modem_3gpp_ignored_facility_locks); break; + case PROP_MODEM_3GPP_INITIAL_EPS_BEARER: + g_value_set_object (value, self->priv->modem_3gpp_initial_eps_bearer); + break; case PROP_MODEM_CDMA_CDMA1X_REGISTRATION_STATE: g_value_set_enum (value, self->priv->modem_cdma_cdma1x_registration_state); break; @@ -11381,6 +11412,7 @@ dispose (GObject *object) g_clear_object (&self->priv->modem_simple_dbus_skeleton); } + g_clear_object (&self->priv->modem_3gpp_initial_eps_bearer); g_clear_object (&self->priv->modem_sim); g_clear_object (&self->priv->modem_bearer_list); g_clear_object (&self->priv->modem_messaging_sms_list); @@ -11489,6 +11521,7 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface) iface->scan_networks_finish = modem_3gpp_scan_networks_finish; iface->set_eps_ue_mode_operation = modem_3gpp_set_eps_ue_mode_operation; iface->set_eps_ue_mode_operation_finish = modem_3gpp_set_eps_ue_mode_operation_finish; + iface->create_initial_eps_bearer = modem_3gpp_create_initial_eps_bearer; } static void @@ -11745,6 +11778,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass) MM_IFACE_MODEM_3GPP_IGNORED_FACILITY_LOCKS); g_object_class_override_property (object_class, + PROP_MODEM_3GPP_INITIAL_EPS_BEARER, + MM_IFACE_MODEM_3GPP_INITIAL_EPS_BEARER); + + 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 9e626126..a90c7204 100644 --- a/src/mm-iface-modem-3gpp.c +++ b/src/mm-iface-modem-3gpp.c @@ -1488,11 +1488,56 @@ mm_iface_modem_3gpp_update_pco_list (MMIfaceModem3gpp *self, /*****************************************************************************/ +void +mm_iface_modem_3gpp_update_initial_eps_bearer (MMIfaceModem3gpp *self, + MMBearerProperties *properties) +{ + MmGdbusModem3gpp *skeleton = NULL; + MMBaseBearer *attach = NULL; + gboolean skip_update = FALSE; + + g_object_get (self, + MM_IFACE_MODEM_3GPP_DBUS_SKELETON, &skeleton, + MM_IFACE_MODEM_3GPP_INITIAL_EPS_BEARER, &attach, + NULL); + g_assert (skeleton); + + if (attach) { + skip_update = (properties && mm_bearer_properties_cmp (properties, mm_base_bearer_peek_config (MM_BASE_BEARER (attach)))); + g_object_unref (attach); + } + + if (skip_update) { + mm_dbg ("skipping initial EPS bearer update: configuration didn't change"); + } else if (properties) { + mm_dbg ("updating initial EPS bearer..."); + + g_assert (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->create_initial_eps_bearer); + attach = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->create_initial_eps_bearer (self, properties); + g_object_set (self, + MM_IFACE_MODEM_3GPP_INITIAL_EPS_BEARER, attach, + NULL); + mm_gdbus_modem3gpp_set_initial_eps_bearer (skeleton, mm_base_bearer_get_path (attach)); + g_object_unref (attach); + } else { + mm_dbg ("clearing initial EPS bearer..."); + g_object_set (self, + MM_IFACE_MODEM_3GPP_INITIAL_EPS_BEARER, NULL, + NULL); + mm_gdbus_modem3gpp_set_initial_eps_bearer (skeleton, NULL); + } + + g_object_unref (skeleton); +} + +/*****************************************************************************/ + typedef struct _DisablingContext DisablingContext; static void interface_disabling_step (GTask *task); typedef enum { DISABLING_STEP_FIRST, + DISABLING_STEP_INITIAL_EPS_BEARER, DISABLING_STEP_PERIODIC_REGISTRATION_CHECKS, DISABLING_STEP_DISABLE_UNSOLICITED_REGISTRATION_EVENTS, DISABLING_STEP_CLEANUP_UNSOLICITED_REGISTRATION_EVENTS, @@ -1568,6 +1613,11 @@ interface_disabling_step (GTask *task) /* Fall down to next step */ ctx->step++; + case DISABLING_STEP_INITIAL_EPS_BEARER: + mm_iface_modem_3gpp_update_initial_eps_bearer (self, NULL); + /* Fall down to next step */ + ctx->step++; + case DISABLING_STEP_PERIODIC_REGISTRATION_CHECKS: /* Disable periodic registration checks, if they were set */ periodic_registration_check_disable (self); @@ -1693,6 +1743,7 @@ typedef enum { ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS, ENABLING_STEP_SETUP_UNSOLICITED_REGISTRATION_EVENTS, ENABLING_STEP_ENABLE_UNSOLICITED_REGISTRATION_EVENTS, + ENABLING_STEP_INITIAL_EPS_BEARER, ENABLING_STEP_LAST } EnablingStep; @@ -1820,6 +1871,33 @@ enable_unsolicited_registration_events_ready (MMIfaceModem3gpp *self, } static void +load_initial_eps_bearer_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + GTask *task) +{ + MMBearerProperties *properties; + EnablingContext *ctx; + GError *error = NULL; + + ctx = g_task_get_task_data (task); + + properties = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_initial_eps_bearer_finish (self, res, &error); + if (!properties) { + mm_dbg ("couldn't load initial default bearer properties: '%s'", error->message); + g_error_free (error); + goto out; + } + + mm_iface_modem_3gpp_update_initial_eps_bearer (self, properties); + g_object_unref (properties); + +out: + /* Go on to next step */ + ctx->step++; + interface_enabling_step (task); +} + +static void interface_enabling_step (GTask *task) { MMIfaceModem3gpp *self; @@ -1901,6 +1979,26 @@ interface_enabling_step (GTask *task) ctx->step++; } + case ENABLING_STEP_INITIAL_EPS_BEARER: { + gboolean eps_supported = FALSE; + + g_object_get (self, + MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, &eps_supported, + NULL); + + if (eps_supported && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_initial_eps_bearer && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_initial_eps_bearer_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_initial_eps_bearer ( + self, + (GAsyncReadyCallback)load_initial_eps_bearer_ready, + task); + return; + } + /* Fall down to next step */ + ctx->step++; + } + case ENABLING_STEP_LAST: /* We are done without errors! */ g_task_return_boolean (task, TRUE); @@ -2191,6 +2289,7 @@ mm_iface_modem_3gpp_initialize (MMIfaceModem3gpp *self, mm_gdbus_modem3gpp_set_enabled_facility_locks (skeleton, MM_MODEM_3GPP_FACILITY_NONE); mm_gdbus_modem3gpp_set_subscription_state (skeleton, MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN); mm_gdbus_modem3gpp_set_pco (skeleton, NULL); + mm_gdbus_modem3gpp_set_initial_eps_bearer (skeleton, NULL); /* Bind our RegistrationState property */ g_object_bind_property (self, MM_IFACE_MODEM_3GPP_REGISTRATION_STATE, @@ -2301,6 +2400,14 @@ iface_modem_3gpp_init (gpointer g_iface) MM_MODEM_3GPP_FACILITY_NONE, G_PARAM_READWRITE)); + g_object_interface_install_property + (g_iface, + g_param_spec_object (MM_IFACE_MODEM_3GPP_INITIAL_EPS_BEARER, + "Initial EPS bearer", + "Initial EPS bearer setup during registration", + MM_TYPE_BASE_BEARER, + G_PARAM_READWRITE)); + initialized = TRUE; } diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h index 920d01a0..90b3eedd 100644 --- a/src/mm-iface-modem-3gpp.h +++ b/src/mm-iface-modem-3gpp.h @@ -21,6 +21,7 @@ #define _LIBMM_INSIDE_MM #include <libmm-glib.h> +#include "mm-base-bearer.h" #include "mm-port-serial-at.h" #define MM_TYPE_IFACE_MODEM_3GPP (mm_iface_modem_3gpp_get_type ()) @@ -34,6 +35,7 @@ #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_IGNORED_FACILITY_LOCKS "iface-modem-3gpp-ignored-facility-locks" +#define MM_IFACE_MODEM_3GPP_INITIAL_EPS_BEARER "iface-modem-3gpp-initial-eps-bearer" #define MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK \ (MM_MODEM_ACCESS_TECHNOLOGY_GSM | \ @@ -145,6 +147,18 @@ struct _MMIfaceModem3gpp { GAsyncResult *res, GError **error); + /* Asynchronous initial default EPS bearer loading */ + void (*load_initial_eps_bearer) (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data); + MMBearerProperties * (*load_initial_eps_bearer_finish) (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error); + + /* Create initial default EPS bearer object */ + MMBaseBearer * (*create_initial_eps_bearer) (MMIfaceModem3gpp *self, + MMBearerProperties *properties); + /* Run CS/PS/EPS registration state checks.. * Note that no registration state is returned, implementations should call * mm_iface_modem_3gpp_update_registration_state(). */ @@ -253,6 +267,8 @@ void mm_iface_modem_3gpp_update_location (MMIfaceModem3gpp *self, gulong cell_id); void mm_iface_modem_3gpp_update_pco_list (MMIfaceModem3gpp *self, const GList *pco_list); +void mm_iface_modem_3gpp_update_initial_eps_bearer (MMIfaceModem3gpp *self, + MMBearerProperties *properties); /* Run all registration checks */ void mm_iface_modem_3gpp_run_registration_checks (MMIfaceModem3gpp *self, |