diff options
Diffstat (limited to 'plugins/quectel/mm-shared-quectel.c')
-rw-r--r-- | plugins/quectel/mm-shared-quectel.c | 89 |
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) |