mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
bluez5: backend-native: Manage 3way commands asynchronously
The call's states should not be updated on 3ways commands but wait for CIEV or CLCC events. This allows to manage user actions on the phone.
This commit is contained in:
parent
8e7a1a5235
commit
bd5de6eb1c
3 changed files with 66 additions and 70 deletions
|
|
@ -184,6 +184,7 @@ struct rfcomm {
|
|||
unsigned int clip_notify:1;
|
||||
unsigned int hfp_hf_3way:1;
|
||||
unsigned int hfp_hf_clcc:1;
|
||||
unsigned int hfp_hf_in_progress:1;
|
||||
unsigned int chld_supported:1;
|
||||
enum hfp_hf_state hf_state;
|
||||
enum hsp_hs_state hs_state;
|
||||
|
|
@ -1424,6 +1425,9 @@ static void hfp_hf_swap_calls(void *data, enum spa_bt_telephony_error *err)
|
|||
if (!rfcomm->chld_supported) {
|
||||
*err = BT_TELEPHONY_ERROR_NOT_SUPPORTED;
|
||||
return;
|
||||
} else if (rfcomm->hfp_hf_in_progress) {
|
||||
*err = BT_TELEPHONY_ERROR_IN_PROGRESS;
|
||||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
|
|
@ -1450,20 +1454,7 @@ static void hfp_hf_swap_calls(void *data, enum spa_bt_telephony_error *err)
|
|||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
bool changed = false;
|
||||
if (call->state == CALL_STATE_ACTIVE) {
|
||||
call->state = CALL_STATE_HELD;
|
||||
changed = true;
|
||||
} else if (call->state == CALL_STATE_HELD) {
|
||||
call->state = CALL_STATE_ACTIVE;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
telephony_call_notify_updated_props(call);
|
||||
}
|
||||
|
||||
rfcomm->hfp_hf_in_progress = true;
|
||||
*err = BT_TELEPHONY_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1471,7 +1462,7 @@ static void hfp_hf_release_and_answer(void *data, enum spa_bt_telephony_error *e
|
|||
{
|
||||
struct rfcomm *rfcomm = data;
|
||||
struct impl *backend = rfcomm->backend;
|
||||
struct spa_bt_telephony_call *call, *tcall;
|
||||
struct spa_bt_telephony_call *call;
|
||||
bool found_active = false;
|
||||
bool found_waiting = false;
|
||||
char reply[20];
|
||||
|
|
@ -1479,6 +1470,9 @@ static void hfp_hf_release_and_answer(void *data, enum spa_bt_telephony_error *e
|
|||
if (!rfcomm->chld_supported) {
|
||||
*err = BT_TELEPHONY_ERROR_NOT_SUPPORTED;
|
||||
return;
|
||||
} else if (rfcomm->hfp_hf_in_progress) {
|
||||
*err = BT_TELEPHONY_ERROR_IN_PROGRESS;
|
||||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
|
|
@ -1501,17 +1495,7 @@ static void hfp_hf_release_and_answer(void *data, enum spa_bt_telephony_error *e
|
|||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each_safe(call, tcall, &rfcomm->telephony_ag->call_list, link) {
|
||||
if (call->state == CALL_STATE_ACTIVE) {
|
||||
call->state = CALL_STATE_DISCONNECTED;
|
||||
telephony_call_notify_updated_props(call);
|
||||
telephony_call_destroy(call);
|
||||
} else if (call->state == CALL_STATE_WAITING) {
|
||||
call->state = CALL_STATE_ACTIVE;
|
||||
telephony_call_notify_updated_props(call);
|
||||
}
|
||||
}
|
||||
|
||||
rfcomm->hfp_hf_in_progress = true;
|
||||
*err = BT_TELEPHONY_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1519,7 +1503,7 @@ static void hfp_hf_release_and_swap(void *data, enum spa_bt_telephony_error *err
|
|||
{
|
||||
struct rfcomm *rfcomm = data;
|
||||
struct impl *backend = rfcomm->backend;
|
||||
struct spa_bt_telephony_call *call, *tcall;
|
||||
struct spa_bt_telephony_call *call;
|
||||
bool found_active = false;
|
||||
bool found_held = false;
|
||||
char reply[20];
|
||||
|
|
@ -1527,6 +1511,9 @@ static void hfp_hf_release_and_swap(void *data, enum spa_bt_telephony_error *err
|
|||
if (!rfcomm->chld_supported) {
|
||||
*err = BT_TELEPHONY_ERROR_NOT_SUPPORTED;
|
||||
return;
|
||||
} else if (rfcomm->hfp_hf_in_progress) {
|
||||
*err = BT_TELEPHONY_ERROR_IN_PROGRESS;
|
||||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
|
|
@ -1553,17 +1540,7 @@ static void hfp_hf_release_and_swap(void *data, enum spa_bt_telephony_error *err
|
|||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each_safe(call, tcall, &rfcomm->telephony_ag->call_list, link) {
|
||||
if (call->state == CALL_STATE_ACTIVE) {
|
||||
call->state = CALL_STATE_DISCONNECTED;
|
||||
telephony_call_notify_updated_props(call);
|
||||
telephony_call_destroy(call);
|
||||
} else if (call->state == CALL_STATE_HELD) {
|
||||
call->state = CALL_STATE_ACTIVE;
|
||||
telephony_call_notify_updated_props(call);
|
||||
}
|
||||
}
|
||||
|
||||
rfcomm->hfp_hf_in_progress = true;
|
||||
*err = BT_TELEPHONY_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1579,6 +1556,9 @@ static void hfp_hf_hold_and_answer(void *data, enum spa_bt_telephony_error *err)
|
|||
if (!rfcomm->chld_supported) {
|
||||
*err = BT_TELEPHONY_ERROR_NOT_SUPPORTED;
|
||||
return;
|
||||
} else if (rfcomm->hfp_hf_in_progress) {
|
||||
*err = BT_TELEPHONY_ERROR_IN_PROGRESS;
|
||||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
|
|
@ -1601,20 +1581,7 @@ static void hfp_hf_hold_and_answer(void *data, enum spa_bt_telephony_error *err)
|
|||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
bool changed = false;
|
||||
if (call->state == CALL_STATE_ACTIVE) {
|
||||
call->state = CALL_STATE_HELD;
|
||||
changed = true;
|
||||
} else if (call->state == CALL_STATE_WAITING) {
|
||||
call->state = CALL_STATE_ACTIVE;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
telephony_call_notify_updated_props(call);
|
||||
}
|
||||
|
||||
rfcomm->hfp_hf_in_progress = true;
|
||||
*err = BT_TELEPHONY_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1677,6 +1644,9 @@ static void hfp_hf_create_multiparty(void *data, enum spa_bt_telephony_error *er
|
|||
if (!rfcomm->chld_supported) {
|
||||
*err = BT_TELEPHONY_ERROR_NOT_SUPPORTED;
|
||||
return;
|
||||
} else if (rfcomm->hfp_hf_in_progress) {
|
||||
*err = BT_TELEPHONY_ERROR_IN_PROGRESS;
|
||||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
|
|
@ -1703,21 +1673,7 @@ static void hfp_hf_create_multiparty(void *data, enum spa_bt_telephony_error *er
|
|||
return;
|
||||
}
|
||||
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
bool changed = false;
|
||||
if (call->state == CALL_STATE_ACTIVE) {
|
||||
call->multiparty = true;
|
||||
changed = true;
|
||||
} else if (call->state == CALL_STATE_HELD) {
|
||||
call->state = CALL_STATE_ACTIVE;
|
||||
call->multiparty = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
telephony_call_notify_updated_props(call);
|
||||
}
|
||||
|
||||
rfcomm->hfp_hf_in_progress = true;
|
||||
*err = BT_TELEPHONY_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -1925,6 +1881,8 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
|
|||
|
||||
if (rfcomm->hfp_hf_clcc)
|
||||
rfcomm_send_cmd(rfcomm, "AT+CLCC");
|
||||
else
|
||||
rfcomm->hfp_hf_in_progress = false;
|
||||
} else if (spa_streq(rfcomm->hf_indicators[indicator], "call")) {
|
||||
if (value == 0) {
|
||||
struct spa_bt_telephony_call *call, *tcall;
|
||||
|
|
@ -1948,6 +1906,8 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
|
|||
|
||||
if (rfcomm->hfp_hf_clcc)
|
||||
rfcomm_send_cmd(rfcomm, "AT+CLCC");
|
||||
else
|
||||
rfcomm->hfp_hf_in_progress = false;
|
||||
} 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;
|
||||
|
|
@ -1970,6 +1930,21 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (value == 1) { /* Swap calls */
|
||||
struct spa_bt_telephony_call *call;
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
bool changed = false;
|
||||
if (call->state == CALL_STATE_ACTIVE) {
|
||||
call->state = CALL_STATE_HELD;
|
||||
changed = true;
|
||||
} else if (call->state == CALL_STATE_HELD) {
|
||||
call->state = CALL_STATE_ACTIVE;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
telephony_call_notify_updated_props(call);
|
||||
}
|
||||
} else if (value == 2) { /* No active calls, place waiting on hold */
|
||||
struct spa_bt_telephony_call *call;
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
|
|
@ -1986,6 +1961,8 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
|
|||
|
||||
if (rfcomm->hfp_hf_clcc)
|
||||
rfcomm_send_cmd(rfcomm, "AT+CLCC");
|
||||
else
|
||||
rfcomm->hfp_hf_in_progress = false;
|
||||
}
|
||||
}
|
||||
} else if (sscanf(token, "+CLIP: \"%16[^\"]\",%u", number, &type) == 2) {
|
||||
|
|
@ -2001,10 +1978,21 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
|
|||
}
|
||||
} else if (sscanf(token, "+CCWA: \"%16[^\"]\",%u", number, &type) == 2) {
|
||||
struct spa_bt_telephony_call *call;
|
||||
bool found = false;
|
||||
|
||||
spa_log_info(backend->log, "Waiting call");
|
||||
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");
|
||||
spa_list_for_each(call, &rfcomm->telephony_ag->call_list, link) {
|
||||
if (call->state == CALL_STATE_WAITING) {
|
||||
spa_log_info(backend->log, "waiting call already in progress (id: %d)", call->id);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
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;
|
||||
|
|
@ -2070,6 +2058,8 @@ static bool rfcomm_hfp_hf(struct rfcomm *rfcomm, char* token)
|
|||
else if (call->id != idx)
|
||||
spa_log_warn(backend->log, "wrong call index: %d, expected: %d", call->id, idx);
|
||||
}
|
||||
|
||||
rfcomm->hfp_hf_in_progress = false;
|
||||
} else if (spa_strstartswith(token, "OK")) {
|
||||
switch(rfcomm->hf_state) {
|
||||
case hfp_hf_brsf:
|
||||
|
|
|
|||
|
|
@ -228,6 +228,7 @@ static void dbus_iter_append_call_properties(DBusMessageIter *i, struct spa_bt_t
|
|||
#define PW_TELEPHONY_ERROR_NOT_SUPPORTED "org.freedesktop.PipeWire.Telephony.Error.NotSupported"
|
||||
#define PW_TELEPHONY_ERROR_INVALID_FORMAT "org.freedesktop.PipeWire.Telephony.Error.InvalidFormat"
|
||||
#define PW_TELEPHONY_ERROR_INVALID_STATE "org.freedesktop.PipeWire.Telephony.Error.InvalidState"
|
||||
#define PW_TELEPHONY_ERROR_IN_PROGRESS "org.freedesktop.PipeWire.Telephony.Error.InProgress"
|
||||
|
||||
static const char *telephony_error_to_dbus (enum spa_bt_telephony_error err)
|
||||
{
|
||||
|
|
@ -240,6 +241,8 @@ static const char *telephony_error_to_dbus (enum spa_bt_telephony_error err)
|
|||
return PW_TELEPHONY_ERROR_INVALID_FORMAT;
|
||||
case BT_TELEPHONY_ERROR_INVALID_STATE:
|
||||
return PW_TELEPHONY_ERROR_INVALID_STATE;
|
||||
case BT_TELEPHONY_ERROR_IN_PROGRESS:
|
||||
return PW_TELEPHONY_ERROR_IN_PROGRESS;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
@ -256,6 +259,8 @@ static const char *telephony_error_to_description (enum spa_bt_telephony_error e
|
|||
return "Invalid phone number or tones";
|
||||
case BT_TELEPHONY_ERROR_INVALID_STATE:
|
||||
return "The current state does not allow this method call";
|
||||
case BT_TELEPHONY_ERROR_IN_PROGRESS:
|
||||
return "Command already in progress";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ enum spa_bt_telephony_error {
|
|||
BT_TELEPHONY_ERROR_NOT_SUPPORTED,
|
||||
BT_TELEPHONY_ERROR_INVALID_FORMAT,
|
||||
BT_TELEPHONY_ERROR_INVALID_STATE,
|
||||
BT_TELEPHONY_ERROR_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum spa_bt_telephony_call_state {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue