diff options
Diffstat (limited to 'src/mm-bearer-qmi.c')
-rw-r--r-- | src/mm-bearer-qmi.c | 322 |
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); } /*****************************************************************************/ |