| /****************************************************************************** |
| * |
| * Copyright (C) 2009-2014 Broadcom Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ******************************************************************************/ |
| |
| /******************************************************************************* |
| * |
| * Filename: btif_gatt_client.c |
| * |
| * Description: GATT client implementation |
| * |
| *******************************************************************************/ |
| |
| #define LOG_TAG "bt_btif_gattc" |
| |
| #include <base/at_exit.h> |
| #include <base/bind.h> |
| #include <base/threading/thread.h> |
| #include <errno.h> |
| #include <hardware/bluetooth.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unordered_set> |
| #include "device/include/controller.h" |
| |
| #include "btcore/include/bdaddr.h" |
| #include "btif_common.h" |
| #include "btif_util.h" |
| |
| #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE)) |
| |
| #include <hardware/bt_gatt.h> |
| |
| #include "bta_api.h" |
| #include "bta_gatt_api.h" |
| #include "btif_config.h" |
| #include "btif_dm.h" |
| #include "btif_gatt.h" |
| #include "btif_gatt_multi_adv_util.h" |
| #include "btif_gatt_util.h" |
| #include "btif_storage.h" |
| #include "btif_storage.h" |
| #include "osi/include/log.h" |
| #include "vendor_api.h" |
| |
| using base::Bind; |
| using base::Owned; |
| |
| extern bt_status_t do_in_jni_thread(const base::Closure &task); |
| extern bt_status_t btif_gattc_test_command_impl(int command, |
| btgatt_test_params_t *params); |
| extern const btgatt_callbacks_t *bt_gatt_callbacks; |
| |
| /******************************************************************************* |
| ** Constants & Macros |
| ********************************************************************************/ |
| |
| #define CLI_CBACK_IN_JNI(P_CBACK, ...) \ |
| if (bt_gatt_callbacks && bt_gatt_callbacks->client->P_CBACK) { \ |
| BTIF_TRACE_API("HAL bt_gatt_callbacks->client->%s", #P_CBACK); \ |
| do_in_jni_thread(Bind(bt_gatt_callbacks->client->P_CBACK, __VA_ARGS__)); \ |
| } else { \ |
| ASSERTC(0, "Callback is NULL", 0); \ |
| } |
| |
| #define CHECK_BTGATT_INIT() \ |
| if (bt_gatt_callbacks == NULL) { \ |
| LOG_WARN(LOG_TAG, "%s: BTGATT not initialized", __FUNCTION__); \ |
| return BT_STATUS_NOT_READY; \ |
| } else { \ |
| LOG_VERBOSE(LOG_TAG, "%s", __FUNCTION__); \ |
| } |
| |
| #define BLE_RESOLVE_ADDR_MSB 0x40 /* bit7, bit6 is 01 to be resolvable random \ |
| */ |
| #define BLE_RESOLVE_ADDR_MASK 0xc0 /* bit 6, and bit7 */ |
| #define BTM_BLE_IS_RESOLVE_BDA(x) \ |
| (((x)[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB) |
| |
| namespace std { |
| template <> |
| struct hash<bt_bdaddr_t> { |
| size_t operator()(const bt_bdaddr_t &f) const { |
| return f.address[0] + f.address[1] + f.address[2] + f.address[3] + |
| f.address[4] + f.address[5]; |
| } |
| }; |
| |
| template <> |
| struct equal_to<bt_bdaddr_t> { |
| size_t operator()(const bt_bdaddr_t &x, const bt_bdaddr_t &y) const { |
| return memcmp(x.address, y.address, BD_ADDR_LEN); |
| } |
| }; |
| } |
| |
| namespace { |
| |
| std::unordered_set<bt_bdaddr_t> p_dev_cb; |
| uint8_t rssi_request_client_if; |
| |
| bt_status_t btif_gattc_multi_adv_disable(int client_if); |
| void btif_multi_adv_stop_cb(void *data) { |
| int client_if = PTR_TO_INT(data); |
| btif_gattc_multi_adv_disable(client_if); // Does context switch |
| } |
| |
| btgattc_error_t btif_gattc_translate_btm_status(tBTM_STATUS status) { |
| switch (status) { |
| case BTM_SUCCESS: |
| case BTM_SUCCESS_NO_SECURITY: |
| return BT_GATTC_COMMAND_SUCCESS; |
| |
| case BTM_CMD_STARTED: |
| return BT_GATTC_COMMAND_STARTED; |
| |
| case BTM_BUSY: |
| return BT_GATTC_COMMAND_BUSY; |
| |
| case BTM_CMD_STORED: |
| return BT_GATTC_COMMAND_STORED; |
| |
| case BTM_NO_RESOURCES: |
| return BT_GATTC_NO_RESOURCES; |
| |
| case BTM_MODE_UNSUPPORTED: |
| case BTM_WRONG_MODE: |
| case BTM_MODE4_LEVEL4_NOT_SUPPORTED: |
| return BT_GATTC_MODE_UNSUPPORTED; |
| |
| case BTM_ILLEGAL_VALUE: |
| case BTM_SCO_BAD_LENGTH: |
| return BT_GATTC_ILLEGAL_VALUE; |
| |
| case BTM_UNKNOWN_ADDR: |
| return BT_GATTC_UNKNOWN_ADDR; |
| |
| case BTM_DEVICE_TIMEOUT: |
| return BT_GATTC_DEVICE_TIMEOUT; |
| |
| case BTM_FAILED_ON_SECURITY: |
| case BTM_REPEATED_ATTEMPTS: |
| case BTM_NOT_AUTHORIZED: |
| return BT_GATTC_SECURITY_ERROR; |
| |
| case BTM_DEV_RESET: |
| case BTM_ILLEGAL_ACTION: |
| return BT_GATTC_INCORRECT_STATE; |
| |
| case BTM_BAD_VALUE_RET: |
| return BT_GATTC_INVALID_CONTROLLER_OUTPUT; |
| |
| case BTM_DELAY_CHECK: |
| return BT_GATTC_DELAYED_ENCRYPTION_CHECK; |
| |
| case BTM_ERR_PROCESSING: |
| default: |
| return BT_GATTC_ERR_PROCESSING; |
| } |
| } |
| |
| void btapp_gattc_req_data(UINT16 event, char *p_dest, char *p_src) { |
| tBTA_GATTC *p_dest_data = (tBTA_GATTC *)p_dest; |
| tBTA_GATTC *p_src_data = (tBTA_GATTC *)p_src; |
| |
| if (!p_src_data || !p_dest_data) return; |
| |
| // Copy basic structure first |
| maybe_non_aligned_memcpy(p_dest_data, p_src_data, sizeof(*p_src_data)); |
| |
| // Allocate buffer for request data if necessary |
| switch (event) { |
| case BTA_GATTC_READ_CHAR_EVT: |
| case BTA_GATTC_READ_DESCR_EVT: |
| |
| if (p_src_data->read.p_value != NULL) { |
| p_dest_data->read.p_value = |
| (tBTA_GATT_UNFMT *)osi_malloc(sizeof(tBTA_GATT_UNFMT)); |
| |
| memcpy(p_dest_data->read.p_value, p_src_data->read.p_value, |
| sizeof(tBTA_GATT_UNFMT)); |
| |
| // Allocate buffer for att value if necessary |
| if (p_src_data->read.p_value->len > 0 && |
| p_src_data->read.p_value->p_value != NULL) { |
| p_dest_data->read.p_value->p_value = |
| (UINT8 *)osi_malloc(p_src_data->read.p_value->len); |
| memcpy(p_dest_data->read.p_value->p_value, |
| p_src_data->read.p_value->p_value, |
| p_src_data->read.p_value->len); |
| } |
| } else { |
| BTIF_TRACE_WARNING("%s :Src read.p_value ptr is NULL for event 0x%x", |
| __FUNCTION__, event); |
| p_dest_data->read.p_value = NULL; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| void btapp_gattc_free_req_data(UINT16 event, tBTA_GATTC *p_data) { |
| switch (event) { |
| case BTA_GATTC_READ_CHAR_EVT: |
| case BTA_GATTC_READ_DESCR_EVT: |
| if (p_data != NULL && p_data->read.p_value != NULL) { |
| if (p_data->read.p_value->len > 0) |
| osi_free_and_reset((void **)&p_data->read.p_value->p_value); |
| |
| osi_free_and_reset((void **)&p_data->read.p_value); |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| void btif_gattc_init_dev_cb(void) { p_dev_cb.clear(); } |
| |
| void btif_gattc_add_remote_bdaddr(BD_ADDR p_bda, uint8_t addr_type) { |
| bt_bdaddr_t bd_addr; |
| memcpy(bd_addr.address, p_bda, BD_ADDR_LEN); |
| p_dev_cb.insert(bd_addr); |
| } |
| |
| BOOLEAN btif_gattc_find_bdaddr(BD_ADDR p_bda) { |
| bt_bdaddr_t bd_addr; |
| memcpy(bd_addr.address, p_bda, BD_ADDR_LEN); |
| return (p_dev_cb.count(bd_addr) != 0); |
| } |
| |
| void btif_gattc_upstreams_evt(uint16_t event, char *p_param) { |
| LOG_VERBOSE(LOG_TAG, "%s: Event %d", __FUNCTION__, event); |
| |
| tBTA_GATTC *p_data = (tBTA_GATTC *)p_param; |
| switch (event) { |
| case BTA_GATTC_REG_EVT: { |
| bt_uuid_t app_uuid; |
| bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.app_uuid); |
| HAL_CBACK(bt_gatt_callbacks, client->register_client_cb, |
| p_data->reg_oper.status, p_data->reg_oper.client_if, &app_uuid); |
| break; |
| } |
| |
| case BTA_GATTC_DEREG_EVT: |
| break; |
| |
| case BTA_GATTC_READ_CHAR_EVT: { |
| btgatt_read_params_t data; |
| set_read_value(&data, &p_data->read); |
| |
| HAL_CBACK(bt_gatt_callbacks, client->read_characteristic_cb, |
| p_data->read.conn_id, p_data->read.status, &data); |
| break; |
| } |
| |
| case BTA_GATTC_WRITE_CHAR_EVT: |
| case BTA_GATTC_PREP_WRITE_EVT: { |
| HAL_CBACK(bt_gatt_callbacks, client->write_characteristic_cb, |
| p_data->write.conn_id, p_data->write.status, |
| p_data->write.handle); |
| break; |
| } |
| |
| case BTA_GATTC_EXEC_EVT: { |
| HAL_CBACK(bt_gatt_callbacks, client->execute_write_cb, |
| p_data->exec_cmpl.conn_id, p_data->exec_cmpl.status); |
| break; |
| } |
| |
| case BTA_GATTC_SEARCH_CMPL_EVT: { |
| HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb, |
| p_data->search_cmpl.conn_id, p_data->search_cmpl.status); |
| break; |
| } |
| |
| case BTA_GATTC_READ_DESCR_EVT: { |
| btgatt_read_params_t data; |
| set_read_value(&data, &p_data->read); |
| |
| HAL_CBACK(bt_gatt_callbacks, client->read_descriptor_cb, |
| p_data->read.conn_id, p_data->read.status, &data); |
| break; |
| } |
| |
| case BTA_GATTC_WRITE_DESCR_EVT: { |
| HAL_CBACK(bt_gatt_callbacks, client->write_descriptor_cb, |
| p_data->write.conn_id, p_data->write.status, |
| p_data->write.handle); |
| break; |
| } |
| |
| case BTA_GATTC_NOTIF_EVT: { |
| btgatt_notify_params_t data; |
| |
| bdcpy(data.bda.address, p_data->notify.bda); |
| memcpy(data.value, p_data->notify.value, p_data->notify.len); |
| |
| data.handle = p_data->notify.handle; |
| data.is_notify = p_data->notify.is_notify; |
| data.len = p_data->notify.len; |
| |
| HAL_CBACK(bt_gatt_callbacks, client->notify_cb, p_data->notify.conn_id, |
| &data); |
| |
| if (p_data->notify.is_notify == FALSE) |
| BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle); |
| |
| break; |
| } |
| |
| case BTA_GATTC_OPEN_EVT: { |
| bt_bdaddr_t bda; |
| bdcpy(bda.address, p_data->open.remote_bda); |
| |
| HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id, |
| p_data->open.status, p_data->open.client_if, &bda); |
| |
| if (GATT_DEF_BLE_MTU_SIZE != p_data->open.mtu && p_data->open.mtu) { |
| HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb, |
| p_data->open.conn_id, p_data->open.status, p_data->open.mtu); |
| } |
| |
| if (p_data->open.status == BTA_GATT_OK) |
| btif_gatt_check_encrypted_link(p_data->open.remote_bda, |
| p_data->open.transport); |
| break; |
| } |
| |
| case BTA_GATTC_CLOSE_EVT: { |
| bt_bdaddr_t bda; |
| bdcpy(bda.address, p_data->close.remote_bda); |
| HAL_CBACK(bt_gatt_callbacks, client->close_cb, p_data->close.conn_id, |
| p_data->status, p_data->close.client_if, &bda); |
| break; |
| } |
| |
| case BTA_GATTC_ACL_EVT: |
| LOG_DEBUG(LOG_TAG, "BTA_GATTC_ACL_EVT: status = %d", p_data->status); |
| /* Ignore for now */ |
| break; |
| |
| case BTA_GATTC_CANCEL_OPEN_EVT: |
| break; |
| |
| case BTA_GATTC_LISTEN_EVT: { |
| HAL_CBACK(bt_gatt_callbacks, client->listen_cb, p_data->reg_oper.status, |
| p_data->reg_oper.client_if); |
| break; |
| } |
| |
| case BTA_GATTC_CFG_MTU_EVT: { |
| HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb, |
| p_data->cfg_mtu.conn_id, p_data->cfg_mtu.status, |
| p_data->cfg_mtu.mtu); |
| break; |
| } |
| |
| case BTA_GATTC_CONGEST_EVT: |
| HAL_CBACK(bt_gatt_callbacks, client->congestion_cb, |
| p_data->congest.conn_id, p_data->congest.congested); |
| break; |
| |
| default: |
| LOG_ERROR(LOG_TAG, "%s: Unhandled event (%d)!", __FUNCTION__, event); |
| break; |
| } |
| |
| btapp_gattc_free_req_data(event, p_data); |
| } |
| |
| void bta_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) { |
| bt_status_t status = btif_transfer_context( |
| btif_gattc_upstreams_evt, (uint16_t)event, (char *)p_data, |
| sizeof(tBTA_GATTC), btapp_gattc_req_data); |
| ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status); |
| } |
| |
| void multi_adv_enable_cb_impl(int client_if, int status, int inst_id) { |
| if (0xFF != inst_id) btif_multi_adv_add_instid_map(client_if, inst_id, false); |
| HAL_CBACK(bt_gatt_callbacks, client->multi_adv_enable_cb, client_if, status); |
| btif_multi_adv_timer_ctrl( |
| client_if, (status == BTA_GATT_OK) ? btif_multi_adv_stop_cb : NULL); |
| } |
| |
| void multi_adv_update_cb_impl(int client_if, int status, int inst_id) { |
| HAL_CBACK(bt_gatt_callbacks, client->multi_adv_update_cb, client_if, status); |
| btif_multi_adv_timer_ctrl( |
| client_if, (status == BTA_GATT_OK) ? btif_multi_adv_stop_cb : NULL); |
| } |
| |
| void multi_adv_data_cb_impl(int client_if, int status, int inst_id) { |
| btif_gattc_clear_clientif(client_if, FALSE); |
| HAL_CBACK(bt_gatt_callbacks, client->multi_adv_data_cb, client_if, status); |
| } |
| |
| void multi_adv_disable_cb_impl(int client_if, int status, int inst_id) { |
| btif_gattc_clear_clientif(client_if, TRUE); |
| HAL_CBACK(bt_gatt_callbacks, client->multi_adv_disable_cb, client_if, status); |
| } |
| |
| void bta_gattc_multi_adv_cback(tBTA_BLE_MULTI_ADV_EVT event, UINT8 inst_id, |
| void *p_ref, tBTA_STATUS status) { |
| uint8_t client_if = 0; |
| |
| if (NULL == p_ref) { |
| BTIF_TRACE_WARNING("%s Invalid p_ref received", __func__); |
| } else { |
| client_if = *(UINT8 *)p_ref; |
| } |
| |
| BTIF_TRACE_DEBUG("%s -Inst ID %d, Status:%x, client_if:%d", __func__, inst_id, |
| status, client_if); |
| |
| if (event == BTA_BLE_MULTI_ADV_ENB_EVT) |
| do_in_jni_thread( |
| Bind(multi_adv_enable_cb_impl, client_if, status, inst_id)); |
| else if (event == BTA_BLE_MULTI_ADV_DISABLE_EVT) |
| do_in_jni_thread( |
| Bind(multi_adv_disable_cb_impl, client_if, status, inst_id)); |
| else if (event == BTA_BLE_MULTI_ADV_PARAM_EVT) |
| do_in_jni_thread( |
| Bind(multi_adv_update_cb_impl, client_if, status, inst_id)); |
| else if (event == BTA_BLE_MULTI_ADV_DATA_EVT) |
| do_in_jni_thread(Bind(multi_adv_data_cb_impl, client_if, status, inst_id)); |
| } |
| |
| void bta_gattc_set_adv_data_cback(tBTA_STATUS call_status) { |
| do_in_jni_thread(Bind(&btif_gattc_cleanup_inst_cb, STD_ADV_INSTID, FALSE)); |
| } |
| |
| void bta_batch_scan_setup_cb(tBTA_BLE_BATCH_SCAN_EVT evt, |
| tBTA_DM_BLE_REF_VALUE ref_value, |
| tBTA_STATUS status) { |
| BTIF_TRACE_DEBUG("bta_batch_scan_setup_cb-Status:%x, client_if:%d, evt=%d", |
| status, ref_value, evt); |
| |
| switch (evt) { |
| case BTA_BLE_BATCH_SCAN_ENB_EVT: { |
| CLI_CBACK_IN_JNI(batchscan_enb_disable_cb, 1, ref_value, status); |
| return; |
| } |
| |
| case BTA_BLE_BATCH_SCAN_DIS_EVT: { |
| CLI_CBACK_IN_JNI(batchscan_enb_disable_cb, 0, ref_value, status); |
| return; |
| } |
| |
| case BTA_BLE_BATCH_SCAN_CFG_STRG_EVT: { |
| CLI_CBACK_IN_JNI(batchscan_cfg_storage_cb, ref_value, status); |
| return; |
| } |
| |
| case BTA_BLE_BATCH_SCAN_DATA_EVT: { |
| CLI_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, 0, 0, 0, |
| nullptr); |
| return; |
| } |
| |
| case BTA_BLE_BATCH_SCAN_THRES_EVT: { |
| CLI_CBACK_IN_JNI(batchscan_threshold_cb, ref_value); |
| return; |
| } |
| |
| default: |
| return; |
| } |
| } |
| |
| void bta_batch_scan_threshold_cb(tBTA_DM_BLE_REF_VALUE ref_value) { |
| CLI_CBACK_IN_JNI(batchscan_threshold_cb, ref_value); |
| } |
| |
| void bta_batch_scan_reports_cb(tBTA_DM_BLE_REF_VALUE ref_value, |
| UINT8 report_format, UINT8 num_records, |
| UINT16 data_len, UINT8 *p_rep_data, |
| tBTA_STATUS status) { |
| BTIF_TRACE_DEBUG("%s - client_if:%d, %d, %d, %d", __FUNCTION__, ref_value, |
| status, num_records, data_len); |
| |
| if (data_len > 0) { |
| uint8_t *data = new uint8_t[data_len]; |
| memcpy(data, p_rep_data, data_len); |
| osi_free(p_rep_data); |
| |
| CLI_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, report_format, |
| num_records, data_len, Owned(data)); |
| } else { |
| CLI_CBACK_IN_JNI(batchscan_reports_cb, ref_value, status, report_format, |
| num_records, 0, nullptr); |
| } |
| } |
| |
| void bta_scan_results_cb_impl(bt_bdaddr_t bd_addr, tBT_DEVICE_TYPE device_type, |
| int8_t rssi, uint8_t addr_type, uint8_t *value) { |
| uint8_t remote_name_len; |
| uint8_t *p_eir_remote_name = NULL; |
| bt_device_type_t dev_type; |
| bt_property_t properties; |
| |
| p_eir_remote_name = BTM_CheckEirData(value, BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, |
| &remote_name_len); |
| |
| if (p_eir_remote_name == NULL) { |
| p_eir_remote_name = BTM_CheckEirData( |
| value, BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len); |
| } |
| |
| if ((addr_type != BLE_ADDR_RANDOM) || (p_eir_remote_name)) { |
| if (!btif_gattc_find_bdaddr(bd_addr.address)) { |
| btif_gattc_add_remote_bdaddr(bd_addr.address, addr_type); |
| |
| if (p_eir_remote_name) { |
| bt_bdname_t bdname; |
| memcpy(bdname.name, p_eir_remote_name, remote_name_len); |
| bdname.name[remote_name_len] = '\0'; |
| |
| LOG_DEBUG(LOG_TAG, "%s BLE device name=%s len=%d dev_type=%d", __func__, |
| bdname.name, remote_name_len, device_type); |
| btif_dm_update_ble_remote_properties(bd_addr.address, bdname.name, |
| device_type); |
| } |
| } |
| } |
| |
| dev_type = (bt_device_type_t)device_type; |
| BTIF_STORAGE_FILL_PROPERTY(&properties, BT_PROPERTY_TYPE_OF_DEVICE, |
| sizeof(dev_type), &dev_type); |
| btif_storage_set_remote_device_property(&(bd_addr), &properties); |
| |
| btif_storage_set_remote_addr_type(&bd_addr, addr_type); |
| |
| HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb, &bd_addr, rssi, value); |
| } |
| |
| void bta_scan_results_cb(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { |
| uint8_t len; |
| |
| if (event == BTA_DM_INQ_CMPL_EVT) { |
| BTIF_TRACE_DEBUG("%s BLE observe complete. Num Resp %d", __func__, |
| p_data->inq_cmpl.num_resps); |
| return; |
| } |
| |
| if (event != BTA_DM_INQ_RES_EVT) { |
| BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __FUNCTION__, event); |
| return; |
| } |
| |
| uint8_t *value = new uint8_t[BTGATT_MAX_ATTR_LEN]; |
| if (p_data->inq_res.p_eir) { |
| memcpy(value, p_data->inq_res.p_eir, 62); |
| |
| if (BTM_CheckEirData(p_data->inq_res.p_eir, |
| BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &len)) { |
| p_data->inq_res.remt_name_not_required = TRUE; |
| } |
| } |
| |
| bt_bdaddr_t bdaddr; |
| bdcpy(bdaddr.address, p_data->inq_res.bd_addr); |
| do_in_jni_thread(Bind(bta_scan_results_cb_impl, bdaddr, |
| p_data->inq_res.device_type, p_data->inq_res.rssi, |
| p_data->inq_res.ble_addr_type, Owned(value))); |
| } |
| |
| void bta_track_adv_event_cb(tBTA_DM_BLE_TRACK_ADV_DATA *p_track_adv_data) { |
| btgatt_track_adv_info_t *btif_scan_track_cb = new btgatt_track_adv_info_t; |
| |
| BTIF_TRACE_DEBUG("%s", __FUNCTION__); |
| btif_gatt_move_track_adv_data(btif_scan_track_cb, |
| (btgatt_track_adv_info_t *)p_track_adv_data); |
| |
| CLI_CBACK_IN_JNI(track_adv_event_cb, Owned(btif_scan_track_cb)); |
| } |
| |
| void btm_read_rssi_cb(tBTM_RSSI_RESULTS *p_result) { |
| bt_bdaddr_t *addr = new bt_bdaddr_t; |
| bdcpy(addr->address, p_result->rem_bda); |
| CLI_CBACK_IN_JNI(read_remote_rssi_cb, rssi_request_client_if, |
| base::Owned(addr), p_result->rssi, p_result->status); |
| } |
| |
| void bta_scan_param_setup_cb(tGATT_IF client_if, tBTM_STATUS status) { |
| CLI_CBACK_IN_JNI(scan_parameter_setup_completed_cb, client_if, |
| btif_gattc_translate_btm_status(status)); |
| } |
| |
| void bta_scan_filt_cfg_cb(tBTA_DM_BLE_PF_ACTION action, |
| tBTA_DM_BLE_SCAN_COND_OP cfg_op, |
| tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, |
| tBTA_STATUS status, tBTA_DM_BLE_REF_VALUE ref_value) { |
| CLI_CBACK_IN_JNI(scan_filter_cfg_cb, action, ref_value, status, cfg_op, |
| avbl_space); |
| } |
| |
| void bta_scan_filt_param_setup_cb(UINT8 action_type, |
| tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, |
| tBTA_DM_BLE_REF_VALUE ref_value, |
| tBTA_STATUS status) { |
| CLI_CBACK_IN_JNI(scan_filter_param_cb, action_type, ref_value, status, |
| avbl_space); |
| } |
| |
| void bta_scan_filt_status_cb(UINT8 action, tBTA_STATUS status, |
| tBTA_DM_BLE_REF_VALUE ref_value) { |
| CLI_CBACK_IN_JNI(scan_filter_status_cb, action, ref_value, status); |
| } |
| |
| /******************************************************************************* |
| ** Client API Functions |
| ********************************************************************************/ |
| |
| void btif_gattc_register_app_impl(tBT_UUID uuid) { |
| btif_gattc_incr_app_count(); |
| BTA_GATTC_AppRegister(&uuid, bta_gattc_cback); |
| } |
| |
| bt_status_t btif_gattc_register_app(bt_uuid_t *uuid) { |
| CHECK_BTGATT_INIT(); |
| |
| tBT_UUID bt_uuid; |
| btif_to_bta_uuid(&bt_uuid, uuid); |
| return do_in_jni_thread(Bind(&btif_gattc_register_app_impl, bt_uuid)); |
| } |
| |
| void btif_gattc_unregister_app_impl(int client_if) { |
| btif_gattc_clear_clientif(client_if, TRUE); |
| btif_gattc_decr_app_count(); |
| BTA_GATTC_AppDeregister(client_if); |
| } |
| |
| bt_status_t btif_gattc_unregister_app(int client_if) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread(Bind(&btif_gattc_unregister_app_impl, client_if)); |
| } |
| |
| bt_status_t btif_gattc_scan(bool start) { |
| CHECK_BTGATT_INIT(); |
| if (start) { |
| btif_gattc_init_dev_cb(); |
| return do_in_jni_thread(Bind(&BTA_DmBleObserve, TRUE, 0, |
| (tBTA_DM_SEARCH_CBACK *)bta_scan_results_cb)); |
| } else { |
| return do_in_jni_thread(Bind(&BTA_DmBleObserve, FALSE, 0, nullptr)); |
| } |
| } |
| |
| void btif_gattc_open_impl(int client_if, BD_ADDR address, bool is_direct, |
| int transport_p) { |
| // Ensure device is in inquiry database |
| int addr_type = 0; |
| int device_type = 0; |
| tBTA_GATT_TRANSPORT transport = (tBTA_GATT_TRANSPORT)BTA_GATT_TRANSPORT_LE; |
| |
| if (btif_get_address_type(address, &addr_type) && |
| btif_get_device_type(address, &device_type) && |
| device_type != BT_DEVICE_TYPE_BREDR) { |
| BTA_DmAddBleDevice(address, addr_type, device_type); |
| } |
| |
| // Check for background connections |
| if (!is_direct) { |
| // Check for privacy 1.0 and 1.1 controller and do not start background |
| // connection if RPA offloading is not supported, since it will not |
| // connect after change of random address |
| if (!controller_get_interface()->supports_ble_privacy() && |
| (addr_type == BLE_ADDR_RANDOM) && BTM_BLE_IS_RESOLVE_BDA(address)) { |
| tBTM_BLE_VSC_CB vnd_capabilities; |
| BTM_BleGetVendorCapabilities(&vnd_capabilities); |
| if (!vnd_capabilities.rpa_offloading) { |
| HAL_CBACK(bt_gatt_callbacks, client->open_cb, 0, BT_STATUS_UNSUPPORTED, |
| client_if, (bt_bdaddr_t *)&address); |
| return; |
| } |
| } |
| BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL); |
| } |
| |
| // Determine transport |
| if (transport_p != GATT_TRANSPORT_AUTO) { |
| transport = transport_p; |
| } else { |
| switch (device_type) { |
| case BT_DEVICE_TYPE_BREDR: |
| transport = BTA_GATT_TRANSPORT_BR_EDR; |
| break; |
| |
| case BT_DEVICE_TYPE_BLE: |
| transport = BTA_GATT_TRANSPORT_LE; |
| break; |
| |
| case BT_DEVICE_TYPE_DUMO: |
| if (transport == GATT_TRANSPORT_LE) |
| transport = BTA_GATT_TRANSPORT_LE; |
| else |
| transport = BTA_GATT_TRANSPORT_BR_EDR; |
| break; |
| } |
| } |
| |
| // Connect! |
| BTIF_TRACE_DEBUG("%s Transport=%d, device type=%d", __func__, transport, |
| device_type); |
| BTA_GATTC_Open(client_if, address, is_direct, transport); |
| } |
| |
| bt_status_t btif_gattc_open(int client_if, const bt_bdaddr_t *bd_addr, |
| bool is_direct, int transport) { |
| CHECK_BTGATT_INIT(); |
| // Closure will own this value and free it. |
| uint8_t *address = new BD_ADDR; |
| bdcpy(address, bd_addr->address); |
| return do_in_jni_thread(Bind(&btif_gattc_open_impl, client_if, |
| base::Owned(address), is_direct, transport)); |
| } |
| |
| void btif_gattc_close_impl(int client_if, BD_ADDR address, int conn_id) { |
| // Disconnect established connections |
| if (conn_id != 0) |
| BTA_GATTC_Close(conn_id); |
| else |
| BTA_GATTC_CancelOpen(client_if, address, TRUE); |
| |
| // Cancel pending background connections (remove from whitelist) |
| BTA_GATTC_CancelOpen(client_if, address, FALSE); |
| } |
| |
| bt_status_t btif_gattc_close(int client_if, const bt_bdaddr_t *bd_addr, |
| int conn_id) { |
| CHECK_BTGATT_INIT(); |
| // Closure will own this value and free it. |
| uint8_t *address = new BD_ADDR; |
| bdcpy(address, bd_addr->address); |
| return do_in_jni_thread( |
| Bind(&btif_gattc_close_impl, client_if, base::Owned(address), conn_id)); |
| } |
| |
| bt_status_t btif_gattc_listen(int client_if, bool start) { |
| CHECK_BTGATT_INIT(); |
| #if (defined(BLE_PERIPHERAL_MODE_SUPPORT) && \ |
| (BLE_PERIPHERAL_MODE_SUPPORT == TRUE)) |
| return do_in_jni_thread(Bind(&BTA_GATTC_Listen, client_if, start, nullptr)); |
| #else |
| return do_in_jni_thread(Bind(&BTA_GATTC_Broadcast, client_if, start)); |
| #endif |
| } |
| |
| void btif_gattc_set_adv_data_impl(btif_adv_data_t *p_adv_data) { |
| const int cbindex = CLNT_IF_IDX; |
| if (cbindex >= 0 && btif_gattc_copy_datacb(cbindex, p_adv_data, false)) { |
| btgatt_multi_adv_common_data *p_multi_adv_data_cb = |
| btif_obtain_multi_adv_data_cb(); |
| if (!p_adv_data->set_scan_rsp) { |
| BTA_DmBleSetAdvConfig(p_multi_adv_data_cb->inst_cb[cbindex].mask, |
| &p_multi_adv_data_cb->inst_cb[cbindex].data, |
| bta_gattc_set_adv_data_cback); |
| } else { |
| BTA_DmBleSetScanRsp(p_multi_adv_data_cb->inst_cb[cbindex].mask, |
| &p_multi_adv_data_cb->inst_cb[cbindex].data, |
| bta_gattc_set_adv_data_cback); |
| } |
| } else { |
| BTIF_TRACE_ERROR("%s: failed to get instance data cbindex: %d", __func__, |
| cbindex); |
| } |
| } |
| |
| bt_status_t btif_gattc_set_adv_data( |
| int client_if, bool set_scan_rsp, bool include_name, bool include_txpower, |
| int min_interval, int max_interval, int appearance, |
| uint16_t manufacturer_len, char *manufacturer_data, |
| uint16_t service_data_len, char *service_data, uint16_t service_uuid_len, |
| char *service_uuid) { |
| CHECK_BTGATT_INIT(); |
| |
| btif_adv_data_t *adv_data = new btif_adv_data_t; |
| |
| btif_gattc_adv_data_packager( |
| client_if, set_scan_rsp, include_name, include_txpower, min_interval, |
| max_interval, appearance, manufacturer_len, manufacturer_data, |
| service_data_len, service_data, service_uuid_len, service_uuid, adv_data); |
| |
| return do_in_jni_thread( |
| Bind(&btif_gattc_set_adv_data_impl, base::Owned(adv_data))); |
| } |
| |
| bt_status_t btif_gattc_refresh(int client_if, const bt_bdaddr_t *bd_addr) { |
| CHECK_BTGATT_INIT(); |
| // Closure will own this value and free it. |
| uint8_t *address = new BD_ADDR; |
| bdcpy(address, bd_addr->address); |
| return do_in_jni_thread(Bind(&BTA_GATTC_Refresh, base::Owned(address))); |
| } |
| |
| bt_status_t btif_gattc_search_service(int conn_id, bt_uuid_t *filter_uuid) { |
| CHECK_BTGATT_INIT(); |
| |
| if (filter_uuid) { |
| tBT_UUID *uuid = new tBT_UUID; |
| btif_to_bta_uuid(uuid, filter_uuid); |
| return do_in_jni_thread( |
| Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, base::Owned(uuid))); |
| } else { |
| return do_in_jni_thread( |
| Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, nullptr)); |
| } |
| } |
| |
| void btif_gattc_get_gatt_db_impl(int conn_id) { |
| btgatt_db_element_t *db = NULL; |
| int count = 0; |
| BTA_GATTC_GetGattDb(conn_id, 0x0000, 0xFFFF, &db, &count); |
| |
| HAL_CBACK(bt_gatt_callbacks, client->get_gatt_db_cb, conn_id, db, count); |
| osi_free(db); |
| } |
| |
| bt_status_t btif_gattc_get_gatt_db(int conn_id) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread(Bind(&btif_gattc_get_gatt_db_impl, conn_id)); |
| } |
| |
| bt_status_t btif_gattc_read_char(int conn_id, uint16_t handle, int auth_req) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread( |
| Bind(&BTA_GATTC_ReadCharacteristic, conn_id, handle, auth_req)); |
| } |
| |
| bt_status_t btif_gattc_read_char_descr(int conn_id, uint16_t handle, |
| int auth_req) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread( |
| Bind(&BTA_GATTC_ReadCharDescr, conn_id, handle, auth_req)); |
| } |
| |
| bt_status_t btif_gattc_write_char(int conn_id, uint16_t handle, int write_type, |
| int len, int auth_req, char *p_value) { |
| CHECK_BTGATT_INIT(); |
| |
| len = len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len; |
| // callback will own this value and free it. |
| UINT8 *value = new UINT8[len]; |
| memcpy(value, p_value, len); |
| |
| return do_in_jni_thread(Bind(&BTA_GATTC_WriteCharValue, conn_id, handle, |
| write_type, len, base::Owned(value), auth_req)); |
| } |
| |
| bt_status_t btif_gattc_write_char_descr(int conn_id, uint16_t handle, |
| int write_type, int len, int auth_req, |
| char *p_value) { |
| len = len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len; |
| |
| // callback will own this value and free it |
| // TODO(jpawlowski): This one is little hacky because of unfmt type, |
| // make it accept len an val like BTA_GATTC_WriteCharValue |
| tBTA_GATT_UNFMT *value = (tBTA_GATT_UNFMT *)new UINT8[sizeof(UINT16) + len]; |
| value->len = len; |
| value->p_value = ((UINT8 *)value) + 2; |
| memcpy(value->p_value, p_value, len); |
| |
| return do_in_jni_thread(Bind(&BTA_GATTC_WriteCharDescr, conn_id, handle, |
| write_type, Owned(value), auth_req)); |
| } |
| |
| bt_status_t btif_gattc_execute_write(int conn_id, int execute) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread( |
| Bind(&BTA_GATTC_ExecuteWrite, conn_id, (uint8_t)execute)); |
| } |
| |
| void btif_gattc_reg_for_notification_impl(tBTA_GATTC_IF client_if, |
| const BD_ADDR bda, UINT16 handle) { |
| tBTA_GATT_STATUS status = BTA_GATTC_RegisterForNotifications( |
| client_if, const_cast<UINT8 *>(bda), handle); |
| |
| // TODO(jpawlowski): conn_id is currently unused |
| HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb, |
| /* conn_id */ 0, 1, status, handle); |
| } |
| |
| bt_status_t btif_gattc_reg_for_notification(int client_if, |
| const bt_bdaddr_t *bd_addr, |
| uint16_t handle) { |
| CHECK_BTGATT_INIT(); |
| |
| uint8_t *address = new BD_ADDR; |
| bdcpy(address, bd_addr->address); |
| return do_in_jni_thread( |
| Bind(base::IgnoreResult(&btif_gattc_reg_for_notification_impl), client_if, |
| base::Owned(address), handle)); |
| } |
| |
| void btif_gattc_dereg_for_notification_impl(tBTA_GATTC_IF client_if, |
| const BD_ADDR bda, UINT16 handle) { |
| tBTA_GATT_STATUS status = BTA_GATTC_DeregisterForNotifications( |
| client_if, const_cast<UINT8 *>(bda), handle); |
| |
| // TODO(jpawlowski): conn_id is currently unused |
| HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb, |
| /* conn_id */ 0, 0, status, handle); |
| } |
| |
| bt_status_t btif_gattc_dereg_for_notification(int client_if, |
| const bt_bdaddr_t *bd_addr, |
| uint16_t handle) { |
| CHECK_BTGATT_INIT(); |
| |
| uint8_t *address = new BD_ADDR; |
| bdcpy(address, bd_addr->address); |
| return do_in_jni_thread( |
| Bind(base::IgnoreResult(&btif_gattc_dereg_for_notification_impl), |
| client_if, base::Owned(address), handle)); |
| } |
| |
| bt_status_t btif_gattc_read_remote_rssi(int client_if, |
| const bt_bdaddr_t *bd_addr) { |
| CHECK_BTGATT_INIT(); |
| rssi_request_client_if = client_if; |
| // Closure will own this value and free it. |
| uint8_t *address = new BD_ADDR; |
| bdcpy(address, bd_addr->address); |
| return do_in_jni_thread(Bind(base::IgnoreResult(&BTM_ReadRSSI), |
| base::Owned(address), |
| (tBTM_CMPL_CB *)btm_read_rssi_cb)); |
| } |
| |
| bt_status_t btif_gattc_configure_mtu(int conn_id, int mtu) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread( |
| Bind(base::IgnoreResult(&BTA_GATTC_ConfigureMTU), conn_id, mtu)); |
| } |
| |
| void btif_gattc_conn_parameter_update_impl(const BD_ADDR addr, int min_interval, |
| int max_interval, int latency, |
| int timeout) { |
| if (BTA_DmGetConnectionState(const_cast<UINT8 *>(addr))) |
| BTA_DmBleUpdateConnectionParams(const_cast<UINT8 *>(addr), min_interval, |
| max_interval, latency, timeout); |
| else |
| BTA_DmSetBlePrefConnParams(const_cast<UINT8 *>(addr), min_interval, |
| max_interval, latency, timeout); |
| } |
| |
| bt_status_t btif_gattc_conn_parameter_update(const bt_bdaddr_t *bd_addr, |
| int min_interval, int max_interval, |
| int latency, int timeout) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread( |
| Bind(base::IgnoreResult(&btif_gattc_conn_parameter_update_impl), |
| bd_addr->address, min_interval, max_interval, latency, timeout)); |
| } |
| |
| void btif_gattc_scan_filter_param_setup_impl( |
| int client_if, uint8_t action, int filt_index, |
| tBTA_DM_BLE_PF_FILT_PARAMS *adv_filt_param) { |
| if (1 == adv_filt_param->dely_mode) |
| BTA_DmBleTrackAdvertiser(client_if, bta_track_adv_event_cb); |
| BTA_DmBleScanFilterSetup(action, filt_index, adv_filt_param, NULL, |
| bta_scan_filt_param_setup_cb, client_if); |
| } |
| |
| bt_status_t btif_gattc_scan_filter_param_setup( |
| btgatt_filt_param_setup_t filt_param) { |
| CHECK_BTGATT_INIT(); |
| BTIF_TRACE_DEBUG("%s", __FUNCTION__); |
| |
| tBTA_DM_BLE_PF_FILT_PARAMS *adv_filt_param = new tBTA_DM_BLE_PF_FILT_PARAMS; |
| adv_filt_param->feat_seln = filt_param.feat_seln; |
| adv_filt_param->list_logic_type = filt_param.list_logic_type; |
| adv_filt_param->filt_logic_type = filt_param.filt_logic_type; |
| adv_filt_param->rssi_high_thres = filt_param.rssi_high_thres; |
| adv_filt_param->rssi_low_thres = filt_param.rssi_low_thres; |
| adv_filt_param->dely_mode = filt_param.dely_mode; |
| adv_filt_param->found_timeout = filt_param.found_timeout; |
| adv_filt_param->lost_timeout = filt_param.lost_timeout; |
| adv_filt_param->found_timeout_cnt = filt_param.found_timeout_cnt; |
| adv_filt_param->num_of_tracking_entries = filt_param.num_of_tracking_entries; |
| |
| return do_in_jni_thread( |
| Bind(base::IgnoreResult(&btif_gattc_scan_filter_param_setup_impl), |
| filt_param.client_if, filt_param.action, filt_param.filt_index, |
| base::Owned(adv_filt_param))); |
| } |
| |
| void btif_gattc_scan_filter_add_srvc_uuid(tBT_UUID uuid, |
| tBTA_DM_BLE_PF_COND_MASK *p_uuid_mask, |
| int action, int filt_type, |
| int filt_index, int client_if) { |
| tBTA_DM_BLE_PF_COND_PARAM cond; |
| memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM)); |
| |
| cond.srvc_uuid.p_target_addr = NULL; |
| cond.srvc_uuid.cond_logic = BTA_DM_BLE_PF_LOGIC_AND; |
| cond.srvc_uuid.uuid = uuid; |
| cond.srvc_uuid.p_uuid_mask = p_uuid_mask; |
| |
| BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond, |
| &bta_scan_filt_cfg_cb, client_if); |
| } |
| |
| void btif_gattc_scan_filter_add_local_name(uint8_t *data, int data_len, |
| int action, int filt_type, |
| int filt_index, int client_if) { |
| tBTA_DM_BLE_PF_COND_PARAM cond; |
| memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM)); |
| |
| cond.local_name.data_len = data_len; |
| cond.local_name.p_data = data; |
| BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond, |
| &bta_scan_filt_cfg_cb, client_if); |
| } |
| |
| void btif_gattc_scan_filter_add_manu_data(int company_id, int company_id_mask, |
| uint8_t *pattern, int pattern_len, |
| uint8_t *pattern_mask, int action, |
| int filt_type, int filt_index, |
| int client_if) { |
| tBTA_DM_BLE_PF_COND_PARAM cond; |
| memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM)); |
| |
| cond.manu_data.company_id = company_id; |
| cond.manu_data.company_id_mask = company_id_mask ? company_id_mask : 0xFFFF; |
| cond.manu_data.data_len = pattern_len; |
| cond.manu_data.p_pattern = pattern; |
| cond.manu_data.p_pattern_mask = pattern_mask; |
| BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond, |
| &bta_scan_filt_cfg_cb, client_if); |
| } |
| |
| void btif_gattc_scan_filter_add_data_pattern(uint8_t *pattern, int pattern_len, |
| uint8_t *pattern_mask, int action, |
| int filt_type, int filt_index, |
| int client_if) { |
| tBTA_DM_BLE_PF_COND_PARAM cond; |
| memset(&cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM)); |
| |
| cond.srvc_data.data_len = pattern_len; |
| cond.srvc_data.p_pattern = pattern; |
| cond.srvc_data.p_pattern_mask = pattern_mask; |
| BTA_DmBleCfgFilterCondition(action, filt_type, filt_index, &cond, |
| &bta_scan_filt_cfg_cb, client_if); |
| } |
| |
| bt_status_t btif_gattc_scan_filter_add_remove( |
| int client_if, int action, int filt_type, int filt_index, int company_id, |
| int company_id_mask, const bt_uuid_t *p_uuid, const bt_uuid_t *p_uuid_mask, |
| const bt_bdaddr_t *bd_addr, char addr_type, int data_len, char *p_data, |
| int mask_len, char *p_mask) { |
| CHECK_BTGATT_INIT(); |
| BTIF_TRACE_DEBUG("%s, %d, %d", __FUNCTION__, action, filt_type); |
| |
| /* If data is passed, both mask and data have to be the same length */ |
| if (data_len != mask_len && NULL != p_data && NULL != p_mask) |
| return BT_STATUS_PARM_INVALID; |
| |
| switch (filt_type) { |
| case BTA_DM_BLE_PF_ADDR_FILTER: // 0 |
| { |
| tBTA_DM_BLE_PF_COND_PARAM *cond = new tBTA_DM_BLE_PF_COND_PARAM; |
| memset(cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM)); |
| |
| bdcpy(cond->target_addr.bda, bd_addr->address); |
| cond->target_addr.type = addr_type; |
| return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action, |
| filt_type, filt_index, base::Owned(cond), |
| &bta_scan_filt_cfg_cb, client_if)); |
| } |
| |
| case BTA_DM_BLE_PF_SRVC_DATA: // 1 |
| return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action, |
| filt_type, filt_index, nullptr, |
| &bta_scan_filt_cfg_cb, client_if)); |
| |
| case BTA_DM_BLE_PF_SRVC_UUID: // 2 |
| { |
| tBT_UUID bt_uuid; |
| btif_to_bta_uuid(&bt_uuid, p_uuid); |
| |
| if (p_uuid_mask != NULL) { |
| tBTA_DM_BLE_PF_COND_MASK *uuid_mask = new tBTA_DM_BLE_PF_COND_MASK; |
| btif_to_bta_uuid_mask(uuid_mask, p_uuid_mask); |
| return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_srvc_uuid, |
| bt_uuid, base::Owned(uuid_mask), action, |
| filt_type, filt_index, client_if)); |
| } |
| |
| return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_srvc_uuid, |
| bt_uuid, nullptr, action, filt_type, |
| filt_index, client_if)); |
| } |
| |
| case BTA_DM_BLE_PF_SRVC_SOL_UUID: // 3 |
| { |
| tBTA_DM_BLE_PF_COND_PARAM *cond = new tBTA_DM_BLE_PF_COND_PARAM; |
| memset(cond, 0, sizeof(tBTA_DM_BLE_PF_COND_PARAM)); |
| |
| cond->solicitate_uuid.p_target_addr = NULL; |
| cond->solicitate_uuid.cond_logic = BTA_DM_BLE_PF_LOGIC_AND; |
| btif_to_bta_uuid(&cond->solicitate_uuid.uuid, p_uuid); |
| |
| return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, action, |
| filt_type, filt_index, base::Owned(cond), |
| &bta_scan_filt_cfg_cb, client_if)); |
| } |
| |
| case BTA_DM_BLE_PF_LOCAL_NAME: // 4 |
| { |
| uint8_t *data = new uint8_t[data_len]; |
| memcpy(data, p_data, data_len); |
| return do_in_jni_thread(Bind(&btif_gattc_scan_filter_add_local_name, |
| base::Owned(data), data_len, action, |
| filt_type, filt_index, client_if)); |
| } |
| |
| case BTA_DM_BLE_PF_MANU_DATA: // 5 |
| { |
| uint8_t *data = new uint8_t[data_len]; |
| memcpy(data, p_data, data_len); |
| |
| uint8_t *mask = new uint8_t[data_len]; |
| memcpy(mask, p_mask, data_len); |
| return do_in_jni_thread( |
| Bind(&btif_gattc_scan_filter_add_manu_data, company_id, |
| company_id_mask, base::Owned(data), data_len, base::Owned(mask), |
| action, filt_type, filt_index, client_if)); |
| } |
| |
| case BTA_DM_BLE_PF_SRVC_DATA_PATTERN: // 6 |
| { |
| uint8_t *data = new uint8_t[data_len]; |
| memcpy(data, p_data, data_len); |
| |
| uint8_t *mask = new uint8_t[data_len]; |
| memcpy(mask, p_mask, data_len); |
| |
| return do_in_jni_thread(Bind( |
| &btif_gattc_scan_filter_add_data_pattern, base::Owned(data), data_len, |
| base::Owned(mask), action, filt_type, filt_index, client_if)); |
| } |
| |
| default: |
| LOG_ERROR(LOG_TAG, "%s: Unknown filter type (%d)!", __func__, action); |
| return (bt_status_t)BTA_GATT_OK; |
| } |
| } |
| |
| bt_status_t btif_gattc_scan_filter_clear(int client_if, int filter_index) { |
| CHECK_BTGATT_INIT(); |
| BTIF_TRACE_DEBUG("%s: filter_index: %d", __FUNCTION__, filter_index); |
| |
| return do_in_jni_thread(Bind(&BTA_DmBleCfgFilterCondition, |
| BTA_DM_BLE_SCAN_COND_CLEAR, |
| BTA_DM_BLE_PF_TYPE_ALL, filter_index, nullptr, |
| &bta_scan_filt_cfg_cb, client_if)); |
| } |
| |
| bt_status_t btif_gattc_scan_filter_enable(int client_if, bool enable) { |
| CHECK_BTGATT_INIT(); |
| BTIF_TRACE_DEBUG("%s: enable: %d", __FUNCTION__, enable); |
| |
| uint8_t action = enable ? 1: 0; |
| |
| return do_in_jni_thread(Bind(&BTA_DmEnableScanFilter, action, |
| &bta_scan_filt_status_cb, client_if)); |
| } |
| |
| bt_status_t btif_gattc_set_scan_parameters(int client_if, int scan_interval, |
| int scan_window) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread( |
| Bind(BTA_DmSetBleScanParams, client_if, scan_interval, scan_window, |
| BTM_BLE_SCAN_MODE_ACTI, |
| (tBLE_SCAN_PARAM_SETUP_CBACK)bta_scan_param_setup_cb)); |
| } |
| |
| int btif_gattc_get_device_type(const bt_bdaddr_t *bd_addr) { |
| int device_type = 0; |
| char bd_addr_str[18] = {0}; |
| |
| bdaddr_to_string(bd_addr, bd_addr_str, sizeof(bd_addr_str)); |
| if (btif_config_get_int(bd_addr_str, "DevType", &device_type)) |
| return device_type; |
| return 0; |
| } |
| |
| void btif_gattc_multi_adv_enable_impl(int client_if, int min_interval, |
| int max_interval, int adv_type, |
| int chnl_map, int tx_power, |
| int timeout_s) { |
| tBTA_BLE_ADV_PARAMS param; |
| param.adv_int_min = min_interval; |
| param.adv_int_max = max_interval; |
| param.adv_type = adv_type; |
| param.channel_map = chnl_map; |
| param.adv_filter_policy = 0; |
| param.tx_power = tx_power; |
| |
| int cbindex = -1; |
| int arrindex = btif_multi_adv_add_instid_map(client_if, INVALID_ADV_INST, true); |
| if (arrindex >= 0) |
| cbindex = btif_gattc_obtain_idx_for_datacb(client_if, CLNT_IF_IDX); |
| |
| if (cbindex >= 0 && arrindex >= 0) { |
| btgatt_multi_adv_common_data *p_multi_adv_data_cb = |
| btif_obtain_multi_adv_data_cb(); |
| memcpy(&p_multi_adv_data_cb->inst_cb[cbindex].param, ¶m, |
| sizeof(tBTA_BLE_ADV_PARAMS)); |
| p_multi_adv_data_cb->inst_cb[cbindex].timeout_s = timeout_s; |
| BTIF_TRACE_DEBUG("%s, client_if value: %d", __FUNCTION__, |
| p_multi_adv_data_cb->clntif_map[arrindex + arrindex]); |
| BTA_BleEnableAdvInstance( |
| &(p_multi_adv_data_cb->inst_cb[cbindex].param), |
| bta_gattc_multi_adv_cback, |
| &(p_multi_adv_data_cb->clntif_map[arrindex + arrindex])); |
| } else { |
| // let the error propagate up from BTA layer |
| BTIF_TRACE_ERROR("%s invalid index arrindex: %d, cbindex: %d", |
| __func__, arrindex, cbindex); |
| BTA_BleEnableAdvInstance(¶m, bta_gattc_multi_adv_cback, NULL); |
| } |
| } |
| |
| bt_status_t btif_gattc_multi_adv_enable(int client_if, int min_interval, |
| int max_interval, int adv_type, |
| int chnl_map, int tx_power, |
| int timeout_s) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread(Bind(btif_gattc_multi_adv_enable_impl, client_if, |
| min_interval, max_interval, adv_type, chnl_map, |
| tx_power, timeout_s)); |
| } |
| |
| void btif_gattc_multi_adv_update_impl(int client_if, int min_interval, |
| int max_interval, int adv_type, |
| int chnl_map, int tx_power) { |
| tBTA_BLE_ADV_PARAMS param; |
| param.adv_int_min = min_interval; |
| param.adv_int_max = max_interval; |
| param.adv_type = adv_type; |
| param.channel_map = chnl_map; |
| param.adv_filter_policy = 0; |
| param.tx_power = tx_power; |
| |
| int inst_id = btif_multi_adv_instid_for_clientif(client_if); |
| int cbindex = btif_gattc_obtain_idx_for_datacb(client_if, CLNT_IF_IDX); |
| if (inst_id >= 0 && cbindex >= 0) { |
| btgatt_multi_adv_common_data *p_multi_adv_data_cb = |
| btif_obtain_multi_adv_data_cb(); |
| memcpy(&p_multi_adv_data_cb->inst_cb[cbindex].param, ¶m, |
| sizeof(tBTA_BLE_ADV_PARAMS)); |
| BTA_BleUpdateAdvInstParam((UINT8)inst_id, |
| &(p_multi_adv_data_cb->inst_cb[cbindex].param)); |
| } else { |
| BTIF_TRACE_ERROR("%s invalid index in BTIF_GATTC_UPDATE_ADV", __FUNCTION__); |
| } |
| } |
| |
| bt_status_t btif_gattc_multi_adv_update(int client_if, int min_interval, |
| int max_interval, int adv_type, |
| int chnl_map, int tx_power, |
| int timeout_s) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread(Bind(btif_gattc_multi_adv_update_impl, client_if, |
| min_interval, max_interval, adv_type, chnl_map, |
| tx_power)); |
| } |
| |
| void btif_gattc_multi_adv_setdata_impl(btif_adv_data_t *p_adv_data) { |
| int cbindex = |
| btif_gattc_obtain_idx_for_datacb(p_adv_data->client_if, CLNT_IF_IDX); |
| int inst_id = btif_multi_adv_instid_for_clientif(p_adv_data->client_if); |
| if (inst_id >= 0 && cbindex >= 0 && |
| btif_gattc_copy_datacb(cbindex, p_adv_data, true)) { |
| btgatt_multi_adv_common_data *p_multi_adv_data_cb = |
| btif_obtain_multi_adv_data_cb(); |
| BTA_BleCfgAdvInstData((UINT8)inst_id, p_adv_data->set_scan_rsp, |
| p_multi_adv_data_cb->inst_cb[cbindex].mask, |
| &p_multi_adv_data_cb->inst_cb[cbindex].data); |
| } else { |
| BTIF_TRACE_ERROR( |
| "%s: failed to get invalid instance data: inst_id:%d cbindex:%d", |
| __func__, inst_id, cbindex); |
| } |
| } |
| |
| bt_status_t btif_gattc_multi_adv_setdata( |
| int client_if, bool set_scan_rsp, bool include_name, bool incl_txpower, |
| int appearance, int manufacturer_len, char *manufacturer_data, |
| int service_data_len, char *service_data, int service_uuid_len, |
| char *service_uuid) { |
| CHECK_BTGATT_INIT(); |
| |
| btif_adv_data_t *multi_adv_data_inst = new btif_adv_data_t; |
| |
| const int min_interval = 0; |
| const int max_interval = 0; |
| |
| btif_gattc_adv_data_packager(client_if, set_scan_rsp, include_name, |
| incl_txpower, min_interval, max_interval, |
| appearance, manufacturer_len, manufacturer_data, |
| service_data_len, service_data, service_uuid_len, |
| service_uuid, multi_adv_data_inst); |
| |
| return do_in_jni_thread(Bind(&btif_gattc_multi_adv_setdata_impl, |
| base::Owned(multi_adv_data_inst))); |
| } |
| |
| void btif_gattc_multi_adv_disable_impl(int client_if) { |
| int inst_id = btif_multi_adv_instid_for_clientif(client_if); |
| if (inst_id >= 0) |
| BTA_BleDisableAdvInstance((UINT8)inst_id); |
| else |
| BTIF_TRACE_ERROR("%s invalid instance ID", __func__); |
| } |
| |
| bt_status_t btif_gattc_multi_adv_disable(int client_if) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread(Bind(btif_gattc_multi_adv_disable_impl, client_if)); |
| } |
| |
| bt_status_t btif_gattc_cfg_storage(int client_if, int batch_scan_full_max, |
| int batch_scan_trunc_max, |
| int batch_scan_notify_threshold) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread( |
| Bind(BTA_DmBleSetStorageParams, batch_scan_full_max, batch_scan_trunc_max, |
| batch_scan_notify_threshold, |
| (tBTA_BLE_SCAN_SETUP_CBACK *)bta_batch_scan_setup_cb, |
| (tBTA_BLE_SCAN_THRESHOLD_CBACK *)bta_batch_scan_threshold_cb, |
| (tBTA_BLE_SCAN_REP_CBACK *)bta_batch_scan_reports_cb, |
| (tBTA_DM_BLE_REF_VALUE)client_if)); |
| } |
| |
| bt_status_t btif_gattc_enb_batch_scan(int client_if, int scan_mode, |
| int scan_interval, int scan_window, |
| int addr_type, int discard_rule) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread(Bind(BTA_DmBleEnableBatchScan, scan_mode, |
| scan_interval, scan_window, discard_rule, |
| addr_type, client_if)); |
| } |
| |
| bt_status_t btif_gattc_dis_batch_scan(int client_if) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread(Bind(BTA_DmBleDisableBatchScan, client_if)); |
| } |
| |
| bt_status_t btif_gattc_read_batch_scan_reports(int client_if, int scan_mode) { |
| CHECK_BTGATT_INIT(); |
| return do_in_jni_thread(Bind(BTA_DmBleReadScanReports, scan_mode, client_if)); |
| } |
| |
| bt_status_t btif_gattc_test_command(int command, btgatt_test_params_t *params) { |
| return btif_gattc_test_command_impl(command, params); |
| } |
| |
| } // namespace |
| |
| const btgatt_client_interface_t btgattClientInterface = { |
| btif_gattc_register_app, |
| btif_gattc_unregister_app, |
| btif_gattc_scan, |
| btif_gattc_open, |
| btif_gattc_close, |
| btif_gattc_listen, |
| btif_gattc_refresh, |
| btif_gattc_search_service, |
| btif_gattc_read_char, |
| btif_gattc_write_char, |
| btif_gattc_read_char_descr, |
| btif_gattc_write_char_descr, |
| btif_gattc_execute_write, |
| btif_gattc_reg_for_notification, |
| btif_gattc_dereg_for_notification, |
| btif_gattc_read_remote_rssi, |
| btif_gattc_scan_filter_param_setup, |
| btif_gattc_scan_filter_add_remove, |
| btif_gattc_scan_filter_clear, |
| btif_gattc_scan_filter_enable, |
| btif_gattc_get_device_type, |
| btif_gattc_set_adv_data, |
| btif_gattc_configure_mtu, |
| btif_gattc_conn_parameter_update, |
| btif_gattc_set_scan_parameters, |
| btif_gattc_multi_adv_enable, |
| btif_gattc_multi_adv_update, |
| btif_gattc_multi_adv_setdata, |
| btif_gattc_multi_adv_disable, |
| btif_gattc_cfg_storage, |
| btif_gattc_enb_batch_scan, |
| btif_gattc_dis_batch_scan, |
| btif_gattc_read_batch_scan_reports, |
| btif_gattc_test_command, |
| btif_gattc_get_gatt_db}; |
| |
| #endif |