OSDN Git Service

Merge "packet: Add Packet classes and tests" am: a275910a49
[android-x86/system-bt.git] / stack / gatt / gatt_api.cc
1 /******************************************************************************
2  *
3  *  Copyright 1999-2012 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  *  this file contains GATT interface functions
22  *
23  ******************************************************************************/
24 #include "bt_target.h"
25
26 #include <base/strings/string_number_conversions.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include "bt_common.h"
30 #include "btm_int.h"
31 #include "device/include/controller.h"
32 #include "gatt_api.h"
33 #include "gatt_int.h"
34 #include "l2c_api.h"
35 #include "stack/gatt/connection_manager.h"
36
37 using bluetooth::Uuid;
38
39 extern bool BTM_BackgroundConnectAddressKnown(const RawAddress& address);
40 /**
41  * Add an service handle range to the list in decending order of the start
42  * handle. Return reference to the newly added element.
43  **/
44 tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) {
45   auto lst_ptr = gatt_cb.hdl_list_info;
46   auto it = lst_ptr->begin();
47   for (; it != lst_ptr->end(); it++) {
48     if (s_handle > it->asgn_range.s_handle) break;
49   }
50
51   auto rit = lst_ptr->emplace(it);
52   return *rit;
53 }
54
55 /*****************************************************************************
56  *
57  *                  GATT SERVER API
58  *
59  *****************************************************************************/
60 /*******************************************************************************
61  *
62  * Function         GATTS_AddHandleRange
63  *
64  * Description      This function add the allocated handles range for the
65  *                  specified application UUID, service UUID and service
66  *                  instance
67  *
68  * Parameter        p_hndl_range:   pointer to allocated handles information
69  *
70  **/
71
72 void GATTS_AddHandleRange(tGATTS_HNDL_RANGE* p_hndl_range) {
73   gatt_add_an_item_to_list(p_hndl_range->s_handle);
74 }
75
76 /*******************************************************************************
77  *
78  * Function         GATTS_NVRegister
79  *
80  * Description      Application manager calls this function to register for
81  *                  NV save callback function.  There can be one and only one
82  *                  NV save callback function.
83  *
84  * Parameter        p_cb_info : callback informaiton
85  *
86  * Returns          true if registered OK, else false
87  *
88  ******************************************************************************/
89 bool GATTS_NVRegister(tGATT_APPL_INFO* p_cb_info) {
90   bool status = false;
91   if (p_cb_info) {
92     gatt_cb.cb_info = *p_cb_info;
93     status = true;
94     gatt_init_srv_chg();
95   }
96
97   return status;
98 }
99
100 static uint16_t compute_service_size(btgatt_db_element_t* service, int count) {
101   int db_size = 0;
102   btgatt_db_element_t* el = service;
103
104   for (int i = 0; i < count; i++, el++)
105     if (el->type == BTGATT_DB_PRIMARY_SERVICE ||
106         el->type == BTGATT_DB_SECONDARY_SERVICE ||
107         el->type == BTGATT_DB_DESCRIPTOR ||
108         el->type == BTGATT_DB_INCLUDED_SERVICE)
109       db_size += 1;
110     else if (el->type == BTGATT_DB_CHARACTERISTIC)
111       db_size += 2;
112     else
113       LOG(ERROR) << __func__ << ": Unknown element type: " << el->type;
114
115   return db_size;
116 }
117
118 static bool is_gatt_attr_type(const Uuid& uuid) {
119   if (uuid == Uuid::From16Bit(GATT_UUID_PRI_SERVICE) ||
120       uuid == Uuid::From16Bit(GATT_UUID_SEC_SERVICE) ||
121       uuid == Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE) ||
122       uuid == Uuid::From16Bit(GATT_UUID_CHAR_DECLARE)) {
123     return true;
124   }
125   return false;
126 }
127
128 /** Update the the last service info for the service list info */
129 static void gatt_update_last_srv_info() {
130   gatt_cb.last_service_handle = 0;
131
132   for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info) {
133     gatt_cb.last_service_handle = el.s_hdl;
134   }
135 }
136
137 /*******************************************************************************
138  *
139  * Function         GATTS_AddService
140  *
141  * Description      This function is called to add GATT service.
142  *
143  * Parameter        gatt_if : application if
144  *                  service : pseudo-representation of service and it's content
145  *                  count   : size of service
146  *
147  * Returns          on success GATT_SERVICE_STARTED is returned, and
148  *                  attribute_handle field inside service elements are filled.
149  *                  on error error status is returned.
150  *
151  ******************************************************************************/
152 uint16_t GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t* service,
153                           int count) {
154   uint16_t s_hdl = 0;
155   bool save_hdl = false;
156   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
157
158   bool is_pri = (service->type == BTGATT_DB_PRIMARY_SERVICE) ? true : false;
159   Uuid svc_uuid = service->uuid;
160
161   LOG(INFO) << __func__;
162
163   if (!p_reg) {
164     LOG(ERROR) << "Inavlid gatt_if=" << +gatt_if;
165     return GATT_INTERNAL_ERROR;
166   }
167
168   uint16_t num_handles = compute_service_size(service, count);
169
170   if (svc_uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) {
171     s_hdl = gatt_cb.hdl_cfg.gatt_start_hdl;
172   } else if (svc_uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
173     s_hdl = gatt_cb.hdl_cfg.gap_start_hdl;
174   } else {
175     if (!gatt_cb.hdl_list_info->empty()) {
176       s_hdl = gatt_cb.hdl_list_info->front().asgn_range.e_handle + 1;
177     }
178
179     if (s_hdl < gatt_cb.hdl_cfg.app_start_hdl)
180       s_hdl = gatt_cb.hdl_cfg.app_start_hdl;
181
182     save_hdl = true;
183   }
184
185   /* check for space */
186   if (num_handles > (0xFFFF - s_hdl + 1)) {
187     LOG(ERROR) << __func__ << ": no handles, s_hdl=" << +s_hdl
188                << " needed=" << num_handles;
189     return GATT_INTERNAL_ERROR;
190   }
191
192   tGATT_HDL_LIST_ELEM& list = gatt_add_an_item_to_list(s_hdl);
193   list.asgn_range.app_uuid128 = p_reg->app_uuid128;
194   list.asgn_range.svc_uuid = svc_uuid;
195   list.asgn_range.s_handle = s_hdl;
196   list.asgn_range.e_handle = s_hdl + num_handles - 1;
197   list.asgn_range.is_primary = is_pri;
198
199   if (save_hdl) {
200     if (gatt_cb.cb_info.p_nv_save_callback)
201       (*gatt_cb.cb_info.p_nv_save_callback)(true, &list.asgn_range);
202   }
203
204   gatts_init_service_db(list.svc_db, svc_uuid, is_pri, s_hdl, num_handles);
205
206   VLOG(1) << __func__ << ": handles needed=" << num_handles
207           << ", s_hdl=" << loghex(list.asgn_range.s_handle)
208           << ", e_hdl=" << loghex(list.asgn_range.e_handle)
209           << ", uuid=" << list.asgn_range.svc_uuid
210           << ", is_primary=" << +list.asgn_range.is_primary;
211
212   service->attribute_handle = s_hdl;
213
214   btgatt_db_element_t* el = service + 1;
215   for (int i = 0; i < count - 1; i++, el++) {
216     const Uuid& uuid = el->uuid;
217
218     if (el->type == BTGATT_DB_CHARACTERISTIC) {
219       /* data validity checking */
220       if (((el->properties & GATT_CHAR_PROP_BIT_AUTH) &&
221            !(el->permissions & GATT_WRITE_SIGNED_PERM)) ||
222           ((el->permissions & GATT_WRITE_SIGNED_PERM) &&
223            !(el->properties & GATT_CHAR_PROP_BIT_AUTH))) {
224         VLOG(1) << "Invalid configuration property=" << loghex(el->properties)
225                 << ", perm=" << loghex(el->permissions);
226         return GATT_INTERNAL_ERROR;
227       }
228
229       if (is_gatt_attr_type(uuid)) {
230         LOG(ERROR) << __func__
231                    << ": attept to add characteristic with UUID equal to GATT "
232                       "Attribute Type "
233                    << uuid;
234         return GATT_INTERNAL_ERROR;
235       }
236
237       el->attribute_handle = gatts_add_characteristic(
238           list.svc_db, el->permissions, el->properties, uuid);
239     } else if (el->type == BTGATT_DB_DESCRIPTOR) {
240       if (is_gatt_attr_type(uuid)) {
241         LOG(ERROR) << __func__
242                    << ": attept to add descriptor with UUID equal to GATT "
243                       "Attribute Type "
244                    << uuid;
245         return GATT_INTERNAL_ERROR;
246       }
247
248       el->attribute_handle =
249           gatts_add_char_descr(list.svc_db, el->permissions, uuid);
250     } else if (el->type == BTGATT_DB_INCLUDED_SERVICE) {
251       tGATT_HDL_LIST_ELEM* p_incl_decl;
252       p_incl_decl = gatt_find_hdl_buffer_by_handle(el->attribute_handle);
253       if (p_incl_decl == nullptr) {
254         VLOG(1) << "Included Service not created";
255         return GATT_INTERNAL_ERROR;
256       }
257
258       el->attribute_handle = gatts_add_included_service(
259           list.svc_db, p_incl_decl->asgn_range.s_handle,
260           p_incl_decl->asgn_range.e_handle, p_incl_decl->asgn_range.svc_uuid);
261     }
262   }
263
264   LOG(INFO) << __func__ << ": service parsed correctly, now starting";
265
266   /*this is a new application service start */
267
268   // find a place for this service in the list
269   auto lst_ptr = gatt_cb.srv_list_info;
270   auto it = lst_ptr->begin();
271   for (; it != lst_ptr->end(); it++) {
272     if (list.asgn_range.s_handle < it->s_hdl) break;
273   }
274   auto rit = lst_ptr->emplace(it);
275
276   tGATT_SRV_LIST_ELEM& elem = *rit;
277   elem.gatt_if = gatt_if;
278   elem.s_hdl = list.asgn_range.s_handle;
279   elem.e_hdl = list.asgn_range.e_handle;
280   elem.p_db = &list.svc_db;
281   elem.is_primary = list.asgn_range.is_primary;
282
283   elem.app_uuid = list.asgn_range.app_uuid128;
284   elem.type = list.asgn_range.is_primary ? GATT_UUID_PRI_SERVICE
285                                          : GATT_UUID_SEC_SERVICE;
286
287   if (elem.type == GATT_UUID_PRI_SERVICE) {
288     Uuid* p_uuid = gatts_get_service_uuid(elem.p_db);
289     elem.sdp_handle = gatt_add_sdp_record(*p_uuid, elem.s_hdl, elem.e_hdl);
290   } else {
291     elem.sdp_handle = 0;
292   }
293
294   gatt_update_last_srv_info();
295
296   VLOG(1) << __func__ << ": allocated el s_hdl=" << loghex(elem.s_hdl)
297           << ", e_hdl=" << loghex(elem.e_hdl) << ", type=" << loghex(elem.type)
298           << ", sdp_hdl=" << loghex(elem.sdp_handle);
299
300   gatt_proc_srv_chg();
301
302   return GATT_SERVICE_STARTED;
303 }
304
305 bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid,
306                        uint16_t start_handle) {
307   for (auto& info : *gatt_cb.srv_list_info) {
308     Uuid* p_this_uuid = gatts_get_service_uuid(info.p_db);
309
310     if (p_this_uuid && app_uuid128 == info.app_uuid &&
311         *p_svc_uuid == *p_this_uuid && (start_handle == info.s_hdl)) {
312       LOG(ERROR) << "Active Service Found: " << *p_svc_uuid;
313       return true;
314     }
315   }
316   return false;
317 }
318
319 /*******************************************************************************
320  *
321  * Function         GATTS_DeleteService
322  *
323  * Description      This function is called to delete a service.
324  *
325  * Parameter        gatt_if       : application interface
326  *                  p_svc_uuid    : service UUID
327  *                  start_handle  : start handle of the service
328  *
329  * Returns          true if the operation succeeded, false if the handle block
330  *                  was not found.
331  *
332  ******************************************************************************/
333 bool GATTS_DeleteService(tGATT_IF gatt_if, Uuid* p_svc_uuid,
334                          uint16_t svc_inst) {
335   VLOG(1) << __func__;
336
337   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
338   if (p_reg == NULL) {
339     LOG(ERROR) << "Applicaiton not foud";
340     return false;
341   }
342
343   auto it =
344       gatt_find_hdl_buffer_by_app_id(p_reg->app_uuid128, p_svc_uuid, svc_inst);
345   if (it == gatt_cb.hdl_list_info->end()) {
346     LOG(ERROR) << "No Service found";
347     return false;
348   }
349
350   gatt_proc_srv_chg();
351
352   if (is_active_service(p_reg->app_uuid128, p_svc_uuid, svc_inst)) {
353     GATTS_StopService(it->asgn_range.s_handle);
354   }
355
356   VLOG(1) << "released handles s_hdl=" << loghex(it->asgn_range.s_handle)
357           << ", e_hdl=" << loghex(it->asgn_range.e_handle);
358
359   if ((it->asgn_range.s_handle >= gatt_cb.hdl_cfg.app_start_hdl) &&
360       gatt_cb.cb_info.p_nv_save_callback)
361     (*gatt_cb.cb_info.p_nv_save_callback)(false, &it->asgn_range);
362
363   gatt_cb.hdl_list_info->erase(it);
364   return true;
365 }
366
367 /*******************************************************************************
368  *
369  * Function         GATTS_StopService
370  *
371  * Description      This function is called to stop a service
372  *
373  * Parameter         service_handle : this is the start handle of a service
374  *
375  * Returns          None.
376  *
377  ******************************************************************************/
378 void GATTS_StopService(uint16_t service_handle) {
379   LOG(INFO) << __func__ << ": " << loghex(service_handle);
380
381   auto it = gatt_sr_find_i_rcb_by_handle(service_handle);
382   if (it == gatt_cb.srv_list_info->end()) {
383     LOG(ERROR) << __func__ << ": service_handle=" << loghex(service_handle)
384                << " is not in use";
385   }
386
387   if (it->sdp_handle) {
388     SDP_DeleteRecord(it->sdp_handle);
389   }
390
391   gatt_cb.srv_list_info->erase(it);
392   gatt_update_last_srv_info();
393 }
394 /*******************************************************************************
395  *
396  * Function         GATTs_HandleValueIndication
397  *
398  * Description      This function sends a handle value indication to a client.
399  *
400  * Parameter        conn_id: connection identifier.
401  *                  attr_handle: Attribute handle of this handle value
402  *                               indication.
403  *                  val_len: Length of the indicated attribute value.
404  *                  p_val: Pointer to the indicated attribute value data.
405  *
406  * Returns          GATT_SUCCESS if sucessfully sent or queued; otherwise error
407  *                  code.
408  *
409  ******************************************************************************/
410 tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle,
411                                          uint16_t val_len, uint8_t* p_val) {
412   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
413   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
414   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
415   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
416
417   VLOG(1) << __func__;
418   if ((p_reg == NULL) || (p_tcb == NULL)) {
419     LOG(ERROR) << __func__ << ": Unknown  conn_id=" << loghex(conn_id);
420     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
421   }
422
423   if (!GATT_HANDLE_IS_VALID(attr_handle)) return GATT_ILLEGAL_PARAMETER;
424
425   tGATT_VALUE indication;
426   indication.conn_id = conn_id;
427   indication.handle = attr_handle;
428   indication.len = val_len;
429   memcpy(indication.value, p_val, val_len);
430   indication.auth_req = GATT_AUTH_REQ_NONE;
431
432   if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
433     VLOG(1) << "Add a pending indication";
434     gatt_add_pending_ind(p_tcb, &indication);
435     return GATT_SUCCESS;
436   }
437
438   tGATT_SR_MSG gatt_sr_msg;
439   gatt_sr_msg.attr_value = indication;
440   BT_HDR* p_msg =
441       attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_IND, &gatt_sr_msg);
442   if (!p_msg) return GATT_NO_RESOURCES;
443
444   tGATT_STATUS cmd_status = attp_send_sr_msg(*p_tcb, p_msg);
445   if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED) {
446     p_tcb->indicate_handle = indication.handle;
447     gatt_start_conf_timer(p_tcb);
448   }
449   return cmd_status;
450 }
451
452 /*******************************************************************************
453  *
454  * Function         GATTS_HandleValueNotification
455  *
456  * Description      This function sends a handle value notification to a client.
457  *
458  * Parameter        conn_id: connection identifier.
459  *                  attr_handle: Attribute handle of this handle value
460  *                               indication.
461  *                  val_len: Length of the indicated attribute value.
462  *                  p_val: Pointer to the indicated attribute value data.
463  *
464  * Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
465  *
466  ******************************************************************************/
467 tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id,
468                                            uint16_t attr_handle,
469                                            uint16_t val_len, uint8_t* p_val) {
470   tGATT_VALUE notif;
471   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
472   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
473   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
474   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
475
476   VLOG(1) << __func__;
477
478   if ((p_reg == NULL) || (p_tcb == NULL)) {
479     LOG(ERROR) << __func__ << "Unknown  conn_id: " << conn_id;
480     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
481   }
482
483   if (!GATT_HANDLE_IS_VALID(attr_handle)) {
484     return GATT_ILLEGAL_PARAMETER;
485   }
486
487   notif.handle = attr_handle;
488   notif.len = val_len;
489   memcpy(notif.value, p_val, val_len);
490   notif.auth_req = GATT_AUTH_REQ_NONE;
491
492   tGATT_STATUS cmd_sent;
493   tGATT_SR_MSG gatt_sr_msg;
494   gatt_sr_msg.attr_value = notif;
495   BT_HDR* p_buf =
496       attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_NOTIF, &gatt_sr_msg);
497   if (p_buf != NULL) {
498     cmd_sent = attp_send_sr_msg(*p_tcb, p_buf);
499   } else
500     cmd_sent = GATT_NO_RESOURCES;
501   return cmd_sent;
502 }
503
504 /*******************************************************************************
505  *
506  * Function         GATTS_SendRsp
507  *
508  * Description      This function sends the server response to client.
509  *
510  * Parameter        conn_id: connection identifier.
511  *                  trans_id: transaction id
512  *                  status: response status
513  *                  p_msg: pointer to message parameters structure.
514  *
515  * Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
516  *
517  ******************************************************************************/
518 tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id,
519                            tGATT_STATUS status, tGATTS_RSP* p_msg) {
520   tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER;
521   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
522   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
523   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
524   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
525
526   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
527           << ", trans_id=" << loghex(trans_id) << ", status=" << loghex(status);
528
529   if ((p_reg == NULL) || (p_tcb == NULL)) {
530     LOG(ERROR) << "Unknown  conn_id=" << loghex(conn_id);
531     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
532   }
533
534   if (p_tcb->sr_cmd.trans_id != trans_id) {
535     LOG(ERROR) << "conn_id=" << loghex(conn_id)
536                << " waiting for op_code=" << loghex(p_tcb->sr_cmd.op_code);
537     return (GATT_WRONG_STATE);
538   }
539   /* Process App response */
540   cmd_sent = gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id,
541                                      p_tcb->sr_cmd.op_code, status, p_msg);
542
543   return cmd_sent;
544 }
545
546 /******************************************************************************/
547 /* GATT Profile Srvr Functions */
548 /******************************************************************************/
549
550 /******************************************************************************/
551 /*                                                                            */
552 /*                  GATT CLIENT APIs                                          */
553 /*                                                                            */
554 /******************************************************************************/
555
556 /*******************************************************************************
557  *
558  * Function         GATTC_ConfigureMTU
559  *
560  * Description      This function is called to configure the ATT MTU size.
561  *
562  * Parameters       conn_id: connection identifier.
563  *                  mtu    - attribute MTU size..
564  *
565  * Returns          GATT_SUCCESS if command started successfully.
566  *
567  ******************************************************************************/
568 tGATT_STATUS GATTC_ConfigureMTU(uint16_t conn_id, uint16_t mtu) {
569   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
570   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
571   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
572   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
573
574   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id) << ", mtu=" << +mtu;
575
576   if ((p_tcb == NULL) || (p_reg == NULL) || (mtu < GATT_DEF_BLE_MTU_SIZE) ||
577       (mtu > GATT_MAX_MTU_SIZE)) {
578     return GATT_ILLEGAL_PARAMETER;
579   }
580
581   /* Validate that the link is BLE, not BR/EDR */
582   if (p_tcb->transport != BT_TRANSPORT_LE) {
583     return GATT_ERROR;
584   }
585
586   if (gatt_is_clcb_allocated(conn_id)) {
587     LOG(ERROR) << "GATT_BUSY conn_id = " << +conn_id;
588     return GATT_BUSY;
589   }
590
591   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
592   if (!p_clcb) return GATT_NO_RESOURCES;
593
594   p_clcb->p_tcb->payload_size = mtu;
595   p_clcb->operation = GATTC_OPTYPE_CONFIG;
596   tGATT_CL_MSG gatt_cl_msg;
597   gatt_cl_msg.mtu = mtu;
598   return attp_send_cl_msg(*p_clcb->p_tcb, p_clcb, GATT_REQ_MTU, &gatt_cl_msg);
599 }
600
601 /*******************************************************************************
602  *
603  * Function         GATTC_Discover
604  *
605  * Description      This function is called to do a discovery procedure on ATT
606  *                  server.
607  *
608  * Parameters       conn_id: connection identifier.
609  *                  disc_type:discovery type.
610  *                  start_handle and end_handle: range of handles for discovery
611  *                  uuid: uuid to discovery. set to Uuid::kEmpty for requests
612  *                        that don't need it
613  *
614  * Returns          GATT_SUCCESS if command received/sent successfully.
615  *
616  ******************************************************************************/
617 tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
618                             uint16_t start_handle, uint16_t end_handle,
619                             const Uuid& uuid) {
620   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
621   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
622   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
623   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
624
625   if ((p_tcb == NULL) || (p_reg == NULL) || (disc_type >= GATT_DISC_MAX)) {
626     LOG(ERROR) << __func__ << " Illegal param: disc_type=" << +disc_type
627                << " conn_id=" << loghex(conn_id);
628     return GATT_ILLEGAL_PARAMETER;
629   }
630
631   LOG(INFO) << __func__ << " conn_id=" << loghex(conn_id)
632             << ", disc_type=" << +disc_type
633             << ", s_handle=" << loghex(start_handle)
634             << ", e_handle=" << loghex(end_handle);
635
636   if (!GATT_HANDLE_IS_VALID(start_handle) ||
637       !GATT_HANDLE_IS_VALID(end_handle) ||
638       /* search by type does not have a valid UUID param */
639       (disc_type == GATT_DISC_SRVC_BY_UUID && uuid.IsEmpty())) {
640     return GATT_ILLEGAL_PARAMETER;
641   }
642
643   if (gatt_is_clcb_allocated(conn_id)) {
644     LOG(ERROR) << __func__ << "GATT_BUSY conn_id = " << +conn_id;
645     return GATT_BUSY;
646   }
647
648   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
649   if (!p_clcb) return GATT_NO_RESOURCES;
650
651   p_clcb->operation = GATTC_OPTYPE_DISCOVERY;
652   p_clcb->op_subtype = disc_type;
653   p_clcb->s_handle = start_handle;
654   p_clcb->e_handle = end_handle;
655   p_clcb->uuid = uuid;
656
657   gatt_act_discovery(p_clcb);
658   return GATT_SUCCESS;
659 }
660
661 tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
662                             uint16_t start_handle, uint16_t end_handle) {
663   return GATTC_Discover(conn_id, disc_type, start_handle, end_handle,
664                         Uuid::kEmpty);
665 }
666
667 /*******************************************************************************
668  *
669  * Function         GATTC_Read
670  *
671  * Description      This function is called to read the value of an attribute
672  *                  from the server.
673  *
674  * Parameters       conn_id: connection identifier.
675  *                  type    - attribute read type.
676  *                  p_read  - read operation parameters.
677  *
678  * Returns          GATT_SUCCESS if command started successfully.
679  *
680  ******************************************************************************/
681 tGATT_STATUS GATTC_Read(uint16_t conn_id, tGATT_READ_TYPE type,
682                         tGATT_READ_PARAM* p_read) {
683   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
684   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
685   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
686   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
687
688   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
689           << ", type=" << loghex(type);
690
691   if ((p_tcb == NULL) || (p_reg == NULL) || (p_read == NULL) ||
692       ((type >= GATT_READ_MAX) || (type == 0))) {
693     LOG(ERROR) << ": illegal param: conn_id=" << loghex(conn_id)
694                << "type=" << loghex(type);
695     return GATT_ILLEGAL_PARAMETER;
696   }
697
698   if (gatt_is_clcb_allocated(conn_id)) {
699     LOG(ERROR) << "GATT_BUSY conn_id=" << loghex(conn_id);
700     return GATT_BUSY;
701   }
702
703   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
704   if (!p_clcb) return GATT_NO_RESOURCES;
705
706   p_clcb->operation = GATTC_OPTYPE_READ;
707   p_clcb->op_subtype = type;
708   p_clcb->auth_req = p_read->by_handle.auth_req;
709   p_clcb->counter = 0;
710
711   switch (type) {
712     case GATT_READ_BY_TYPE:
713     case GATT_READ_CHAR_VALUE:
714       p_clcb->s_handle = p_read->service.s_handle;
715       p_clcb->e_handle = p_read->service.e_handle;
716       p_clcb->uuid = p_read->service.uuid;
717       break;
718     case GATT_READ_MULTIPLE: {
719       p_clcb->s_handle = 0;
720       /* copy multiple handles in CB */
721       tGATT_READ_MULTI* p_read_multi =
722           (tGATT_READ_MULTI*)osi_malloc(sizeof(tGATT_READ_MULTI));
723       p_clcb->p_attr_buf = (uint8_t*)p_read_multi;
724       memcpy(p_read_multi, &p_read->read_multiple, sizeof(tGATT_READ_MULTI));
725       break;
726     }
727     case GATT_READ_BY_HANDLE:
728     case GATT_READ_PARTIAL:
729       p_clcb->uuid = Uuid::kEmpty;
730       p_clcb->s_handle = p_read->by_handle.handle;
731
732       if (type == GATT_READ_PARTIAL) {
733         p_clcb->counter = p_read->partial.offset;
734       }
735
736       break;
737     default:
738       break;
739   }
740
741   /* start security check */
742   if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
743   return GATT_SUCCESS;
744 }
745
746 /*******************************************************************************
747  *
748  * Function         GATTC_Write
749  *
750  * Description      This function is called to write the value of an attribute
751  *                  to the server.
752  *
753  * Parameters       conn_id: connection identifier.
754  *                  type    - attribute write type.
755  *                  p_write  - write operation parameters.
756  *
757  * Returns          GATT_SUCCESS if command started successfully.
758  *
759  ******************************************************************************/
760 tGATT_STATUS GATTC_Write(uint16_t conn_id, tGATT_WRITE_TYPE type,
761                          tGATT_VALUE* p_write) {
762   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
763   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
764   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
765   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
766
767   if ((p_tcb == NULL) || (p_reg == NULL) || (p_write == NULL) ||
768       ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) &&
769        (type != GATT_WRITE_NO_RSP))) {
770     LOG(ERROR) << __func__ << " Illegal param: conn_id=" << loghex(conn_id)
771                << ", type=" << loghex(type);
772     return GATT_ILLEGAL_PARAMETER;
773   }
774
775   if (gatt_is_clcb_allocated(conn_id)) {
776     LOG(ERROR) << "GATT_BUSY conn_id=" << loghex(conn_id);
777     return GATT_BUSY;
778   }
779
780   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
781   if (!p_clcb) return GATT_NO_RESOURCES;
782
783   p_clcb->operation = GATTC_OPTYPE_WRITE;
784   p_clcb->op_subtype = type;
785   p_clcb->auth_req = p_write->auth_req;
786
787   p_clcb->p_attr_buf = (uint8_t*)osi_malloc(sizeof(tGATT_VALUE));
788   memcpy(p_clcb->p_attr_buf, (void*)p_write, sizeof(tGATT_VALUE));
789
790   tGATT_VALUE* p = (tGATT_VALUE*)p_clcb->p_attr_buf;
791   if (type == GATT_WRITE_PREPARE) {
792     p_clcb->start_offset = p_write->offset;
793     p->offset = 0;
794   }
795
796   if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
797   return GATT_SUCCESS;
798 }
799
800 /*******************************************************************************
801  *
802  * Function         GATTC_ExecuteWrite
803  *
804  * Description      This function is called to send an Execute write request to
805  *                  the server.
806  *
807  * Parameters       conn_id: connection identifier.
808  *                  is_execute - to execute or cancel the prepared write
809  *                               request(s)
810  *
811  * Returns          GATT_SUCCESS if command started successfully.
812  *
813  ******************************************************************************/
814 tGATT_STATUS GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute) {
815   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
816   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
817   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
818   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
819
820   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
821           << ", is_execute=" << +is_execute;
822
823   if ((p_tcb == NULL) || (p_reg == NULL)) {
824     LOG(ERROR) << " Illegal param: conn_id=" << loghex(conn_id);
825     return GATT_ILLEGAL_PARAMETER;
826   }
827
828   if (gatt_is_clcb_allocated(conn_id)) {
829     LOG(ERROR) << " GATT_BUSY conn_id=" << loghex(conn_id);
830     return GATT_BUSY;
831   }
832
833   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
834   if (!p_clcb) return GATT_NO_RESOURCES;
835
836   p_clcb->operation = GATTC_OPTYPE_EXE_WRITE;
837   tGATT_EXEC_FLAG flag =
838       is_execute ? GATT_PREP_WRITE_EXEC : GATT_PREP_WRITE_CANCEL;
839   gatt_send_queue_write_cancel(*p_clcb->p_tcb, p_clcb, flag);
840   return GATT_SUCCESS;
841 }
842
843 /*******************************************************************************
844  *
845  * Function         GATTC_SendHandleValueConfirm
846  *
847  * Description      This function is called to send a handle value confirmation
848  *                  as response to a handle value notification from server.
849  *
850  * Parameters       conn_id: connection identifier.
851  *                  handle: the handle of the attribute confirmation.
852  *
853  * Returns          GATT_SUCCESS if command started successfully.
854  *
855  ******************************************************************************/
856 tGATT_STATUS GATTC_SendHandleValueConfirm(uint16_t conn_id, uint16_t handle) {
857   VLOG(1) << __func__ << " conn_id=" << loghex(conn_id)
858           << ", handle=" << loghex(handle);
859
860   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id));
861   if (!p_tcb) {
862     LOG(ERROR) << "Unknown conn_id=" << loghex(conn_id);
863     return GATT_ILLEGAL_PARAMETER;
864   }
865
866   if (p_tcb->ind_count == 0) {
867     VLOG(1) << " conn_id: " << loghex(conn_id)
868             << " ignored not waiting for indicaiton ack";
869     return GATT_SUCCESS;
870   }
871
872   alarm_cancel(p_tcb->ind_ack_timer);
873
874   VLOG(1) << "notif_count= " << p_tcb->ind_count;
875   /* send confirmation now */
876   tGATT_CL_MSG gatt_cl_msg;
877   gatt_cl_msg.handle = handle;
878   tGATT_STATUS ret =
879       attp_send_cl_msg(*p_tcb, nullptr, GATT_HANDLE_VALUE_CONF, &gatt_cl_msg);
880
881   p_tcb->ind_count = 0;
882
883   return ret;
884 }
885
886 /******************************************************************************/
887 /*                                                                            */
888 /*                  GATT  APIs                                                */
889 /*                                                                            */
890 /******************************************************************************/
891 /*******************************************************************************
892  *
893  * Function         GATT_SetIdleTimeout
894  *
895  * Description      This function (common to both client and server) sets the
896  *                  idle timeout for a tansport connection
897  *
898  * Parameter        bd_addr:   target device bd address.
899  *                  idle_tout: timeout value in seconds.
900  *
901  * Returns          void
902  *
903  ******************************************************************************/
904 void GATT_SetIdleTimeout(const RawAddress& bd_addr, uint16_t idle_tout,
905                          tBT_TRANSPORT transport) {
906   bool status = false;
907
908   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
909   if (p_tcb != NULL) {
910     if (p_tcb->att_lcid == L2CAP_ATT_CID) {
911       status = L2CA_SetFixedChannelTout(bd_addr, L2CAP_ATT_CID, idle_tout);
912
913       if (idle_tout == GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP)
914         L2CA_SetIdleTimeoutByBdAddr(p_tcb->peer_bda,
915                                     GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP,
916                                     BT_TRANSPORT_LE);
917     } else {
918       status = L2CA_SetIdleTimeout(p_tcb->att_lcid, idle_tout, false);
919     }
920   }
921
922   VLOG(1) << __func__ << " idle_tout=" << idle_tout << ", status=" << +status
923           << " (1-OK 0-not performed)";
924 }
925
926 /*******************************************************************************
927  *
928  * Function         GATT_Register
929  *
930  * Description      This function is called to register an  application
931  *                  with GATT
932  *
933  * Parameter        p_app_uuid128: Application UUID
934  *                  p_cb_info: callback functions.
935  *
936  * Returns          0 for error, otherwise the index of the client registered
937  *                  with GATT
938  *
939  ******************************************************************************/
940 tGATT_IF GATT_Register(const Uuid& app_uuid128, tGATT_CBACK* p_cb_info) {
941   tGATT_REG* p_reg;
942   uint8_t i_gatt_if = 0;
943   tGATT_IF gatt_if = 0;
944
945   LOG(INFO) << __func__ << " " << app_uuid128;
946
947   for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
948        i_gatt_if++, p_reg++) {
949     if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
950       LOG(ERROR) << "application already registered.";
951       return 0;
952     }
953   }
954
955   for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
956        i_gatt_if++, p_reg++) {
957     if (!p_reg->in_use) {
958       memset(p_reg, 0, sizeof(tGATT_REG));
959       i_gatt_if++; /* one based number */
960       p_reg->app_uuid128 = app_uuid128;
961       gatt_if = p_reg->gatt_if = (tGATT_IF)i_gatt_if;
962       p_reg->app_cb = *p_cb_info;
963       p_reg->in_use = true;
964
965       LOG(INFO) << "allocated gatt_if=" << +gatt_if;
966       return gatt_if;
967     }
968   }
969
970   LOG(ERROR) << "can't Register GATT client, MAX client reached: "
971              << GATT_MAX_APPS;
972   return 0;
973 }
974
975 /*******************************************************************************
976  *
977  * Function         GATT_Deregister
978  *
979  * Description      This function deregistered the application from GATT.
980  *
981  * Parameters       gatt_if: applicaiton interface.
982  *
983  * Returns          None.
984  *
985  ******************************************************************************/
986 void GATT_Deregister(tGATT_IF gatt_if) {
987   VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
988
989   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
990   /* Index 0 is GAP and is never deregistered */
991   if ((gatt_if == 0) || (p_reg == NULL)) {
992     LOG(ERROR) << "invalid gatt_if=" << +gatt_if;
993     return;
994   }
995
996   /* stop all services  */
997   /* todo an applcaiton can not be deregistered if its services is also used by
998     other application
999     deregisteration need to bed performed in an orderly fashion
1000     no check for now */
1001   for (auto it = gatt_cb.srv_list_info->begin();
1002        it != gatt_cb.srv_list_info->end();) {
1003     if (it->gatt_if == gatt_if) {
1004       GATTS_StopService(it++->s_hdl);
1005     } else {
1006       ++it;
1007     }
1008   }
1009
1010   /* free all services db buffers if owned by this application */
1011   gatt_free_srvc_db_buffer_app_id(p_reg->app_uuid128);
1012
1013   /* When an application deregisters, check remove the link associated with the
1014    * app */
1015   tGATT_TCB* p_tcb;
1016   int i, j;
1017   for (i = 0, p_tcb = gatt_cb.tcb; i < GATT_MAX_PHY_CHANNEL; i++, p_tcb++) {
1018     if (!p_tcb->in_use) continue;
1019
1020     if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE) {
1021       gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1022     }
1023
1024     tGATT_CLCB* p_clcb;
1025     for (j = 0, p_clcb = &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; j++, p_clcb++) {
1026       if (p_clcb->in_use && (p_clcb->p_reg->gatt_if == gatt_if) &&
1027           (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx)) {
1028         alarm_cancel(p_clcb->gatt_rsp_timer_ent);
1029         gatt_clcb_dealloc(p_clcb);
1030         break;
1031       }
1032     }
1033   }
1034
1035   connection_manager::on_app_deregistered(gatt_if);
1036
1037   memset(p_reg, 0, sizeof(tGATT_REG));
1038 }
1039
1040 /*******************************************************************************
1041  *
1042  * Function         GATT_StartIf
1043  *
1044  * Description      This function is called after registration to start
1045  *                  receiving callbacks for registered interface.  Function may
1046  *                  call back with connection status and queued notifications
1047  *
1048  * Parameter        gatt_if: applicaiton interface.
1049  *
1050  * Returns          None.
1051  *
1052  ******************************************************************************/
1053 void GATT_StartIf(tGATT_IF gatt_if) {
1054   tGATT_REG* p_reg;
1055   tGATT_TCB* p_tcb;
1056   RawAddress bda;
1057   uint8_t start_idx, found_idx;
1058   uint16_t conn_id;
1059   tGATT_TRANSPORT transport;
1060
1061   VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
1062   p_reg = gatt_get_regcb(gatt_if);
1063   if (p_reg != NULL) {
1064     start_idx = 0;
1065     while (
1066         gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
1067       p_tcb = gatt_find_tcb_by_addr(bda, transport);
1068       if (p_reg->app_cb.p_conn_cb && p_tcb) {
1069         conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1070         (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, true, 0, transport);
1071       }
1072       start_idx = ++found_idx;
1073     }
1074   }
1075 }
1076
1077 /*******************************************************************************
1078  *
1079  * Function         GATT_Connect
1080  *
1081  * Description      This function initiate a connecttion to a remote device on
1082  *                  GATT channel.
1083  *
1084  * Parameters       gatt_if: applicaiton interface
1085  *                  bd_addr: peer device address.
1086  *                  is_direct: is a direct conenection or a background auto
1087  *                             connection
1088  *
1089  * Returns          true if connection started; false if connection start
1090  *                  failure.
1091  *
1092  ******************************************************************************/
1093 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1094                   tBT_TRANSPORT transport, bool opportunistic) {
1095   uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
1096   return GATT_Connect(gatt_if, bd_addr, is_direct, transport, opportunistic,
1097                       phy);
1098 }
1099
1100 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1101                   tBT_TRANSPORT transport, bool opportunistic,
1102                   uint8_t initiating_phys) {
1103   LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << ", address=" << bd_addr;
1104
1105   /* Make sure app is registered */
1106   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1107   if (!p_reg) {
1108     LOG(ERROR) << "gatt_if = " << +gatt_if << " is not registered";
1109     return false;
1110   }
1111
1112   if (!is_direct && transport != BT_TRANSPORT_LE) {
1113     LOG(ERROR) << "Unsupported transport for background connection";
1114     return false;
1115   }
1116
1117   if (opportunistic) {
1118     LOG(INFO) << __func__ << " opportunistic connection";
1119     return true;
1120   }
1121
1122   bool ret;
1123   if (is_direct) {
1124     ret = gatt_act_connect(p_reg, bd_addr, transport, initiating_phys);
1125   } else {
1126     if (!BTM_BackgroundConnectAddressKnown(bd_addr)) {
1127       //  RPA can rotate, causing address to "expire" in the background
1128       //  connection list. RPA is allowed for direct connect, as such request
1129       //  times out after 30 seconds
1130       LOG(INFO) << "Can't add RPA to background connection.";
1131       ret = true;
1132     } else {
1133       ret = connection_manager::background_connect_add(gatt_if, bd_addr);
1134     }
1135   }
1136
1137   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1138   // background connections don't necessarily create tcb
1139   if (p_tcb && ret)
1140     gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, !is_direct);
1141
1142   return ret;
1143 }
1144
1145 /*******************************************************************************
1146  *
1147  * Function         GATT_CancelConnect
1148  *
1149  * Description      This function terminate the connection initaition to a
1150  *                  remote device on GATT channel.
1151  *
1152  * Parameters       gatt_if: client interface. If 0 used as unconditionally
1153  *                           disconnect, typically used for direct connection
1154  *                           cancellation.
1155  *                  bd_addr: peer device address.
1156  *
1157  * Returns          true if the connection started; false otherwise.
1158  *
1159  ******************************************************************************/
1160 bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr,
1161                         bool is_direct) {
1162   LOG(INFO) << __func__ << ": gatt_if:" << +gatt_if << ", address: " << bd_addr
1163             << ", direct:" << is_direct;
1164
1165   tGATT_REG* p_reg;
1166   if (gatt_if) {
1167     p_reg = gatt_get_regcb(gatt_if);
1168     if (!p_reg) {
1169       LOG(ERROR) << "gatt_if=" << +gatt_if << " is not registered";
1170       return false;
1171     }
1172
1173     if (is_direct)
1174       return gatt_cancel_open(gatt_if, bd_addr);
1175     else
1176       return gatt_auto_connect_dev_remove(p_reg->gatt_if, bd_addr);
1177   }
1178
1179   VLOG(1) << " unconditional";
1180
1181   /* only LE connection can be cancelled */
1182   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
1183   if (p_tcb && !p_tcb->app_hold_link.empty()) {
1184     for (auto it = p_tcb->app_hold_link.begin();
1185          it != p_tcb->app_hold_link.end();) {
1186       auto next = std::next(it);
1187       // gatt_cancel_open modifies the app_hold_link.
1188       gatt_cancel_open(*it, bd_addr);
1189
1190       it = next;
1191     }
1192   }
1193
1194   if (!connection_manager::remove_unconditional(bd_addr)) {
1195     LOG(ERROR)
1196         << __func__
1197         << ": no app associated with the bg device for unconditional removal";
1198     return false;
1199   }
1200
1201   return true;
1202 }
1203
1204 /*******************************************************************************
1205  *
1206  * Function         GATT_Disconnect
1207  *
1208  * Description      This function disconnects the GATT channel for this
1209  *                  registered application.
1210  *
1211  * Parameters       conn_id: connection identifier.
1212  *
1213  * Returns          GATT_SUCCESS if disconnected.
1214  *
1215  ******************************************************************************/
1216 tGATT_STATUS GATT_Disconnect(uint16_t conn_id) {
1217   LOG(INFO) << __func__ << " conn_id=" << loghex(conn_id);
1218
1219   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1220   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1221   if (!p_tcb) return GATT_ILLEGAL_PARAMETER;
1222
1223   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1224   gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1225   return GATT_SUCCESS;
1226 }
1227
1228 /*******************************************************************************
1229  *
1230  * Function         GATT_GetConnectionInfor
1231  *
1232  * Description      This function uses conn_id to find its associated BD address
1233  *                  and application interface
1234  *
1235  * Parameters        conn_id: connection id  (input)
1236  *                   p_gatt_if: applicaiton interface (output)
1237  *                   bd_addr: peer device address. (output)
1238  *
1239  * Returns          true the ligical link information is found for conn_id
1240  *
1241  ******************************************************************************/
1242 bool GATT_GetConnectionInfor(uint16_t conn_id, tGATT_IF* p_gatt_if,
1243                              RawAddress& bd_addr, tBT_TRANSPORT* p_transport) {
1244   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1245   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1246   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1247   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1248
1249   VLOG(1) << __func__ << " conn_id=" << loghex(conn_id);
1250
1251   if (!p_tcb || !p_reg) return false;
1252
1253   bd_addr = p_tcb->peer_bda;
1254   *p_gatt_if = gatt_if;
1255   *p_transport = p_tcb->transport;
1256   return true;
1257 }
1258
1259 /*******************************************************************************
1260  *
1261  * Function         GATT_GetConnIdIfConnected
1262  *
1263  * Description      This function find the conn_id if the logical link for BD
1264  *                  address and applciation interface is connected
1265  *
1266  * Parameters        gatt_if: applicaiton interface (input)
1267  *                   bd_addr: peer device address. (input)
1268  *                   p_conn_id: connection id  (output)
1269  *                   transport: transport option
1270  *
1271  * Returns          true the logical link is connected
1272  *
1273  ******************************************************************************/
1274 bool GATT_GetConnIdIfConnected(tGATT_IF gatt_if, const RawAddress& bd_addr,
1275                                uint16_t* p_conn_id, tBT_TRANSPORT transport) {
1276   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1277   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1278   bool status = false;
1279
1280   if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)) {
1281     *p_conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1282     status = true;
1283   }
1284
1285   VLOG(1) << __func__ << " status= " << +status;
1286   return status;
1287 }