Skip to content

zblue: hfp: hf: avoid call hci_send_sync in bluetoothd#392

Open
expliyh wants to merge 1 commit intoopen-vela:devfrom
expliyh:84390
Open

zblue: hfp: hf: avoid call hci_send_sync in bluetoothd#392
expliyh wants to merge 1 commit intoopen-vela:devfrom
expliyh:84390

Conversation

@expliyh
Copy link
Contributor

@expliyh expliyh commented Jan 22, 2026

bug: v/84390

Rootcause: should not call hci_send_sync in bluetoothd

gzh-terry
gzh-terry previously approved these changes Jan 22, 2026
@@ -52,6 +52,14 @@ typedef struct _hf_connect_params {
uint8_t channel;
} hf_connect_params_t;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the advantages of defining a new structure? It's recommended to reuse the original pointers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines 413 to 458
if (!params->sco_conn) {
BT_LOGE("%s, Invalid sco_conn parameter", __func__);
free(params);
Copy link
Contributor

@chengkai15 chengkai15 Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the judgment here is duplicated. Could find_connection_by_sco handle this by checking for null pointers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logs are printed only in the first function called in SAL to avoid duplicate log output.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Zephyr HFP HF SAL implementation to avoid executing potentially blocking/synchronous HCI operations (e.g., those that may invoke hci_send_sync) directly in bluetoothd, by deferring SCO audio connect/disconnect operations to the service loop worker.

Changes:

  • Added dedicated parameter structs for deferred HFP HF SCO connect/disconnect operations.
  • Introduced do_hf_sco_connect() / do_hf_sco_disconnect() worker callbacks.
  • Updated bt_sal_hfp_hf_connect_audio() and bt_sal_hfp_hf_disconnect_audio() to queue work via service_loop_work() instead of calling stack APIs inline.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

hf = params->hf;
free(params);

sal_conn = find_connection_by_hf(hf);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dito

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logs are printed only in the first function called in SAL to avoid duplicate log output.

@expliyh expliyh force-pushed the 84390 branch 2 times, most recently from 1a16b88 to 55c5320 Compare January 30, 2026 03:39
@expliyh expliyh force-pushed the 84390 branch 4 times, most recently from 6ddddf5 to 4ed9b55 Compare February 2, 2026 03:51
@expliyh expliyh force-pushed the 84390 branch 8 times, most recently from b57c1ab to 571ff98 Compare February 3, 2026 03:39
chengkai15
chengkai15 previously approved these changes Feb 3, 2026
BT_LOGE("%s, failed to allocate calls list", __func__);
free(sal_conn);
return NULL;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

newline

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}
}

if (!sal_conn) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a duplicate of line 541.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the address check, since the state machine is responsible for avoiding duplicate connections.

}

bt_hfp_hf_connection_t* sal_conn = find_connection_by_addr(addr);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move the

if (!sal_conn) {
        BT_LOGE("%s, No initiating connection", __func__);
        bt_conn_unref(conn);
        return BT_STATUS_NOMEM;
    }

here would be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't change: This function is invoked twice, and sal_conn == NULL is expected on the first call. Therefore, the check must not be moved.

chengkai15
chengkai15 previously approved these changes Feb 4, 2026
zhangyuan376
zhangyuan376 previously approved these changes Feb 4, 2026
if (do_hf_connect(0 /* bt_controller_id_t */, &bd_addr, NULL) != BT_STATUS_SUCCESS) {
free(g_conn_params);
g_conn_params = NULL;
if (do_hf_connect(0 /* bt_controller_id_t */, &bd_addr, &channel) != BT_STATUS_SUCCESS) {
Copy link
Contributor

@gzh-terry gzh-terry Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add service_loop_work for do_hf_connect as well, so we can ensure that do_hf_connect always happend in worker thread.

Then move these after error:

hfp_hf_on_connection_state_changed(&bd_addr, PROFILE_STATE_DISCONNECTED, 0, 0);
bt_list_remove(g_sal_hf_conn_list, sal_conn);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if do_hf_connect fails, it will report disconnected state. we may report disconnected state twice if we move it after error

bt_address_t addr;
bt_hfp_hf_connection_t* sal_conn;

if (bt_sal_get_remote_address(conn, &addr) != BT_STATUS_SUCCESS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove addr that is never used.

err = Z_API(bt_hfp_hf_audio_connect)(hf);
if (err) {
BT_LOGE("%s, Failed to connect HFP HF SCO, err=%d", __func__, err);
hfp_hf_on_audio_connection_state_changed(&sal_conn->addr, HFP_AUDIO_STATE_DISCONNECTED, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if sal_conn->sco_conn == NULL before this audio connection.
At least, we can report HFP_AUDIO_STATE_CONNECTED when err = -ECONNREFUSED

@expliyh expliyh dismissed stale reviews from chengkai15 and zhangyuan376 via b138dcc February 6, 2026 08:04
@expliyh expliyh force-pushed the 84390 branch 3 times, most recently from c669567 to a1d9da6 Compare February 6, 2026 08:48
BT_LOGE("%s, Previous connection ongoing", __func__);
bt_hfp_hf_connection_t* sal_conn = find_connection_by_addr(addr);
if (sal_conn) {
BT_LOGW("%s, Connection already exists or in progress", __func__);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution:
Before this change, BT_STATUS_BUSY indicated an HFP connection was being established.
After this change, it indicates an HFP connection is either being established or has already been established.

Please double-check that this matches the expected logic.

}
bt_hfp_hf_connection_t* sal_conn = find_connection_by_addr(addr);

BT_LOGD("%s, SDP not discovered", __func__);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log is now incorrect.
We can only say do_hf_sdp_discover is called at this stage.
Nobody knows if SDP is already discovered now.

bt_conn_unref(conn);
return BT_STATUS_FAIL;
}
bt_hfp_hf_connection_t* sal_conn = find_connection_by_addr(addr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put this check before bt_conn_lookup_addr_br

@@ -325,44 +336,32 @@ static bt_status_t do_hf_connect(bt_controller_id_t id, bt_address_t* addr, void
return BT_STATUS_NOT_FOUND;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Report PROFILE_STATE_DISCONNECTED here, since the service is now stay in PROFILE_STATE_CONNECTING

int err;
uint16_t port;

bt_address_t bd_addr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove bd_addr, use sal_conn->addr

BT_LOGE("%s, could not find sal_conn", __func__);
return BT_SDP_DISCOVER_UUID_STOP;
}
if (bt_sal_get_remote_address(conn, &bd_addr) != BT_STATUS_SUCCESS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove bt_sal_get_remote_address, use sal_conn->addr


static void do_hf_slc_connect(service_work_t* work, void* userdata)
{
uint8_t* channel = (uint8_t*)userdata;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove (uint8_t*)
Force cast is not required for void*

return;
}

/* Get the address from the first connection in the list that has no hf */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do this.
Use userdata to transfer any necessary information, for example, conn

bug: v/84390

Rootcause: should not call hci_send_sync in bluetoothd
Signed-off-by: YuhengLi <liyuheng@xiaomi.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants