diff options
-rw-r--r-- | plugins/quectel/mm-broadband-modem-qmi-quectel.c | 14 | ||||
-rw-r--r-- | plugins/quectel/mm-broadband-modem-quectel.c | 14 | ||||
-rw-r--r-- | plugins/quectel/mm-shared-quectel.c | 40 | ||||
-rw-r--r-- | plugins/quectel/mm-shared-quectel.h | 3 | ||||
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 136 | ||||
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 2 | ||||
-rw-r--r-- | src/mm-shared-qmi.c | 455 | ||||
-rw-r--r-- | src/mm-shared-qmi.h | 6 |
8 files changed, 50 insertions, 620 deletions
diff --git a/plugins/quectel/mm-broadband-modem-qmi-quectel.c b/plugins/quectel/mm-broadband-modem-qmi-quectel.c index 9548c46c..067b4601 100644 --- a/plugins/quectel/mm-broadband-modem-qmi-quectel.c +++ b/plugins/quectel/mm-broadband-modem-qmi-quectel.c @@ -27,7 +27,6 @@ static void iface_modem_location_init (MMIfaceModemLocation *iface); static void iface_modem_time_init (MMIfaceModemTime *iface); static void shared_quectel_init (MMSharedQuectel *iface); -static MMIfaceModem *iface_modem_parent; static MMIfaceModemLocation *iface_modem_location_parent; G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmiQuectel, mm_broadband_modem_qmi_quectel, MM_TYPE_BROADBAND_MODEM_QMI, 0, @@ -63,18 +62,10 @@ mm_broadband_modem_qmi_quectel_init (MMBroadbandModemQmiQuectel *self) static void iface_modem_init (MMIfaceModem *iface) { - iface_modem_parent = g_type_interface_peek_parent (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 MMIfaceModem * -peek_parent_modem_interface (MMSharedQuectel *self) -{ - return iface_modem_parent; -} - static void iface_modem_firmware_init (MMIfaceModemFirmware *iface) { @@ -96,7 +87,7 @@ iface_modem_location_init (MMIfaceModemLocation *iface) } static MMIfaceModemLocation * -peek_parent_modem_location_interface (MMSharedQuectel *self) +peek_parent_location_interface (MMSharedQuectel *self) { return iface_modem_location_parent; } @@ -111,8 +102,7 @@ iface_modem_time_init (MMIfaceModemTime *iface) static void shared_quectel_init (MMSharedQuectel *iface) { - iface->peek_parent_modem_interface = peek_parent_modem_interface; - iface->peek_parent_modem_location_interface = peek_parent_modem_location_interface; + iface->peek_parent_location_interface = peek_parent_location_interface; } static void diff --git a/plugins/quectel/mm-broadband-modem-quectel.c b/plugins/quectel/mm-broadband-modem-quectel.c index ae2b7234..f6b6e176 100644 --- a/plugins/quectel/mm-broadband-modem-quectel.c +++ b/plugins/quectel/mm-broadband-modem-quectel.c @@ -27,7 +27,6 @@ static void iface_modem_location_init (MMIfaceModemLocation *iface); static void iface_modem_time_init (MMIfaceModemTime *iface); static void shared_quectel_init (MMSharedQuectel *iface); -static MMIfaceModem *iface_modem_parent; static MMIfaceModemLocation *iface_modem_location_parent; G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQuectel, mm_broadband_modem_quectel, MM_TYPE_BROADBAND_MODEM, 0, @@ -63,18 +62,10 @@ mm_broadband_modem_quectel_init (MMBroadbandModemQuectel *self) static void iface_modem_init (MMIfaceModem *iface) { - iface_modem_parent = g_type_interface_peek_parent (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 MMIfaceModem * -peek_parent_modem_interface (MMSharedQuectel *self) -{ - return iface_modem_parent; -} - static void iface_modem_firmware_init (MMIfaceModemFirmware *iface) { @@ -96,7 +87,7 @@ iface_modem_location_init (MMIfaceModemLocation *iface) } static MMIfaceModemLocation * -peek_parent_modem_location_interface (MMSharedQuectel *self) +peek_parent_location_interface (MMSharedQuectel *self) { return iface_modem_location_parent; } @@ -111,8 +102,7 @@ iface_modem_time_init (MMIfaceModemTime *iface) static void shared_quectel_init (MMSharedQuectel *iface) { - iface->peek_parent_modem_interface = peek_parent_modem_interface; - iface->peek_parent_modem_location_interface = peek_parent_modem_location_interface; + iface->peek_parent_location_interface = peek_parent_location_interface; } static void diff --git a/plugins/quectel/mm-shared-quectel.c b/plugins/quectel/mm-shared-quectel.c index 0274fbe1..4d8423ae 100644 --- a/plugins/quectel/mm-shared-quectel.c +++ b/plugins/quectel/mm-shared-quectel.c @@ -43,7 +43,6 @@ typedef enum { } FeatureSupport; typedef struct { - MMIfaceModem *iface_modem_parent; MMIfaceModemLocation *iface_modem_location_parent; MMModemLocationSource provided_sources; MMModemLocationSource enabled_sources; @@ -66,11 +65,8 @@ get_private (MMSharedQuectel *self) priv->enabled_sources = MM_MODEM_LOCATION_SOURCE_NONE; priv->qgps_supported = FEATURE_SUPPORT_UNKNOWN; - g_assert (MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_modem_location_interface); - priv->iface_modem_location_parent = MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_modem_location_interface (self); - - g_assert (MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_modem_interface); - priv->iface_modem_parent = MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_modem_interface (self); + g_assert (MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_location_interface); + priv->iface_modem_location_parent = MM_SHARED_QUECTEL_GET_INTERFACE (self)->peek_parent_location_interface (self); g_object_set_qdata (G_OBJECT (self), private_quark, priv); } @@ -174,37 +170,16 @@ mm_shared_quectel_setup_sim_hot_swap_finish (MMIfaceModem *self, return g_task_propagate_boolean (G_TASK (res), error); } -static void -parent_setup_sim_hot_swap_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - Private *priv; - g_autoptr(GError) error = NULL; - - priv = get_private (MM_SHARED_QUECTEL (self)); - - if (!priv->iface_modem_parent->setup_sim_hot_swap_finish (self, res, &error)) - mm_obj_dbg (self, "additional SIM hot swap detection setup failed: %s", error->message); - - /* The +QUSIM based setup never fails, so we can safely return success here */ - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - void mm_shared_quectel_setup_sim_hot_swap (MMIfaceModem *self, GAsyncReadyCallback callback, gpointer user_data) { - Private *priv; MMPortSerialAt *ports[2]; GTask *task; GRegex *pattern; guint i; - priv = get_private (MM_SHARED_QUECTEL (self)); - task = g_task_new (self, NULL, callback, user_data); ports[0] = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)); @@ -225,17 +200,6 @@ mm_shared_quectel_setup_sim_hot_swap (MMIfaceModem *self, g_regex_unref (pattern); mm_obj_dbg (self, "+QUSIM detection set up"); - - /* Now, if available, setup parent logic */ - if (priv->iface_modem_parent->setup_sim_hot_swap && - priv->iface_modem_parent->setup_sim_hot_swap_finish) { - priv->iface_modem_parent->setup_sim_hot_swap (self, - (GAsyncReadyCallback) parent_setup_sim_hot_swap_ready, - task); - return; - } - - /* Otherwise, we're done */ g_task_return_boolean (task, TRUE); g_object_unref (task); } diff --git a/plugins/quectel/mm-shared-quectel.h b/plugins/quectel/mm-shared-quectel.h index 1a49c29b..88023b3b 100644 --- a/plugins/quectel/mm-shared-quectel.h +++ b/plugins/quectel/mm-shared-quectel.h @@ -37,8 +37,7 @@ typedef struct _MMSharedQuectel MMSharedQuectel; struct _MMSharedQuectel { GTypeInterface g_iface; - MMIfaceModem * (* peek_parent_modem_interface) (MMSharedQuectel *self); - MMIfaceModemLocation * (* peek_parent_modem_location_interface) (MMSharedQuectel *self); + MMIfaceModemLocation * (* peek_parent_location_interface) (MMSharedQuectel *self); }; GType mm_shared_quectel_get_type (void); diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c index e0a34573..7633cece 100644 --- a/src/mm-broadband-modem-mbim.c +++ b/src/mm-broadband-modem-mbim.c @@ -3554,9 +3554,16 @@ cleanup_unsolicited_events_3gpp (MMIfaceModem3gpp *_self, gpointer user_data) { MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + gboolean is_sim_hot_swap_configured = FALSE; + + g_object_get (self, + MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED, &is_sim_hot_swap_configured, + NULL); self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_SIGNAL_QUALITY; self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_CONNECT; + if (is_sim_hot_swap_configured) + self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO; self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_PACKET_SERVICE; if (self->priv->is_pco_supported) self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_PCO; @@ -3784,124 +3791,67 @@ modem_3gpp_enable_unsolicited_registration_events (MMIfaceModem3gpp *_self, /*****************************************************************************/ /* Setup SIM hot swap */ -typedef struct { - MbimDevice *device; - GError *subscriber_info_error; -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - GError *qmi_error; -#endif -} SetupSimHotSwapContext; - -static void -setup_sim_hot_swap_context_free (SetupSimHotSwapContext *ctx) -{ -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - g_clear_error (&ctx->qmi_error); -#endif - g_clear_error (&ctx->subscriber_info_error); - g_clear_object (&ctx->device); - g_slice_free (SetupSimHotSwapContext, ctx); -} - static gboolean -modem_setup_sim_hot_swap_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) +modem_setup_sim_hot_swap_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) { return g_task_propagate_boolean (G_TASK (res), error); } static void -sim_hot_swap_complete (GTask *task) +enable_subscriber_info_unsolicited_events_ready (MMBroadbandModemMbim *self, + GAsyncResult *res, + GTask *task) { - SetupSimHotSwapContext *ctx; + GError *error = NULL; - ctx = g_task_get_task_data (task); + if (!common_enable_disable_unsolicited_events_finish (self, res, &error)) { + mm_obj_dbg (self, "failed to enable subscriber info events: %s", error->message); + g_task_return_error (task, error); + g_object_unref (task); + return; + } - /* If MBIM based logic worked, success */ - if (!ctx->subscriber_info_error) - g_task_return_boolean (task, TRUE); -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - /* Otherwise, If QMI-over-MBIM based logic worked, success */ - else if (!ctx->qmi_error) - g_task_return_boolean (task, TRUE); -#endif - /* Otherwise, prefer MBIM specific error */ - else - g_task_return_error (task, g_steal_pointer (&ctx->subscriber_info_error)); + g_task_return_boolean (task, TRUE); g_object_unref (task); } -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - -static void -qmi_setup_sim_hot_swap_ready (MMIfaceModem *self, - GAsyncResult *res, - GTask *task) -{ - SetupSimHotSwapContext *ctx; - - ctx = g_task_get_task_data (task); - if (!mm_shared_qmi_setup_sim_hot_swap_finish (self, res, &ctx->qmi_error)) - mm_obj_dbg (self, "couldn't setup SIM hot swap using QMI over MBIM: %s", ctx->qmi_error->message); - - sim_hot_swap_complete (task); -} - -#endif - static void -enable_subscriber_info_unsolicited_events_ready (MMBroadbandModemMbim *self, - GAsyncResult *res, - GTask *task) +setup_subscriber_info_unsolicited_events_ready (MMBroadbandModemMbim *self, + GAsyncResult *res, + GTask *task) { - SetupSimHotSwapContext *ctx; - - ctx = g_task_get_task_data (task); + GError *error = NULL; - if (!common_enable_disable_unsolicited_events_finish (self, res, &ctx->subscriber_info_error)) { - mm_obj_dbg (self, "failed to enable subscriber info events: %s", ctx->subscriber_info_error->message); - /* reset setup flags if enabling failed */ - self->priv->setup_flags &= ~PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO; - common_setup_cleanup_unsolicited_events_sync (self, ctx->device, FALSE); + if (!common_setup_cleanup_unsolicited_events_finish (self, res, &error)) { + mm_obj_dbg (self, "failed to set up subscriber info events: %s", error->message); + g_task_return_error (task, error); + g_object_unref (task); + return; } -#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED - mm_shared_qmi_setup_sim_hot_swap (MM_IFACE_MODEM (self), - (GAsyncReadyCallback)qmi_setup_sim_hot_swap_ready, - task); -#else - sim_hot_swap_complete (task); -#endif + self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO; + common_enable_disable_unsolicited_events (self, + (GAsyncReadyCallback)enable_subscriber_info_unsolicited_events_ready, + task); } static void -modem_setup_sim_hot_swap (MMIfaceModem *_self, - GAsyncReadyCallback callback, - gpointer user_data) +modem_setup_sim_hot_swap (MMIfaceModem *_self, + GAsyncReadyCallback callback, + gpointer user_data) { - MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); - MbimDevice *device; - GTask *task; - SetupSimHotSwapContext *ctx; - - if (!peek_device (self, &device, callback, user_data)) - return; + MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self); + GTask *task; task = g_task_new (self, NULL, callback, user_data); - ctx = g_slice_new0 (SetupSimHotSwapContext); - ctx->device = g_object_ref (device); - g_task_set_task_data (task, ctx, (GDestroyNotify)setup_sim_hot_swap_context_free); - /* Setup flags synchronously, which never fails */ self->priv->setup_flags |= PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO; - common_setup_cleanup_unsolicited_events_sync (self, ctx->device, TRUE); - - /* Enable flags asynchronously, which may fail */ - self->priv->enable_flags |= PROCESS_NOTIFICATION_FLAG_SUBSCRIBER_INFO; - common_enable_disable_unsolicited_events (self, - (GAsyncReadyCallback)enable_subscriber_info_unsolicited_events_ready, - task); + common_setup_cleanup_unsolicited_events (self, + TRUE, + (GAsyncReadyCallback)setup_subscriber_info_unsolicited_events_ready, + task); } /*****************************************************************************/ diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index 5aa909b6..5bc3327c 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -9277,8 +9277,6 @@ iface_modem_init (MMIfaceModem *iface) iface->load_sim_slots_finish = mm_shared_qmi_load_sim_slots_finish; iface->set_primary_sim_slot = mm_shared_qmi_set_primary_sim_slot; iface->set_primary_sim_slot_finish = mm_shared_qmi_set_primary_sim_slot_finish; - iface->setup_sim_hot_swap = mm_shared_qmi_setup_sim_hot_swap; - iface->setup_sim_hot_swap_finish = mm_shared_qmi_setup_sim_hot_swap_finish; /* Create QMI-specific bearer */ iface->create_bearer = modem_create_bearer; diff --git a/src/mm-shared-qmi.c b/src/mm-shared-qmi.c index bea47a39..5ae54349 100644 --- a/src/mm-shared-qmi.c +++ b/src/mm-shared-qmi.c @@ -92,12 +92,6 @@ typedef struct { gboolean config_active_default; GArray *config_list; gint config_active_i; - - /* Slot status monitoring */ - QmiClient *uim_client; - gulong uim_slot_status_indication_id; - gulong uim_refresh_indication_id; - guint uim_refresh_start_timeout_id; } Private; static void @@ -117,14 +111,6 @@ private_free (Private *priv) g_signal_handler_disconnect (priv->loc_client, priv->loc_location_nmea_indication_id); if (priv->loc_client) g_object_unref (priv->loc_client); - if (priv->uim_slot_status_indication_id) - g_signal_handler_disconnect (priv->uim_client, priv->uim_slot_status_indication_id); - if (priv->uim_refresh_indication_id) - g_signal_handler_disconnect (priv->uim_client, priv->uim_refresh_indication_id); - if (priv->uim_client) - g_object_unref (priv->uim_client); - if (priv->uim_refresh_start_timeout_id) - g_source_remove (priv->uim_refresh_start_timeout_id); g_strfreev (priv->loc_assistance_data_servers); g_slice_free (Private, priv); } @@ -3616,447 +3602,6 @@ mm_shared_qmi_set_primary_sim_slot (MMIfaceModem *self, } /*****************************************************************************/ -/* SIM hot swap detection */ - -#define REFRESH_START_TIMEOUT_SECS 3 - -gboolean -mm_shared_qmi_setup_sim_hot_swap_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error) -{ - return g_task_propagate_boolean (G_TASK (res), error); -} - -static void -uim_refresh_complete (QmiClientUim *client, - QmiUimSessionType session_type) -{ - g_autoptr(QmiMessageUimRefreshCompleteInput) refresh_complete_input; - GArray *dummy_aid; - - dummy_aid = g_array_new (FALSE, FALSE, sizeof (guint8)); - - refresh_complete_input = qmi_message_uim_refresh_complete_input_new (); - qmi_message_uim_refresh_complete_input_set_session ( - refresh_complete_input, - session_type, - dummy_aid, /* ignored */ - NULL); - qmi_message_uim_refresh_complete_input_set_info ( - refresh_complete_input, - TRUE, - NULL); - - qmi_client_uim_refresh_complete ( - client, - refresh_complete_input, - 10, - NULL, - NULL, - NULL); - g_array_unref (dummy_aid); -} - -static gboolean -uim_start_refresh_timeout (MMSharedQmi *self) -{ - Private *priv; - - priv = get_private (self); - priv->uim_refresh_start_timeout_id = 0; - - mm_obj_dbg (self, "refresh start timed out; trigger SIM change check"); - - mm_iface_modem_check_for_sim_swap (MM_IFACE_MODEM (self), 0, NULL, NULL, NULL); - - return G_SOURCE_REMOVE; -} - -static void -uim_refresh_indication_cb (QmiClientUim *client, - QmiIndicationUimRefreshOutput *output, - MMSharedQmi *self) -{ - QmiUimRefreshStage stage; - QmiUimRefreshMode mode; - QmiUimSessionType session_type; - Private *priv; - g_autoptr(GError) error = NULL; - - priv = get_private (self); - - if (!qmi_indication_uim_refresh_output_get_event (output, - &stage, - &mode, - &session_type, - NULL, - NULL, - &error)) { - mm_obj_warn (self, "couldn't process UIM refresh indication: %s", error->message); - return; - } - - mm_obj_dbg (self, "refresh indication received: session type '%s', stage '%s', mode '%s'", - qmi_uim_session_type_get_string (session_type), - qmi_uim_refresh_stage_get_string (stage), - qmi_uim_refresh_mode_get_string (mode)); - - /* Support only the first slot for now. Primary GW provisioning is used in old modems. */ - if (session_type != QMI_UIM_SESSION_TYPE_CARD_SLOT_1 && - session_type != QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING) { - mm_obj_warn (self, "refresh session type not supported: %s", qmi_uim_session_type_get_string (session_type)); - return; - } - - /* Currently we handle only UICC Reset type refresh, which can be used - * in profile switch scenarios. In other cases we just trigger 'refresh - * complete' during start phase. Signal to notify about potential SIM - * profile switch is triggered when the refresh is ending. If it were - * triggered in start phase, reading SIM files seems to fail with - * an internal error. - * - * It's possible that 'end-with-success' stage never appears. For that, - * we start a timer at 'start' stage and if it expires, the SIM change - * check is triggered anyway. */ - if (stage == QMI_UIM_REFRESH_STAGE_START) { - if (mode == QMI_UIM_REFRESH_MODE_RESET) { - if (!priv->uim_refresh_start_timeout_id) - priv->uim_refresh_start_timeout_id = g_timeout_add_seconds (REFRESH_START_TIMEOUT_SECS, - (GSourceFunc)uim_start_refresh_timeout, - self); - } else - uim_refresh_complete (client, session_type); - } else if (stage == QMI_UIM_REFRESH_STAGE_END_WITH_SUCCESS) { - if (mode == QMI_UIM_REFRESH_MODE_RESET) { - if (priv->uim_refresh_start_timeout_id) { - g_source_remove (priv->uim_refresh_start_timeout_id); - priv->uim_refresh_start_timeout_id = 0; - } - mm_iface_modem_check_for_sim_swap (MM_IFACE_MODEM (self), 0, NULL, NULL, NULL); - } - } -} - -static void -uim_slot_status_indication_cb (QmiClientUim *client, - QmiIndicationUimSlotStatusOutput *output, - MMSharedQmi *self) -{ - GArray *physical_slots = NULL; - guint i; - g_autoptr(GError) error = NULL; - - mm_obj_dbg (self, "received slot status indication"); - - if (!qmi_indication_uim_slot_status_output_get_physical_slot_status (output, - &physical_slots, - &error)) { - mm_obj_warn (self, "could not process slot status indication: %s", error->message); - return; - } - - for (i = 0; i < physical_slots->len; i++) { - QmiPhysicalSlotStatusSlot *slot_status; - - slot_status = &g_array_index (physical_slots, QmiPhysicalSlotStatusSlot, i); - - /* We only care about active slot changes */ - if (slot_status->physical_slot_status == QMI_UIM_SLOT_STATE_ACTIVE) { - g_autofree gchar *iccid = NULL; - - if (slot_status->iccid && slot_status->iccid->len > 0) - iccid = mm_bcd_to_string ((const guint8 *) slot_status->iccid->data, slot_status->iccid->len); - - mm_iface_modem_check_for_sim_swap (MM_IFACE_MODEM (self), - i + 1, /* Slot index */ - iccid, - NULL, - NULL); - } - } -} - -static void -uim_refresh_register_iccid_change_ready (QmiClientUim *client, - GAsyncResult *res, - GTask *task) -{ - MMSharedQmi *self; - Private *priv; - g_autoptr(QmiMessageUimRefreshRegisterOutput) output = NULL; - g_autoptr(GError) error = NULL; - - self = g_task_get_source_object (task); - priv = get_private (self); - - output = qmi_client_uim_refresh_register_finish (client, res, &error); - if (!output || !qmi_message_uim_refresh_register_output_get_result (output, &error)) { - mm_obj_dbg (self, "refresh registration using 'refresh register' failed: %s", error->message); - g_clear_object (&priv->uim_client); - g_task_return_new_error (task, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED, - "SIM hot swap detection not supported by modem"); - } else { - mm_obj_dbg (self, "registered for SIM refresh events using 'refresh register'"); - priv->uim_refresh_indication_id = - g_signal_connect (client, - "refresh", - G_CALLBACK (uim_refresh_indication_cb), - self); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -/* This is the last resort if 'refresh register all' does not work. It works - * on some older modems. Those modems may not also support QMI_UIM_SESSION_TYPE_CARD_SLOT_1 - * so we'll use QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING */ -static void -uim_refresh_register_iccid_change (GTask *task) -{ - MMSharedQmi *self; - Private *priv; - QmiMessageUimRefreshRegisterInputInfoFilesElement file_element; - guint8 val; - g_autoptr(QmiMessageUimRefreshRegisterInput) refresh_register_input = NULL; - g_autoptr(GArray) dummy_aid = NULL; - g_autoptr(GArray) file = NULL; - g_autoptr(GArray) file_element_path = NULL; - - self = g_task_get_source_object (task); - priv = get_private (MM_SHARED_QMI (self)); - - mm_obj_dbg (self, "register for refresh file indication"); - - dummy_aid = g_array_new (FALSE, FALSE, sizeof (guint8)); - - file = g_array_sized_new (FALSE, FALSE, sizeof (QmiMessageUimRefreshRegisterInputInfoFilesElement), 1); - - file_element_path = g_array_sized_new (FALSE, FALSE, sizeof (guint8), 2); - val = 0x00; - g_array_append_val (file_element_path, val); - val = 0x3F; - g_array_append_val (file_element_path, val); - - - memset (&file_element, 0, sizeof (file_element)); - file_element.file_id = 0x2FE2; /* ICCID */ - file_element.path = file_element_path; - g_array_append_val (file, file_element); - - refresh_register_input = qmi_message_uim_refresh_register_input_new (); - qmi_message_uim_refresh_register_input_set_info (refresh_register_input, - TRUE, - FALSE, - file, - NULL); - qmi_message_uim_refresh_register_input_set_session (refresh_register_input, - QMI_UIM_SESSION_TYPE_PRIMARY_GW_PROVISIONING, - dummy_aid, - NULL); - - qmi_client_uim_refresh_register (QMI_CLIENT_UIM (priv->uim_client), - refresh_register_input, - 10, - NULL, - (GAsyncReadyCallback) uim_refresh_register_iccid_change_ready, - task); -} - -/* Refresh registration and event handling. - * This is used only as fallback in case slot status indications do not work - * in the particular modem (determined by UIM Get Slot Status failing) for - * detecting ICCID changing due to a profile switch. - * - * We assume that devices not supporting UIM Get Slot Status only have a - * single slot, for which we register refresh events. - */ - -static void -uim_refresh_register_all_ready (QmiClientUim *client, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(QmiMessageUimRefreshRegisterAllOutput) output = NULL; - g_autoptr(GError) error = NULL; - MMIfaceModem *self; - Private *priv; - - self = g_task_get_source_object (task); - priv = get_private (MM_SHARED_QMI (self)); - - output = qmi_client_uim_refresh_register_all_finish (client, res, &error); - if (!output || !qmi_message_uim_refresh_register_all_output_get_result (output, &error)) { - if (g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_NOT_SUPPORTED) || - g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INVALID_QMI_COMMAND)) { - /* As last resort, if 'refresh register all' fails, try a plain 'refresh register'. - * Some older modems may not support 'refresh register all'. */ - uim_refresh_register_iccid_change (task); - return; - } - - mm_obj_dbg (self, "refresh register all operation failed: %s", error->message); - g_clear_object (&priv->uim_client); - g_task_return_error (task, g_steal_pointer (&error)); - } else { - mm_obj_dbg (self, "registered for all SIM refresh events"); - priv->uim_refresh_indication_id = - g_signal_connect (client, - "refresh", - G_CALLBACK (uim_refresh_indication_cb), - self); - g_task_return_boolean (task, TRUE); - } - g_object_unref (task); -} - -static void -uim_slot_status_not_supported (GTask *task) -{ - MMIfaceModem *self; - Private *priv; - g_autoptr(QmiMessageUimRefreshRegisterAllInput) refresh_register_all_input = NULL; - g_autoptr(GArray) dummy_aid = NULL; - - self = g_task_get_source_object (task); - priv = get_private (MM_SHARED_QMI (self)); - - g_assert (!priv->uim_refresh_indication_id); - - mm_obj_dbg (self, "slot status not supported by modem: register for refresh indications"); - - dummy_aid = g_array_new (FALSE, FALSE, sizeof (guint8)); - refresh_register_all_input = qmi_message_uim_refresh_register_all_input_new (); - - qmi_message_uim_refresh_register_all_input_set_info (refresh_register_all_input, - TRUE, - NULL); - qmi_message_uim_refresh_register_all_input_set_session (refresh_register_all_input, - QMI_UIM_SESSION_TYPE_CARD_SLOT_1, - dummy_aid, - NULL); - - qmi_client_uim_refresh_register_all (QMI_CLIENT_UIM (priv->uim_client), - refresh_register_all_input, - 10, - NULL, - (GAsyncReadyCallback) uim_refresh_register_all_ready, - task); -} - -static void -uim_check_get_slot_status_ready (QmiClientUim *client, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(QmiMessageUimGetSlotStatusOutput) output = NULL; - g_autoptr(GError) error = NULL; - MMIfaceModem *self; - Private *priv; - - self = g_task_get_source_object (task); - priv = get_private (MM_SHARED_QMI (self)); - - output = qmi_client_uim_get_slot_status_finish (client, res, &error); - if (!output || !qmi_message_uim_get_slot_status_output_get_result (output, &error)) { - if (priv->uim_slot_status_indication_id) { - g_signal_handler_disconnect (client, priv->uim_slot_status_indication_id); - priv->uim_slot_status_indication_id = 0; - } - - if (g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_NOT_SUPPORTED) || - g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INVALID_QMI_COMMAND)) { - uim_slot_status_not_supported (task); - return; - } - - mm_obj_dbg (self, "slot status retrieval failed: %s", error->message); - g_clear_object (&priv->uim_client); - g_task_return_error (task, g_steal_pointer (&error)); - g_object_unref (task); - return; - } - - mm_obj_dbg (self, "slot status retrieval succeeded: monitoring slot status indications"); - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -uim_register_events_ready (QmiClientUim *client, - GAsyncResult *res, - GTask *task) -{ - g_autoptr(QmiMessageUimRegisterEventsOutput) output = NULL; - g_autoptr(GError) error = NULL; - MMIfaceModem *self; - Private *priv; - - self = g_task_get_source_object (task); - priv = get_private (MM_SHARED_QMI (self)); - - /* If event registration fails, go on with initialization. In that case - * we cannot use slot status indications to detect eUICC profile switches. */ - output = qmi_client_uim_register_events_finish (client, res, &error); - if (output && qmi_message_uim_register_events_output_get_result (output, &error)) { - g_assert (!priv->uim_slot_status_indication_id); - priv->uim_slot_status_indication_id = g_signal_connect (priv->uim_client, - "slot-status", - G_CALLBACK (uim_slot_status_indication_cb), - self); - mm_obj_dbg (self, "registered for slot status indications"); - - /* Successful registration does not mean that the modem actually sends - * physical slot status indications; invoke Get Slot Status to find out if - * the modem really supports slot status. */ - qmi_client_uim_get_slot_status (client, - NULL, - 10, - NULL, - (GAsyncReadyCallback) uim_check_get_slot_status_ready, - task); - return; - } - - mm_obj_dbg (self, "not registered for slot status indications: %s", error->message); - uim_slot_status_not_supported (task); -} - -void -mm_shared_qmi_setup_sim_hot_swap (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_autoptr(QmiMessageUimRegisterEventsInput) register_events_input = NULL; - GTask *task; - QmiClient *client = NULL; - Private *priv; - - if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self), - QMI_SERVICE_UIM, &client, - callback, user_data)) - return; - - task = g_task_new (self, NULL, callback, user_data); - priv = get_private (MM_SHARED_QMI (self)); - - g_assert (!priv->uim_slot_status_indication_id); - g_assert (!priv->uim_client); - priv->uim_client = g_object_ref (client); - - register_events_input = qmi_message_uim_register_events_input_new (); - qmi_message_uim_register_events_input_set_event_registration_mask (register_events_input, - QMI_UIM_EVENT_REGISTRATION_FLAG_PHYSICAL_SLOT_STATUS, - NULL); - qmi_client_uim_register_events (QMI_CLIENT_UIM (priv->uim_client), - register_events_input, - 10, - NULL, - (GAsyncReadyCallback) uim_register_events_ready, - task); -} - -/*****************************************************************************/ /* Location: Set SUPL server */ typedef struct { diff --git a/src/mm-shared-qmi.h b/src/mm-shared-qmi.h index 9af00b9d..3b288187 100644 --- a/src/mm-shared-qmi.h +++ b/src/mm-shared-qmi.h @@ -179,12 +179,6 @@ void mm_shared_qmi_set_primary_sim_slot (MMIfaceMode gboolean mm_shared_qmi_set_primary_sim_slot_finish (MMIfaceModem *self, GAsyncResult *res, GError **error); -void mm_shared_qmi_setup_sim_hot_swap (MMIfaceModem *self, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean mm_shared_qmi_setup_sim_hot_swap_finish (MMIfaceModem *self, - GAsyncResult *res, - GError **error); /* Shared QMI location support */ |