zblue: hfp: hf: avoid call hci_send_sync in bluetoothd#392
zblue: hfp: hf: avoid call hci_send_sync in bluetoothd#392expliyh wants to merge 1 commit intoopen-vela:devfrom
Conversation
| @@ -52,6 +52,14 @@ typedef struct _hf_connect_params { | |||
| uint8_t channel; | |||
| } hf_connect_params_t; | |||
|
|
|||
There was a problem hiding this comment.
What are the advantages of defining a new structure? It's recommended to reuse the original pointers.
| if (!params->sco_conn) { | ||
| BT_LOGE("%s, Invalid sco_conn parameter", __func__); | ||
| free(params); |
There was a problem hiding this comment.
It seems that the judgment here is duplicated. Could find_connection_by_sco handle this by checking for null pointers?
There was a problem hiding this comment.
Logs are printed only in the first function called in SAL to avoid duplicate log output.
There was a problem hiding this comment.
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()andbt_sal_hfp_hf_disconnect_audio()to queue work viaservice_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); |
There was a problem hiding this comment.
Logs are printed only in the first function called in SAL to avoid duplicate log output.
1a16b88 to
55c5320
Compare
6ddddf5 to
4ed9b55
Compare
b57c1ab to
571ff98
Compare
| BT_LOGE("%s, failed to allocate calls list", __func__); | ||
| free(sal_conn); | ||
| return NULL; | ||
| } |
| } | ||
| } | ||
|
|
||
| if (!sal_conn) { |
There was a problem hiding this comment.
It is a duplicate of line 541.
There was a problem hiding this comment.
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); | ||
|
|
There was a problem hiding this comment.
move the
if (!sal_conn) {
BT_LOGE("%s, No initiating connection", __func__);
bt_conn_unref(conn);
return BT_STATUS_NOMEM;
}
here would be better.
There was a problem hiding this comment.
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.
| 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) { |
There was a problem hiding this comment.
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);
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
Check if sal_conn->sco_conn == NULL before this audio connection.
At least, we can report HFP_AUDIO_STATE_CONNECTED when err = -ECONNREFUSED
c669567 to
a1d9da6
Compare
| 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__); |
There was a problem hiding this comment.
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__); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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; | |||
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 */ |
There was a problem hiding this comment.
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>
bug: v/84390
Rootcause: should not call hci_send_sync in bluetoothd