From 320d906f8e64b1713dc09c8e95316c4de515f70f Mon Sep 17 00:00:00 2001 From: Dylan Van Assche 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