diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem.c | 135 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp-profile-manager.c | 6 |
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; |