diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2021-10-25 21:39:46 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-11-17 11:30:01 +0100 |
commit | 81302efa661f848455a1bfe44b27608b11d6d49b (patch) | |
tree | c4ee58c60d071f992c6bab8c8016e557e6d490eb /src | |
parent | 21c775703c9e3852fdda206a9658cb236613ef85 (diff) |
iface-modem: use external dispatcher to attempt FCC unlock
We remove the built-in FCC unlock procedures from the ModemManager, we
will no longer run them automatically, and instead rely on external
scripts/programs to do that.
Packages providing the external FCC unlock tools can install them in
${pkglibdir}/fcc-unlock.d.
Users manually enabling external FCC unlock tools can install them in
${pkgsysconfdir}/fcc-unlock.d.
The user-enabled path takes precedence over the package-enabled one.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/meson.build | 3 | ||||
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 2 | ||||
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 2 | ||||
-rw-r--r-- | src/mm-fcc-unlock-dispatcher.c | 319 | ||||
-rw-r--r-- | src/mm-fcc-unlock-dispatcher.h | 47 | ||||
-rw-r--r-- | src/mm-iface-modem.c | 68 | ||||
-rw-r--r-- | src/mm-iface-modem.h | 8 | ||||
-rw-r--r-- | src/mm-shared-qmi.c | 50 | ||||
-rw-r--r-- | src/mm-shared-qmi.h | 6 |
10 files changed, 432 insertions, 77 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index b4899e4c..38944f23 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -292,6 +292,8 @@ CLEANFILES += $(DAEMON_ENUMS_GENERATED) ModemManager_CPPFLAGS = \ -DPLUGINDIR=\"$(pkglibdir)\" \ + -DFCCUNLOCKDIRPACKAGE=\"${pkglibdir}/fcc-unlock.d\" \ + -DFCCUNLOCKDIRUSER=\"${pkgsysconfdir}/fcc-unlock.d\" \ -DMM_COMPILATION \ $(NULL) @@ -311,6 +313,8 @@ ModemManager_SOURCES = \ mm-private-boxed-types.c \ mm-auth-provider.h \ mm-auth-provider.c \ + mm-fcc-unlock-dispatcher.h \ + mm-fcc-unlock-dispatcher.c \ mm-filter.h \ mm-filter.c \ mm-base-manager.c \ diff --git a/src/meson.build b/src/meson.build index 3fe78f11..989f8d7b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -200,6 +200,7 @@ sources = files( 'mm-call-list.c', 'mm-context.c', 'mm-device.c', + 'mm-fcc-unlock-dispatcher.c', 'mm-filter.c', 'mm-iface-modem-3gpp.c', 'mm-iface-modem-3gpp-profile-manager.c', @@ -250,6 +251,8 @@ deps = [ c_args = [ '-DMM_COMPILATION', '-DPLUGINDIR="@0@"'.format(mm_prefix / mm_pkglibdir), + '-DFCCUNLOCKDIRPACKAGE="@0@"'.format(mm_prefix / mm_pkglibdir / 'fcc-unlock.d'), + '-DFCCUNLOCKDIRUSER="@0@"'.format(mm_prefix / mm_pkgsysconfdir / 'fcc-unlock.d'), ] if enable_qrtr diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index e664b381..21b2b959 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -7975,8 +7975,6 @@ iface_modem_init (MMIfaceModem *iface) iface->load_current_bands_finish = mm_shared_qmi_load_current_bands_finish; iface->set_current_bands = mm_shared_qmi_set_current_bands; iface->set_current_bands_finish = mm_shared_qmi_set_current_bands_finish; - iface->fcc_unlock = mm_shared_qmi_fcc_unlock; - iface->fcc_unlock_finish = mm_shared_qmi_fcc_unlock_finish; #endif /* Additional actions */ diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index ef511bb1..7bfec84e 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -12381,8 +12381,6 @@ iface_modem_init (MMIfaceModem *iface) /* Enabling/disabling */ iface->modem_power_up = modem_power_up; iface->modem_power_up_finish = modem_power_up_down_off_finish; - iface->fcc_unlock = mm_shared_qmi_fcc_unlock; - iface->fcc_unlock_finish = mm_shared_qmi_fcc_unlock_finish; iface->modem_after_power_up = NULL; iface->modem_after_power_up_finish = NULL; iface->modem_power_down = modem_power_down; diff --git a/src/mm-fcc-unlock-dispatcher.c b/src/mm-fcc-unlock-dispatcher.c new file mode 100644 index 00000000..a033d998 --- /dev/null +++ b/src/mm-fcc-unlock-dispatcher.c @@ -0,0 +1,319 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include <config.h> +#include <sys/stat.h> + +#include <ModemManager.h> +#include "mm-errors-types.h" +#include "mm-utils.h" +#include "mm-log-object.h" +#include "mm-fcc-unlock-dispatcher.h" + +#if !defined FCCUNLOCKDIRPACKAGE +# error FCCUNLOCKDIRPACKAGE must be defined at build time +#endif + +#if !defined FCCUNLOCKDIRUSER +# error FCCUNLOCKDIRUSER must be defined at build time +#endif + +/* Maximum time a FCC unlock command is allowed to run before + * us killing it */ +#define MAX_FCC_UNLOCK_EXEC_TIME_SECS 5 + +struct _MMFccUnlockDispatcher { + GObject parent; + GSubprocessLauncher *launcher; +}; + +struct _MMFccUnlockDispatcherClass { + GObjectClass parent; +}; + +static void log_object_iface_init (MMLogObjectInterface *iface); + +G_DEFINE_TYPE_EXTENDED (MMFccUnlockDispatcher, mm_fcc_unlock_dispatcher, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (MM_TYPE_LOG_OBJECT, log_object_iface_init)) + +/*****************************************************************************/ + +static gchar * +log_object_build_id (MMLogObject *_self) +{ + return g_strdup ("fcc-unlock-dispatcher"); +} + +/*****************************************************************************/ + +typedef struct { + gchar *filename; + GSubprocess *subprocess; + guint timeout_id; +} RunContext; + +static void +run_context_free (RunContext *ctx) +{ + g_assert (!ctx->timeout_id); + g_clear_object (&ctx->subprocess); + g_free (ctx->filename); + g_slice_free (RunContext, ctx); +} + +gboolean +mm_fcc_unlock_dispatcher_run_finish (MMFccUnlockDispatcher *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static gboolean +subprocess_wait_timed_out (GTask *task) +{ + MMFccUnlockDispatcher *self; + RunContext *ctx; + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + mm_obj_warn (self, "forcing exit on %s FCC unlock operation", ctx->filename); + g_subprocess_force_exit (ctx->subprocess); + + ctx->timeout_id = 0; + return G_SOURCE_REMOVE; +} + +static void +subprocess_wait_ready (GSubprocess *subprocess, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + RunContext *ctx; + + /* cleanup timeout before any return */ + ctx = g_task_get_task_data (task); + if (ctx->timeout_id) { + g_source_remove (ctx->timeout_id); + ctx->timeout_id = 0; + } + + if (!g_subprocess_wait_finish (subprocess, res, &error)) { + g_prefix_error (&error, "FCC unlock operation wait failed: "); + g_task_return_error (task, error); + } else if (!g_subprocess_get_successful (subprocess)) { + if (g_subprocess_get_if_signaled (subprocess)) + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "FCC unlock operation aborted with signal %d", + g_subprocess_get_term_sig (subprocess)); + else if (g_subprocess_get_if_exited (subprocess)) + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "FCC unlock operation finished with status %d", + g_subprocess_get_exit_status (subprocess)); + else + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "FCC unlock operation failed"); + } else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static gboolean +validate_file (const gchar *path, + GError **error) +{ + g_autoptr(GFile) file = NULL; + g_autoptr(GFileInfo) file_info = NULL; + guint32 file_mode; + guint32 file_uid; + + file = g_file_new_for_path (path); + file_info = g_file_query_info (file, + (G_FILE_ATTRIBUTE_STANDARD_SIZE "," + G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET "," + G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "," + G_FILE_ATTRIBUTE_UNIX_MODE "," + G_FILE_ATTRIBUTE_UNIX_UID), + G_FILE_QUERY_INFO_NONE, + NULL, + error); + if (!file_info) + return FALSE; + + if (g_file_info_get_is_symlink (file_info)) { + const gchar *link_target; + + link_target = g_file_info_get_symlink_target (file_info); + if (g_strcmp0 (link_target, "/dev/null") == 0) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_ABORTED, + "Link '%s' to /dev/null is not executable", path); + return FALSE; + } + } + + if (g_file_info_get_size (file_info) == 0) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_ABORTED, + "File '%s' is empty", path); + return FALSE; + } + + file_uid = g_file_info_get_attribute_uint32 (file_info, G_FILE_ATTRIBUTE_UNIX_UID); + if (file_uid != 0) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_ABORTED, + "File '%s' not owned by root", path); + return FALSE; + } + + file_mode = g_file_info_get_attribute_uint32 (file_info, G_FILE_ATTRIBUTE_UNIX_MODE); + if (!S_ISREG (file_mode)) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_ABORTED, + "File '%s' is not regular", path); + return FALSE; + } + if (file_mode & (S_IWGRP | S_IWOTH)) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_ABORTED, + "File '%s' is writable by group or other", path); + return FALSE; + } + if (file_mode & S_ISUID) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_ABORTED, + "File '%s' is set-UID", path); + return FALSE; + } + if (!(file_mode & S_IXUSR)) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_ABORTED, + "File '%s' is not executable by the owner", path); + return FALSE; + } + + return TRUE; +} + +void +mm_fcc_unlock_dispatcher_run (MMFccUnlockDispatcher *self, + guint vid, + guint pid, + const gchar *modem_dbus_path, + const GStrv modem_ports, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + RunContext *ctx; + guint i; + const gchar *enabled_dirs[] = { + FCCUNLOCKDIRUSER, /* sysconfdir */ + FCCUNLOCKDIRPACKAGE, /* libdir */ + }; + + task = g_task_new (self, cancellable, callback, user_data); + ctx = g_slice_new0 (RunContext); + g_task_set_task_data (task, ctx, (GDestroyNotify) run_context_free); + + ctx->filename = g_strdup_printf ("%04x:%04x", vid, pid); + + for (i = 0; i < G_N_ELEMENTS (enabled_dirs); i++) { + GPtrArray *aux; + g_auto(GStrv) argv = NULL; + g_autofree gchar *path = NULL; + g_autoptr(GError) error = NULL; + guint j; + + path = g_build_path (G_DIR_SEPARATOR_S, enabled_dirs[i], ctx->filename, NULL); + + /* Validation checks to see if we should run it or not */ + if (!validate_file (path, &error)) { + mm_obj_dbg (self, "Cannot run FCC unlock operation from %s: %s", + path, error->message); + continue; + } + + /* build argv */ + aux = g_ptr_array_new (); + g_ptr_array_add (aux, g_steal_pointer (&path)); + g_ptr_array_add (aux, g_strdup (modem_dbus_path)); + for (j = 0; modem_ports && modem_ports[j]; j++) + g_ptr_array_add (aux, g_strdup (modem_ports[j])); + g_ptr_array_add (aux, NULL); + argv = (GStrv) g_ptr_array_free (aux, FALSE); + + /* create and launch subprocess */ + ctx->subprocess = g_subprocess_launcher_spawnv (self->launcher, + (const gchar * const *)argv, + &error); + if (!ctx->subprocess) { + g_prefix_error (&error, "FCC unlock operation launch from %s failed: ", path); + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + /* setup timeout */ + ctx->timeout_id = g_timeout_add_seconds (MAX_FCC_UNLOCK_EXEC_TIME_SECS, + (GSourceFunc)subprocess_wait_timed_out, + task); + + /* wait for subprocess exit */ + g_subprocess_wait_async (ctx->subprocess, + cancellable, + (GAsyncReadyCallback)subprocess_wait_ready, + task); + return; + } + + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "FCC unlock operation launch aborted: no valid program found"); + g_object_unref (task); +} + +/*****************************************************************************/ + +static void +mm_fcc_unlock_dispatcher_init (MMFccUnlockDispatcher *self) +{ + self->launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_SILENCE | G_SUBPROCESS_FLAGS_STDERR_SILENCE); + + /* inherit parent's environment */ + g_subprocess_launcher_set_environ (self->launcher, NULL); +} + +static void +dispose (GObject *object) +{ + MMFccUnlockDispatcher *self = MM_FCC_UNLOCK_DISPATCHER (object); + + g_clear_object (&self->launcher); + + G_OBJECT_CLASS (mm_fcc_unlock_dispatcher_parent_class)->dispose (object); +} + +static void +log_object_iface_init (MMLogObjectInterface *iface) +{ + iface->build_id = log_object_build_id; +} + +static void +mm_fcc_unlock_dispatcher_class_init (MMFccUnlockDispatcherClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->dispose = dispose; +} + +MM_DEFINE_SINGLETON_GETTER (MMFccUnlockDispatcher, mm_fcc_unlock_dispatcher_get, MM_TYPE_FCC_UNLOCK_DISPATCHER) diff --git a/src/mm-fcc-unlock-dispatcher.h b/src/mm-fcc-unlock-dispatcher.h new file mode 100644 index 00000000..53a1b4c0 --- /dev/null +++ b/src/mm-fcc-unlock-dispatcher.h @@ -0,0 +1,47 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2021 Aleksander Morgado <aleksander@aleksander.es> + */ + +#ifndef MM_FCC_UNLOCK_DISPATCHER_H +#define MM_FCC_UNLOCK_DISPATCHER_H + +#include <config.h> +#include <gio/gio.h> + +#define MM_TYPE_FCC_UNLOCK_DISPATCHER (mm_fcc_unlock_dispatcher_get_type ()) +#define MM_FCC_UNLOCK_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_FCC_UNLOCK_DISPATCHER, MMFccUnlockDispatcher)) +#define MM_FCC_UNLOCK_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_FCC_UNLOCK_DISPATCHER, MMFccUnlockDispatcherClass)) +#define MM_IS_FCC_UNLOCK_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_FCC_UNLOCK_DISPATCHER)) +#define MM_IS_FCC_UNLOCK_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_FCC_UNLOCK_DISPATCHER)) +#define MM_FCC_UNLOCK_DISPATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_FCC_UNLOCK_DISPATCHER, MMFccUnlockDispatcherClass)) + +typedef struct _MMFccUnlockDispatcher MMFccUnlockDispatcher; +typedef struct _MMFccUnlockDispatcherClass MMFccUnlockDispatcherClass; +typedef struct _MMFccUnlockDispatcherPrivate MMFccUnlockDispatcherPrivate; + +GType mm_fcc_unlock_dispatcher_get_type (void); +MMFccUnlockDispatcher *mm_fcc_unlock_dispatcher_get (void); +void mm_fcc_unlock_dispatcher_run (MMFccUnlockDispatcher *self, + guint vid, + guint pid, + const gchar *modem_dbus_path, + const GStrv ports, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_fcc_unlock_dispatcher_run_finish (MMFccUnlockDispatcher *self, + GAsyncResult *res, + GError **error); + +#endif /* MM_FCC_UNLOCK_DISPATCHER_H */ diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c index 3806661c..7712f602 100644 --- a/src/mm-iface-modem.c +++ b/src/mm-iface-modem.c @@ -28,6 +28,7 @@ #include "mm-private-boxed-types.h" #include "mm-log-object.h" #include "mm-context.h" +#include "mm-fcc-unlock-dispatcher.h" #if defined WITH_QMI # include "mm-broadband-modem-qmi.h" #endif @@ -3844,15 +3845,18 @@ modem_after_power_up_ready (MMIfaceModem *self, } static void -fcc_unlock_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) +fcc_unlock_dispatcher_ready (MMFccUnlockDispatcher *dispatcher, + GAsyncResult *res, + GTask *task) { + MMIfaceModem *self; SetPowerStateContext *ctx; g_autoptr(GError) error = NULL; + self = g_task_get_source_object (task); ctx = g_task_get_task_data (task); - if (!MM_IFACE_MODEM_GET_INTERFACE (self)->fcc_unlock_finish (self, res, &error)) + + if (!mm_fcc_unlock_dispatcher_run_finish (dispatcher, res, &error)) mm_obj_dbg (self, "couldn't run FCC unlock: %s", error->message); /* always retry, even on reported error */ @@ -3861,6 +3865,54 @@ fcc_unlock_ready (MMIfaceModem *self, } static void +fcc_unlock (GTask *task) +{ + MMIfaceModem *self; + MMFccUnlockDispatcher *dispatcher; + MMModemPortInfo *port_infos; + guint n_port_infos = 0; + guint i; + GPtrArray *aux; + g_auto(GStrv) modem_ports = NULL; + + self = g_task_get_source_object (task); + + dispatcher = mm_fcc_unlock_dispatcher_get (); + + aux = g_ptr_array_new (); + port_infos = mm_base_modem_get_port_infos (MM_BASE_MODEM (self), &n_port_infos); + for (i = 0; i < n_port_infos; i++) { + switch (port_infos[i].type) { + case MM_MODEM_PORT_TYPE_AT: + case MM_MODEM_PORT_TYPE_QMI: + case MM_MODEM_PORT_TYPE_MBIM: + g_ptr_array_add (aux, g_strdup (port_infos[i].name)); + break; + case MM_MODEM_PORT_TYPE_UNKNOWN: + case MM_MODEM_PORT_TYPE_NET: + case MM_MODEM_PORT_TYPE_QCDM: + case MM_MODEM_PORT_TYPE_GPS: + case MM_MODEM_PORT_TYPE_AUDIO: + case MM_MODEM_PORT_TYPE_IGNORED: + default: + break; + } + } + mm_modem_port_info_array_free (port_infos, n_port_infos); + g_ptr_array_add (aux, NULL); + modem_ports = (GStrv) g_ptr_array_free (aux, FALSE); + + mm_fcc_unlock_dispatcher_run (dispatcher, + mm_base_modem_get_vendor_id (MM_BASE_MODEM (self)), + mm_base_modem_get_product_id (MM_BASE_MODEM (self)), + g_dbus_object_get_object_path (G_DBUS_OBJECT (self)), + modem_ports, + g_task_get_cancellable (task), + (GAsyncReadyCallback)fcc_unlock_dispatcher_ready, + task); +} + +static void requested_power_setup_ready (MMIfaceModem *self, GAsyncResult *res, GTask *task) @@ -3959,13 +4011,11 @@ set_power_state_step (GTask *task) if ((ctx->requested_power_state == MM_MODEM_POWER_STATE_ON) && ctx->saved_error && g_error_matches (ctx->saved_error, MM_CORE_ERROR, MM_CORE_ERROR_RETRY) && - !ctx->fcc_unlock_attempted && - MM_IFACE_MODEM_GET_INTERFACE (self)->fcc_unlock && - MM_IFACE_MODEM_GET_INTERFACE (self)->fcc_unlock_finish) { + !ctx->fcc_unlock_attempted) { mm_obj_dbg (self, "attempting fcc unlock..."); - ctx->fcc_unlock_attempted = TRUE; g_clear_error (&ctx->saved_error); - MM_IFACE_MODEM_GET_INTERFACE (self)->fcc_unlock (self, (GAsyncReadyCallback)fcc_unlock_ready, task); + ctx->fcc_unlock_attempted = TRUE; + fcc_unlock (task); return; } ctx->step++; diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h index 34f3297b..2abadf27 100644 --- a/src/mm-iface-modem.h +++ b/src/mm-iface-modem.h @@ -270,14 +270,6 @@ struct _MMIfaceModem { GAsyncResult *res, GError **error); - /* Asynchronous FCC unlock operation */ - void (* fcc_unlock) (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); - gboolean (* fcc_unlock_finish) (MMIfaceModem *self, - GAsyncResult *res, - GError **error); - /* Asynchronous modem power-up operation */ void (*modem_power_up) (MMIfaceModem *self, GAsyncReadyCallback callback, diff --git a/src/mm-shared-qmi.c b/src/mm-shared-qmi.c index f6b2a44d..c9a90812 100644 --- a/src/mm-shared-qmi.c +++ b/src/mm-shared-qmi.c @@ -4221,56 +4221,6 @@ mm_shared_qmi_setup_sim_hot_swap (MMIfaceModem *self, } /*****************************************************************************/ -/* FCC unlock (Modem interface) */ - -gboolean -mm_shared_qmi_fcc_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -dms_set_fcc_authentication_ready (QmiClientDms *client, - GAsyncResult *res, - GTask *task) -{ - GError *error = NULL; - g_autoptr(QmiMessageDmsSetFccAuthenticationOutput) output = NULL; - - output = qmi_client_dms_set_fcc_authentication_finish (client, res, &error); - if (!output || !qmi_message_dms_set_fcc_authentication_output_get_result (output, &error)) - g_task_return_error (task, error); - else - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -void -mm_shared_qmi_fcc_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - QmiClient *client = NULL; - - if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self), - QMI_SERVICE_DMS, &client, - callback, user_data)) - return; - - task = g_task_new (self, NULL, callback, user_data); - - qmi_client_dms_set_fcc_authentication (QMI_CLIENT_DMS (client), - NULL, - 5, - NULL, - (GAsyncReadyCallback)dms_set_fcc_authentication_ready, - task); -} - -/*****************************************************************************/ /* Location: Set SUPL server */ typedef struct { diff --git a/src/mm-shared-qmi.h b/src/mm-shared-qmi.h index 5ffa85c0..7c24c472 100644 --- a/src/mm-shared-qmi.h +++ b/src/mm-shared-qmi.h @@ -191,12 +191,6 @@ void mm_shared_qmi_setup_sim_hot_swap (MMIfaceMode gboolean mm_shared_qmi_setup_sim_hot_swap_finish (MMIfaceModem *self, GAsyncResult *res, GError **error); -void mm_shared_qmi_fcc_unlock (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_qmi_fcc_unlock_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); /* Shared QMI location support */ |