aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem.c135
-rw-r--r--src/mm-iface-modem-3gpp-profile-manager.c6
2 files changed, 141 insertions, 0 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 41906c2e..291978ef 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -209,6 +209,8 @@ struct _MMBroadbandModemPrivate {
MMModem3gppFacility modem_3gpp_ignored_facility_locks;
MMBaseBearer *modem_3gpp_initial_eps_bearer;
MMModem3gppPacketServiceState modem_3gpp_packet_service_state;
+ gboolean initial_eps_bearer_cid_support_checked;
+ gint initial_eps_bearer_cid;
/*<--- Modem 3GPP Profile Manager interface --->*/
/* Properties */
@@ -2918,6 +2920,136 @@ modem_load_access_technologies (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Load initial EPS bearer settings currently configured in modem (3GPP interface) */
+
+static MMBearerProperties *
+modem_3gpp_load_initial_eps_bearer_settings_finish (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return MM_BEARER_PROPERTIES (g_task_propagate_pointer (G_TASK (res), error));
+}
+
+static void
+load_initial_eps_bearer_get_profile_ready (MMIfaceModem3gppProfileManager *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ GError *error = NULL;
+ g_autoptr(MM3gppProfile) profile = NULL;
+ MMBearerProperties *props;
+
+ profile = mm_iface_modem_3gpp_profile_manager_get_profile_finish (self, res, &error);
+ if (!profile) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ props = mm_bearer_properties_new_from_profile (profile, &error);
+ if (!props)
+ g_task_return_error (task, error);
+ else
+ g_task_return_pointer (task, props, g_object_unref);
+ g_object_unref (task);
+}
+
+static void
+load_initial_eps_bearer_profile (GTask *task)
+{
+ MMBroadbandModem *self;
+
+ self = g_task_get_source_object (task);
+ g_assert (self->priv->initial_eps_bearer_cid_support_checked);
+
+ if (self->priv->initial_eps_bearer_cid < 0) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+ "initial EPS bearer context management unsupported");
+ g_object_unref (task);
+ return;
+ }
+
+ /* Note that we may be calling this before initializing the 3GPP profile manager interface,
+ * but it should not be an issue, because the interface initialization exclusively checks
+ * for the feature support and takes care of creating the DBus skeleton. There is currently
+ * no explicit state initialized that is required for operations later on. Ideally, though,
+ * an interface method should not be used unless it is initialized, but in this case it's
+ * problematic because the profile manager interface is initialized always *after* the 3GPP
+ * interface. */
+ mm_iface_modem_3gpp_profile_manager_get_profile (
+ MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self),
+ self->priv->initial_eps_bearer_cid,
+ (GAsyncReadyCallback) load_initial_eps_bearer_get_profile_ready,
+ task);
+}
+
+static void
+initial_eps_bearer_cid_cgdcont_test_ready (MMBaseModem *_self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
+ const gchar *response;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (self->priv->initial_eps_bearer_cid < 0);
+
+ response = mm_base_modem_at_command_full_finish (_self, res, &error);
+ if (!response)
+ mm_obj_dbg (self, "failed +CGDCONT format check : %s", error->message);
+ else {
+ GList *format_list;
+ guint min_cid;
+
+ format_list = mm_3gpp_parse_cgdcont_test_response (response, self, &error);
+ if (error)
+ mm_obj_dbg (self, "error parsing +CGDCONT test response: %s", error->message);
+ else if (!mm_3gpp_pdp_context_format_list_find_range (format_list, MM_BEARER_IP_FAMILY_IPV4, &min_cid, NULL)) {
+ /* We check for IPv4 following the assumption that modems will generally support v4, while
+ * v6 is considered optional. If we ever find a modem supporting v6 exclusively and not v4
+ * we would need to update this logic to also check for v6. */
+ mm_obj_dbg (self, "context format check for IP not found");
+ } else {
+ mm_obj_dbg (self, "initial EPS bearer context cid found: %u", min_cid);
+ self->priv->initial_eps_bearer_cid = (gint) min_cid;
+ }
+ mm_3gpp_pdp_context_format_list_free (format_list);
+ }
+
+ load_initial_eps_bearer_profile (task);
+}
+
+static void
+modem_3gpp_load_initial_eps_bearer_settings (MMIfaceModem3gpp *_self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
+ GTask *task;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ /* Lookup which is supposed to be the initial EPS bearer context cid.
+ * - As per 3GPP specs, it should be cid=0
+ * - Qualcomm based modems default this to cid=1
+ */
+ if (G_UNLIKELY (!self->priv->initial_eps_bearer_cid_support_checked)) {
+ self->priv->initial_eps_bearer_cid_support_checked = TRUE;
+ g_assert (self->priv->initial_eps_bearer_cid < 0);
+ mm_obj_dbg (self, "looking for the initial EPS bearer context cid,,,");
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "+CGDCONT=?",
+ 3,
+ TRUE, /* cached */
+ (GAsyncReadyCallback)initial_eps_bearer_cid_cgdcont_test_ready,
+ task);
+ return;
+ }
+
+ load_initial_eps_bearer_profile (task);
+}
+
+/*****************************************************************************/
/* Setup/Cleanup unsolicited events (3GPP interface) */
static gboolean
@@ -13372,6 +13504,7 @@ mm_broadband_modem_init (MMBroadbandModem *self)
self->priv->modem_cmer_disable_mode = MM_3GPP_CMER_MODE_NONE;
self->priv->modem_cmer_ind = MM_3GPP_CMER_IND_NONE;
self->priv->flow_control = MM_FLOW_CONTROL_NONE;
+ self->priv->initial_eps_bearer_cid = -1;
}
static void
@@ -13543,6 +13676,8 @@ iface_modem_3gpp_init (MMIfaceModem3gppInterface *iface)
iface->load_enabled_facility_locks_finish = modem_3gpp_load_enabled_facility_locks_finish;
iface->load_eps_ue_mode_operation = modem_3gpp_load_eps_ue_mode_operation;
iface->load_eps_ue_mode_operation_finish = modem_3gpp_load_eps_ue_mode_operation_finish;
+ iface->load_initial_eps_bearer_settings = modem_3gpp_load_initial_eps_bearer_settings;
+ iface->load_initial_eps_bearer_settings_finish = modem_3gpp_load_initial_eps_bearer_settings_finish;
/* Enabling steps */
iface->setup_unsolicited_events = modem_3gpp_setup_unsolicited_events;
diff --git a/src/mm-iface-modem-3gpp-profile-manager.c b/src/mm-iface-modem-3gpp-profile-manager.c
index 45a12bb0..01d3c791 100644
--- a/src/mm-iface-modem-3gpp-profile-manager.c
+++ b/src/mm-iface-modem-3gpp-profile-manager.c
@@ -878,6 +878,9 @@ mm_iface_modem_3gpp_profile_manager_set_profile (MMIfaceModem3gppProfileManager
}
/*****************************************************************************/
+/* Get a single profile.
+ * NOTE: this method may be called before the interface is initialized.
+ */
MM3gppProfile *
mm_iface_modem_3gpp_profile_manager_get_profile_finish (MMIfaceModem3gppProfileManager *self,
@@ -963,6 +966,9 @@ mm_iface_modem_3gpp_profile_manager_get_profile (MMIfaceModem3gppProfileManager
}
/*****************************************************************************/
+/* List all profiles.
+ * NOTE: this method may be called before the interface is initialized.
+ */
typedef struct {
GList *profiles;