aboutsummaryrefslogtreecommitdiff
path: root/src/mm-bearer-qmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-bearer-qmi.c')
-rw-r--r--src/mm-bearer-qmi.c166
1 files changed, 123 insertions, 43 deletions
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index f30c3e90..8926918c 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -415,6 +415,7 @@ static void cleanup_event_report_unsolicited_events (MMBearerQmi *self,
typedef enum {
CONNECT_STEP_FIRST,
+ CONNECT_STEP_LOAD_PROFILE_SETTINGS,
CONNECT_STEP_OPEN_QMI_PORT,
CONNECT_STEP_SETUP_DATA_FORMAT,
CONNECT_STEP_SETUP_LINK,
@@ -445,6 +446,7 @@ typedef struct {
MMPortQmi *qmi;
QmiSioPort sio_port;
+ gint profile_id;
MMBearerIpMethod ip_method;
gboolean explicit_qmi_open;
gchar *user;
@@ -980,32 +982,30 @@ static QmiMessageWdsStartNetworkInput *
build_start_network_input (ConnectContext *ctx)
{
QmiMessageWdsStartNetworkInput *input;
- gboolean has_user, has_password;
g_assert (ctx->running_ipv4 || ctx->running_ipv6);
g_assert (!(ctx->running_ipv4 && ctx->running_ipv6));
input = qmi_message_wds_start_network_input_new ();
- if (ctx->apn && ctx->apn[0])
- qmi_message_wds_start_network_input_set_apn (input, ctx->apn, NULL);
-
- has_user = (ctx->user && ctx->user[0]);
- has_password = (ctx->password && ctx->password[0]);
-
- /* Need to add auth info? */
- if (has_user || has_password || ctx->auth != QMI_WDS_AUTHENTICATION_NONE) {
- /* We define a valid auth preference if we have either user or password, or an explicit
- * request for one to be set. If no explicit one was given, default to CHAP. */
- qmi_message_wds_start_network_input_set_authentication_preference (
- input,
- (ctx->auth != QMI_WDS_AUTHENTICATION_NONE) ? ctx->auth : QMI_WDS_AUTHENTICATION_CHAP,
- NULL);
-
- if (has_user)
- qmi_message_wds_start_network_input_set_username (input, ctx->user, NULL);
- if (has_password)
- qmi_message_wds_start_network_input_set_password (input, ctx->password, NULL);
+ /* When requesting to connect through a profile, add the profile-id setting */
+ if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) {
+ g_assert (ctx->profile_id <= (gint)G_MAXUINT8);
+ qmi_message_wds_start_network_input_set_profile_index_3gpp (input, (guint8)ctx->profile_id, NULL);
+ } else {
+ /* If user gives empty string as APN, we also skip setting it in the
+ * request. */
+ if (ctx->apn && ctx->apn[0])
+ qmi_message_wds_start_network_input_set_apn (input, ctx->apn, NULL);
+
+ /* Auth info */
+ qmi_message_wds_start_network_input_set_authentication_preference (input, ctx->auth, NULL);
+ if (ctx->auth != QMI_WDS_AUTHENTICATION_NONE) {
+ if (ctx->user)
+ qmi_message_wds_start_network_input_set_username (input, ctx->user, NULL);
+ if (ctx->user)
+ qmi_message_wds_start_network_input_set_password (input, ctx->password, NULL);
+ }
}
/* Only add the IP family preference TLV if explicitly requested a given
@@ -1486,6 +1486,66 @@ qmi_port_open_ready (MMPortQmi *qmi,
connect_context_step (task);
}
+static gboolean
+load_ip_type_settings_from_profile (ConnectContext *ctx,
+ MM3gppProfile *profile,
+ GError **error)
+{
+ MMBearerIpFamily ip_family;
+
+ ip_family = mm_3gpp_profile_get_ip_type (profile);
+ if (mm_3gpp_normalize_ip_family (&ip_family))
+ ctx->no_ip_family_preference = TRUE;
+ if (ip_family & MM_BEARER_IP_FAMILY_IPV4)
+ ctx->ipv4 = TRUE;
+ if (ip_family & MM_BEARER_IP_FAMILY_IPV6)
+ ctx->ipv6 = TRUE;
+ if (ip_family & MM_BEARER_IP_FAMILY_IPV4V6) {
+ ctx->ipv4 = TRUE;
+ ctx->ipv6 = TRUE;
+ }
+ if (!ctx->ipv4 && !ctx->ipv6) {
+ g_autofree gchar *str = NULL;
+
+ str = mm_bearer_ip_family_build_string_from_mask (ip_family);
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+ "Unsupported IP type requested: '%s'", str);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+get_profile_ready (MMIfaceModem3gppProfileManager *modem,
+ GAsyncResult *res,
+ GTask *task)
+{
+ ConnectContext *ctx;
+ GError *error = NULL;
+ g_autoptr(MM3gppProfile) profile = NULL;
+
+ ctx = g_task_get_task_data (task);
+
+ profile = mm_iface_modem_3gpp_profile_manager_get_profile_finish (modem, res, &error);
+ if (!profile) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ if (!load_ip_type_settings_from_profile (ctx, profile, &error)) {
+ g_prefix_error (&error, "Couldn't load ip type settings from profile: ");
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ /* Keep on */
+ ctx->step++;
+ connect_context_step (task);
+}
+
static void
connect_context_step (GTask *task)
{
@@ -1518,11 +1578,24 @@ connect_context_step (GTask *task)
switch (ctx->step) {
case CONNECT_STEP_FIRST:
- g_assert (ctx->ipv4 || ctx->ipv6);
+ ctx->step++;
+ /* fall through */
+
+ case CONNECT_STEP_LOAD_PROFILE_SETTINGS:
+ if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) {
+ mm_obj_dbg (self, "loading connection settings from profile '%d'...", ctx->profile_id);
+ mm_iface_modem_3gpp_profile_manager_get_profile (
+ MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (ctx->modem),
+ ctx->profile_id,
+ (GAsyncReadyCallback)get_profile_ready,
+ task);
+ return;
+ }
ctx->step++;
/* fall through */
case CONNECT_STEP_OPEN_QMI_PORT:
+ g_assert (ctx->ipv4 || ctx->ipv6);
/* If we're explicitly opening the port (e.g. using a different cdc-wdm
* port because the primary one is already connected by a different
* bearer), then make sure we also close it if anything goes wrong and
@@ -1945,6 +2018,9 @@ connect_context_step (GTask *task)
ctx->ipv6_config);
mm_bearer_connect_result_set_multiplexed (connect_result, !!ctx->link);
+ if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN)
+ mm_bearer_connect_result_set_profile_id (connect_result, ctx->profile_id);
+
complete_connect (task, connect_result, NULL);
return;
}
@@ -1969,8 +2045,8 @@ load_settings_from_bearer (MMBearerQmi *self,
GError **error)
{
MMBearerAllowedAuth bearer_auth;
- MMBearerIpFamily ip_family;
GError *inner_error = NULL;
+ const gchar *str;
/* If no multiplex setting given by the user, assume requested */
ctx->multiplex = mm_bearer_properties_get_multiplex (properties);
@@ -1983,6 +2059,22 @@ load_settings_from_bearer (MMBearerQmi *self,
ctx->link_prefix_hint = g_strdup_printf ("qmapmux%u.", mm_base_modem_get_dbus_id (MM_BASE_MODEM (modem)));
}
+ /* If profile id is given, we'll launch the connection specifying the profile id in use
+ * exclusively, so we ignore any additional user provided setting */
+ ctx->profile_id = mm_bearer_properties_get_profile_id (properties);
+ if (ctx->profile_id != MM_3GPP_PROFILE_ID_UNKNOWN) {
+ /* Is this a 3GPP2 only modem and profile id was given? If so, error, as we don't support
+ * 3GPP2 profiles in ModemManager */
+ if (mm_iface_modem_is_cdma_only (MM_IFACE_MODEM (modem))) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "3GPP2 doesn't support profile id setting");
+ return FALSE;
+ }
+ /* All done now, we'll need to load IP type settings later on once
+ * we load the real profile to use */
+ return TRUE;
+ }
+
/* APN settings */
ctx->apn = g_strdup (mm_bearer_properties_get_apn (properties));
/* Is this a 3GPP only modem and no APN was given? If so, error */
@@ -1999,29 +2091,17 @@ load_settings_from_bearer (MMBearerQmi *self,
}
/* IP type settings */
- ip_family = mm_bearer_properties_get_ip_type (properties);
- if (mm_3gpp_normalize_ip_family (&ip_family))
- ctx->no_ip_family_preference = TRUE;
- if (ip_family & MM_BEARER_IP_FAMILY_IPV4)
- ctx->ipv4 = TRUE;
- if (ip_family & MM_BEARER_IP_FAMILY_IPV6)
- ctx->ipv6 = TRUE;
- if (ip_family & MM_BEARER_IP_FAMILY_IPV4V6) {
- ctx->ipv4 = TRUE;
- ctx->ipv6 = TRUE;
- }
- if (!ctx->ipv4 && !ctx->ipv6) {
- g_autofree gchar *str = NULL;
-
- str = mm_bearer_ip_family_build_string_from_mask (ip_family);
- g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
- "Unsupported IP type requested: '%s'", str);
+ if (!load_ip_type_settings_from_profile (ctx, mm_bearer_properties_peek_3gpp_profile (properties), error))
return FALSE;
- }
- /* Auth settings */
- ctx->user = g_strdup (mm_bearer_properties_get_user (properties));
- ctx->password = g_strdup (mm_bearer_properties_get_password (properties));
+ /* Auth settings; in we treat user/password empty strings as no strings */
+ str = mm_bearer_properties_get_user (properties);
+ if (str && str[0])
+ ctx->user = g_strdup (str);
+ str = mm_bearer_properties_get_password (properties);
+ if (str && str[0])
+ ctx->password = g_strdup (str);
+
if (!ctx->user && !ctx->password)
ctx->auth = QMI_WDS_AUTHENTICATION_NONE;
else {