From 4ced8116a9a6ea0a4b95702bd2ca863dd3396f58 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Wed, 12 Oct 2011 16:00:00 -0500 Subject: voicecall: Fix HangupAll for HFP HFP does not implement HangupAll natively and most AGs do not support releasing held calls by id. Work around this by using hangup active and then dropping all held calls if no waiting calls exist. Otherwise fall back to releasing calls by id. --- src/voicecall.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/voicecall.c b/src/voicecall.c index 2fabbae3..17d42b3a 100644 --- a/src/voicecall.c +++ b/src/voicecall.c @@ -120,6 +120,7 @@ static const char *default_en_list_no_sim[] = { "119", "118", "999", "110", "08", "000", NULL }; static void generic_callback(const struct ofono_error *error, void *data); +static void hangup_all_active(const struct ofono_error *error, void *data); static void multirelease_callback(const struct ofono_error *err, void *data); static gboolean tone_request_run(gpointer user_data); @@ -1700,12 +1701,15 @@ static DBusMessage *manager_hangup_all(DBusConnection *conn, vc->pending = dbus_message_ref(msg); - if (vc->driver->hangup_all == NULL) { - voicecalls_release_queue(vc, vc->call_list, - voicecalls_release_done); - voicecalls_release_next(vc); - } else + if (vc->driver->hangup_all) { vc->driver->hangup_all(vc, generic_callback, vc); + return NULL; + } + + if (voicecalls_num_held(vc) > 0) + vc->driver->hangup_active(vc, hangup_all_active, vc); + else + vc->driver->hangup_active(vc, generic_callback, vc); return NULL; } @@ -2291,6 +2295,35 @@ static void generic_callback(const struct ofono_error *error, void *data) __ofono_dbus_pending_reply(&vc->pending, reply); } +static void hangup_all_active(const struct ofono_error *error, void *data) +{ + struct ofono_voicecall *vc = data; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + __ofono_dbus_pending_reply(&vc->pending, + __ofono_error_failed(vc->pending)); + return; + } + + /* + * If we have waiting call, we cannot use CHLD=0 due to side effects + * to that call. Instead we try to hangup all calls one by one, + * which might fail if the modem / AG does not support release_specific + * for held calls. In that case the waiting call and held calls will + * remain. + */ + if (vc->driver->release_all_held == NULL || + voicecalls_have_waiting(vc)) { + GSList *held = voicecalls_held_list(vc); + + voicecalls_release_queue(vc, held, voicecalls_release_done); + voicecalls_release_next(vc); + + g_slist_free(held); + } else + vc->driver->release_all_held(vc, generic_callback, vc); +} + static void multirelease_callback(const struct ofono_error *error, void *data) { struct ofono_voicecall *vc = data; -- cgit v1.2.3