From 3af93cbe18709864a10c3efd752e7db44f41c18f Mon Sep 17 00:00:00 2001 From: Maxim Anisimov Date: Fri, 5 Jun 2020 08:57:48 +0300 Subject: broadband-modem-qmi: switch USSD state to idle when ussd session is terminated by network The cellular operator can break the interactive USSD session. In this case, it is necessary to process this situation otherwise --3gpp-ussd-initiate or --3gpp-ussd-respond will give an error. Signed-off-by: Maxim Anisimov --- src/mm-broadband-modem-qmi.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src') diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index ea52ea00..2926d2fb 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -128,6 +128,7 @@ struct _MMBroadbandModemQmiPrivate { /* 3GPP USSD helpers */ guint ussd_indication_id; + guint ussd_release_indication_id; gboolean ussd_unsolicited_events_enabled; gboolean ussd_unsolicited_events_setup; GTask *pending_ussd_action; @@ -7314,6 +7315,30 @@ ussd_indication_cb (QmiClientVoice *client, process_ussd_message (self, user_action, utf8, error); } +static void +ussd_release_indication_cb (QmiClientVoice *client, + MMBroadbandModemQmi *self) +{ + GTask *pending_task; + GError *error; + + mm_iface_modem_3gpp_ussd_update_state (MM_IFACE_MODEM_3GPP_USSD (self), + MM_MODEM_3GPP_USSD_SESSION_STATE_IDLE); + + error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_ABORTED, "USSD terminated by network"); + + pending_task = g_steal_pointer (&self->priv->pending_ussd_action); + if (pending_task) { + g_task_return_error (pending_task, error); + g_object_unref (pending_task); + return; + } + + /* If no pending task, just report the error */ + mm_obj_dbg (self, "USSD release indication: %s", error->message); + g_error_free (error); +} + /*****************************************************************************/ /* Setup/cleanup unsolicited events */ @@ -7357,10 +7382,19 @@ common_3gpp_ussd_setup_cleanup_unsolicited_events (MMBroadbandModemQmi *self, "ussd", G_CALLBACK (ussd_indication_cb), self); + g_assert (self->priv->ussd_release_indication_id == 0); + self->priv->ussd_release_indication_id = + g_signal_connect (client, + "release-ussd", + G_CALLBACK (ussd_release_indication_cb), + self); } else { g_assert (self->priv->ussd_indication_id != 0); g_signal_handler_disconnect (client, self->priv->ussd_indication_id); self->priv->ussd_indication_id = 0; + g_assert (self->priv->ussd_release_indication_id != 0); + g_signal_handler_disconnect (client, self->priv->ussd_release_indication_id); + self->priv->ussd_release_indication_id = 0; } g_task_return_boolean (task, TRUE); -- cgit v1.2.3-70-g09d2