Merge branch 'bugfix/fix_hid_connection_failed_bug_v4.4' into 'release/v4.4'

fix(bt/bluedroid): Fix HID connection bugs[backport 4.4]

See merge request espressif/esp-idf!30592
This commit is contained in:
Wang Meng Yang 2024-05-21 16:47:07 +08:00
commit 22dd4ba5e8
12 changed files with 120 additions and 43 deletions

View File

@ -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); 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 * Function bta_hd_cback

View File

@ -62,6 +62,7 @@ enum {
BTA_HD_VC_UNPLUG_DONE_ACT, BTA_HD_VC_UNPLUG_DONE_ACT,
BTA_HD_SUSPEND_ACT, BTA_HD_SUSPEND_ACT,
BTA_HD_EXIT_SUSPEND_ACT, BTA_HD_EXIT_SUSPEND_ACT,
BTA_HD_OPEN_FAILURE,
BTA_HD_NUM_ACTIONS 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_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_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_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 */ /* 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_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_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_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_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_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, /* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},

View File

@ -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_vc_unplug_done_act(tBTA_HD_DATA *p_data);
extern void bta_hd_suspend_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_exit_suspend_act(tBTA_HD_DATA *p_data);
extern void bta_hd_open_failure(tBTA_HD_DATA *p_data);
#endif #endif

View File

@ -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); 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); 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; 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) { 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); 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: \ APPL_TRACE_DEBUG ("bta_hh_sdp_cmpl: HID_HostOpenDev failed: \
Status 0x%2X", ret); Status 0x%2X", ret);
#endif #endif
conn_dat.is_orig = HID_HostConnectOrig(p_cb->hid_handle);
/* open fail, remove device from management device list */ /* open fail, remove device from management device list */
HID_HostRemoveDev( p_cb->hid_handle); HID_HostRemoveDev( p_cb->hid_handle);
status = BTA_HH_ERR; 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); HID_HostRemoveDev( p_cb->incoming_hid_handle);
} }
conn_dat.status = status; 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); (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
/* move state machine W4_CONN ->IDLE */ /* 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)); memset((void *)&conn, 0, sizeof (tBTA_HH_CONN));
conn.handle = dev_handle; conn.handle = dev_handle;
/* check if host initiate the connection*/ conn.is_orig = HID_HostConnectOrig(dev_handle);
conn.is_orig = !p_cb->incoming_conn;
bdcpy(conn.bda, p_cb->addr); bdcpy(conn.bda, p_cb->addr);
/* increase connection number */ /* 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) { if (p_cb->app_id != 0) {
bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data); bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
} else } 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 */ performed, do it first */
{ {
/* store the handle here in case sdp fails - need to disconnect */ /* 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 ** Function bta_hh_handsk_act
** **
** Description HID Host process a handshake acknoledgement. ** Description HID Host process a handshake acknowledgement.
** **
** **
** Returns void ** 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; p_cb->w4_evt = 0;
break; 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_RPT_EVT:
case BTA_HH_SET_PROTO_EVT: case BTA_HH_SET_PROTO_EVT:
case BTA_HH_SET_IDLE_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: case BTA_HH_OPEN_EVT:
conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK; conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK;
conn.handle = p_cb->hid_handle; conn.handle = p_cb->hid_handle;
/* check if host initiate the connection*/ conn.is_orig = HID_HostConnectOrig(p_cb->hid_handle);
conn.is_orig = !p_cb->incoming_conn;
bdcpy(conn.bda, p_cb->addr); bdcpy(conn.bda, p_cb->addr);
(* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn); (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn);
#if BTA_HH_DEBUG #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; break;
default: default:
/* unknow transaction handshake response */ /* unknown transaction handshake response */
APPL_TRACE_DEBUG("unknown transaction type"); APPL_TRACE_DEBUG("unknown transaction type");
break; 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); bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
return; 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) ? conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ?
BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR; BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
/* check if host initiate the connection*/ /* 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); bdcpy(conn_dat.bda, p_cb->addr);
HID_HostCloseDev(p_cb->hid_handle); 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 */ /* Check reason for closing */
if ((reason & (HID_L2CAP_CONN_FAIL | HID_L2CAP_REQ_FAIL)) || /* Failure to initialize connection (page timeout or l2cap error) */ 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 */ (reason == HID_ERR_L2CAP_FAILED)) { /* Failure creating l2cap connection */
/* Failure in opening connection */ /* Failure in opening connection */
conn_dat.handle = p_cb->hid_handle; conn_dat.handle = p_cb->hid_handle;
conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR; conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
/* check if host initiate the connection*/ /* 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); bdcpy(conn_dat.bda, p_cb->addr);
HID_HostCloseDev(p_cb->hid_handle); HID_HostCloseDev(p_cb->hid_handle);

View File

@ -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.status = BTA_HH_ERR_DB_FULL;
cback_data.conn.handle = BTA_HH_INVALID_HANDLE; cback_data.conn.handle = BTA_HH_INVALID_HANDLE;
/* check if host initiate the connection*/ /* check if host initiate the connection*/
cback_data.conn.is_orig = !p_cb->incoming_conn; cback_data.conn.is_orig = TRUE;
break; break;
/* DB full, BTA_HhAddDev */ /* DB full, BTA_HhAddDev */
case BTA_HH_API_MAINT_DEV_EVT: case BTA_HH_API_MAINT_DEV_EVT:

View File

@ -261,7 +261,7 @@ static void btc_hd_deinit(void)
} }
btc_hd_cb.service_dereg_active = FALSE; 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 // and disable after receiving unregister event from lower layer
if (is_hidd_app_register()) { if (is_hidd_app_register()) {
btc_hd_unregister_app(true); 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_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda);
btc_hd_cb.status = BTC_HD_CONNECTED; 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.status = p_data->conn.status;
param.open.conn_status = p_data->conn.conn_status; param.open.conn_status = p_data->conn.conn_status;

View File

@ -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 * Function btc_hh_stop_vup_timer
* *
* Description stop vitual unplug timer * Description stop virtual unplug timer
* *
* Returns void * 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++) { for (i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
p_added_dev = &btc_hh_cb.added_devices[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); BTA_HhRemoveDev(p_added_dev->dev_handle);
btc_storage_remove_hid_info((bt_bdaddr_t *)p_added_dev->bd_addr); btc_storage_remove_hid_info((bt_bdaddr_t *)p_added_dev->bd_addr);
memset(p_added_dev->bd_addr, 0, 6); 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); BTC_TRACE_ERROR("%s exceeded the maximum supported HID device number %d!", __func__, BTC_HH_MAX_HID);
ret = ESP_HIDH_ERR_NO_RES; ret = ESP_HIDH_ERR_NO_RES;
break; 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++) { 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.conn_status = ESP_HIDH_CONN_STATE_DISCONNECTING;
param.unplug.handle = p_dev->dev_handle; param.unplug.handle = p_dev->dev_handle;
} else if ((p_dev != NULL) && (p_dev->dev_status == ESP_HIDH_CONN_STATE_CONNECTED)) { } 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 */ /* start the timer */
btc_hh_start_vup_timer(arg->unplug.bd_addr); btc_hh_start_vup_timer(arg->unplug.bd_addr);
p_dev->local_vup = true; p_dev->local_vup = true;

View File

@ -231,7 +231,7 @@ static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
tHID_CONN *p_hcon = &hd_cb.device.conn; 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); 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) { 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; return;
} }
if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) || 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) { if (result != L2CAP_CONN_OK) {
HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__); 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; p_hcon->ctrl_cid = 0;
else } else {
p_hcon->intr_cid = 0; p_hcon->intr_cid = 0;
}
hidd_conn_disconnect(); hidd_conn_disconnect();
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL); hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL);
return; 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); HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
p_hcon = &hd_cb.device.conn; p_hcon = &hd_cb.device.conn;
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) { 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; return;
} }
if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE)) 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 // update flags
if (cid == p_hcon->ctrl_cid) { if (cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE; 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; p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) { if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
p_hcon->conn_state = HID_CONN_STATE_UNUSED; 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); HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid, p_cfg->result);
p_hcon = &hd_cb.device.conn; p_hcon = &hd_cb.device.conn;
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) { 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; return;
} }
if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) { 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 // update flags
if (cid == p_hcon->ctrl_cid) { if (cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE; 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; p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) { if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
p_hcon->conn_state = HID_CONN_STATE_UNUSED; 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); HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed);
p_hcon = &hd_cb.device.conn; 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)) { 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; return;
} }
if (ack_needed)
if (ack_needed) {
L2CA_DisconnectRsp(cid); L2CA_DisconnectRsp(cid);
}
if (cid == p_hcon->ctrl_cid) { if (cid == p_hcon->ctrl_cid) {
p_hcon->ctrl_cid = 0; p_hcon->ctrl_cid = 0;
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL; 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 * Function hidd_l2cif_disconnect_cfm
* *
* Description Handles L2CAP disconection response * Description Handles L2CAP disconnection response
* *
* Returns void * 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); HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result);
p_hcon = &hd_cb.device.conn; 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)) { 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; return;
} }
if (cid == p_hcon->ctrl_cid) { 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); HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested);
p_hcon = &hd_cb.device.conn; 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)) { 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; return;
} }
if (congested) { 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); HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
p_hcon = &hd_cb.device.conn; 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)) { 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); osi_free(p_msg);
return; return;
} }
@ -645,7 +652,7 @@ tHID_STATUS hidd_conn_initiate(void)
p_dev->conn.ctrl_cid = 0; p_dev->conn.ctrl_cid = 0;
p_dev->conn.intr_cid = 0; p_dev->conn.intr_cid = 0;
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL; 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); BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN);
/* Check if L2CAP started the connection process */ /* Check if L2CAP started the connection process */
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) { if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) {

View File

@ -651,4 +651,23 @@ BOOLEAN hid_known_hid_device (BD_ADDR bd_addr)
return FALSE; 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 = hidh_conn_is_orig(dev_handle);
} while (0);
return ret;
}
#endif //HID_HOST_INCLUDED #endif //HID_HOST_INCLUDED

View File

@ -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) { if (l2cap_cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE; p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE) &&
(p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) { (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
/* Connect interrupt channel */ /* Connect interrupt channel */
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */ 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) { 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) { if (l2cap_cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE; p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE) &&
(p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) { (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
/* Connect interrupt channel */ /* Connect interrupt channel */
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */ 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) { 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 */ 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 */ /* 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) { if (p_dev->attr_mask & HID_SEC_REQUIRED) {
service_id = BTM_SEC_SERVICE_HIDH_SEC_CTRL; service_id = BTM_SEC_SERVICE_HIDH_SEC_CTRL;
@ -989,6 +989,20 @@ tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
return ( HID_SUCCESS ); 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);
}
/******************************************************************************* /*******************************************************************************
** **

View File

@ -39,7 +39,6 @@ typedef struct per_device_ctb {
UINT16 attr_mask; /* 0x01- virtual_cable; 0x02- normally_connectable; 0x03- reconn_initiate; UINT16 attr_mask; /* 0x01- virtual_cable; 0x02- normally_connectable; 0x03- reconn_initiate;
0x04- sdp_disable; */ 0x04- sdp_disable; */
UINT8 state; /* Device state if in HOST-KNOWN mode */ UINT8 state; /* Device state if in HOST-KNOWN mode */
UINT8 conn_substate;
UINT8 conn_tries; /* Remembers to the number of connection attempts while CONNECTING */ UINT8 conn_tries; /* Remembers to the number of connection attempts while CONNECTING */
tHID_CONN conn; /* L2CAP channel info */ tHID_CONN conn; /* L2CAP channel info */
@ -66,6 +65,7 @@ extern tHID_STATUS hidh_conn_reg (void);
extern void hidh_conn_dereg( void ); extern void hidh_conn_dereg( void );
extern tHID_STATUS hidh_conn_disconnect (UINT8 dhandle); extern tHID_STATUS hidh_conn_disconnect (UINT8 dhandle);
extern tHID_STATUS hidh_conn_initiate (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); extern void hidh_proc_repage_timeout (TIMER_LIST_ENT *p_tle);
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -249,6 +249,17 @@ BOOLEAN hid_known_hid_device (BD_ADDR bd_addr);
*******************************************************************************/ *******************************************************************************/
extern UINT8 HID_HostSetTraceLevel (UINT8 new_level); 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 #ifdef __cplusplus
} }
#endif #endif