aboutsummaryrefslogtreecommitdiff
path: root/plugins/quectel/mm-shared-quectel.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/quectel/mm-shared-quectel.c')
-rw-r--r--plugins/quectel/mm-shared-quectel.c89
1 files changed, 89 insertions, 0 deletions
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)