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.c322
1 files changed, 145 insertions, 177 deletions
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index d375fb7f..f30c3e90 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -28,6 +28,7 @@
#include <libmm-glib.h>
#include "mm-iface-modem.h"
+#include "mm-iface-modem-3gpp-profile-manager.h"
#include "mm-bearer-qmi.h"
#include "mm-modem-helpers-qmi.h"
#include "mm-port-enums-types.h"
@@ -438,43 +439,44 @@ typedef enum {
typedef struct {
MMBearerQmi *self;
- ConnectStep step;
- MMPort *data;
- MMPortQmi *qmi;
- QmiSioPort sio_port;
- MMBearerMultiplexSupport multiplex;
- gboolean explicit_qmi_open;
- gchar *user;
- gchar *password;
- gchar *apn;
- QmiWdsAuthentication auth;
- gboolean no_ip_family_preference;
-
+ MMBaseModem *modem;
+ ConnectStep step;
+ MMPort *data;
+ MMPortQmi *qmi;
+ QmiSioPort sio_port;
+
+ MMBearerIpMethod ip_method;
+ gboolean explicit_qmi_open;
+ gchar *user;
+ gchar *password;
+ gchar *apn;
+ QmiWdsAuthentication auth;
+ gboolean no_ip_family_preference;
+
+ MMBearerMultiplexSupport multiplex;
QmiWdaDataAggregationProtocol dap;
guint mux_id;
gchar *link_prefix_hint;
gchar *link_name;
MMPort *link;
- MMBearerIpMethod ip_method;
-
- gboolean ipv4;
- gboolean running_ipv4;
- QmiClientWds *client_ipv4;
- guint packet_service_status_ipv4_indication_id;
- guint event_report_ipv4_indication_id;
- guint32 packet_data_handle_ipv4;
+ gboolean ipv4;
+ gboolean running_ipv4;
+ QmiClientWds *client_ipv4;
+ guint packet_service_status_ipv4_indication_id;
+ guint event_report_ipv4_indication_id;
+ guint32 packet_data_handle_ipv4;
MMBearerIpConfig *ipv4_config;
- GError *error_ipv4;
-
- gboolean ipv6;
- gboolean running_ipv6;
- QmiClientWds *client_ipv6;
- guint packet_service_status_ipv6_indication_id;
- guint event_report_ipv6_indication_id;
- guint32 packet_data_handle_ipv6;
+ GError *error_ipv4;
+
+ gboolean ipv6;
+ gboolean running_ipv6;
+ QmiClientWds *client_ipv6;
+ guint packet_service_status_ipv6_indication_id;
+ guint event_report_ipv6_indication_id;
+ guint32 packet_data_handle_ipv6;
MMBearerIpConfig *ipv6_config;
- GError *error_ipv6;
+ GError *error_ipv6;
} ConnectContext;
static void
@@ -544,8 +546,9 @@ connect_context_free (ConnectContext *ctx)
g_clear_object (&ctx->ipv6_config);
g_clear_object (&ctx->data);
- g_object_unref (ctx->qmi);
- g_object_unref (ctx->self);
+ g_clear_object (&ctx->qmi);
+ g_clear_object (&ctx->modem);
+ g_clear_object (&ctx->self);
g_slice_free (ConnectContext, ctx);
}
@@ -1958,167 +1961,138 @@ cancel_operation_cancellable (GCancellable *cancellable,
g_cancellable_cancel (operation_cancellable);
}
-static void
-_connect (MMBaseBearer *_self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+static gboolean
+load_settings_from_bearer (MMBearerQmi *self,
+ MMBaseModem *modem,
+ ConnectContext *ctx,
+ MMBearerProperties *properties,
+ GError **error)
{
- MMBearerQmi *self = MM_BEARER_QMI (_self);
- MMBearerProperties *properties = NULL;
- ConnectContext *ctx;
- MMBaseModem *modem = NULL;
- MMPort *data = NULL;
- MMPortQmi *qmi = NULL;
- QmiSioPort sio_port = QMI_SIO_PORT_NONE;
- GError *error = NULL;
- const gchar *apn;
- GTask *task;
- GCancellable *operation_cancellable = NULL;
+ MMBearerAllowedAuth bearer_auth;
+ MMBearerIpFamily ip_family;
+ GError *inner_error = NULL;
- g_object_get (self,
- MM_BASE_BEARER_MODEM, &modem,
- NULL);
- g_assert (modem);
+ /* If no multiplex setting given by the user, assume requested */
+ ctx->multiplex = mm_bearer_properties_get_multiplex (properties);
+ if (ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_UNKNOWN)
+ ctx->multiplex = MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED;
- /* Grab a data port */
- data = mm_base_modem_get_best_data_port (modem, MM_PORT_TYPE_NET);
- if (!data) {
- g_task_report_new_error (
- self,
- callback,
- user_data,
- _connect,
- MM_CORE_ERROR,
- MM_CORE_ERROR_NOT_FOUND,
- "No valid data port found to launch connection");
- goto out;
+ /* The link prefix hint given must be modem-specific */
+ if (ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED ||
+ ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) {
+ ctx->link_prefix_hint = g_strdup_printf ("qmapmux%u.", mm_base_modem_get_dbus_id (MM_BASE_MODEM (modem)));
}
- /* Each data port has a single QMI port associated */
- qmi = mm_broadband_modem_qmi_get_port_qmi_for_data (MM_BROADBAND_MODEM_QMI (modem), data, &sio_port, &error);
- if (!qmi) {
- g_task_report_error (
- self,
- callback,
- user_data,
- _connect,
- error);
- goto out;
+ /* 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 */
+ if (mm_iface_modem_is_3gpp_only (MM_IFACE_MODEM (modem)) && !ctx->apn) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "3GPP connection logic requires APN setting");
+ return FALSE;
+ }
+ /* Is this a 3GPP2 only modem and APN was given? If so, error */
+ if (mm_iface_modem_is_cdma_only (MM_IFACE_MODEM (modem)) && ctx->apn) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "3GPP2 doesn't support APN setting");
+ return FALSE;
}
- /* Check whether we have an APN */
- apn = mm_bearer_properties_get_apn (mm_base_bearer_peek_config (_self));
-
- /* Is this a 3GPP only modem and no APN was given? If so, error */
- if (mm_iface_modem_is_3gpp_only (MM_IFACE_MODEM (modem)) && !apn) {
- g_task_report_new_error (
- self,
- callback,
- user_data,
- _connect,
- MM_CORE_ERROR,
- MM_CORE_ERROR_INVALID_ARGS,
- "3GPP connection logic requires APN setting");
- goto out;
+ /* 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;
- /* Is this a 3GPP2 only modem and APN was given? If so, error */
- if (mm_iface_modem_is_cdma_only (MM_IFACE_MODEM (modem)) && apn) {
- g_task_report_new_error (
- self,
- callback,
- user_data,
- _connect,
- MM_CORE_ERROR,
- MM_CORE_ERROR_INVALID_ARGS,
- "3GPP2 doesn't support APN setting");
- goto out;
+ 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;
}
- ctx = g_slice_new0 (ConnectContext);
- ctx->self = g_object_ref (self);
- ctx->qmi = g_object_ref (qmi);
- ctx->sio_port = sio_port;
- ctx->dap = mm_port_qmi_get_data_aggregation_protocol (ctx->qmi);
- ctx->mux_id = QMI_DEVICE_MUX_ID_UNBOUND;
- ctx->data = g_object_ref (data);
- ctx->step = CONNECT_STEP_FIRST;
- ctx->ip_method = MM_BEARER_IP_METHOD_UNKNOWN;
+ /* Auth settings */
+ ctx->user = g_strdup (mm_bearer_properties_get_user (properties));
+ ctx->password = g_strdup (mm_bearer_properties_get_password (properties));
+ if (!ctx->user && !ctx->password)
+ ctx->auth = QMI_WDS_AUTHENTICATION_NONE;
+ else {
+ bearer_auth = mm_bearer_properties_get_allowed_auth (properties);
+ ctx->auth = mm_bearer_allowed_auth_to_qmi_authentication (bearer_auth, self, &inner_error);
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+ }
- /* If no multiplex setting given by the user, assume requested */
- ctx->multiplex = MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED;
+ return TRUE;
+}
- g_object_get (self,
- MM_BASE_BEARER_CONFIG, &properties,
- NULL);
+static void
+_connect (MMBaseBearer *_self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBearerQmi *self = MM_BEARER_QMI (_self);
+ ConnectContext *ctx;
+ GError *error = NULL;
+ GTask *task;
+ g_autoptr(GCancellable) operation_cancellable = NULL;
+ g_autoptr(MMBaseModem) modem = NULL;
+ g_autoptr(MMBearerProperties) properties = NULL;
operation_cancellable = g_cancellable_new ();
task = g_task_new (self, operation_cancellable, callback, user_data);
g_task_set_check_cancellable (task, FALSE);
- g_task_set_task_data (task, ctx, (GDestroyNotify)connect_context_free);
- if (properties) {
- MMBearerAllowedAuth auth;
- MMBearerIpFamily ip_family;
- MMBearerMultiplexSupport multiplex;
-
- ctx->apn = g_strdup (mm_bearer_properties_get_apn (properties));
- ctx->user = g_strdup (mm_bearer_properties_get_user (properties));
- ctx->password = g_strdup (mm_bearer_properties_get_password (properties));
-
- 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) {
- gchar *str;
-
- str = mm_bearer_ip_family_build_string_from_mask (ip_family);
- g_task_return_new_error (
- task,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED,
- "Unsupported IP type requested: '%s'",
- str);
- g_object_unref (task);
- g_free (str);
- goto out;
- }
+ g_object_get (self,
+ MM_BASE_BEARER_MODEM, &modem,
+ MM_BASE_BEARER_CONFIG, &properties,
+ NULL);
+ g_assert (modem);
- auth = mm_bearer_properties_get_allowed_auth (properties);
- g_object_unref (properties);
+ ctx = g_slice_new0 (ConnectContext);
+ ctx->self = g_object_ref (self);
+ ctx->modem = g_object_ref (modem);
+ ctx->mux_id = QMI_DEVICE_MUX_ID_UNBOUND;
+ ctx->sio_port = QMI_SIO_PORT_NONE;
+ ctx->step = CONNECT_STEP_FIRST;
+ ctx->ip_method = MM_BEARER_IP_METHOD_UNKNOWN;
+ g_task_set_task_data (task, ctx, (GDestroyNotify)connect_context_free);
- if (!ctx->user && !ctx->password)
- ctx->auth = QMI_WDS_AUTHENTICATION_NONE;
- else {
- auth = mm_bearer_properties_get_allowed_auth (properties);
- ctx->auth = mm_bearer_allowed_auth_to_qmi_authentication (auth, self, &error);
- if (error) {
- g_task_return_error (task, error);
- g_object_unref (task);
- goto out;
- }
- }
+ /* Grab a data port */
+ ctx->data = mm_base_modem_get_best_data_port (modem, MM_PORT_TYPE_NET);
+ if (!ctx->data) {
+ g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND,
+ "No valid data port found to launch connection");
+ g_object_unref (task);
+ return;
+ }
- multiplex = mm_bearer_properties_get_multiplex (properties);
- if (multiplex != MM_BEARER_MULTIPLEX_SUPPORT_UNKNOWN)
- ctx->multiplex = multiplex;
+ /* Each data port has a single QMI port associated */
+ ctx->qmi = mm_broadband_modem_qmi_get_port_qmi_for_data (MM_BROADBAND_MODEM_QMI (modem), ctx->data, &ctx->sio_port, &error);
+ if (!ctx->qmi) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
}
+ ctx->dap = mm_port_qmi_get_data_aggregation_protocol (ctx->qmi);
- if (ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUESTED ||
- ctx->multiplex == MM_BEARER_MULTIPLEX_SUPPORT_REQUIRED) {
- /* the link prefix hint given must be modem-specific */
- ctx->link_prefix_hint = g_strdup_printf ("qmapmux%u.", mm_base_modem_get_dbus_id (MM_BASE_MODEM (modem)));
+ /* load all settings from bearer */
+ if (!load_settings_from_bearer (self, modem, ctx, properties, &error)) {
+ g_prefix_error (&error, "Invalid bearer properties: ");
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
}
/* setup network cancellable */
@@ -2139,16 +2113,10 @@ _connect (MMBaseBearer *_self,
/* Run! */
mm_obj_dbg (self, "launching connection with QMI port (%s) and data port (%s) (multiplex %s)",
- mm_port_get_device (MM_PORT (qmi)),
- mm_port_get_device (data),
+ mm_port_get_device (MM_PORT (ctx->qmi)),
+ mm_port_get_device (ctx->data),
mm_bearer_multiplex_support_get_string (ctx->multiplex));
connect_context_step (task);
-
- out:
- g_clear_object (&operation_cancellable);
- g_clear_object (&qmi);
- g_clear_object (&data);
- g_clear_object (&modem);
}
/*****************************************************************************/