Skip to content

Commit 03ca91f

Browse files
lylezhu2012kartben
authored andcommitted
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 <[email protected]>
1 parent 36ec017 commit 03ca91f

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

subsys/bluetooth/host/classic/hfp_ag.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,20 @@ static void ag_notify_call_held_ind(struct bt_hfp_ag *ag, void *user_data)
665665
}
666666
}
667667

668+
static void release_call(struct bt_hfp_ag_call *call)
669+
{
670+
atomic_clear_bit(call->flags, BT_HFP_AG_CALL_IN_USING);
671+
k_work_cancel_delayable(&call->ringing_work);
672+
k_work_cancel_delayable(&call->deferred_work);
673+
/*
674+
* Because it is uncertain whether `ringing_work` and `deferred_work` have been cancelled,
675+
* do not clear ringing_work and deferred_work.
676+
* Use `offsetof()` to get the offset of `ringing_work` to avoid access the fields
677+
* `ringing_work` and `deferred_work`.
678+
*/
679+
(void)memset(call, 0, offsetof(struct bt_hfp_ag_call, ringing_work));
680+
}
681+
668682
static void free_call(struct bt_hfp_ag_call *call)
669683
{
670684
int call_count;
@@ -673,9 +687,7 @@ static void free_call(struct bt_hfp_ag_call *call)
673687

674688
ag = call->ag;
675689

676-
k_work_cancel_delayable(&call->ringing_work);
677-
k_work_cancel_delayable(&call->deferred_work);
678-
memset(call, 0, sizeof(*call));
690+
release_call(call);
679691

680692
call_count = get_none_released_calls(ag);
681693

@@ -3195,7 +3207,6 @@ static void hfp_ag_connected(struct bt_rfcomm_dlc *dlc)
31953207
static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc)
31963208
{
31973209
struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc);
3198-
bt_hfp_call_state_t call_state;
31993210
sys_snode_t *node;
32003211
struct bt_ag_tx *tx;
32013212
struct bt_hfp_ag_call *call;
@@ -3227,15 +3238,11 @@ static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc)
32273238
continue;
32283239
}
32293240

3230-
hfp_ag_lock(ag);
3231-
call_state = call->call_state;
3232-
hfp_ag_unlock(ag);
3233-
if ((call_state == BT_HFP_CALL_ALERTING) || (call_state == BT_HFP_CALL_ACTIVE) ||
3234-
(call_state == BT_HFP_CALL_HOLD)) {
3235-
bt_hfp_ag_terminate_cb(ag, call);
3236-
}
3241+
release_call(call);
32373242
}
32383243

3244+
hfp_ag_close_sco(ag);
3245+
32393246
ag->acl_conn = NULL;
32403247

32413248
LOG_DBG("AG %p", ag);
@@ -3465,6 +3472,12 @@ static void bt_ag_deferred_work(struct k_work *work)
34653472
struct bt_hfp_ag_call *call = CONTAINER_OF(dwork, struct bt_hfp_ag_call, deferred_work);
34663473
struct bt_hfp_ag *ag = call->ag;
34673474

3475+
LOG_DBG("");
3476+
3477+
if (!atomic_test_bit(call->flags, BT_HFP_AG_CALL_IN_USING)) {
3478+
return;
3479+
}
3480+
34683481
(void)hfp_ag_next_step(ag, bt_ag_deferred_work_cb, call);
34693482
}
34703483

@@ -3508,6 +3521,12 @@ static void bt_ag_ringing_work(struct k_work *work)
35083521
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
35093522
struct bt_hfp_ag_call *call = CONTAINER_OF(dwork, struct bt_hfp_ag_call, ringing_work);
35103523

3524+
LOG_DBG("");
3525+
3526+
if (!atomic_test_bit(call->flags, BT_HFP_AG_CALL_IN_USING)) {
3527+
return;
3528+
}
3529+
35113530
(void)hfp_ag_next_step(call->ag, bt_ag_ringing_work_cb, call);
35123531
}
35133532

0 commit comments

Comments
 (0)