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_closure_api.h"
45 #include "bta_gatt_api.h"
46 #include "btif_config.h"
47 #include "btif_dm.h"
48 #include "btif_gatt.h"
49 #include "btif_gatt_util.h"
50 #include "btif_storage.h"
51 #include "osi/include/log.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_CANCEL_OPEN_EVT:
167 break;
168
169 case BTA_GATTC_CFG_MTU_EVT: {
170 HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb,
171 p_data->cfg_mtu.conn_id, p_data->cfg_mtu.status,
172 p_data->cfg_mtu.mtu);
173 break;
174 }
175
176 case BTA_GATTC_CONGEST_EVT:
177 HAL_CBACK(bt_gatt_callbacks, client->congestion_cb,
178 p_data->congest.conn_id, p_data->congest.congested);
179 break;
180
181 case BTA_GATTC_PHY_UPDATE_EVT:
182 HAL_CBACK(bt_gatt_callbacks, client->phy_updated_cb,
183 p_data->phy_update.conn_id, p_data->phy_update.tx_phy,
184 p_data->phy_update.rx_phy, p_data->phy_update.status);
185 break;
186
187 case BTA_GATTC_CONN_UPDATE_EVT:
188 HAL_CBACK(bt_gatt_callbacks, client->conn_updated_cb,
189 p_data->conn_update.conn_id, p_data->conn_update.interval,
190 p_data->conn_update.latency, p_data->conn_update.timeout,
191 p_data->conn_update.status);
192 break;
193
194 default:
195 LOG_ERROR(LOG_TAG, "%s: Unhandled event (%d)!", __func__, event);
196 break;
197 }
198 }
199
bta_gattc_cback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)200 void bta_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
201 bt_status_t status =
202 btif_transfer_context(btif_gattc_upstreams_evt, (uint16_t)event,
203 (char*)p_data, sizeof(tBTA_GATTC), NULL);
204 ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
205 }
206
btm_read_rssi_cb(void * p_void)207 void btm_read_rssi_cb(void* p_void) {
208 tBTM_RSSI_RESULT* p_result = (tBTM_RSSI_RESULT*)p_void;
209
210 if (!p_result) return;
211
212 CLI_CBACK_IN_JNI(read_remote_rssi_cb, rssi_request_client_if,
213 p_result->rem_bda, p_result->rssi, p_result->status);
214 }
215
216 /*******************************************************************************
217 * Client API Functions
218 ******************************************************************************/
219
btif_gattc_register_app(const Uuid & uuid)220 bt_status_t btif_gattc_register_app(const Uuid& uuid) {
221 CHECK_BTGATT_INIT();
222
223 return do_in_jni_thread(Bind(
224 [](const Uuid& uuid) {
225 BTA_GATTC_AppRegister(
226 bta_gattc_cback,
227 base::Bind(
228 [](const Uuid& uuid, uint8_t client_id, uint8_t status) {
229 do_in_jni_thread(Bind(
230 [](const Uuid& uuid, uint8_t client_id, uint8_t status) {
231 HAL_CBACK(bt_gatt_callbacks, client->register_client_cb,
232 status, client_id, uuid);
233 },
234 uuid, client_id, status));
235 },
236 uuid));
237 },
238 uuid));
239 }
240
btif_gattc_unregister_app_impl(int client_if)241 void btif_gattc_unregister_app_impl(int client_if) {
242 BTA_GATTC_AppDeregister(client_if);
243 }
244
btif_gattc_unregister_app(int client_if)245 bt_status_t btif_gattc_unregister_app(int client_if) {
246 CHECK_BTGATT_INIT();
247 return do_in_jni_thread(Bind(&btif_gattc_unregister_app_impl, client_if));
248 }
249
btif_gattc_open_impl(int client_if,RawAddress address,bool is_direct,int transport_p,bool opportunistic,int initiating_phys)250 void btif_gattc_open_impl(int client_if, RawAddress address, bool is_direct,
251 int transport_p, bool opportunistic,
252 int initiating_phys) {
253 // Ensure device is in inquiry database
254 int addr_type = 0;
255 int device_type = 0;
256 tGATT_TRANSPORT transport = (tGATT_TRANSPORT)GATT_TRANSPORT_LE;
257
258 if (btif_get_address_type(address, &addr_type) &&
259 btif_get_device_type(address, &device_type) &&
260 device_type != BT_DEVICE_TYPE_BREDR) {
261 BTA_DmAddBleDevice(address, addr_type, device_type);
262 }
263
264 // Check for background connections
265 if (!is_direct) {
266 // Check for privacy 1.0 and 1.1 controller and do not start background
267 // connection if RPA offloading is not supported, since it will not
268 // connect after change of random address
269 if (!controller_get_interface()->supports_ble_privacy() &&
270 (addr_type == BLE_ADDR_RANDOM) && BTM_BLE_IS_RESOLVE_BDA(address)) {
271 tBTM_BLE_VSC_CB vnd_capabilities;
272 BTM_BleGetVendorCapabilities(&vnd_capabilities);
273 if (!vnd_capabilities.rpa_offloading) {
274 HAL_CBACK(bt_gatt_callbacks, client->open_cb, 0, BT_STATUS_UNSUPPORTED,
275 client_if, address);
276 return;
277 }
278 }
279 BTA_DmBleStartAutoConn();
280 }
281
282 // Determine transport
283 if (transport_p != GATT_TRANSPORT_AUTO) {
284 transport = transport_p;
285 } else {
286 switch (device_type) {
287 case BT_DEVICE_TYPE_BREDR:
288 transport = GATT_TRANSPORT_BR_EDR;
289 break;
290
291 case BT_DEVICE_TYPE_BLE:
292 transport = GATT_TRANSPORT_LE;
293 break;
294
295 case BT_DEVICE_TYPE_DUMO:
296 if (transport_p == GATT_TRANSPORT_LE)
297 transport = GATT_TRANSPORT_LE;
298 else
299 transport = GATT_TRANSPORT_BR_EDR;
300 break;
301 }
302 }
303
304 // Connect!
305 BTIF_TRACE_DEBUG("%s Transport=%d, device type=%d, phy=%d", __func__,
306 transport, device_type, initiating_phys);
307 BTA_GATTC_Open(client_if, address, is_direct, transport, opportunistic,
308 initiating_phys);
309 }
310
btif_gattc_open(int client_if,const RawAddress & bd_addr,bool is_direct,int transport,bool opportunistic,int initiating_phys)311 bt_status_t btif_gattc_open(int client_if, const RawAddress& bd_addr,
312 bool is_direct, int transport, bool opportunistic,
313 int initiating_phys) {
314 CHECK_BTGATT_INIT();
315 // Closure will own this value and free it.
316 return do_in_jni_thread(Bind(&btif_gattc_open_impl, client_if, bd_addr,
317 is_direct, transport, opportunistic,
318 initiating_phys));
319 }
320
btif_gattc_close_impl(int client_if,RawAddress address,int conn_id)321 void btif_gattc_close_impl(int client_if, RawAddress address, int conn_id) {
322 // Disconnect established connections
323 if (conn_id != 0)
324 BTA_GATTC_Close(conn_id);
325 else
326 BTA_GATTC_CancelOpen(client_if, address, true);
327
328 // Cancel pending background connections (remove from whitelist)
329 BTA_GATTC_CancelOpen(client_if, address, false);
330 }
331
btif_gattc_close(int client_if,const RawAddress & bd_addr,int conn_id)332 bt_status_t btif_gattc_close(int client_if, const RawAddress& bd_addr,
333 int conn_id) {
334 CHECK_BTGATT_INIT();
335 return do_in_jni_thread(
336 Bind(&btif_gattc_close_impl, client_if, bd_addr, conn_id));
337 }
338
btif_gattc_refresh(int client_if,const RawAddress & bd_addr)339 bt_status_t btif_gattc_refresh(int client_if, const RawAddress& bd_addr) {
340 CHECK_BTGATT_INIT();
341 return do_in_jni_thread(Bind(&BTA_GATTC_Refresh, bd_addr));
342 }
343
btif_gattc_search_service(int conn_id,const Uuid * filter_uuid)344 bt_status_t btif_gattc_search_service(int conn_id, const Uuid* filter_uuid) {
345 CHECK_BTGATT_INIT();
346
347 if (filter_uuid) {
348 Uuid* uuid = new Uuid(*filter_uuid);
349 return do_in_jni_thread(
350 Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, base::Owned(uuid)));
351 } else {
352 return do_in_jni_thread(
353 Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, nullptr));
354 }
355 }
356
btif_gattc_discover_service_by_uuid(int conn_id,const Uuid & uuid)357 void btif_gattc_discover_service_by_uuid(int conn_id, const Uuid& uuid) {
358 do_in_jni_thread(Bind(&BTA_GATTC_DiscoverServiceByUuid, conn_id, uuid));
359 }
360
btif_gattc_get_gatt_db_impl(int conn_id)361 void btif_gattc_get_gatt_db_impl(int conn_id) {
362 btgatt_db_element_t* db = NULL;
363 int count = 0;
364 BTA_GATTC_GetGattDb(conn_id, 0x0000, 0xFFFF, &db, &count);
365
366 HAL_CBACK(bt_gatt_callbacks, client->get_gatt_db_cb, conn_id, db, count);
367 osi_free(db);
368 }
369
btif_gattc_get_gatt_db(int conn_id)370 bt_status_t btif_gattc_get_gatt_db(int conn_id) {
371 CHECK_BTGATT_INIT();
372 return do_in_jni_thread(Bind(&btif_gattc_get_gatt_db_impl, conn_id));
373 }
374
read_char_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)375 void read_char_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
376 uint16_t len, uint8_t* value, void* data) {
377 btgatt_read_params_t* params = new btgatt_read_params_t;
378 params->value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
379 params->status = status;
380 params->handle = handle;
381 params->value.len = len;
382 CHECK(len <= BTGATT_MAX_ATTR_LEN);
383 if (len > 0) memcpy(params->value.value, value, len);
384
385 // clang-tidy analyzer complains about |params| is leaked. It doesn't know
386 // that |param| will be freed by the callback function.
387 CLI_CBACK_IN_JNI(read_characteristic_cb, conn_id, status, /* NOLINT */
388 base::Owned(params));
389 }
390
btif_gattc_read_char(int conn_id,uint16_t handle,int auth_req)391 bt_status_t btif_gattc_read_char(int conn_id, uint16_t handle, int auth_req) {
392 CHECK_BTGATT_INIT();
393 return do_in_jni_thread(Bind(&BTA_GATTC_ReadCharacteristic, conn_id, handle,
394 auth_req, read_char_cb, nullptr));
395 }
396
read_using_char_uuid_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)397 void read_using_char_uuid_cb(uint16_t conn_id, tGATT_STATUS status,
398 uint16_t handle, uint16_t len, uint8_t* value,
399 void* data) {
400 btgatt_read_params_t* params = new btgatt_read_params_t;
401 params->value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
402 params->status = status;
403 params->handle = handle;
404 params->value.len = len;
405 CHECK(len <= BTGATT_MAX_ATTR_LEN);
406 if (len > 0) memcpy(params->value.value, value, len);
407
408 // clang-tidy analyzer complains about |params| is leaked. It doesn't know
409 // that |param| will be freed by the callback function.
410 CLI_CBACK_IN_JNI(read_characteristic_cb, conn_id, status, /* NOLINT */
411 base::Owned(params));
412 }
413
btif_gattc_read_using_char_uuid(int conn_id,const Uuid & uuid,uint16_t s_handle,uint16_t e_handle,int auth_req)414 bt_status_t btif_gattc_read_using_char_uuid(int conn_id, const Uuid& uuid,
415 uint16_t s_handle,
416 uint16_t e_handle, int auth_req) {
417 CHECK_BTGATT_INIT();
418 return do_in_jni_thread(Bind(&BTA_GATTC_ReadUsingCharUuid, conn_id, uuid,
419 s_handle, e_handle, auth_req,
420 read_using_char_uuid_cb, nullptr));
421 }
422
read_desc_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)423 void read_desc_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
424 uint16_t len, uint8_t* value, void* data) {
425 btgatt_read_params_t params;
426 params.value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
427 params.status = status;
428 params.handle = handle;
429 params.value.len = len;
430 CHECK(len <= BTGATT_MAX_ATTR_LEN);
431 if (len > 0) memcpy(params.value.value, value, len);
432
433 CLI_CBACK_IN_JNI(read_descriptor_cb, conn_id, status, params);
434 }
435
btif_gattc_read_char_descr(int conn_id,uint16_t handle,int auth_req)436 bt_status_t btif_gattc_read_char_descr(int conn_id, uint16_t handle,
437 int auth_req) {
438 CHECK_BTGATT_INIT();
439 return do_in_jni_thread(Bind(&BTA_GATTC_ReadCharDescr, conn_id, handle,
440 auth_req, read_desc_cb, nullptr));
441 }
442
write_char_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,void * data)443 void write_char_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
444 void* data) {
445 CLI_CBACK_IN_JNI(write_characteristic_cb, conn_id, status, handle);
446 }
447
btif_gattc_write_char(int conn_id,uint16_t handle,int write_type,int auth_req,vector<uint8_t> value)448 bt_status_t btif_gattc_write_char(int conn_id, uint16_t handle, int write_type,
449 int auth_req, vector<uint8_t> value) {
450 CHECK_BTGATT_INIT();
451
452 if (value.size() > BTGATT_MAX_ATTR_LEN) value.resize(BTGATT_MAX_ATTR_LEN);
453
454 return do_in_jni_thread(Bind(&BTA_GATTC_WriteCharValue, conn_id, handle,
455 write_type, std::move(value), auth_req,
456 write_char_cb, nullptr));
457 }
458
write_descr_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,void * data)459 void write_descr_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
460 void* data) {
461 CLI_CBACK_IN_JNI(write_descriptor_cb, conn_id, status, handle);
462 }
463
btif_gattc_write_char_descr(int conn_id,uint16_t handle,int auth_req,vector<uint8_t> value)464 bt_status_t btif_gattc_write_char_descr(int conn_id, uint16_t handle,
465 int auth_req, vector<uint8_t> value) {
466 CHECK_BTGATT_INIT();
467
468 if (value.size() > BTGATT_MAX_ATTR_LEN) value.resize(BTGATT_MAX_ATTR_LEN);
469
470 return do_in_jni_thread(Bind(&BTA_GATTC_WriteCharDescr, conn_id, handle,
471 std::move(value), auth_req, write_descr_cb,
472 nullptr));
473 }
474
btif_gattc_execute_write(int conn_id,int execute)475 bt_status_t btif_gattc_execute_write(int conn_id, int execute) {
476 CHECK_BTGATT_INIT();
477 return do_in_jni_thread(
478 Bind(&BTA_GATTC_ExecuteWrite, conn_id, (uint8_t)execute));
479 }
480
btif_gattc_reg_for_notification_impl(tGATT_IF client_if,const RawAddress & bda,uint16_t handle)481 void btif_gattc_reg_for_notification_impl(tGATT_IF client_if,
482 const RawAddress& bda,
483 uint16_t handle) {
484 tGATT_STATUS status =
485 BTA_GATTC_RegisterForNotifications(client_if, bda, handle);
486
487 // TODO(jpawlowski): conn_id is currently unused
488 HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
489 /* conn_id */ 0, 1, status, handle);
490 }
491
btif_gattc_reg_for_notification(int client_if,const RawAddress & bd_addr,uint16_t handle)492 bt_status_t btif_gattc_reg_for_notification(int client_if,
493 const RawAddress& bd_addr,
494 uint16_t handle) {
495 CHECK_BTGATT_INIT();
496
497 return do_in_jni_thread(
498 Bind(base::IgnoreResult(&btif_gattc_reg_for_notification_impl), client_if,
499 bd_addr, handle));
500 }
501
btif_gattc_dereg_for_notification_impl(tGATT_IF client_if,const RawAddress & bda,uint16_t handle)502 void btif_gattc_dereg_for_notification_impl(tGATT_IF client_if,
503 const RawAddress& bda,
504 uint16_t handle) {
505 tGATT_STATUS status =
506 BTA_GATTC_DeregisterForNotifications(client_if, bda, handle);
507
508 // TODO(jpawlowski): conn_id is currently unused
509 HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
510 /* conn_id */ 0, 0, status, handle);
511 }
512
btif_gattc_dereg_for_notification(int client_if,const RawAddress & bd_addr,uint16_t handle)513 bt_status_t btif_gattc_dereg_for_notification(int client_if,
514 const RawAddress& bd_addr,
515 uint16_t handle) {
516 CHECK_BTGATT_INIT();
517
518 return do_in_jni_thread(
519 Bind(base::IgnoreResult(&btif_gattc_dereg_for_notification_impl),
520 client_if, bd_addr, handle));
521 }
522
btif_gattc_read_remote_rssi(int client_if,const RawAddress & bd_addr)523 bt_status_t btif_gattc_read_remote_rssi(int client_if,
524 const RawAddress& bd_addr) {
525 CHECK_BTGATT_INIT();
526 rssi_request_client_if = client_if;
527
528 return do_in_jni_thread(
529 Bind(base::IgnoreResult(&BTM_ReadRSSI), bd_addr, btm_read_rssi_cb));
530 }
531
btif_gattc_configure_mtu(int conn_id,int mtu)532 bt_status_t btif_gattc_configure_mtu(int conn_id, int mtu) {
533 CHECK_BTGATT_INIT();
534 return do_in_jni_thread(
535 Bind(base::IgnoreResult(&BTA_GATTC_ConfigureMTU), conn_id, mtu));
536 }
537
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)538 void btif_gattc_conn_parameter_update_impl(RawAddress addr, int min_interval,
539 int max_interval, int latency,
540 int timeout, uint16_t min_ce_len,
541 uint16_t max_ce_len) {
542 if (BTA_DmGetConnectionState(addr))
543 BTA_DmBleUpdateConnectionParams(addr, min_interval, max_interval, latency,
544 timeout, min_ce_len, max_ce_len);
545 else
546 BTA_DmSetBlePrefConnParams(addr, min_interval, max_interval, latency,
547 timeout);
548 }
549
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)550 bt_status_t btif_gattc_conn_parameter_update(const RawAddress& bd_addr,
551 int min_interval, int max_interval,
552 int latency, int timeout,
553 uint16_t min_ce_len,
554 uint16_t max_ce_len) {
555 CHECK_BTGATT_INIT();
556 return do_in_jni_thread(Bind(
557 base::IgnoreResult(&btif_gattc_conn_parameter_update_impl), bd_addr,
558 min_interval, max_interval, latency, timeout, min_ce_len, max_ce_len));
559 }
560
btif_gattc_set_preferred_phy(const RawAddress & bd_addr,uint8_t tx_phy,uint8_t rx_phy,uint16_t phy_options)561 bt_status_t btif_gattc_set_preferred_phy(const RawAddress& bd_addr,
562 uint8_t tx_phy, uint8_t rx_phy,
563 uint16_t phy_options) {
564 CHECK_BTGATT_INIT();
565 do_in_bta_thread(FROM_HERE,
566 Bind(&BTM_BleSetPhy, bd_addr, tx_phy, rx_phy, phy_options));
567 return BT_STATUS_SUCCESS;
568 }
569
btif_gattc_read_phy(const RawAddress & bd_addr,base::Callback<void (uint8_t tx_phy,uint8_t rx_phy,uint8_t status)> cb)570 bt_status_t btif_gattc_read_phy(
571 const RawAddress& bd_addr,
572 base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb) {
573 CHECK_BTGATT_INIT();
574 do_in_bta_thread(FROM_HERE, Bind(&BTM_BleReadPhy, bd_addr,
575 jni_thread_wrapper(FROM_HERE, cb)));
576 return BT_STATUS_SUCCESS;
577 }
578
btif_gattc_get_device_type(const RawAddress & bd_addr)579 int btif_gattc_get_device_type(const RawAddress& bd_addr) {
580 int device_type = 0;
581
582 if (btif_config_get_int(bd_addr.ToString().c_str(), "DevType", &device_type))
583 return device_type;
584 return 0;
585 }
586
btif_gattc_test_command(int command,const btgatt_test_params_t & params)587 bt_status_t btif_gattc_test_command(int command,
588 const btgatt_test_params_t& params) {
589 return btif_gattc_test_command_impl(command, ¶ms);
590 }
591
592 } // namespace
593
594 const btgatt_client_interface_t btgattClientInterface = {
595 btif_gattc_register_app,
596 btif_gattc_unregister_app,
597 btif_gattc_open,
598 btif_gattc_close,
599 btif_gattc_refresh,
600 btif_gattc_search_service,
601 btif_gattc_discover_service_by_uuid,
602 btif_gattc_read_char,
603 btif_gattc_read_using_char_uuid,
604 btif_gattc_write_char,
605 btif_gattc_read_char_descr,
606 btif_gattc_write_char_descr,
607 btif_gattc_execute_write,
608 btif_gattc_reg_for_notification,
609 btif_gattc_dereg_for_notification,
610 btif_gattc_read_remote_rssi,
611 btif_gattc_get_device_type,
612 btif_gattc_configure_mtu,
613 btif_gattc_conn_parameter_update,
614 btif_gattc_set_preferred_phy,
615 btif_gattc_read_phy,
616 btif_gattc_test_command,
617 btif_gattc_get_gatt_db};
618