All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Frédéric Danis" <frederic.danis@collabora.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v2 09/12] audio/hfp-hf: Add multi calls support
Date: Thu,  1 Oct 2026 23:10:33 +0200	[thread overview]
Message-ID: <20261001211036.1760396-10-frederic.danis@collabora.com> (raw)
In-Reply-To: <20261001211036.1760396-1-frederic.danis@collabora.com>

From: Frédéric Danis <frederic.danis.oss@gmail.com>

This implements the SwapCalls, ReleaseAndAnswer, ReleaseAndSwap and
HoldAndAnswer methods from org.bluez.Telephony1.
---
 profiles/audio/hfp-hf.c | 142 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 142 insertions(+)

diff --git a/profiles/audio/hfp-hf.c b/profiles/audio/hfp-hf.c
index 1843b6758..25dce517f 100644
--- a/profiles/audio/hfp-hf.c
+++ b/profiles/audio/hfp-hf.c
@@ -503,6 +503,144 @@ static DBusMessage *dial(DBusConnection *conn, DBusMessage *msg,
 	return NULL;
 }
 
+static DBusMessage *swap_calls(DBusConnection *conn, DBusMessage *msg,
+				void *profile_data)
+{
+	struct hfp_device *dev = profile_data;
+	const struct queue_entry *entry;
+	bool found_held = false;
+	bool ret;
+
+	for (entry = queue_get_entries(dev->calls); entry;
+					entry = entry->next) {
+		struct call *call = entry->data;
+
+		if (call->state == CALL_STATE_HELD) {
+			found_held = true;
+			break;
+		}
+	}
+
+	if (!found_held) {
+		return btd_error_failed(msg,
+					"Swap calls command failed: "
+					"no held calls");
+	}
+
+	ret = hfp_hf_swap_calls(dev->hf, cmd_complete,
+					dbus_message_ref(msg));
+	if (!ret)
+		return btd_error_failed(msg, "Swap calls command failed");
+
+	return NULL;
+}
+
+static DBusMessage *release_and_answer(DBusConnection *conn, DBusMessage *msg,
+					void *profile_data)
+{
+	struct hfp_device *dev = profile_data;
+	const struct queue_entry *entry;
+	bool found_active = false;
+	bool found_waiting = false;
+	bool ret;
+
+	for (entry = queue_get_entries(dev->calls); entry;
+					entry = entry->next) {
+		struct call *call = entry->data;
+
+		if (call->state == CALL_STATE_ACTIVE)
+			found_active = true;
+		else if (call->state == CALL_STATE_WAITING)
+			found_waiting = true;
+	}
+
+	if (!found_active || !found_waiting) {
+		return btd_error_failed(msg,
+					"Release and answer command failed: "
+					"no active and waiting calls");
+	}
+
+	ret = hfp_hf_release_and_accept(dev->hf, cmd_complete,
+					dbus_message_ref(msg));
+	if (!ret)
+		return btd_error_failed(msg,
+					"Release and answer command failed");
+
+	return NULL;
+}
+
+static DBusMessage *release_and_swap(DBusConnection *conn, DBusMessage *msg,
+					void *profile_data)
+{
+	struct hfp_device *dev = profile_data;
+	const struct queue_entry *entry;
+	bool found_active = false;
+	bool found_held = false;
+	bool ret;
+
+	for (entry = queue_get_entries(dev->calls); entry;
+					entry = entry->next) {
+		struct call *call = entry->data;
+
+		if (call->state == CALL_STATE_WAITING) {
+			return btd_error_failed(msg,
+					"Release and swap command failed: "
+					"waiting call exists");
+		} else if (call->state == CALL_STATE_ACTIVE)
+			found_active = true;
+		else if (call->state == CALL_STATE_HELD)
+			found_held = true;
+	}
+
+	if (!found_active || !found_held) {
+		return btd_error_failed(msg,
+					"Release and swap command failed: "
+					"no active and held calls");
+	}
+
+	ret = hfp_hf_release_and_accept(dev->hf, cmd_complete,
+					dbus_message_ref(msg));
+	if (!ret)
+		return btd_error_failed(msg,
+					"Release and swap command failed");
+
+	return NULL;
+}
+
+static DBusMessage *hold_and_answer(DBusConnection *conn, DBusMessage *msg,
+					void *profile_data)
+{
+	struct hfp_device *dev = profile_data;
+	const struct queue_entry *entry;
+	bool found_active = false;
+	bool found_waiting = false;
+	bool ret;
+
+	for (entry = queue_get_entries(dev->calls); entry;
+					entry = entry->next) {
+		struct call *call = entry->data;
+
+		if (call->state == CALL_STATE_ACTIVE)
+			found_active = true;
+		else if (call->state == CALL_STATE_WAITING)
+			found_waiting = true;
+	}
+
+	if (!found_active || !found_waiting) {
+		return btd_error_failed(msg,
+					"Hold and answer command failed: "
+					"no active and waiting calls");
+	}
+
+	ret = hfp_hf_swap_calls(dev->hf, cmd_complete,
+					dbus_message_ref(msg));
+	if (!ret)
+		return btd_error_failed(msg,
+					"Hold and answer command failed");
+
+	return NULL;
+}
+
 static DBusMessage *hangup_all(DBusConnection *conn, DBusMessage *msg,
 				void *profile_data)
 {
@@ -569,6 +707,10 @@ static DBusMessage *call_hangup(DBusConnection *conn, DBusMessage *msg,
 
 struct telephony_callbacks hfp_callbacks = {
 	.dial = dial,
+	.swap_calls = swap_calls,
+	.release_and_answer = release_and_answer,
+	.release_and_swap = release_and_swap,
+	.hold_and_answer = hold_and_answer,
 	.hangup_all = hangup_all,
 	.send_tones = send_tones,
 	.call_answer = call_answer,
-- 
2.43.0


  parent reply	other threads:[~2026-10-01 21:10 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-01 21:10 [PATCH BlueZ v2 00/12] hfp-hf: Enhance HFP Hands-Free profile support Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 01/12] audio/hfp-hf: Add HFP HF server and SDP record Frédéric Danis
2026-10-02  0:53   ` hfp-hf: Enhance HFP Hands-Free profile support bluez.test.bot
2026-10-01 21:10 ` [PATCH BlueZ v2 02/12] audio/hfp-hf: Add MediaEndpoint for HFP codecs Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 03/12] client/player: Add MediaEndpoints for HFP HF codecs Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 04/12] shared/hfp: Add hangup all calls support Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 05/12] audio/hfp-hf: " Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 06/12] shared/hfp: Add send tones support Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 07/12] audio/hfp-hf: Add Send Tones support Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 08/12] client/telephony: Add Send Tones menu entry Frédéric Danis
2026-10-01 21:10 ` Frédéric Danis [this message]
2026-10-01 21:10 ` [PATCH BlueZ v2 10/12] client/telephony: Add multi calls support Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 11/12] shared/hfp: Add codecs support Frédéric Danis
2026-10-01 21:10 ` [PATCH BlueZ v2 12/12] audio/hfp-hf: " Frédéric Danis
2026-10-05 20:20 ` [PATCH BlueZ v2 00/12] hfp-hf: Enhance HFP Hands-Free profile support patchwork-bot+bluetooth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261001211036.1760396-10-frederic.danis@collabora.com \
    --to=frederic.danis@collabora.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.