bluez5: backend-native: add CLCC support

Start call id at 1 as for the index calls in HFP, and move this id
to spa_bt_telephony_[ag|call] so they can be used by CLCC to retrieve
the related call.

if enhanced call status is supported, send AT+CLCC on +CIEV events to
get the calls information.
This commit is contained in:
Frédéric Danis 2024-10-15 12:21:27 +02:00 committed by Wim Taymans
parent a8363ff92b
commit f5e08677a2
3 changed files with 84 additions and 10 deletions

View file

@ -183,6 +183,7 @@ struct rfcomm {
unsigned int extended_error_reporting:1;
unsigned int clip_notify:1;
unsigned int hfp_hf_3way:1;
unsigned int hfp_hf_clcc:1;
unsigned int chld_supported:1;
enum hfp_hf_state hf_state;
enum hsp_hs_state hs_state;
@ -1774,6 +1775,7 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
(rfcomm->msbc_supported_by_hfp || rfcomm->lc3_supported_by_hfp))
rfcomm->codec_negotiation_supported = true;
rfcomm->hfp_hf_3way = (features & SPA_BT_HFP_AG_FEATURE_3WAY) != 0;
rfcomm->hfp_hf_clcc = (features & SPA_BT_HFP_AG_FEATURE_ENHANCED_CALL_STATUS) != 0;
} else if (sscanf(token, "+BCS:%u", &selected_codec) == 1 && rfcomm->codec_negotiation_supported) {
if (selected_codec != HFP_AUDIO_CODEC_CVSD && selected_codec != HFP_AUDIO_CODEC_MSBC &&
selected_codec != HFP_AUDIO_CODEC_LC3_SWB) {
@ -1920,6 +1922,9 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
}
}
}
if (rfcomm->hfp_hf_clcc)
rfcomm_send_cmd(rfcomm, "AT+CLCC");
} else if (spa_streq(rfcomm->hf_indicators[indicator], "call")) {
if (value == 0) {
struct spa_bt_telephony_call *call, *tcall;
@ -1941,6 +1946,9 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
}
}
}
if (rfcomm->hfp_hf_clcc)
rfcomm_send_cmd(rfcomm, "AT+CLCC");
} else if (spa_streq(rfcomm->hf_indicators[indicator], "callheld")) {
if (value == 0) { /* Reject waiting call or no held calls */
struct spa_bt_telephony_call *call, *tcall;
@ -1976,6 +1984,9 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
telephony_call_notify_updated_props(call);
}
}
if (rfcomm->hfp_hf_clcc)
rfcomm_send_cmd(rfcomm, "AT+CLCC");
}
}
} else if (sscanf(token, "+CLIP: \"%16[^\"]\",%u", number, &type) == 2) {
@ -1995,6 +2006,66 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
call = hfp_hf_add_call(rfcomm, rfcomm->telephony_ag, CALL_STATE_WAITING, number);
if (call == NULL)
spa_log_warn(backend->log, "failed to create waiting call");
} else if (spa_strstartswith(token, "+CLCC: ")) {
struct spa_bt_telephony_call *call;
int idx;
unsigned int status, mpty;
bool found = false;
token[strcspn(token, "\r")] = 0;
token[strcspn(token, "\n")] = 0;
token += strlen("+CLCC: ");
token[strcspn(token, ",")] = 0;
idx = atoi(token);
token += strcspn(token, "\0") + 1;
// Skip direction
token[strcspn(token, ",")] = 0;
token += strcspn(token, "\0") + 1;
token[strcspn(token, ",")] = 0;
status = atoi(token);
token += strcspn(token, "\0") + 1;
// Skip mode
token[strcspn(token, ",")] = 0;
token += strcspn(token, "\0") + 1;
token[strcspn(token, ",")] = 0;
mpty = atoi(token);
token += strcspn(token, "\0") + 1;
if (strlen(token) > 0) {
if (sscanf(token, "\"%16[^\"]\",%u", number, &type) != 2) {
spa_log_warn(backend->log, "Failed to parse number: %s", token);
number[0] = '\0';
}
}
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
if (call->id == idx) {
bool changed = false;
found = true;
if (call->state != status) {
call->state =status;
changed = true;
}
if (call->multiparty != mpty) {
call->multiparty = mpty;
changed = true;
}
if (strlen(number) && !spa_streq(number, call->line_identification)) {
if (call->line_identification)
free(call->line_identification);
call->line_identification = strdup(number);
changed = true;
}
if (changed)
telephony_call_notify_updated_props(call);
}
}
if (!found) {
spa_log_warn(backend->log, "unknown call index: %u", idx);
}
} else if (spa_strstartswith(token, "OK")) {
switch(rfcomm->hf_state) {
case hfp_hf_brsf:
@ -3036,7 +3107,8 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
rfcomm->transport->path, handler);
} else if (profile == SPA_BT_PROFILE_HFP_AG) {
/* Start SLC connection */
unsigned int hf_features = SPA_BT_HFP_HF_FEATURE_CLIP | SPA_BT_HFP_HF_FEATURE_3WAY;
unsigned int hf_features = SPA_BT_HFP_HF_FEATURE_CLIP | SPA_BT_HFP_HF_FEATURE_3WAY |
SPA_BT_HFP_HF_FEATURE_ENHANCED_CALL_STATUS;
bool has_msbc = device_supports_codec(backend, rfcomm->device, HFP_AUDIO_CODEC_MSBC);
bool has_lc3 = device_supports_codec(backend, rfcomm->device, HFP_AUDIO_CODEC_LC3_SWB);