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