diff options
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 177 |
1 files changed, 160 insertions, 17 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 99fa798f..0349be6d 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -93,6 +93,10 @@ struct _MMBroadbandModemQmiPrivate { /* New devices may not support the legacy DMS UIM commands */ gboolean dms_uim_deprecated; + /* Whether autoconnect disabling needs to be checked up during + * the device enabling */ + gboolean autoconnect_checked; + /* 3GPP/CDMA registration helpers */ gchar *current_operator_id; gchar *current_operator_description; @@ -8393,39 +8397,178 @@ signal_load_values (MMIfaceModemSignal *self, /*****************************************************************************/ /* First enabling step */ +typedef struct { + MMPortQmi *qmi; + QmiClientWds *wds; +} EnablingStartedContext; + +static void +enabling_started_context_free (EnablingStartedContext *ctx) +{ + if (ctx->wds) { + mm_port_qmi_release_client (ctx->qmi, QMI_SERVICE_WDS, MM_PORT_QMI_FLAG_DEFAULT); + g_clear_object (&ctx->wds); + } + g_clear_object (&ctx->qmi); + g_slice_free (EnablingStartedContext, ctx); +} + static gboolean -enabling_started_finish (MMBroadbandModem *self, - GAsyncResult *res, - GError **error) +enabling_started_finish (MMBroadbandModem *self, + GAsyncResult *res, + GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void -parent_enabling_started_ready (MMBroadbandModem *self, - GAsyncResult *res, - GTask *task) +wds_set_autoconnect_settings_ready (QmiClientWds *client, + GAsyncResult *res, + GTask *task) { - GError *error = NULL; + MMBroadbandModemQmi *self; + g_autoptr(GError) error = NULL; + g_autoptr(QmiMessageWdsSetAutoconnectSettingsOutput) output = NULL; - if (!MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_qmi_parent_class)->enabling_started_finish ( - self, - res, - &error)) { + self = g_task_get_source_object (task); + + output = qmi_client_wds_set_autoconnect_settings_finish (client, res, &error); + if (!output || !qmi_message_wds_set_autoconnect_settings_output_get_result (output, &error)) + mm_obj_warn (self, "failed disabling autoconnect: %s", error->message); + else + mm_obj_info (self, "autoconnect explicitly disabled"); + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +wds_get_autoconnect_settings_ready (QmiClientWds *client, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemQmi *self; + QmiWdsAutoconnectSetting autoconnect_setting; + g_autoptr(GError) error = NULL; + g_autoptr(QmiMessageWdsSetAutoconnectSettingsInput) input = NULL; + g_autoptr(QmiMessageWdsGetAutoconnectSettingsOutput) output = NULL; + + self = g_task_get_source_object (task); + + output = qmi_client_wds_get_autoconnect_settings_finish (client, res, &error); + if (!output || + !qmi_message_wds_get_autoconnect_settings_output_get_result (output, &error) || + !qmi_message_wds_get_autoconnect_settings_output_get_status (output, &autoconnect_setting, &error)) { + mm_obj_warn (self, "failed checking whether autoconnect is disabled or not: %s", error->message); + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + if (autoconnect_setting != QMI_WDS_AUTOCONNECT_SETTING_ENABLED) { + mm_obj_dbg (self, "autoconnect is already disabled"); + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + mm_obj_dbg (self, "need to explicitly disable autoconnect"); + input = qmi_message_wds_set_autoconnect_settings_input_new (); + qmi_message_wds_set_autoconnect_settings_input_set_status (input, QMI_WDS_AUTOCONNECT_SETTING_DISABLED, NULL); + qmi_client_wds_set_autoconnect_settings (client, + input, + 10, + NULL, + (GAsyncReadyCallback) wds_set_autoconnect_settings_ready, + task); +} + +static void +enabling_wds_client_ready (MMPortQmi *qmi, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemQmi *self; + EnablingStartedContext *ctx; + g_autoptr(GError) error = NULL; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + if (!mm_port_qmi_allocate_client_finish (qmi, res, &error)) { + mm_obj_warn (self, "cannot check whether autoconnect is disabled or not: " + "couldn't allocate client for WDS service: %s", error->message); + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + ctx->wds = QMI_CLIENT_WDS (mm_port_qmi_get_client (ctx->qmi, + QMI_SERVICE_WDS, + MM_PORT_QMI_FLAG_DEFAULT)); + + qmi_client_wds_get_autoconnect_settings (ctx->wds, + NULL, + 5, + NULL, + (GAsyncReadyCallback) wds_get_autoconnect_settings_ready, + task); +} + +static void +parent_enabling_started_ready (MMBroadbandModem *_self, + GAsyncResult *res, + GTask *task) +{ + MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self); + EnablingStartedContext *ctx; + g_autoptr(GError) error = NULL; + + if (!MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_qmi_parent_class)->enabling_started_finish (_self, res, &error)) { /* Don't treat this as fatal. Parent enabling may fail if it cannot grab a primary * AT port, which isn't really an issue in QMI-based modems */ mm_obj_dbg (self, "couldn't start parent enabling: %s", error->message); - g_error_free (error); } - g_task_return_boolean (task, TRUE); - g_object_unref (task); + /* If the autoconnect check has already been done, we're finished */ + if (self->priv->autoconnect_checked) { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + /* The connection logic doesn't work properly when the device is already set + * to autoconnect, so automatically disable autoconnect ourselves. */ + mm_obj_dbg (self, "need to check whether autoconnect is disabled or not..."); + self->priv->autoconnect_checked = TRUE; + + /* Setup context */ + ctx = g_slice_new0 (EnablingStartedContext); + g_task_set_task_data (task, ctx, (GDestroyNotify)enabling_started_context_free); + + /* Keep a full port reference around */ + ctx->qmi = mm_base_modem_get_port_qmi (MM_BASE_MODEM (self)); + if (!ctx->qmi) { + mm_obj_warn (self, "cannot check whether autoconnect is disabled or not: couldn't peek QMI port"); + /* not fatal, just assume autoconnect is disabled */ + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + /* By default there is no generic WDS client preallocated in the QMI port, + * so explicitly allocate one ourselves */ + mm_port_qmi_allocate_client (ctx->qmi, + QMI_SERVICE_WDS, + MM_PORT_QMI_FLAG_DEFAULT, + NULL, + (GAsyncReadyCallback)enabling_wds_client_ready, + task); } static void -enabling_started (MMBroadbandModem *self, - GAsyncReadyCallback callback, - gpointer user_data) +enabling_started (MMBroadbandModem *self, + GAsyncReadyCallback callback, + gpointer user_data) { GTask *task; |