fix(bt/bluedroid): Fix HID Device connection failed bug

Closes https://github.com/espressif/esp-idf/issues/13671
pull/14633/head
liqigan 2024-04-23 15:08:27 +08:00 zatwierdzone przez BOT
rodzic cf2bd8029d
commit 970029c2f4
8 zmienionych plików z 69 dodań i 26 usunięć

Wyświetl plik

@ -722,6 +722,26 @@ extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data)
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
}
/*******************************************************************************
*
* Function bta_hd_open_failure
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_open_failure(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
tBTA_HD cback_data = {0};
bdcpy(cback_data.conn.bda, p_cback->addr);
cback_data.conn.status = BTA_HD_ERROR;
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_cback

Wyświetl plik

@ -62,6 +62,7 @@ enum {
BTA_HD_VC_UNPLUG_DONE_ACT,
BTA_HD_SUSPEND_ACT,
BTA_HD_EXIT_SUSPEND_ACT,
BTA_HD_OPEN_FAILURE,
BTA_HD_NUM_ACTIONS
};
@ -74,7 +75,7 @@ const tBTA_HD_ACTION bta_hd_action[] = {
bta_hd_disconnect_act, bta_hd_add_device_act, bta_hd_remove_device_act, bta_hd_send_report_act,
bta_hd_report_error_act, bta_hd_vc_unplug_act, bta_hd_open_act, bta_hd_close_act,
bta_hd_intr_data_act, bta_hd_get_report_act, bta_hd_set_report_act, bta_hd_set_protocol_act,
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act,
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act, bta_hd_open_failure
};
/* state table information */
@ -118,7 +119,7 @@ const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = {
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_OPEN_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_OPEN_FAILURE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},

Wyświetl plik

@ -164,5 +164,6 @@ extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data);
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data);
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data);
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data);
extern void bta_hd_open_failure(tBTA_HD_DATA *p_data);
#endif

Wyświetl plik

@ -261,7 +261,7 @@ static void btc_hd_deinit(void)
}
btc_hd_cb.service_dereg_active = FALSE;
// unresgister app will also relase the connection
// unregister app will also release the connection
// and disable after receiving unregister event from lower layer
if (is_hidd_app_register()) {
btc_hd_unregister_app(true);
@ -844,6 +844,8 @@ void btc_hd_cb_handler(btc_msg_t *msg)
// }
// btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda);
btc_hd_cb.status = BTC_HD_CONNECTED;
} else if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
btc_hd_cb.status = BTC_HD_DISCONNECTED;
}
param.open.status = p_data->conn.status;
param.open.conn_status = p_data->conn.conn_status;

Wyświetl plik

@ -231,7 +231,7 @@ static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
tHID_CONN *p_hcon = &hd_cb.device.conn;
HIDD_TRACE_EVENT("%s: cid=%04x result=%d, conn_state=%d", __func__, cid, result, p_hcon->conn_state);
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) ||
@ -243,10 +243,12 @@ static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
}
if (result != L2CAP_CONN_OK) {
HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__);
if (cid == p_hcon->ctrl_cid)
if (cid == p_hcon->ctrl_cid) {
p_hcon->ctrl_cid = 0;
else
} else {
p_hcon->intr_cid = 0;
}
hidd_conn_disconnect();
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL);
return;
@ -278,7 +280,7 @@ static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
p_hcon = &hd_cb.device.conn;
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE))
@ -297,7 +299,8 @@ static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
// update flags
if (cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE) &&
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
@ -330,7 +333,7 @@ static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid, p_cfg->result);
p_hcon = &hd_cb.device.conn;
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) {
@ -357,7 +360,8 @@ static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
// update flags
if (cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE) &&
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
@ -389,11 +393,14 @@ static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed)
HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (ack_needed)
if (ack_needed) {
L2CA_DisconnectRsp(cid);
}
if (cid == p_hcon->ctrl_cid) {
p_hcon->ctrl_cid = 0;
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
@ -417,7 +424,7 @@ static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed)
*
* Function hidd_l2cif_disconnect_cfm
*
* Description Handles L2CAP disconection response
* Description Handles L2CAP disconnection response
*
* Returns void
*
@ -428,7 +435,7 @@ static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result)
HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (cid == p_hcon->ctrl_cid) {
@ -465,7 +472,7 @@ static void hidd_l2cif_cong_ind(uint16_t cid, bool congested)
HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (congested) {
@ -492,7 +499,7 @@ static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg)
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
osi_free(p_msg);
return;
}
@ -645,7 +652,7 @@ tHID_STATUS hidd_conn_initiate(void)
p_dev->conn.ctrl_cid = 0;
p_dev->conn.intr_cid = 0;
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL;
p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
p_dev->conn.conn_flags |= HID_CONN_FLAGS_IS_ORIG;
BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN);
/* Check if L2CAP started the connection process */
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) {

Wyświetl plik

@ -379,7 +379,6 @@ 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 ;
@ -487,7 +486,6 @@ 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 );
}
@ -666,7 +664,7 @@ BOOLEAN HID_HostConnectOrig(UINT8 dev_handle)
break;
}
ret = hh_cb.devices[dev_handle].is_orig;
ret = hidh_conn_is_orig(dev_handle);
} while (0);
return ret;

Wyświetl plik

@ -457,8 +457,8 @@ static void hidh_l2cif_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
if (l2cap_cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
(p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE) &&
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
/* Connect interrupt channel */
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) {
@ -528,8 +528,8 @@ static void hidh_l2cif_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
if (l2cap_cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
(p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE) &&
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
/* Connect interrupt channel */
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) {
@ -968,7 +968,7 @@ tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
/* We are the originator of this connection */
p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
p_dev->conn.conn_flags |= HID_CONN_FLAGS_IS_ORIG;
if (p_dev->attr_mask & HID_SEC_REQUIRED) {
service_id = BTM_SEC_SERVICE_HIDH_SEC_CTRL;
@ -989,6 +989,20 @@ tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
return ( HID_SUCCESS );
}
/*******************************************************************************
**
** Function hidh_conn_is_orig
**
** Description This function check if we are the originator of this connection
**
** Returns BOOLEAN
**
*******************************************************************************/
BOOLEAN hidh_conn_is_orig(UINT8 dhandle)
{
tHID_HOST_DEV_CTB *p_dev = &hh_cb.devices[dhandle];
return (p_dev->conn.conn_flags & HID_CONN_FLAGS_IS_ORIG);
}
/*******************************************************************************
**

Wyświetl plik

@ -35,7 +35,6 @@ 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; */
@ -66,6 +65,7 @@ extern tHID_STATUS hidh_conn_reg (void);
extern void hidh_conn_dereg( void );
extern tHID_STATUS hidh_conn_disconnect (UINT8 dhandle);
extern tHID_STATUS hidh_conn_initiate (UINT8 dhandle);
extern BOOLEAN hidh_conn_is_orig(UINT8 dhandle);
extern void hidh_proc_repage_timeout (TIMER_LIST_ENT *p_tle);
#ifdef __cplusplus
extern "C" {