Bluetooth: Classic: HFP_AG: Don't change call status if SLC broken
In current implementation, the active/hold call will be terminated and notify the upper layer the status change of calls when the SLC is broken. But the calls should not be terminated in this case. Do not terminate the calls and only clear the status of all calls. And disconnect the SCO connection if it is established. Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
This commit is contained in:
parent
36ec017a38
commit
03ca91fef4
1 changed files with 30 additions and 11 deletions
|
@ -665,6 +665,20 @@ static void ag_notify_call_held_ind(struct bt_hfp_ag *ag, void *user_data)
|
|||
}
|
||||
}
|
||||
|
||||
static void release_call(struct bt_hfp_ag_call *call)
|
||||
{
|
||||
atomic_clear_bit(call->flags, BT_HFP_AG_CALL_IN_USING);
|
||||
k_work_cancel_delayable(&call->ringing_work);
|
||||
k_work_cancel_delayable(&call->deferred_work);
|
||||
/*
|
||||
* Because it is uncertain whether `ringing_work` and `deferred_work` have been cancelled,
|
||||
* do not clear ringing_work and deferred_work.
|
||||
* Use `offsetof()` to get the offset of `ringing_work` to avoid access the fields
|
||||
* `ringing_work` and `deferred_work`.
|
||||
*/
|
||||
(void)memset(call, 0, offsetof(struct bt_hfp_ag_call, ringing_work));
|
||||
}
|
||||
|
||||
static void free_call(struct bt_hfp_ag_call *call)
|
||||
{
|
||||
int call_count;
|
||||
|
@ -673,9 +687,7 @@ static void free_call(struct bt_hfp_ag_call *call)
|
|||
|
||||
ag = call->ag;
|
||||
|
||||
k_work_cancel_delayable(&call->ringing_work);
|
||||
k_work_cancel_delayable(&call->deferred_work);
|
||||
memset(call, 0, sizeof(*call));
|
||||
release_call(call);
|
||||
|
||||
call_count = get_none_released_calls(ag);
|
||||
|
||||
|
@ -3195,7 +3207,6 @@ static void hfp_ag_connected(struct bt_rfcomm_dlc *dlc)
|
|||
static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc)
|
||||
{
|
||||
struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc);
|
||||
bt_hfp_call_state_t call_state;
|
||||
sys_snode_t *node;
|
||||
struct bt_ag_tx *tx;
|
||||
struct bt_hfp_ag_call *call;
|
||||
|
@ -3227,15 +3238,11 @@ static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc)
|
|||
continue;
|
||||
}
|
||||
|
||||
hfp_ag_lock(ag);
|
||||
call_state = call->call_state;
|
||||
hfp_ag_unlock(ag);
|
||||
if ((call_state == BT_HFP_CALL_ALERTING) || (call_state == BT_HFP_CALL_ACTIVE) ||
|
||||
(call_state == BT_HFP_CALL_HOLD)) {
|
||||
bt_hfp_ag_terminate_cb(ag, call);
|
||||
}
|
||||
release_call(call);
|
||||
}
|
||||
|
||||
hfp_ag_close_sco(ag);
|
||||
|
||||
ag->acl_conn = NULL;
|
||||
|
||||
LOG_DBG("AG %p", ag);
|
||||
|
@ -3465,6 +3472,12 @@ static void bt_ag_deferred_work(struct k_work *work)
|
|||
struct bt_hfp_ag_call *call = CONTAINER_OF(dwork, struct bt_hfp_ag_call, deferred_work);
|
||||
struct bt_hfp_ag *ag = call->ag;
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
if (!atomic_test_bit(call->flags, BT_HFP_AG_CALL_IN_USING)) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)hfp_ag_next_step(ag, bt_ag_deferred_work_cb, call);
|
||||
}
|
||||
|
||||
|
@ -3508,6 +3521,12 @@ static void bt_ag_ringing_work(struct k_work *work)
|
|||
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
|
||||
struct bt_hfp_ag_call *call = CONTAINER_OF(dwork, struct bt_hfp_ag_call, ringing_work);
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
if (!atomic_test_bit(call->flags, BT_HFP_AG_CALL_IN_USING)) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)hfp_ag_next_step(call->ag, bt_ag_ringing_work_cb, call);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue