• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &params);
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