From a91bee2b4c89dbd95c729f5e6bf5d23c396dd0b1 Mon Sep 17 00:00:00 2001 From: liqigan Date: Wed, 10 Apr 2024 14:58:50 +0800 Subject: [PATCH] fix(bt/bluedroid): Fix HID Host connection bugs 1. Fix is_orig value inconsistency for HIDH open event 2. Fix the error state for repeat connection of the same device --- .../bt/host/bluedroid/bta/hh/bta_hh_act.c | 29 +++++++++---------- .../bt/host/bluedroid/bta/hh/bta_hh_main.c | 2 +- .../bluedroid/btc/profile/std/hid/btc_hh.c | 11 +++++-- .../bt/host/bluedroid/stack/hid/hidh_api.c | 21 ++++++++++++++ .../bluedroid/stack/hid/include/hid_int.h | 2 +- .../bluedroid/stack/include/stack/hidh_api.h | 11 +++++++ 6 files changed, 55 insertions(+), 21 deletions(-) diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_act.c b/components/bt/host/bluedroid/bta/hh/bta_hh_act.c index 604b5e95b5..6d933ee870 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_act.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_act.c @@ -276,7 +276,7 @@ static void bta_hh_di_sdp_cback(UINT16 result) bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0); } - } else { /* no DI recrod available */ + } else { /* no DI record available */ bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0); } @@ -358,7 +358,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) return; } - /* GetSDPRecord. at one time only one SDP precedure can be active */ + /* GetSDPRecord. at one time only one SDP procedure can be active */ else if (!bta_hh_cb.p_disc_db) { bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *) osi_malloc(p_bta_hh_cfg->sdp_db_size); @@ -429,6 +429,7 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl: HID_HostOpenDev failed: \ Status 0x%2X", ret); #endif + conn_dat.is_orig = HID_HostConnectOrig(p_cb->hid_handle); /* open fail, remove device from management device list */ HID_HostRemoveDev( p_cb->hid_handle); status = BTA_HH_ERR; @@ -452,8 +453,6 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) HID_HostRemoveDev( p_cb->incoming_hid_handle); } conn_dat.status = status; - /* check if host initiate the connection*/ - conn_dat.is_orig = !p_cb->incoming_conn; (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat); /* move state machine W4_CONN ->IDLE */ @@ -523,8 +522,7 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) memset((void *)&conn, 0, sizeof (tBTA_HH_CONN)); conn.handle = dev_handle; - /* check if host initiate the connection*/ - conn.is_orig = !p_cb->incoming_conn; + conn.is_orig = HID_HostConnectOrig(dev_handle); bdcpy(conn.bda, p_cb->addr); /* increase connection number */ @@ -596,7 +594,7 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) if (p_cb->app_id != 0) { bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data); } else - /* app_id == 0 indicates an incoming conenction request arrives without SDP + /* app_id == 0 indicates an incoming connection request arrives without SDP performed, do it first */ { /* store the handle here in case sdp fails - need to disconnect */ @@ -637,7 +635,7 @@ void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) ** ** Function bta_hh_handsk_act ** -** Description HID Host process a handshake acknoledgement. +** Description HID Host process a handshake acknowledgement. ** ** ** Returns void @@ -674,7 +672,7 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) p_cb->w4_evt = 0; break; - /* acknoledgement from HID device for SET_ transaction */ + /* acknowledgement from HID device for SET_ transaction */ case BTA_HH_SET_RPT_EVT: case BTA_HH_SET_PROTO_EVT: case BTA_HH_SET_IDLE_EVT : @@ -693,8 +691,7 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) case BTA_HH_OPEN_EVT: conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK; conn.handle = p_cb->hid_handle; - /* check if host initiate the connection*/ - conn.is_orig = !p_cb->incoming_conn; + conn.is_orig = HID_HostConnectOrig(p_cb->hid_handle); bdcpy(conn.bda, p_cb->addr); (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn); #if BTA_HH_DEBUG @@ -704,12 +701,12 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) break; default: - /* unknow transaction handshake response */ + /* unknown transaction handshake response */ APPL_TRACE_DEBUG("unknown transaction type"); break; } - /* transaction achknoledgement received, inform PM for mode change */ + /* transaction acknowledgement received, inform PM for mode change */ bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr); return; } @@ -799,7 +796,7 @@ void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR; /* check if host initiate the connection*/ - conn_dat.is_orig = !p_cb->incoming_conn; + conn_dat.is_orig = HID_HostConnectOrig(p_cb->hid_handle); bdcpy(conn_dat.bda, p_cb->addr); HID_HostCloseDev(p_cb->hid_handle); @@ -844,13 +841,13 @@ void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) /* Check reason for closing */ if ((reason & (HID_L2CAP_CONN_FAIL | HID_L2CAP_REQ_FAIL)) || /* Failure to initialize connection (page timeout or l2cap error) */ - (reason == HID_ERR_AUTH_FAILED) || /* Authenication error (while initiating) */ + (reason == HID_ERR_AUTH_FAILED) || /* Authentication error (while initiating) */ (reason == HID_ERR_L2CAP_FAILED)) { /* Failure creating l2cap connection */ /* Failure in opening connection */ conn_dat.handle = p_cb->hid_handle; conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR; /* check if host initiate the connection*/ - conn_dat.is_orig = !p_cb->incoming_conn; + conn_dat.is_orig = HID_HostConnectOrig(p_cb->hid_handle); bdcpy(conn_dat.bda, p_cb->addr); HID_HostCloseDev(p_cb->hid_handle); diff --git a/components/bt/host/bluedroid/bta/hh/bta_hh_main.c b/components/bt/host/bluedroid/bta/hh/bta_hh_main.c index 663d28e96f..19f1045b1b 100644 --- a/components/bt/host/bluedroid/bta/hh/bta_hh_main.c +++ b/components/bt/host/bluedroid/bta/hh/bta_hh_main.c @@ -293,7 +293,7 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data) cback_data.conn.status = BTA_HH_ERR_DB_FULL; cback_data.conn.handle = BTA_HH_INVALID_HANDLE; /* check if host initiate the connection*/ - cback_data.conn.is_orig = !p_cb->incoming_conn; + cback_data.conn.is_orig = TRUE; break; /* DB full, BTA_HhAddDev */ case BTA_HH_API_MAINT_DEV_EVT: diff --git a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c index 7202371e7b..1d6f20201e 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c +++ b/components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c @@ -189,7 +189,7 @@ static btc_hh_device_t *btc_hh_find_connected_dev_by_bda(BD_ADDR bd_addr) * * Function btc_hh_stop_vup_timer * - * Description stop vitual unplug timer + * Description stop virtual unplug timer * * Returns void ******************************************************************************/ @@ -316,7 +316,7 @@ void btc_hh_remove_device(BD_ADDR bd_addr) for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) { p_added_dev = &btc_hh_cb.added_devices[i]; - if (p_added_dev->bd_addr == bd_addr) { + if (memcmp(p_added_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0) { BTA_HhRemoveDev(p_added_dev->dev_handle); btc_storage_remove_hid_info((bt_bdaddr_t *)p_added_dev->bd_addr); memset(p_added_dev->bd_addr, 0, 6); @@ -544,6 +544,11 @@ static void btc_hh_connect(btc_hidh_args_t *arg) BTC_TRACE_ERROR("%s exceeded the maximum supported HID device number %d!", __func__, BTC_HH_MAX_HID); ret = ESP_HIDH_ERR_NO_RES; break; + } else if (dev && dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED) { + BTC_TRACE_WARNING("%s Device[%s] already connected", __func__, + bdaddr_to_string((const bt_bdaddr_t *)arg->connect.bd_addr, bdstr, sizeof(bdstr))); + param.open.conn_status = ESP_HIDH_CONN_STATE_CONNECTED; + break; } for (int i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) { @@ -662,7 +667,7 @@ static void btc_hh_virtual_unplug(btc_hidh_args_t *arg) param.unplug.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING; param.unplug.handle = p_dev->dev_handle; } else if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED)) { - BTC_TRACE_WARNING("%s: Virtual unplug not suported, disconnecting device", __func__); + BTC_TRACE_WARNING("%s: Virtual unplug not supported, disconnecting device", __func__); /* start the timer */ btc_hh_start_vup_timer(arg->unplug.bd_addr); p_dev->local_vup = true; diff --git a/components/bt/host/bluedroid/stack/hid/hidh_api.c b/components/bt/host/bluedroid/stack/hid/hidh_api.c index ea8e73a75c..bacc5a016a 100644 --- a/components/bt/host/bluedroid/stack/hid/hidh_api.c +++ b/components/bt/host/bluedroid/stack/hid/hidh_api.c @@ -379,6 +379,7 @@ tHID_STATUS HID_HostAddDev ( BD_ADDR addr, UINT16 attr_mask, UINT8 *handle ) if (!hh_cb.devices[i].in_use) { hh_cb.devices[i].in_use = TRUE; hh_cb.devices[i].delay_remove = FALSE; + hh_cb.devices[i].is_orig = FALSE; memcpy( hh_cb.devices[i].addr, addr, sizeof( BD_ADDR ) ) ; hh_cb.devices[i].state = HID_DEV_NO_CONN; hh_cb.devices[i].conn_tries = 0 ; @@ -486,6 +487,7 @@ tHID_STATUS HID_HostOpenDev ( UINT8 dev_handle ) } hh_cb.devices[dev_handle].conn_tries = 1; + hh_cb.devices[dev_handle].is_orig = TRUE; return hidh_conn_initiate( dev_handle ); } @@ -651,4 +653,23 @@ BOOLEAN hid_known_hid_device (BD_ADDR bd_addr) return FALSE; } +BOOLEAN HID_HostConnectOrig(UINT8 dev_handle) +{ + BOOLEAN ret = FALSE; + + do { + if (!hh_cb.reg_flag) { + break; + } + + if ((dev_handle >= HID_HOST_MAX_DEVICES) || (!hh_cb.devices[dev_handle].in_use)) { + break; + } + + ret = hh_cb.devices[dev_handle].is_orig; + } while (0); + + return ret; +} + #endif //HID_HOST_INCLUDED diff --git a/components/bt/host/bluedroid/stack/hid/include/hid_int.h b/components/bt/host/bluedroid/stack/hid/include/hid_int.h index b42089662d..865aadf966 100644 --- a/components/bt/host/bluedroid/stack/hid/include/hid_int.h +++ b/components/bt/host/bluedroid/stack/hid/include/hid_int.h @@ -35,11 +35,11 @@ enum { HID_DEV_NO_CONN, HID_DEV_CONNECTED }; typedef struct per_device_ctb { BOOLEAN in_use; BOOLEAN delay_remove; + BOOLEAN is_orig; BD_ADDR addr; /* BD-Addr of the host device */ UINT16 attr_mask; /* 0x01- virtual_cable; 0x02- normally_connectable; 0x03- reconn_initiate; 0x04- sdp_disable; */ UINT8 state; /* Device state if in HOST-KNOWN mode */ - UINT8 conn_substate; UINT8 conn_tries; /* Remembers to the number of connection attempts while CONNECTING */ tHID_CONN conn; /* L2CAP channel info */ diff --git a/components/bt/host/bluedroid/stack/include/stack/hidh_api.h b/components/bt/host/bluedroid/stack/include/stack/hidh_api.h index 2ddaf1c51a..2445163db5 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hidh_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/hidh_api.h @@ -249,6 +249,17 @@ BOOLEAN hid_known_hid_device (BD_ADDR bd_addr); *******************************************************************************/ extern UINT8 HID_HostSetTraceLevel (UINT8 new_level); +/******************************************************************************* +** +** Function HID_HostConnectOrig +** +** Description Check if the HID Host initiates the connection +** +** Returns TRUE if the HID Host initiates the connection else FALSE +** +*******************************************************************************/ +extern BOOLEAN HID_HostConnectOrig(UINT8 dev_handle); + #ifdef __cplusplus } #endif