f9c7ffa9b6
PulseAudio is used for handling all audio on postmarketOS. This also involves Bluetooth audio such as A2DP, HSP and HFP audio. In the case of HFP/HSP, the HF and AG can interact with each other through AT commands defined in the Bluetooth HFP 1.8 spec. This set of patches implements HFP support to allow Bluetooth devices to accept/reject/hangup calls, dial numbers, DTMF tone generation, query signal strength, roaming status, service status, AG battery level, call status, etc. More details in the upstream MR: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/693 Available in edge for testing this merge request with a broader user base. Not intended for backporting to stable branches. [ci:skip-build]: already built successfully in CI
108 lines
4.5 KiB
Diff
108 lines
4.5 KiB
Diff
From 320d906f8e64b1713dc09c8e95316c4de515f70f Mon Sep 17 00:00:00 2001
|
|
From: Dylan Van Assche <me@dylanvanassche.be>
|
|
Date: Fri, 15 Apr 2022 08:18:48 +0200
|
|
Subject: [PATCH 20/26] bluetooth: support AT+CLCC
|
|
|
|
Report ongoing calls when the HF sends an AT+CLCC command.
|
|
Currently, only one ongoing call is supported, three-way calling is not
|
|
implemented. Any additional calls are ignored.
|
|
---
|
|
src/modules/bluetooth/backend-native.c | 61 ++++++++++++++++++++++++++
|
|
src/modules/bluetooth/bluez5-util.h | 9 ++++
|
|
2 files changed, 70 insertions(+)
|
|
|
|
diff --git a/src/modules/bluetooth/backend-native.c b/src/modules/bluetooth/backend-native.c
|
|
index fec24a57b..faefed9bd 100644
|
|
--- a/src/modules/bluetooth/backend-native.c
|
|
+++ b/src/modules/bluetooth/backend-native.c
|
|
@@ -768,6 +768,67 @@ static bool hfp_rfcomm_handle(int fd, pa_bluetooth_transport *t, const char *buf
|
|
return false;
|
|
}
|
|
pa_assert_not_reached();
|
|
+ } else if (strstr(buf, "AT+CLCC")) {
|
|
+ pa_hashmap *calls;
|
|
+ call_status_t *call;
|
|
+ unsigned int type;
|
|
+ unsigned int clcc_status;
|
|
+
|
|
+ /* Return error if ModemManager is unavailable */
|
|
+ if (!discovery->native_backend->modemmanager || !pa_modemmanager_has_modem(discovery->native_backend->modemmanager)) {
|
|
+ pa_log_debug("ModemManager backend unavailable, cannot answer AT+CLCC");
|
|
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_CONNECTION_TO_PHONE);
|
|
+ return false;
|
|
+ } else if (!pa_modemmanager_has_service(discovery->native_backend->modemmanager)) {
|
|
+ pa_log_debug("No network service, cannot answer AT+CLCC");
|
|
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_NO_NETWORK_SERVICE);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ calls = pa_modemmanager_get_calls(discovery->native_backend->modemmanager);
|
|
+
|
|
+ /* Check if we have any ongoing calls, if not return OK */
|
|
+ if (pa_hashmap_isempty(calls))
|
|
+ return true;
|
|
+
|
|
+ /* FIXME: support three-way calling */
|
|
+ call = pa_hashmap_first(calls);
|
|
+
|
|
+ /* Map call status to CLCC status numbers */
|
|
+ if (call->status == PA_MODEMMANAGER_CALL_STATE_INVALID) {
|
|
+ pa_log_warn("Unable to answer AT+CLCC, call state is unknown");
|
|
+ rfcomm_write_error(discovery->native_backend, fd, CMEE_AG_FAILURE);
|
|
+ return false;
|
|
+ } else if (call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_RINGING) {
|
|
+ clcc_status = CLCC_INCOMING;
|
|
+ } else if (!call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_RINGING) {
|
|
+ clcc_status = CLCC_ALERTING;
|
|
+ } else if (!call->is_incoming && call->status == PA_MODEMMANAGER_CALL_STATE_DIALING) {
|
|
+ clcc_status = CLCC_DIALING;
|
|
+ } else if (call->status == PA_MODEMMANAGER_CALL_STATE_ACTIVE) {
|
|
+ clcc_status = CLCC_ACTIVE;
|
|
+ } else if (call->status == PA_MODEMMANAGER_CALL_STATE_TERMINATED) {
|
|
+ pa_log_debug("Call terminated already, do not report it.");
|
|
+ return true;
|
|
+ /* FIXME: support three-way calling */
|
|
+ } else {
|
|
+ pa_assert_not_reached();
|
|
+ }
|
|
+
|
|
+ /* Check if call has a number, if not drop it since number and type are optional */
|
|
+ if (!call->number) {
|
|
+ rfcomm_write_response(fd, "+CLCC: %d,%d,%d,%d,%d", 1, call->is_incoming, clcc_status, 0, 0);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ /* International numbers start with '+' */
|
|
+ if (strncmp("+", call->number, 1) == 0)
|
|
+ type = CLIP_INTERNATIONAL_NUMBER;
|
|
+ else
|
|
+ type = CLIP_NATIONAL_NUMBER;
|
|
+
|
|
+ rfcomm_write_response(fd, "+CLCC: %d,%d,%d,%d,%d,\"%s\",%d", 1, call->is_incoming, clcc_status, 0, 0, call->number, type);
|
|
+ return true;
|
|
}
|
|
|
|
/*
|
|
diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h
|
|
index 638a793b7..fb88f00e2 100644
|
|
--- a/src/modules/bluetooth/bluez5-util.h
|
|
+++ b/src/modules/bluetooth/bluez5-util.h
|
|
@@ -233,6 +233,15 @@ typedef enum pa_bluetooth_clip {
|
|
CLIP_NATIONAL_NUMBER = 129
|
|
} pa_bluetooth_clip_t;
|
|
|
|
+/* CLCC call states, described in Bluetooth HFP 1.8 spec */
|
|
+/* FIXME: support three-way calling */
|
|
+typedef enum pa_bluetooth_clcc {
|
|
+ CLCC_ACTIVE = 0,
|
|
+ CLCC_DIALING = 2,
|
|
+ CLCC_ALERTING = 3,
|
|
+ CLCC_INCOMING = 4
|
|
+} pa_bluetooth_clcc_t;
|
|
+
|
|
#ifdef HAVE_BLUEZ_5_OFONO_HEADSET
|
|
pa_bluetooth_backend *pa_bluetooth_ofono_backend_new(pa_core *c, pa_bluetooth_discovery *y);
|
|
void pa_bluetooth_ofono_backend_free(pa_bluetooth_backend *b);
|
|
--
|
|
2.35.1
|
|
|