1 /******************************************************************************
2 *
3 * Copyright 2009-2014 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /*******************************************************************************
20 *
21 * Filename: btif_gatt_client.c
22 *
23 * Description: GATT client implementation
24 *
25 ******************************************************************************/
26
27 #define LOG_TAG "bt_btif_gattc"
28
29 #include <base/at_exit.h>
30 #include <base/bind.h>
31 #include <base/threading/thread.h>
32 #include <errno.h>
33 #include <hardware/bluetooth.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "device/include/controller.h"
37
38 #include "btif_common.h"
39 #include "btif_util.h"
40
41 #include <hardware/bt_gatt.h>
42
43 #include "bta_api.h"
44 #include "bta_gatt_api.h"
45 #include "btif_config.h"
46 #include "btif_dm.h"
47 #include "btif_gatt.h"
48 #include "btif_gatt_util.h"
49 #include "btif_storage.h"
50 #include "osi/include/log.h"
51 #include "stack/include/btu.h"
52 #include "vendor_api.h"
53
54 using base::Bind;
55 using base::Owned;
56 using bluetooth::Uuid;
57 using std::vector;
58
59 extern bt_status_t btif_gattc_test_command_impl(
60 int command, const btgatt_test_params_t* params);
61 extern const btgatt_callbacks_t* bt_gatt_callbacks;
62
63 /*******************************************************************************
64 * Constants & Macros
65 ******************************************************************************/
66
67 #define CLI_CBACK_IN_JNI(P_CBACK, ...) \
68 do { \
69 if (bt_gatt_callbacks && bt_gatt_callbacks->client->P_CBACK) { \
70 BTIF_TRACE_API("HAL bt_gatt_callbacks->client->%s", #P_CBACK); \
71 do_in_jni_thread(Bind(bt_gatt_callbacks->client->P_CBACK, __VA_ARGS__)); \
72 } else { \
73 ASSERTC(0, "Callback is NULL", 0); \
74 } \
75 } while (0)
76
77 #define CHECK_BTGATT_INIT() \
78 do { \
79 if (bt_gatt_callbacks == NULL) { \
80 LOG_WARN(LOG_TAG, "%s: BTGATT not initialized", __func__); \
81 return BT_STATUS_NOT_READY; \
82 } else { \
83 LOG_VERBOSE(LOG_TAG, "%s", __func__); \
84 } \
85 } while (0)
86
87 #define BLE_RESOLVE_ADDR_MSB \
88 0x40 /* bit7, bit6 is 01 to be resolvable random \
89 */
90 #define BLE_RESOLVE_ADDR_MASK 0xc0 /* bit 6, and bit7 */
BTM_BLE_IS_RESOLVE_BDA(const RawAddress & x)91 inline bool BTM_BLE_IS_RESOLVE_BDA(const RawAddress& x) {
92 return ((x.address)[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB;
93 }
94 namespace {
95
96 uint8_t rssi_request_client_if;
97
btif_gattc_upstreams_evt(uint16_t event,char * p_param)98 void btif_gattc_upstreams_evt(uint16_t event, char* p_param) {
99 LOG_VERBOSE(LOG_TAG, "%s: Event %d", __func__, event);
100
101 tBTA_GATTC* p_data = (tBTA_GATTC*)p_param;
102 switch (event) {
103 case BTA_GATTC_DEREG_EVT:
104 break;
105
106 case BTA_GATTC_EXEC_EVT: {
107 HAL_CBACK(bt_gatt_callbacks, client->execute_write_cb,
108 p_data->exec_cmpl.conn_id, p_data->exec_cmpl.status);
109 break;
110 }
111
112 case BTA_GATTC_SEARCH_CMPL_EVT: {
113 HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb,
114 p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
115 break;
116 }
117
118 case BTA_GATTC_NOTIF_EVT: {
119 btgatt_notify_params_t data;
120
121 data.bda = p_data->notify.bda;
122 memcpy(data.value, p_data->notify.value, p_data->notify.len);
123
124 data.handle = p_data->notify.handle;
125 data.is_notify = p_data->notify.is_notify;
126 data.len = p_data->notify.len;
127
128 HAL_CBACK(bt_gatt_callbacks, client->notify_cb, p_data->notify.conn_id,
129 data);
130
131 if (!p_data->notify.is_notify)
132 BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle);
133
134 break;
135 }
136
137 case BTA_GATTC_OPEN_EVT: {
138 DVLOG(1) << "BTA_GATTC_OPEN_EVT " << p_data->open.remote_bda;
139 HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id,
140 p_data->open.status, p_data->open.client_if,
141 p_data->open.remote_bda);
142
143 if (GATT_DEF_BLE_MTU_SIZE != p_data->open.mtu && p_data->open.mtu) {
144 HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb,
145 p_data->open.conn_id, p_data->open.status, p_data->open.mtu);
146 }
147
148 if (p_data->open.status == GATT_SUCCESS)
149 btif_gatt_check_encrypted_link(p_data->open.remote_bda,
150 p_data->open.transport);
151 break;
152 }
153
154 case BTA_GATTC_CLOSE_EVT: {
155 HAL_CBACK(bt_gatt_callbacks, client->close_cb, p_data->close.conn_id,
156 p_data->status, p_data->close.client_if,
157 p_data->close.remote_bda);
158 break;
159 }
160
161 case BTA_GATTC_ACL_EVT:
162 LOG_DEBUG(LOG_TAG, "BTA_GATTC_ACL_EVT: status = %d", p_data->status);
163 /* Ignore for now */
164 break;
165
166 case BTA_GATTC_SEARCH_RES_EVT:
167 break;
168
169 case BTA_GATTC_CANCEL_OPEN_EVT:
170 break;
171
172 case BTA_GATTC_CFG_MTU_EVT: {
173 HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb,
174 p_data->cfg_mtu.conn_id, p_data->cfg_mtu.status,
175 p_data->cfg_mtu.mtu);
176 break;
177 }
178
179 case BTA_GATTC_CONGEST_EVT:
180 HAL_CBACK(bt_gatt_callbacks, client->congestion_cb,
181 p_data->congest.conn_id, p_data->congest.congested);
182 break;
183
184 case BTA_GATTC_PHY_UPDATE_EVT:
185 HAL_CBACK(bt_gatt_callbacks, client->phy_updated_cb,
186 p_data->phy_update.conn_id, p_data->phy_update.tx_phy,
187 p_data->phy_update.rx_phy, p_data->phy_update.status);
188 break;
189
190 case BTA_GATTC_CONN_UPDATE_EVT:
191 HAL_CBACK(bt_gatt_callbacks, client->conn_updated_cb,
192 p_data->conn_update.conn_id, p_data->conn_update.interval,
193 p_data->conn_update.latency, p_data->conn_update.timeout,
194 p_data->conn_update.status);
195 break;
196
197 default:
198 LOG_ERROR(LOG_TAG, "%s: Unhandled event (%d)!", __func__, event);
199 break;
200 }
201 }
202
bta_gattc_cback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)203 void bta_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
204 bt_status_t status =
205 btif_transfer_context(btif_gattc_upstreams_evt, (uint16_t)event,
206 (char*)p_data, sizeof(tBTA_GATTC), NULL);
207 ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
208 }
209
btm_read_rssi_cb(void * p_void)210 void btm_read_rssi_cb(void* p_void) {
211 tBTM_RSSI_RESULT* p_result = (tBTM_RSSI_RESULT*)p_void;
212
213 if (!p_result) return;
214
215 CLI_CBACK_IN_JNI(read_remote_rssi_cb, rssi_request_client_if,
216 p_result->rem_bda, p_result->rssi, p_result->status);
217 }
218
219 /*******************************************************************************
220 * Client API Functions
221 ******************************************************************************/
222
btif_gattc_register_app(const Uuid & uuid)223 bt_status_t btif_gattc_register_app(const Uuid& uuid) {
224 CHECK_BTGATT_INIT();
225
226 return do_in_jni_thread(Bind(
227 [](const Uuid& uuid) {
228 BTA_GATTC_AppRegister(
229 bta_gattc_cback,
230 base::Bind(
231 [](const Uuid& uuid, uint8_t client_id, uint8_t status) {
232 do_in_jni_thread(Bind(
233 [](const Uuid& uuid, uint8_t client_id, uint8_t status) {
234 HAL_CBACK(bt_gatt_callbacks, client->register_client_cb,
235 status, client_id, uuid);
236 },
237 uuid, client_id, status));
238 },
239 uuid));
240 },
241 uuid));
242 }
243
btif_gattc_unregister_app_impl(int client_if)244 void btif_gattc_unregister_app_impl(int client_if) {
245 BTA_GATTC_AppDeregister(client_if);
246 }
247
btif_gattc_unregister_app(int client_if)248 bt_status_t btif_gattc_unregister_app(int client_if) {
249 CHECK_BTGATT_INIT();
250 return do_in_jni_thread(Bind(&btif_gattc_unregister_app_impl, client_if));
251 }
252
btif_gattc_open_impl(int client_if,RawAddress address,bool is_direct,int transport_p,bool opportunistic,int initiating_phys)253 void btif_gattc_open_impl(int client_if, RawAddress address, bool is_direct,
254 int transport_p, bool opportunistic,
255 int initiating_phys) {
256 // Ensure device is in inquiry database
257 int addr_type = 0;
258 int device_type = 0;
259 tGATT_TRANSPORT transport = (tGATT_TRANSPORT)GATT_TRANSPORT_LE;
260
261 if (btif_get_address_type(address, &addr_type) &&
262 btif_get_device_type(address, &device_type) &&
263 device_type != BT_DEVICE_TYPE_BREDR) {
264 BTA_DmAddBleDevice(address, addr_type, device_type);
265 }
266
267 // Check for background connections
268 if (!is_direct) {
269 // Check for privacy 1.0 and 1.1 controller and do not start background
270 // connection if RPA offloading is not supported, since it will not
271 // connect after change of random address
272 if (!controller_get_interface()->supports_ble_privacy() &&
273 (addr_type == BLE_ADDR_RANDOM) && BTM_BLE_IS_RESOLVE_BDA(address)) {
274 tBTM_BLE_VSC_CB vnd_capabilities;
275 BTM_BleGetVendorCapabilities(&vnd_capabilities);
276 if (!vnd_capabilities.rpa_offloading) {
277 HAL_CBACK(bt_gatt_callbacks, client->open_cb, 0, BT_STATUS_UNSUPPORTED,
278 client_if, address);
279 return;
280 }
281 }
282 }
283
284 // Determine transport
285 if (transport_p != GATT_TRANSPORT_AUTO) {
286 transport = transport_p;
287 } else {
288 switch (device_type) {
289 case BT_DEVICE_TYPE_BREDR:
290 transport = GATT_TRANSPORT_BR_EDR;
291 break;
292
293 case BT_DEVICE_TYPE_BLE:
294 transport = GATT_TRANSPORT_LE;
295 break;
296
297 case BT_DEVICE_TYPE_DUMO:
298 if (transport_p == GATT_TRANSPORT_LE)
299 transport = GATT_TRANSPORT_LE;
300 else
301 transport = GATT_TRANSPORT_BR_EDR;
302 break;
303 }
304 }
305
306 // Connect!
307 BTIF_TRACE_DEBUG("%s Transport=%d, device type=%d, phy=%d", __func__,
308 transport, device_type, initiating_phys);
309 BTA_GATTC_Open(client_if, address, is_direct, transport, opportunistic,
310 initiating_phys);
311 }
312
btif_gattc_open(int client_if,const RawAddress & bd_addr,bool is_direct,int transport,bool opportunistic,int initiating_phys)313 bt_status_t btif_gattc_open(int client_if, const RawAddress& bd_addr,
314 bool is_direct, int transport, bool opportunistic,
315 int initiating_phys) {
316 CHECK_BTGATT_INIT();
317 // Closure will own this value and free it.
318 return do_in_jni_thread(Bind(&btif_gattc_open_impl, client_if, bd_addr,
319 is_direct, transport, opportunistic,
320 initiating_phys));
321 }
322
btif_gattc_close_impl(int client_if,RawAddress address,int conn_id)323 void btif_gattc_close_impl(int client_if, RawAddress address, int conn_id) {
324 // Disconnect established connections
325 if (conn_id != 0)
326 BTA_GATTC_Close(conn_id);
327 else
328 BTA_GATTC_CancelOpen(client_if, address, true);
329
330 // Cancel pending background connections (remove from whitelist)
331 BTA_GATTC_CancelOpen(client_if, address, false);
332 }
333
btif_gattc_close(int client_if,const RawAddress & bd_addr,int conn_id)334 bt_status_t btif_gattc_close(int client_if, const RawAddress& bd_addr,
335 int conn_id) {
336 CHECK_BTGATT_INIT();
337 return do_in_jni_thread(
338 Bind(&btif_gattc_close_impl, client_if, bd_addr, conn_id));
339 }
340
btif_gattc_refresh(int client_if,const RawAddress & bd_addr)341 bt_status_t btif_gattc_refresh(int client_if, const RawAddress& bd_addr) {
342 CHECK_BTGATT_INIT();
343 return do_in_jni_thread(Bind(&BTA_GATTC_Refresh, bd_addr));
344 }
345
btif_gattc_search_service(int conn_id,const Uuid * filter_uuid)346 bt_status_t btif_gattc_search_service(int conn_id, const Uuid* filter_uuid) {
347 CHECK_BTGATT_INIT();
348
349 if (filter_uuid) {
350 Uuid* uuid = new Uuid(*filter_uuid);
351 return do_in_jni_thread(
352 Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, base::Owned(uuid)));
353 } else {
354 return do_in_jni_thread(
355 Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, nullptr));
356 }
357 }
358
btif_gattc_discover_service_by_uuid(int conn_id,const Uuid & uuid)359 void btif_gattc_discover_service_by_uuid(int conn_id, const Uuid& uuid) {
360 do_in_jni_thread(Bind(&BTA_GATTC_DiscoverServiceByUuid, conn_id, uuid));
361 }
362
btif_gattc_get_gatt_db_impl(int conn_id)363 void btif_gattc_get_gatt_db_impl(int conn_id) {
364 btgatt_db_element_t* db = NULL;
365 int count = 0;
366 BTA_GATTC_GetGattDb(conn_id, 0x0000, 0xFFFF, &db, &count);
367
368 HAL_CBACK(bt_gatt_callbacks, client->get_gatt_db_cb, conn_id, db, count);
369 osi_free(db);
370 }
371
btif_gattc_get_gatt_db(int conn_id)372 bt_status_t btif_gattc_get_gatt_db(int conn_id) {
373 CHECK_BTGATT_INIT();
374 return do_in_jni_thread(Bind(&btif_gattc_get_gatt_db_impl, conn_id));
375 }
376
read_char_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)377 void read_char_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
378 uint16_t len, uint8_t* value, void* data) {
379 btgatt_read_params_t* params = new btgatt_read_params_t;
380 params->value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
381 params->status = status;
382 params->handle = handle;
383 params->value.len = len;
384 CHECK(len <= BTGATT_MAX_ATTR_LEN);
385 if (len > 0) memcpy(params->value.value, value, len);
386
387 // clang-tidy analyzer complains about |params| is leaked. It doesn't know
388 // that |param| will be freed by the callback function.
389 CLI_CBACK_IN_JNI(read_characteristic_cb, conn_id, status, /* NOLINT */
390 base::Owned(params));
391 }
392
btif_gattc_read_char(int conn_id,uint16_t handle,int auth_req)393 bt_status_t btif_gattc_read_char(int conn_id, uint16_t handle, int auth_req) {
394 CHECK_BTGATT_INIT();
395 return do_in_jni_thread(Bind(&BTA_GATTC_ReadCharacteristic, conn_id, handle,
396 auth_req, read_char_cb, nullptr));
397 }
398
read_using_char_uuid_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)399 void read_using_char_uuid_cb(uint16_t conn_id, tGATT_STATUS status,
400 uint16_t handle, uint16_t len, uint8_t* value,
401 void* data) {
402 btgatt_read_params_t* params = new btgatt_read_params_t;
403 params->value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
404 params->status = status;
405 params->handle = handle;
406 params->value.len = len;
407 CHECK(len <= BTGATT_MAX_ATTR_LEN);
408 if (len > 0) memcpy(params->value.value, value, len);
409
410 // clang-tidy analyzer complains about |params| is leaked. It doesn't know
411 // that |param| will be freed by the callback function.
412 CLI_CBACK_IN_JNI(read_characteristic_cb, conn_id, status, /* NOLINT */
413 base::Owned(params));
414 }
415
btif_gattc_read_using_char_uuid(int conn_id,const Uuid & uuid,uint16_t s_handle,uint16_t e_handle,int auth_req)416 bt_status_t btif_gattc_read_using_char_uuid(int conn_id, const Uuid& uuid,
417 uint16_t s_handle,
418 uint16_t e_handle, int auth_req) {
419 CHECK_BTGATT_INIT();
420 return do_in_jni_thread(Bind(&BTA_GATTC_ReadUsingCharUuid, conn_id, uuid,
421 s_handle, e_handle, auth_req,
422 read_using_char_uuid_cb, nullptr));
423 }
424
read_desc_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)425 void read_desc_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
426 uint16_t len, uint8_t* value, void* data) {
427 btgatt_read_params_t params;
428 params.value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
429 params.status = status;
430 params.handle = handle;
431 params.value.len = len;
432 CHECK(len <= BTGATT_MAX_ATTR_LEN);
433 if (len > 0) memcpy(params.value.value, value, len);
434
435 CLI_CBACK_IN_JNI(read_descriptor_cb, conn_id, status, params);
436 }
437
btif_gattc_read_char_descr(int conn_id,uint16_t handle,int auth_req)438 bt_status_t btif_gattc_read_char_descr(int conn_id, uint16_t handle,
439 int auth_req) {
440 CHECK_BTGATT_INIT();
441 return do_in_jni_thread(Bind(&BTA_GATTC_ReadCharDescr, conn_id, handle,
442 auth_req, read_desc_cb, nullptr));
443 }
444
write_char_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,void * data)445 void write_char_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
446 void* data) {
447 CLI_CBACK_IN_JNI(write_characteristic_cb, conn_id, status, handle);
448 }
449
btif_gattc_write_char(int conn_id,uint16_t handle,int write_type,int auth_req,vector<uint8_t> value)450 bt_status_t btif_gattc_write_char(int conn_id, uint16_t handle, int write_type,
451 int auth_req, vector<uint8_t> value) {
452 CHECK_BTGATT_INIT();
453
454 if (value.size() > BTGATT_MAX_ATTR_LEN) value.resize(BTGATT_MAX_ATTR_LEN);
455
456 return do_in_jni_thread(Bind(&BTA_GATTC_WriteCharValue, conn_id, handle,
457 write_type, std::move(value), auth_req,
458 write_char_cb, nullptr));
459 }
460
write_descr_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,void * data)461 void write_descr_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
462 void* data) {
463 CLI_CBACK_IN_JNI(write_descriptor_cb, conn_id, status, handle);
464 }
465
btif_gattc_write_char_descr(int conn_id,uint16_t handle,int auth_req,vector<uint8_t> value)466 bt_status_t btif_gattc_write_char_descr(int conn_id, uint16_t handle,
467 int auth_req, vector<uint8_t> value) {
468 CHECK_BTGATT_INIT();
469
470 if (value.size() > BTGATT_MAX_ATTR_LEN) value.resize(BTGATT_MAX_ATTR_LEN);
471
472 return do_in_jni_thread(Bind(&BTA_GATTC_WriteCharDescr, conn_id, handle,
473 std::move(value), auth_req, write_descr_cb,
474 nullptr));
475 }
476
btif_gattc_execute_write(int conn_id,int execute)477 bt_status_t btif_gattc_execute_write(int conn_id, int execute) {
478 CHECK_BTGATT_INIT();
479 return do_in_jni_thread(
480 Bind(&BTA_GATTC_ExecuteWrite, conn_id, (uint8_t)execute));
481 }
482
btif_gattc_reg_for_notification_impl(tGATT_IF client_if,const RawAddress & bda,uint16_t handle)483 void btif_gattc_reg_for_notification_impl(tGATT_IF client_if,
484 const RawAddress& bda,
485 uint16_t handle) {
486 tGATT_STATUS status =
487 BTA_GATTC_RegisterForNotifications(client_if, bda, handle);
488
489 // TODO(jpawlowski): conn_id is currently unused
490 HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
491 /* conn_id */ 0, 1, status, handle);
492 }
493
btif_gattc_reg_for_notification(int client_if,const RawAddress & bd_addr,uint16_t handle)494 bt_status_t btif_gattc_reg_for_notification(int client_if,
495 const RawAddress& bd_addr,
496 uint16_t handle) {
497 CHECK_BTGATT_INIT();
498
499 return do_in_jni_thread(
500 Bind(base::IgnoreResult(&btif_gattc_reg_for_notification_impl), client_if,
501 bd_addr, handle));
502 }
503
btif_gattc_dereg_for_notification_impl(tGATT_IF client_if,const RawAddress & bda,uint16_t handle)504 void btif_gattc_dereg_for_notification_impl(tGATT_IF client_if,
505 const RawAddress& bda,
506 uint16_t handle) {
507 tGATT_STATUS status =
508 BTA_GATTC_DeregisterForNotifications(client_if, bda, handle);
509
510 // TODO(jpawlowski): conn_id is currently unused
511 HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
512 /* conn_id */ 0, 0, status, handle);
513 }
514
btif_gattc_dereg_for_notification(int client_if,const RawAddress & bd_addr,uint16_t handle)515 bt_status_t btif_gattc_dereg_for_notification(int client_if,
516 const RawAddress& bd_addr,
517 uint16_t handle) {
518 CHECK_BTGATT_INIT();
519
520 return do_in_jni_thread(
521 Bind(base::IgnoreResult(&btif_gattc_dereg_for_notification_impl),
522 client_if, bd_addr, handle));
523 }
524
btif_gattc_read_remote_rssi(int client_if,const RawAddress & bd_addr)525 bt_status_t btif_gattc_read_remote_rssi(int client_if,
526 const RawAddress& bd_addr) {
527 CHECK_BTGATT_INIT();
528 rssi_request_client_if = client_if;
529
530 return do_in_jni_thread(
531 Bind(base::IgnoreResult(&BTM_ReadRSSI), bd_addr, btm_read_rssi_cb));
532 }
533
btif_gattc_configure_mtu(int conn_id,int mtu)534 bt_status_t btif_gattc_configure_mtu(int conn_id, int mtu) {
535 CHECK_BTGATT_INIT();
536 return do_in_jni_thread(
537 Bind(base::IgnoreResult(&BTA_GATTC_ConfigureMTU), conn_id, mtu));
538 }
539
btif_gattc_conn_parameter_update_impl(RawAddress addr,int min_interval,int max_interval,int latency,int timeout,uint16_t min_ce_len,uint16_t max_ce_len)540 void btif_gattc_conn_parameter_update_impl(RawAddress addr, int min_interval,
541 int max_interval, int latency,
542 int timeout, uint16_t min_ce_len,
543 uint16_t max_ce_len) {
544 if (BTA_DmGetConnectionState(addr))
545 BTA_DmBleUpdateConnectionParams(addr, min_interval, max_interval, latency,
546 timeout, min_ce_len, max_ce_len);
547 else
548 BTA_DmSetBlePrefConnParams(addr, min_interval, max_interval, latency,
549 timeout);
550 }
551
btif_gattc_conn_parameter_update(const RawAddress & bd_addr,int min_interval,int max_interval,int latency,int timeout,uint16_t min_ce_len,uint16_t max_ce_len)552 bt_status_t btif_gattc_conn_parameter_update(const RawAddress& bd_addr,
553 int min_interval, int max_interval,
554 int latency, int timeout,
555 uint16_t min_ce_len,
556 uint16_t max_ce_len) {
557 CHECK_BTGATT_INIT();
558 return do_in_jni_thread(Bind(
559 base::IgnoreResult(&btif_gattc_conn_parameter_update_impl), bd_addr,
560 min_interval, max_interval, latency, timeout, min_ce_len, max_ce_len));
561 }
562
btif_gattc_set_preferred_phy(const RawAddress & bd_addr,uint8_t tx_phy,uint8_t rx_phy,uint16_t phy_options)563 bt_status_t btif_gattc_set_preferred_phy(const RawAddress& bd_addr,
564 uint8_t tx_phy, uint8_t rx_phy,
565 uint16_t phy_options) {
566 CHECK_BTGATT_INIT();
567 do_in_main_thread(FROM_HERE,
568 Bind(&BTM_BleSetPhy, bd_addr, tx_phy, rx_phy, phy_options));
569 return BT_STATUS_SUCCESS;
570 }
571
btif_gattc_read_phy(const RawAddress & bd_addr,base::Callback<void (uint8_t tx_phy,uint8_t rx_phy,uint8_t status)> cb)572 bt_status_t btif_gattc_read_phy(
573 const RawAddress& bd_addr,
574 base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb) {
575 CHECK_BTGATT_INIT();
576 do_in_main_thread(FROM_HERE, Bind(&BTM_BleReadPhy, bd_addr,
577 jni_thread_wrapper(FROM_HERE, cb)));
578 return BT_STATUS_SUCCESS;
579 }
580
btif_gattc_get_device_type(const RawAddress & bd_addr)581 int btif_gattc_get_device_type(const RawAddress& bd_addr) {
582 int device_type = 0;
583
584 if (btif_config_get_int(bd_addr.ToString().c_str(), "DevType", &device_type))
585 return device_type;
586 return 0;
587 }
588
btif_gattc_test_command(int command,const btgatt_test_params_t & params)589 bt_status_t btif_gattc_test_command(int command,
590 const btgatt_test_params_t& params) {
591 return btif_gattc_test_command_impl(command, ¶ms);
592 }
593
594 } // namespace
595
596 const btgatt_client_interface_t btgattClientInterface = {
597 btif_gattc_register_app,
598 btif_gattc_unregister_app,
599 btif_gattc_open,
600 btif_gattc_close,
601 btif_gattc_refresh,
602 btif_gattc_search_service,
603 btif_gattc_discover_service_by_uuid,
604 btif_gattc_read_char,
605 btif_gattc_read_using_char_uuid,
606 btif_gattc_write_char,
607 btif_gattc_read_char_descr,
608 btif_gattc_write_char_descr,
609 btif_gattc_execute_write,
610 btif_gattc_reg_for_notification,
611 btif_gattc_dereg_for_notification,
612 btif_gattc_read_remote_rssi,
613 btif_gattc_get_device_type,
614 btif_gattc_configure_mtu,
615 btif_gattc_conn_parameter_update,
616 btif_gattc_set_preferred_phy,
617 btif_gattc_read_phy,
618 btif_gattc_test_command,
619 btif_gattc_get_gatt_db};
620