Merge branch 'bugfix/fix_hidh_connection_bug' into 'master'

Bugfix/Fix HID Host bug when handling the two consecutive connection request

Closes IDFGH-9100

See merge request espressif/esp-idf!21988
This commit is contained in:
Jiang Jiang Jian 2023-03-10 03:48:48 +08:00
commit 1f05281913
7 changed files with 45 additions and 17 deletions

View File

@ -459,8 +459,7 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
/* move state machine W4_CONN ->IDLE */
bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
/* if this is an outgoing connection to an unknown device, clean up cb */
if (p_cb->app_id == 0 && !p_cb->incoming_conn) {
if (p_cb->app_id == 0) {
/* clean up device control block */
bta_hh_clean_up_kdev(p_cb);
}

View File

@ -88,6 +88,7 @@ UINT8 bta_hh_find_cb(BD_ADDR bda)
for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
if (!bta_hh_cb.kdev[xx].in_use) {
bdcpy(bta_hh_cb.kdev[xx].addr, bda);
bta_hh_cb.kdev[xx].in_use = TRUE;
break;
}
}

View File

@ -378,6 +378,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;
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 ;
@ -443,10 +444,20 @@ tHID_STATUS HID_HostRemoveDev ( UINT8 dev_handle )
}
HID_HostCloseDev( dev_handle ) ;
hh_cb.devices[dev_handle].in_use = FALSE;
hh_cb.devices[dev_handle].conn.conn_state = HID_CONN_STATE_UNUSED;
hh_cb.devices[dev_handle].conn.ctrl_cid = hh_cb.devices[dev_handle].conn.intr_cid = 0;
hh_cb.devices[dev_handle].attr_mask = 0;
if (hh_cb.devices[dev_handle].conn.conn_state == HID_CONN_STATE_DISCONNECTING_INTR ||
hh_cb.devices[dev_handle].conn.conn_state == HID_CONN_STATE_DISCONNECTING_CTRL) {
// delay the remove action, to close the control and the interrupt channel
hh_cb.devices[dev_handle].delay_remove = TRUE;
} else {
HIDH_TRACE_WARNING("%s dev_handle:%d conn_state:%d", __func__, dev_handle,
hh_cb.devices[dev_handle].conn.conn_state);
hh_cb.devices[dev_handle].in_use = FALSE;
hh_cb.devices[dev_handle].conn.conn_state = HID_CONN_STATE_UNUSED;
hh_cb.devices[dev_handle].conn.ctrl_cid = hh_cb.devices[dev_handle].conn.intr_cid = 0;
hh_cb.devices[dev_handle].attr_mask = 0;
}
return HID_SUCCESS;
}

View File

@ -110,6 +110,7 @@ tHID_STATUS hidh_conn_reg (void)
for (xx = 0; xx < HID_HOST_MAX_DEVICES; xx++) {
hh_cb.devices[xx].in_use = FALSE ;
hh_cb.devices[xx].delay_remove = FALSE;
hh_cb.devices[xx].conn.conn_state = HID_CONN_STATE_UNUSED;
}
@ -681,6 +682,12 @@ static void hidh_l2cif_disconnect_cfm (UINT16 l2cap_cid, UINT16 result)
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
hh_cb.devices[dhandle].state = HID_DEV_NO_CONN;
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
// removes the device from list devices that host has to manage
if (hh_cb.devices[dhandle].delay_remove) {
hh_cb.devices[dhandle].in_use = FALSE;
hh_cb.devices[dhandle].delay_remove = FALSE;
hh_cb.devices[dhandle].attr_mask = 0;
}
hh_cb.callback( dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, p_hcon->disc_reason, NULL ) ;
}
}

View File

@ -34,6 +34,7 @@ enum { HID_DEV_NO_CONN, HID_DEV_CONNECTED };
typedef struct per_device_ctb {
BOOLEAN in_use;
BOOLEAN delay_remove;
BD_ADDR addr; /* BD-Addr of the host device */
UINT16 attr_mask; /* 0x01- virtual_cable; 0x02- normally_connectable; 0x03- reconn_initiate;
0x04- sdp_disable; */

View File

@ -244,17 +244,15 @@ static void esp_hh_cb(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param)
break;
} else {
ESP_LOGD(TAG, "incoming device connect");
if (param->open.status == ESP_HIDH_OK) {
if ((dev = hidh_dev_ctor(param->open.bd_addr)) == NULL) {
ESP_LOGE(TAG, "%s create device failed!", __func__);
param->open.status = ESP_HIDH_ERR_NO_RES;
break;
}
esp_hidh_dev_lock(dev);
dev->opened = false; // not opened by ourself
dev->is_orig = false;
esp_hidh_dev_unlock(dev);
if ((dev = hidh_dev_ctor(param->open.bd_addr)) == NULL) {
ESP_LOGE(TAG, "%s create device failed!", __func__);
param->open.status = ESP_HIDH_ERR_NO_RES;
break;
}
esp_hidh_dev_lock(dev);
dev->opened = false; // not opened by ourself
dev->is_orig = false;
esp_hidh_dev_unlock(dev);
}
}

View File

@ -11,6 +11,9 @@
#include <string.h>
#include <stdbool.h>
#include "esp_event_base.h"
#if CONFIG_BT_HID_HOST_ENABLED
#include "esp_hidh_api.h"
#endif /* CONFIG_BT_HID_HOST_ENABLED */
ESP_EVENT_DEFINE_BASE(ESP_HIDH_EVENTS);
#define ESP_HIDH_DELAY_FREE_TO 100000 // us
@ -801,7 +804,15 @@ void esp_hidh_post_process_event_handler(void *event_handler_arg, esp_event_base
switch (event) {
case ESP_HIDH_OPEN_EVENT:
if (param->open.status != ESP_OK) {
esp_hidh_dev_free_inner(param->open.dev);
esp_hidh_dev_t *dev = param->open.dev;
if (dev) {
#if CONFIG_BT_HID_HOST_ENABLED
if (esp_hidh_dev_transport_get(dev) == ESP_HID_TRANSPORT_BT && param->open.status == ESP_HIDH_ERR_SDP) {
break;
}
#endif /* CONFIG_BT_HID_HOST_ENABLED */
esp_hidh_dev_free_inner(dev);
}
}
break;
case ESP_HIDH_CLOSE_EVENT: