aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/quectel/mm-broadband-modem-qmi-quectel.c9
-rw-r--r--plugins/quectel/mm-broadband-modem-quectel.c9
-rw-r--r--plugins/quectel/mm-shared-quectel.c89
-rw-r--r--plugins/quectel/mm-shared-quectel.h6
4 files changed, 113 insertions, 0 deletions
diff --git a/plugins/quectel/mm-broadband-modem-qmi-quectel.c b/plugins/quectel/mm-broadband-modem-qmi-quectel.c
index 14adf984..96eda0e5 100644
--- a/plugins/quectel/mm-broadband-modem-qmi-quectel.c
+++ b/plugins/quectel/mm-broadband-modem-qmi-quectel.c
@@ -19,10 +19,12 @@
#include "mm-shared-quectel.h"
#include "mm-iface-modem-firmware.h"
+static void iface_modem_init (MMIfaceModem *iface);
static void shared_quectel_init (MMSharedQuectel *iface);
static void iface_modem_firmware_init (MMIfaceModemFirmware *iface);
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmiQuectel, mm_broadband_modem_qmi_quectel, MM_TYPE_BROADBAND_MODEM_QMI, 0,
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QUECTEL, shared_quectel_init))
@@ -50,6 +52,13 @@ mm_broadband_modem_qmi_quectel_init (MMBroadbandModemQmiQuectel *self)
}
static void
+iface_modem_init (MMIfaceModem *iface)
+{
+ iface->setup_sim_hot_swap = mm_shared_quectel_setup_sim_hot_swap;
+ iface->setup_sim_hot_swap_finish = mm_shared_quectel_setup_sim_hot_swap_finish;
+}
+
+static void
iface_modem_firmware_init (MMIfaceModemFirmware *iface)
{
iface->load_update_settings = mm_shared_quectel_firmware_load_update_settings;
diff --git a/plugins/quectel/mm-broadband-modem-quectel.c b/plugins/quectel/mm-broadband-modem-quectel.c
index 6a43a87d..6dfa5bb7 100644
--- a/plugins/quectel/mm-broadband-modem-quectel.c
+++ b/plugins/quectel/mm-broadband-modem-quectel.c
@@ -19,10 +19,12 @@
#include "mm-shared-quectel.h"
#include "mm-iface-modem-firmware.h"
+static void iface_modem_init (MMIfaceModem *iface);
static void shared_quectel_init (MMSharedQuectel *iface);
static void iface_modem_firmware_init (MMIfaceModemFirmware *iface);
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQuectel, mm_broadband_modem_quectel, MM_TYPE_BROADBAND_MODEM, 0,
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QUECTEL, shared_quectel_init))
@@ -57,6 +59,13 @@ mm_broadband_modem_quectel_init (MMBroadbandModemQuectel *self)
}
static void
+iface_modem_init (MMIfaceModem *iface)
+{
+ iface->setup_sim_hot_swap = mm_shared_quectel_setup_sim_hot_swap;
+ iface->setup_sim_hot_swap_finish = mm_shared_quectel_setup_sim_hot_swap_finish;
+}
+
+static void
shared_quectel_init (MMSharedQuectel *iface)
{
}
diff --git a/plugins/quectel/mm-shared-quectel.c b/plugins/quectel/mm-shared-quectel.c
index f451026b..76107e79 100644
--- a/plugins/quectel/mm-shared-quectel.c
+++ b/plugins/quectel/mm-shared-quectel.c
@@ -21,6 +21,7 @@
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
+#include "mm-log-object.h"
#include "mm-iface-modem-firmware.h"
#include "mm-base-modem.h"
#include "mm-base-modem-at.h"
@@ -72,6 +73,94 @@ mm_shared_quectel_firmware_load_update_settings (MMIfaceModemFirmware *self,
}
/*****************************************************************************/
+/* "+QUSIM: 1" URC is emitted by Quectel modems after the USIM has been
+ * (re)initialized. We register a handler for this URC and perform a check
+ * for SIM swap when it is encountered. The motivation for this is to detect
+ * M2M eUICC profile switches. According to SGP.02 chapter 3.2.1, the eUICC
+ * shall trigger a REFRESH operation with eUICC reset when a new profile is
+ * enabled. The +QUSIM URC appears after the eUICC has restarted and can act
+ * as a trigger for profile switch check. This should basically be handled
+ * the same as a physical SIM swap, so the existing SIM hot swap mechanism
+ * is used.
+ */
+
+static void
+quectel_qusim_check_for_sim_swap_ready (MMIfaceModem *self,
+ GAsyncResult *res)
+{
+ GError *error = NULL;
+
+ if (!MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish (self, res, &error)) {
+ mm_obj_warn (self, "couldn't check SIM swap: %s", error->message);
+ g_error_free (error);
+ } else
+ mm_obj_dbg (self, "check SIM swap completed");
+}
+
+static void
+quectel_qusim_unsolicited_handler (MMPortSerialAt *port,
+ GMatchInfo *match_info,
+ MMIfaceModem* self)
+{
+ if (MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap &&
+ MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap_finish) {
+ mm_obj_dbg (self, "checking SIM swap");
+ MM_IFACE_MODEM_GET_INTERFACE (self)->check_for_sim_swap (
+ self,
+ (GAsyncReadyCallback)quectel_qusim_check_for_sim_swap_ready,
+ NULL);
+ }
+}
+
+gboolean
+mm_shared_quectel_setup_sim_hot_swap_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+void
+mm_shared_quectel_setup_sim_hot_swap (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMPortSerialAt *port_primary;
+ MMPortSerialAt *port_secondary;
+ GTask *task;
+ GRegex *pattern;
+
+ task = g_task_new (self, NULL, callback, user_data);
+
+ port_primary = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
+ port_secondary = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
+
+ pattern = g_regex_new ("\\+QUSIM:\\s*1\\r\\n", G_REGEX_RAW, 0, NULL);
+ g_assert (pattern);
+
+ if (port_primary)
+ mm_port_serial_at_add_unsolicited_msg_handler (
+ port_primary,
+ pattern,
+ (MMPortSerialAtUnsolicitedMsgFn)quectel_qusim_unsolicited_handler,
+ self,
+ NULL);
+
+ if (port_secondary)
+ mm_port_serial_at_add_unsolicited_msg_handler (
+ port_secondary,
+ pattern,
+ (MMPortSerialAtUnsolicitedMsgFn)quectel_qusim_unsolicited_handler,
+ self,
+ NULL);
+
+ g_regex_unref (pattern);
+ mm_obj_dbg (self, "+QUSIM detection set up");
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+/*****************************************************************************/
static void
shared_quectel_init (gpointer g_iface)
diff --git a/plugins/quectel/mm-shared-quectel.h b/plugins/quectel/mm-shared-quectel.h
index 4ebcfd61..22ee8bee 100644
--- a/plugins/quectel/mm-shared-quectel.h
+++ b/plugins/quectel/mm-shared-quectel.h
@@ -45,5 +45,11 @@ void mm_shared_quectel_firmware_load_update_settings
MMFirmwareUpdateSettings *mm_shared_quectel_firmware_load_update_settings_finish (MMIfaceModemFirmware *self,
GAsyncResult *res,
GError **error);
+void mm_shared_quectel_setup_sim_hot_swap (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mm_shared_quectel_setup_sim_hot_swap_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
#endif /* MM_SHARED_QUECTEL_H */