Loading system/bta/hh/bta_hh_act.cc +1 −1 Original line number Diff line number Diff line Loading @@ -989,7 +989,7 @@ void bta_hh_close_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { void bta_hh_get_dscp_act(tBTA_HH_DEV_CB* p_cb, UNUSED_ATTR const tBTA_HH_DATA* p_data) { if (p_cb->is_le_device) { if (p_cb->hid_srvc.in_use) { if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED) { p_cb->dscp_info.hid_handle = p_cb->hid_handle; } bta_hh_le_get_dscp_act(p_cb); Loading system/bta/hh/bta_hh_int.h +7 −1 Original line number Diff line number Diff line Loading @@ -147,8 +147,14 @@ typedef struct { #define BTA_HH_LE_RPT_MAX 20 #endif enum tBTA_HH_SERVICE_STATE { BTA_HH_SERVICE_UNKNOWN, BTA_HH_SERVICE_CHANGED, BTA_HH_SERVICE_DISCOVERED, }; typedef struct { bool in_use; tBTA_HH_SERVICE_STATE state; uint8_t srvc_inst_id; tBTA_HH_LE_RPT report[BTA_HH_LE_RPT_MAX]; Loading system/bta/hh/bta_hh_le.cc +133 −33 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ static const char* bta_hh_le_rpt_name[4] = {"UNKNOWN", "INPUT", "OUTPUT", static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB* p_cb) { APPL_TRACE_DEBUG("%s: HID Report DB", __func__); if (!p_cb->hid_srvc.in_use) return; if (p_cb->hid_srvc.state < BTA_HH_SERVICE_DISCOVERED) return; tBTA_HH_LE_RPT* p_rpt = &p_cb->hid_srvc.report[0]; Loading Loading @@ -304,7 +304,8 @@ static tBTA_HH_DEV_CB* bta_hh_le_find_dev_cb_by_bda(const RawAddress& bda) { ******************************************************************************/ static uint8_t bta_hh_le_find_service_inst_by_battery_inst_id( tBTA_HH_DEV_CB* p_cb, uint8_t ba_inst_id) { if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.incl_srvc_inst == ba_inst_id) { if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED && p_cb->hid_srvc.incl_srvc_inst == ba_inst_id) { return p_cb->hid_srvc.srvc_inst_id; } return BTA_HH_IDX_INVALID; Loading Loading @@ -849,7 +850,8 @@ static void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB* p_cb) { tBTA_HH_HSDATA hs_data; p_cb->w4_evt = BTA_HH_GET_PROTO_EVT; if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.proto_mode_handle != 0) { if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED && p_cb->hid_srvc.proto_mode_handle != 0) { BtaGattQueue::ReadCharacteristic(p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle, get_protocol_mode_cb, p_cb); Loading Loading @@ -877,8 +879,18 @@ static void bta_hh_le_dis_cback(const RawAddress& addr, tDIS_VALUE* p_dis_value) { tBTA_HH_DEV_CB* p_cb = bta_hh_le_find_dev_cb_by_bda(addr); if (p_cb == NULL || p_dis_value == NULL) { APPL_TRACE_ERROR("received unexpected/error DIS callback"); if (p_cb == nullptr) { LOG_WARN("Unknown address"); return; } if (p_cb->status == BTA_HH_ERR_SDP) { LOG_WARN("HID service was not found"); return; } if (p_dis_value == nullptr) { LOG_WARN("Invalid value"); return; } Loading Loading @@ -965,7 +977,7 @@ void bta_hh_security_cmpl(tBTA_HH_DEV_CB* p_cb, UNUSED_ATTR const tBTA_HH_DATA* p_buf) { APPL_TRACE_DEBUG("%s", __func__); if (p_cb->status == BTA_HH_OK) { if (!p_cb->hid_srvc.in_use) { if (p_cb->hid_srvc.state < BTA_HH_SERVICE_DISCOVERED) { APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load"); /* start loading the cache if not in stack */ Loading @@ -977,7 +989,8 @@ void bta_hh_security_cmpl(tBTA_HH_DEV_CB* p_cb, } } /* discovery has been done for HID service */ if (p_cb->app_id != 0 && p_cb->hid_srvc.in_use) { if (p_cb->app_id != 0 && p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED) { APPL_TRACE_DEBUG("%s: discovery has been done for HID service", __func__); /* configure protocol mode */ if (!bta_hh_le_set_protocol_mode(p_cb, p_cb->mode)) { Loading Loading @@ -1148,6 +1161,14 @@ static void bta_hh_le_close(const tBTA_GATTC_CLOSE& gattc_data) { ADDRESS_TO_LOGGABLE_CSTR(gattc_data.remote_bda)); return; } if (p_cb->hid_srvc.state == BTA_HH_SERVICE_CHANGED) { /* Service change would have already prompted a local disconnection */ LOG_WARN("Disconnected after service changed indication:%s", ADDRESS_TO_LOGGABLE_CSTR(gattc_data.remote_bda)); return; } p_cb->conn_id = GATT_INVALID_CONN_ID; p_cb->security_pending = false; Loading Loading @@ -1449,14 +1470,15 @@ static void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL* p_data) { if (p_dev_cb == NULL) return; if (p_data->status != GATT_SUCCESS) { LOG_ERROR("Service discovery failed %d", p_data->status); p_dev_cb->status = BTA_HH_ERR_SDP; /* close the connection and report service discovery complete with error */ bta_hh_le_api_disc_act(p_dev_cb); return; } const std::list<gatt::Service>* services = BTA_GATTC_GetServices(p_data->conn_id); const std::list<gatt::Service>* services = BTA_GATTC_GetServices(p_data->conn_id); const gatt::Service* gap_service = nullptr; const gatt::Service* scp_service = nullptr; bool have_hid = false; for (const gatt::Service& service : *services) { Loading @@ -1465,7 +1487,7 @@ static void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL* p_data) { have_hid = true; /* found HID primamry service */ p_dev_cb->hid_srvc.in_use = true; p_dev_cb->hid_srvc.state = BTA_HH_SERVICE_DISCOVERED; p_dev_cb->hid_srvc.srvc_inst_id = service.handle; p_dev_cb->hid_srvc.proto_mode_handle = 0; p_dev_cb->hid_srvc.control_point_handle = 0; Loading @@ -1475,31 +1497,42 @@ static void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL* p_data) { APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__, p_dev_cb->hid_srvc.srvc_inst_id); } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_SCAN_PARAM)) { for (const gatt::Characteristic& charac : service.characteristics) { if (charac.uuid == Uuid::From16Bit(GATT_UUID_SCAN_REFRESH)) { if (charac.properties & GATT_CHAR_PROP_BIT_NOTIFY) p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT; else p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE; break; scp_service = &service; } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { gap_service = &service; } } } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { // TODO(jpawlowski): this should be done by GAP profile, remove when GAP // is fixed. for (const gatt::Characteristic& charac : service.characteristics) { if (!have_hid) { LOG_ERROR("HID service not found"); p_dev_cb->status = BTA_HH_ERR_SDP; bta_hh_le_api_disc_act(p_dev_cb); return; } if (gap_service != nullptr) { // TODO: This should be done by GAP profile, remove when GAP is fixed. for (const gatt::Characteristic& charac : gap_service->characteristics) { if (charac.uuid == Uuid::From16Bit(GATT_UUID_GAP_PREF_CONN_PARAM)) { /* read the char value */ BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id, charac.value_handle, BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id, charac.value_handle, read_pref_conn_params_cb, p_dev_cb); break; } } } if (scp_service != nullptr) { for (const gatt::Characteristic& charac : scp_service->characteristics) { if (charac.uuid == Uuid::From16Bit(GATT_UUID_SCAN_REFRESH)) { if (charac.properties & GATT_CHAR_PROP_BIT_NOTIFY) { p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT; } else { p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE; } break; } } } bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status); Loading Loading @@ -1600,7 +1633,7 @@ void bta_hh_le_open_fail(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { bta_hh_clear_service_cache(p_cb); } if (p_cb->is_le_device) { if (p_cb->is_le_device && p_cb->status != BTA_HH_ERR_SDP) { LOG_DEBUG("gd_acl: Re-adding HID device to acceptlist"); // gd removes from bg list after failed connection // Correct the cached state to allow re-add to acceptlist. Loading Loading @@ -1965,7 +1998,7 @@ void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { * ******************************************************************************/ void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB* p_cb) { if (p_cb->hid_srvc.in_use) { if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED) { p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc.descriptor.dl_len; p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc.descriptor.dsc_list; Loading Loading @@ -2063,6 +2096,65 @@ void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB* p_dev_cb) { bta_hh_le_deregister_input_notif(p_dev_cb); } static void bta_hh_le_service_changed(RawAddress remote_bda) { tBTA_HH_DEV_CB* p_cb = bta_hh_le_find_dev_cb_by_bda(remote_bda); if (p_cb == nullptr) { LOG_WARN("Received close event with unknown device:%s", ADDRESS_TO_LOGGABLE_CSTR(remote_bda)); return; } /* Forget the cached reports */ bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id); p_cb->dscp_info.descriptor.dsc_list = NULL; osi_free_and_reset((void**)&p_cb->hid_srvc.rpt_map); p_cb->hid_srvc = {}; p_cb->hid_srvc.state = BTA_HH_SERVICE_CHANGED; p_cb->status = BTA_HH_HS_SERVICE_CHANGED; /* Pretend that the HOGP device disconnected so that higher layers don't try to communicate with it while the GATT database is rediscovered. */ const tBTA_HH_DATA data = { .le_close = { .conn_id = p_cb->conn_id, .reason = GATT_CONN_OK, .hdr = { .event = BTA_HH_GATT_CLOSE_EVT, .layer_specific = static_cast<uint16_t>(p_cb->hid_handle), }, }, }; bta_hh_sm_execute(p_cb, BTA_HH_GATT_CLOSE_EVT, &data); } static void bta_hh_le_service_discovery_done(RawAddress remote_bda) { tBTA_HH_DEV_CB* p_cb = bta_hh_le_find_dev_cb_by_bda(remote_bda); if (p_cb == nullptr) { LOG_WARN("Received service discovery done event for unknown device:%s", ADDRESS_TO_LOGGABLE_CSTR(remote_bda)); return; } if (p_cb->hid_srvc.state == BTA_HH_SERVICE_CHANGED) { /* Service rediscovery completed after service change. Pretend to have connected with a new HOGP device. */ p_cb->hid_srvc.state = BTA_HH_SERVICE_UNKNOWN; const tBTA_GATTC_OPEN open = { .status = GATT_SUCCESS, .conn_id = p_cb->conn_id, .client_if = bta_hh_cb.gatt_if, .remote_bda = remote_bda, .transport = BT_TRANSPORT_LE, .mtu = 0, }; bta_hh_sm_execute(p_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA*)&open); } else { LOG_INFO("Discovery done, service state: %d", p_cb->hid_srvc.state); } } /******************************************************************************* * * Function bta_hh_gattc_callback Loading Loading @@ -2104,6 +2196,14 @@ static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { bta_hh_le_input_rpt_notify(&p_data->notify); break; case BTA_GATTC_SRVC_CHG_EVT: bta_hh_le_service_changed(p_data->remote_bda); break; case BTA_GATTC_SRVC_DISC_DONE_EVT: bta_hh_le_service_discovery_done(p_data->remote_bda); break; case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */ p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda); if (p_dev_cb) { Loading Loading @@ -2134,7 +2234,7 @@ static void bta_hh_process_cache_rpt(tBTA_HH_DEV_CB* p_cb, if (num_rpt != 0) /* no cache is found */ { p_cb->hid_srvc.in_use = true; p_cb->hid_srvc.state = BTA_HH_SERVICE_UNKNOWN; /* set the descriptor info */ p_cb->hid_srvc.descriptor.dl_len = p_cb->dscp_info.descriptor.dl_len; Loading system/bta/include/bta_hh_api.h +2 −1 Original line number Diff line number Diff line Loading @@ -138,7 +138,8 @@ typedef enum : uint8_t { BTA_HH_ERR_NO_RES, /* out of system resources */ BTA_HH_ERR_AUTH_FAILED, /* authentication fail */ BTA_HH_ERR_HDL, BTA_HH_ERR_SEC BTA_HH_ERR_SEC, BTA_HH_HS_SERVICE_CHANGED /* GATT service changed on the peer */ } tBTA_HH_STATUS; inline tBTA_HH_STATUS to_bta_hh_status(uint32_t status) { Loading system/btif/src/btif_hh.cc +7 −0 Original line number Diff line number Diff line Loading @@ -878,6 +878,13 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) { if (p_dev->local_vup) { p_dev->local_vup = false; BTA_DmRemoveDevice(p_dev->bd_addr); } else if (p_data->dev_status.status == BTA_HH_HS_SERVICE_CHANGED) { /* Local disconnection due to service change in the HOGP device. HID descriptor would be read again, so remove it from cache. */ LOG_WARN( "Removing cached descriptor due to service change, handle = %d", p_data->dev_status.handle); btif_storage_remove_hid_info(p_dev->bd_addr); } btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED; Loading Loading
system/bta/hh/bta_hh_act.cc +1 −1 Original line number Diff line number Diff line Loading @@ -989,7 +989,7 @@ void bta_hh_close_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { void bta_hh_get_dscp_act(tBTA_HH_DEV_CB* p_cb, UNUSED_ATTR const tBTA_HH_DATA* p_data) { if (p_cb->is_le_device) { if (p_cb->hid_srvc.in_use) { if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED) { p_cb->dscp_info.hid_handle = p_cb->hid_handle; } bta_hh_le_get_dscp_act(p_cb); Loading
system/bta/hh/bta_hh_int.h +7 −1 Original line number Diff line number Diff line Loading @@ -147,8 +147,14 @@ typedef struct { #define BTA_HH_LE_RPT_MAX 20 #endif enum tBTA_HH_SERVICE_STATE { BTA_HH_SERVICE_UNKNOWN, BTA_HH_SERVICE_CHANGED, BTA_HH_SERVICE_DISCOVERED, }; typedef struct { bool in_use; tBTA_HH_SERVICE_STATE state; uint8_t srvc_inst_id; tBTA_HH_LE_RPT report[BTA_HH_LE_RPT_MAX]; Loading
system/bta/hh/bta_hh_le.cc +133 −33 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ static const char* bta_hh_le_rpt_name[4] = {"UNKNOWN", "INPUT", "OUTPUT", static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB* p_cb) { APPL_TRACE_DEBUG("%s: HID Report DB", __func__); if (!p_cb->hid_srvc.in_use) return; if (p_cb->hid_srvc.state < BTA_HH_SERVICE_DISCOVERED) return; tBTA_HH_LE_RPT* p_rpt = &p_cb->hid_srvc.report[0]; Loading Loading @@ -304,7 +304,8 @@ static tBTA_HH_DEV_CB* bta_hh_le_find_dev_cb_by_bda(const RawAddress& bda) { ******************************************************************************/ static uint8_t bta_hh_le_find_service_inst_by_battery_inst_id( tBTA_HH_DEV_CB* p_cb, uint8_t ba_inst_id) { if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.incl_srvc_inst == ba_inst_id) { if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED && p_cb->hid_srvc.incl_srvc_inst == ba_inst_id) { return p_cb->hid_srvc.srvc_inst_id; } return BTA_HH_IDX_INVALID; Loading Loading @@ -849,7 +850,8 @@ static void bta_hh_le_get_protocol_mode(tBTA_HH_DEV_CB* p_cb) { tBTA_HH_HSDATA hs_data; p_cb->w4_evt = BTA_HH_GET_PROTO_EVT; if (p_cb->hid_srvc.in_use && p_cb->hid_srvc.proto_mode_handle != 0) { if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED && p_cb->hid_srvc.proto_mode_handle != 0) { BtaGattQueue::ReadCharacteristic(p_cb->conn_id, p_cb->hid_srvc.proto_mode_handle, get_protocol_mode_cb, p_cb); Loading Loading @@ -877,8 +879,18 @@ static void bta_hh_le_dis_cback(const RawAddress& addr, tDIS_VALUE* p_dis_value) { tBTA_HH_DEV_CB* p_cb = bta_hh_le_find_dev_cb_by_bda(addr); if (p_cb == NULL || p_dis_value == NULL) { APPL_TRACE_ERROR("received unexpected/error DIS callback"); if (p_cb == nullptr) { LOG_WARN("Unknown address"); return; } if (p_cb->status == BTA_HH_ERR_SDP) { LOG_WARN("HID service was not found"); return; } if (p_dis_value == nullptr) { LOG_WARN("Invalid value"); return; } Loading Loading @@ -965,7 +977,7 @@ void bta_hh_security_cmpl(tBTA_HH_DEV_CB* p_cb, UNUSED_ATTR const tBTA_HH_DATA* p_buf) { APPL_TRACE_DEBUG("%s", __func__); if (p_cb->status == BTA_HH_OK) { if (!p_cb->hid_srvc.in_use) { if (p_cb->hid_srvc.state < BTA_HH_SERVICE_DISCOVERED) { APPL_TRACE_DEBUG("bta_hh_security_cmpl no reports loaded, try to load"); /* start loading the cache if not in stack */ Loading @@ -977,7 +989,8 @@ void bta_hh_security_cmpl(tBTA_HH_DEV_CB* p_cb, } } /* discovery has been done for HID service */ if (p_cb->app_id != 0 && p_cb->hid_srvc.in_use) { if (p_cb->app_id != 0 && p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED) { APPL_TRACE_DEBUG("%s: discovery has been done for HID service", __func__); /* configure protocol mode */ if (!bta_hh_le_set_protocol_mode(p_cb, p_cb->mode)) { Loading Loading @@ -1148,6 +1161,14 @@ static void bta_hh_le_close(const tBTA_GATTC_CLOSE& gattc_data) { ADDRESS_TO_LOGGABLE_CSTR(gattc_data.remote_bda)); return; } if (p_cb->hid_srvc.state == BTA_HH_SERVICE_CHANGED) { /* Service change would have already prompted a local disconnection */ LOG_WARN("Disconnected after service changed indication:%s", ADDRESS_TO_LOGGABLE_CSTR(gattc_data.remote_bda)); return; } p_cb->conn_id = GATT_INVALID_CONN_ID; p_cb->security_pending = false; Loading Loading @@ -1449,14 +1470,15 @@ static void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL* p_data) { if (p_dev_cb == NULL) return; if (p_data->status != GATT_SUCCESS) { LOG_ERROR("Service discovery failed %d", p_data->status); p_dev_cb->status = BTA_HH_ERR_SDP; /* close the connection and report service discovery complete with error */ bta_hh_le_api_disc_act(p_dev_cb); return; } const std::list<gatt::Service>* services = BTA_GATTC_GetServices(p_data->conn_id); const std::list<gatt::Service>* services = BTA_GATTC_GetServices(p_data->conn_id); const gatt::Service* gap_service = nullptr; const gatt::Service* scp_service = nullptr; bool have_hid = false; for (const gatt::Service& service : *services) { Loading @@ -1465,7 +1487,7 @@ static void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL* p_data) { have_hid = true; /* found HID primamry service */ p_dev_cb->hid_srvc.in_use = true; p_dev_cb->hid_srvc.state = BTA_HH_SERVICE_DISCOVERED; p_dev_cb->hid_srvc.srvc_inst_id = service.handle; p_dev_cb->hid_srvc.proto_mode_handle = 0; p_dev_cb->hid_srvc.control_point_handle = 0; Loading @@ -1475,31 +1497,42 @@ static void bta_hh_le_srvc_search_cmpl(tBTA_GATTC_SEARCH_CMPL* p_data) { APPL_TRACE_DEBUG("%s: have HID service inst_id= %d", __func__, p_dev_cb->hid_srvc.srvc_inst_id); } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_SCAN_PARAM)) { for (const gatt::Characteristic& charac : service.characteristics) { if (charac.uuid == Uuid::From16Bit(GATT_UUID_SCAN_REFRESH)) { if (charac.properties & GATT_CHAR_PROP_BIT_NOTIFY) p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT; else p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE; break; scp_service = &service; } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { gap_service = &service; } } } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { // TODO(jpawlowski): this should be done by GAP profile, remove when GAP // is fixed. for (const gatt::Characteristic& charac : service.characteristics) { if (!have_hid) { LOG_ERROR("HID service not found"); p_dev_cb->status = BTA_HH_ERR_SDP; bta_hh_le_api_disc_act(p_dev_cb); return; } if (gap_service != nullptr) { // TODO: This should be done by GAP profile, remove when GAP is fixed. for (const gatt::Characteristic& charac : gap_service->characteristics) { if (charac.uuid == Uuid::From16Bit(GATT_UUID_GAP_PREF_CONN_PARAM)) { /* read the char value */ BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id, charac.value_handle, BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id, charac.value_handle, read_pref_conn_params_cb, p_dev_cb); break; } } } if (scp_service != nullptr) { for (const gatt::Characteristic& charac : scp_service->characteristics) { if (charac.uuid == Uuid::From16Bit(GATT_UUID_SCAN_REFRESH)) { if (charac.properties & GATT_CHAR_PROP_BIT_NOTIFY) { p_dev_cb->scps_notify |= BTA_HH_LE_SCPS_NOTIFY_SPT; } else { p_dev_cb->scps_notify = BTA_HH_LE_SCPS_NOTIFY_NONE; } break; } } } bta_hh_le_gatt_disc_cmpl(p_dev_cb, p_dev_cb->status); Loading Loading @@ -1600,7 +1633,7 @@ void bta_hh_le_open_fail(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { bta_hh_clear_service_cache(p_cb); } if (p_cb->is_le_device) { if (p_cb->is_le_device && p_cb->status != BTA_HH_ERR_SDP) { LOG_DEBUG("gd_acl: Re-adding HID device to acceptlist"); // gd removes from bg list after failed connection // Correct the cached state to allow re-add to acceptlist. Loading Loading @@ -1965,7 +1998,7 @@ void bta_hh_le_write_dev_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { * ******************************************************************************/ void bta_hh_le_get_dscp_act(tBTA_HH_DEV_CB* p_cb) { if (p_cb->hid_srvc.in_use) { if (p_cb->hid_srvc.state >= BTA_HH_SERVICE_DISCOVERED) { p_cb->dscp_info.descriptor.dl_len = p_cb->hid_srvc.descriptor.dl_len; p_cb->dscp_info.descriptor.dsc_list = p_cb->hid_srvc.descriptor.dsc_list; Loading Loading @@ -2063,6 +2096,65 @@ void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB* p_dev_cb) { bta_hh_le_deregister_input_notif(p_dev_cb); } static void bta_hh_le_service_changed(RawAddress remote_bda) { tBTA_HH_DEV_CB* p_cb = bta_hh_le_find_dev_cb_by_bda(remote_bda); if (p_cb == nullptr) { LOG_WARN("Received close event with unknown device:%s", ADDRESS_TO_LOGGABLE_CSTR(remote_bda)); return; } /* Forget the cached reports */ bta_hh_le_co_reset_rpt_cache(p_cb->addr, p_cb->app_id); p_cb->dscp_info.descriptor.dsc_list = NULL; osi_free_and_reset((void**)&p_cb->hid_srvc.rpt_map); p_cb->hid_srvc = {}; p_cb->hid_srvc.state = BTA_HH_SERVICE_CHANGED; p_cb->status = BTA_HH_HS_SERVICE_CHANGED; /* Pretend that the HOGP device disconnected so that higher layers don't try to communicate with it while the GATT database is rediscovered. */ const tBTA_HH_DATA data = { .le_close = { .conn_id = p_cb->conn_id, .reason = GATT_CONN_OK, .hdr = { .event = BTA_HH_GATT_CLOSE_EVT, .layer_specific = static_cast<uint16_t>(p_cb->hid_handle), }, }, }; bta_hh_sm_execute(p_cb, BTA_HH_GATT_CLOSE_EVT, &data); } static void bta_hh_le_service_discovery_done(RawAddress remote_bda) { tBTA_HH_DEV_CB* p_cb = bta_hh_le_find_dev_cb_by_bda(remote_bda); if (p_cb == nullptr) { LOG_WARN("Received service discovery done event for unknown device:%s", ADDRESS_TO_LOGGABLE_CSTR(remote_bda)); return; } if (p_cb->hid_srvc.state == BTA_HH_SERVICE_CHANGED) { /* Service rediscovery completed after service change. Pretend to have connected with a new HOGP device. */ p_cb->hid_srvc.state = BTA_HH_SERVICE_UNKNOWN; const tBTA_GATTC_OPEN open = { .status = GATT_SUCCESS, .conn_id = p_cb->conn_id, .client_if = bta_hh_cb.gatt_if, .remote_bda = remote_bda, .transport = BT_TRANSPORT_LE, .mtu = 0, }; bta_hh_sm_execute(p_cb, BTA_HH_GATT_OPEN_EVT, (tBTA_HH_DATA*)&open); } else { LOG_INFO("Discovery done, service state: %d", p_cb->hid_srvc.state); } } /******************************************************************************* * * Function bta_hh_gattc_callback Loading Loading @@ -2104,6 +2196,14 @@ static void bta_hh_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { bta_hh_le_input_rpt_notify(&p_data->notify); break; case BTA_GATTC_SRVC_CHG_EVT: bta_hh_le_service_changed(p_data->remote_bda); break; case BTA_GATTC_SRVC_DISC_DONE_EVT: bta_hh_le_service_discovery_done(p_data->remote_bda); break; case BTA_GATTC_ENC_CMPL_CB_EVT: /* 17 */ p_dev_cb = bta_hh_le_find_dev_cb_by_bda(p_data->enc_cmpl.remote_bda); if (p_dev_cb) { Loading Loading @@ -2134,7 +2234,7 @@ static void bta_hh_process_cache_rpt(tBTA_HH_DEV_CB* p_cb, if (num_rpt != 0) /* no cache is found */ { p_cb->hid_srvc.in_use = true; p_cb->hid_srvc.state = BTA_HH_SERVICE_UNKNOWN; /* set the descriptor info */ p_cb->hid_srvc.descriptor.dl_len = p_cb->dscp_info.descriptor.dl_len; Loading
system/bta/include/bta_hh_api.h +2 −1 Original line number Diff line number Diff line Loading @@ -138,7 +138,8 @@ typedef enum : uint8_t { BTA_HH_ERR_NO_RES, /* out of system resources */ BTA_HH_ERR_AUTH_FAILED, /* authentication fail */ BTA_HH_ERR_HDL, BTA_HH_ERR_SEC BTA_HH_ERR_SEC, BTA_HH_HS_SERVICE_CHANGED /* GATT service changed on the peer */ } tBTA_HH_STATUS; inline tBTA_HH_STATUS to_bta_hh_status(uint32_t status) { Loading
system/btif/src/btif_hh.cc +7 −0 Original line number Diff line number Diff line Loading @@ -878,6 +878,13 @@ static void btif_hh_upstreams_evt(uint16_t event, char* p_param) { if (p_dev->local_vup) { p_dev->local_vup = false; BTA_DmRemoveDevice(p_dev->bd_addr); } else if (p_data->dev_status.status == BTA_HH_HS_SERVICE_CHANGED) { /* Local disconnection due to service change in the HOGP device. HID descriptor would be read again, so remove it from cache. */ LOG_WARN( "Removing cached descriptor due to service change, handle = %d", p_data->dev_status.handle); btif_storage_remove_hid_info(p_dev->bd_addr); } btif_hh_cb.status = (BTIF_HH_STATUS)BTIF_HH_DEV_DISCONNECTED; Loading