aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mm-base-call.c42
-rw-r--r--src/mm-base-call.h1
2 files changed, 37 insertions, 6 deletions
diff --git a/src/mm-base-call.c b/src/mm-base-call.c
index 0d09a09d..ce41112e 100644
--- a/src/mm-base-call.c
+++ b/src/mm-base-call.c
@@ -34,6 +34,7 @@
#include "mm-base-modem.h"
#include "mm-log.h"
#include "mm-modem-helpers.h"
+#include "mm-error-helpers.h"
G_DEFINE_TYPE (MMBaseCall, mm_base_call, MM_GDBUS_TYPE_CALL_SKELETON)
@@ -69,6 +70,11 @@ struct _MMBaseCallPrivate {
/* Ongoing call index */
guint index;
+
+ /* Start cancellable, used when the call state transition to
+ * 'terminated' is coming asynchronously (e.g. via in-call state
+ * update notifications) */
+ GCancellable *start_cancellable;
};
/*****************************************************************************/
@@ -148,8 +154,19 @@ handle_start_ready (MMBaseCall *self,
{
GError *error = NULL;
+ g_clear_object (&ctx->self->priv->start_cancellable);
+
if (!MM_BASE_CALL_GET_CLASS (self)->start_finish (self, res, &error)) {
mm_warn ("Couldn't start call : '%s'", error->message);
+
+ /* When cancelled via the start cancellable, it's because we got an early in-call error
+ * before the call attempt was reported as started. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
+ g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_CANCELLED)) {
+ g_clear_error (&error);
+ error = mm_connection_error_for_code (MM_CONNECTION_ERROR_NO_DIALTONE);
+ }
+
/* Convert errors into call state updates */
if (g_error_matches (error, MM_CONNECTION_ERROR, MM_CONNECTION_ERROR_NO_DIALTONE))
mm_base_call_change_state (self, MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_ERROR);
@@ -159,6 +176,7 @@ handle_start_ready (MMBaseCall *self,
mm_base_call_change_state (self, MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_REFUSED_OR_BUSY);
else
mm_base_call_change_state (self, MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_UNKNOWN);
+
g_dbus_method_invocation_take_error (ctx->invocation, error);
handle_start_context_free (ctx);
return;
@@ -220,7 +238,12 @@ handle_start_auth_ready (MMBaseModem *modem,
mm_base_call_change_state (ctx->self, MM_CALL_STATE_DIALING, MM_CALL_STATE_REASON_OUTGOING_STARTED);
+ /* Setup start cancellable to get notified of termination asynchronously */
+ g_assert (!ctx->self->priv->start_cancellable);
+ ctx->self->priv->start_cancellable = g_cancellable_new ();
+
MM_BASE_CALL_GET_CLASS (ctx->self)->start (ctx->self,
+ ctx->self->priv->start_cancellable,
(GAsyncReadyCallback)handle_start_ready,
ctx);
}
@@ -970,6 +993,8 @@ mm_base_call_change_state (MMBaseCall *self,
g_source_remove (self->priv->incoming_timeout);
self->priv->incoming_timeout = 0;
}
+ /* cancel start if ongoing */
+ g_cancellable_cancel (self->priv->start_cancellable);
}
mm_gdbus_call_set_state (MM_GDBUS_CALL (self), new_state);
@@ -1021,6 +1046,7 @@ call_start_ready (MMBaseModem *modem,
static void
call_start (MMBaseCall *self,
+ GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
@@ -1030,12 +1056,15 @@ call_start (MMBaseCall *self,
task = g_task_new (self, NULL, callback, user_data);
cmd = g_strdup_printf ("ATD%s;", mm_gdbus_call_get_number (MM_GDBUS_CALL (self)));
- mm_base_modem_at_command (self->priv->modem,
- cmd,
- 90,
- FALSE,
- (GAsyncReadyCallback)call_start_ready,
- task);
+ mm_base_modem_at_command_full (self->priv->modem,
+ mm_base_modem_peek_port_primary (self->priv->modem),
+ cmd,
+ 90,
+ FALSE, /* no cached */
+ FALSE, /* no raw */
+ cancellable,
+ (GAsyncReadyCallback)call_start_ready,
+ task);
g_free (cmd);
}
@@ -1400,6 +1429,7 @@ finalize (GObject *object)
{
MMBaseCall *self = MM_BASE_CALL (object);
+ g_assert (!self->priv->start_cancellable);
g_free (self->priv->path);
G_OBJECT_CLASS (mm_base_call_parent_class)->finalize (object);
diff --git a/src/mm-base-call.h b/src/mm-base-call.h
index 973bcafa..8d6944f5 100644
--- a/src/mm-base-call.h
+++ b/src/mm-base-call.h
@@ -54,6 +54,7 @@ struct _MMBaseCallClass {
/* Start the call */
void (* start) (MMBaseCall *self,
+ GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (* start_finish) (MMBaseCall *self,