aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/meson.build3
-rw-r--r--src/mm-broadband-modem-mbim.c2
-rw-r--r--src/mm-broadband-modem-qmi.c2
-rw-r--r--src/mm-fcc-unlock-dispatcher.c319
-rw-r--r--src/mm-fcc-unlock-dispatcher.h47
-rw-r--r--src/mm-iface-modem.c68
-rw-r--r--src/mm-iface-modem.h8
-rw-r--r--src/mm-shared-qmi.c50
-rw-r--r--src/mm-shared-qmi.h6
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 */