diff options
-rw-r--r-- | plugins/quectel/mm-broadband-modem-qmi-quectel.c | 9 | ||||
-rw-r--r-- | plugins/quectel/mm-broadband-modem-quectel.c | 9 | ||||
-rw-r--r-- | plugins/quectel/mm-shared-quectel.c | 89 | ||||
-rw-r--r-- | plugins/quectel/mm-shared-quectel.h | 6 |
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 */ |