From: Ivan Podogov Date: Thu, 19 Jan 2017 17:19:37 +0000 (+0000) Subject: HID: Fix forced disconnection flow. X-Git-Tag: android-x86-8.1-r1~196^2~19^2~42^2~49 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=367373ba8bcfb1d9db41b1904de372483991fc10;p=android-x86%2Fsystem-bt.git HID: Fix forced disconnection flow. In some cases, we end up in a state where we can neither connect nor forcefully end connection, and will require disabling the Bluetooth adapter to fix this state. When a device is taking too long to connect (or out of range), the user may want to cancel the connection by calling disconnect method, which will be ignored in any state other than BTA_HD_CONN_ST. It is a lot better to immediately cease the connection process at this point, so: - BTA_HD_API_DISCONNECT_EVT is now not ignored in BTA_HD_IDLE_ST; - bta_hd_disconnect_act now reports a correct MAC address during disconnection (it used to send 00:00:00:00:00:00 before); - HidDevDisconnect now allows to forcefully end the connection, and does it in exactly the same way we handle the errors. When L2CAP connection fails, both hidd_l2cif_config_ind and hidd_l2cif_config_cfm set conn_state to HID_CONN_STATE_UNUSED, which is immediately overwritten by the hidd_conn_disconnect call (it will set conn_state to HID_CONN_STATE_DISCONNECTING, because ctrl_cid != 0 in both cases), thus making any subsequent calls to connect failing with "already connecting" error. More than that, all functions send the HID_DHOST_EVT_CLOSE event when failing, which is, again, ignored in the BTA_HD_IDLE_ST state. So: - BTA_HD_INT_CLOSE_EVT is now not ignored in BTA_HD_IDLE_ST; - conn_state is set to HID_CONN_STATE_UNUSED after the call to hidd_conn_disconnect, but before sending the close event. Test: Build, run, connect/disconnect multiple times. Change-Id: I85bb03f760bb9a6fd4c1b944d515232c1be12300 --- diff --git a/bta/hd/bta_hd_act.cc b/bta/hd/bta_hd_act.cc index 613d2983b..da36482e1 100644 --- a/bta/hd/bta_hd_act.cc +++ b/bta/hd/bta_hd_act.cc @@ -305,10 +305,10 @@ extern void bta_hd_disconnect_act(UNUSED_ATTR tBTA_HD_DATA* p_data) { return; } - bdcpy(cback_data.conn.bda, bta_hd_cb.bd_addr); - cback_data.conn.status = BTHD_CONN_STATE_DISCONNECTING; - - bta_hd_cb.p_cback(BTA_HD_CONN_STATE_EVT, &cback_data); + if (HID_DevGetDevice(&cback_data.conn.bda) == HID_SUCCESS) { + cback_data.conn.status = BTHD_CONN_STATE_DISCONNECTING; + bta_hd_cb.p_cback(BTA_HD_CONN_STATE_EVT, &cback_data); + } } /******************************************************************************* diff --git a/bta/hd/bta_hd_main.cc b/bta/hd/bta_hd_main.cc index 3e4fa574a..02577f645 100644 --- a/bta/hd/bta_hd_main.cc +++ b/bta/hd/bta_hd_main.cc @@ -122,14 +122,14 @@ const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = { /* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, /* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_UNREGISTER_ACT, BTA_HD_INIT_ST}, /* BTA_HD_API_CONNECT_EVT */ {BTA_HD_CONNECT_ACT, BTA_HD_IDLE_ST}, - /* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST}, + /* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_IDLE_ST}, /* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_IDLE_ST}, /* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_IDLE_ST}, /* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, 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_IGNORE, 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_CLOSE_ACT, 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}, diff --git a/stack/hid/hidd_api.cc b/stack/hid/hidd_api.cc index adaba584d..bce5ef520 100644 --- a/stack/hid/hidd_api.cc +++ b/stack/hid/hidd_api.cc @@ -496,6 +496,14 @@ tHID_STATUS HID_DevDisconnect(void) { } if (hd_cb.device.state == HIDD_DEV_NO_CONN) { + /* If we are still trying to connect, just close the connection. */ + if (hd_cb.device.conn.conn_state != HID_CONN_STATE_UNUSED) { + tHID_STATUS ret = hidd_conn_disconnect(); + hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED; + hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, + HID_ERR_DISCONNECTING, NULL); + return ret; + } return HID_ERR_NO_CONNECTION; } diff --git a/stack/hid/hidd_conn.cc b/stack/hid/hidd_conn.cc index 19f81e736..c76e545c9 100644 --- a/stack/hid/hidd_conn.cc +++ b/stack/hid/hidd_conn.cc @@ -373,8 +373,8 @@ static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) { 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; hidd_conn_disconnect(); + p_hcon->conn_state = HID_CONN_STATE_UNUSED; HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", __func__); @@ -456,8 +456,8 @@ static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) { 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; hidd_conn_disconnect(); + p_hcon->conn_state = HID_CONN_STATE_UNUSED; HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", __func__);