• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  **/
gatt_add_an_item_to_list(uint16_t s_handle)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 
GATTS_AddHandleRange(tGATTS_HNDL_RANGE * p_hndl_range)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  ******************************************************************************/
GATTS_NVRegister(tGATT_APPL_INFO * p_cb_info)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 
compute_service_size(btgatt_db_element_t * service,int count)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 
is_gatt_attr_type(const Uuid & uuid)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 */
gatt_update_last_srv_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  ******************************************************************************/
GATTS_AddService(tGATT_IF gatt_if,btgatt_db_element_t * service,int count)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 
is_active_service(const Uuid & app_uuid128,Uuid * p_svc_uuid,uint16_t start_handle)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  ******************************************************************************/
GATTS_DeleteService(tGATT_IF gatt_if,Uuid * p_svc_uuid,uint16_t svc_inst)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  ******************************************************************************/
GATTS_StopService(uint16_t service_handle)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     return;
386   }
387 
388   if (it->sdp_handle) {
389     SDP_DeleteRecord(it->sdp_handle);
390   }
391 
392   gatt_cb.srv_list_info->erase(it);
393   gatt_update_last_srv_info();
394 }
395 /*******************************************************************************
396  *
397  * Function         GATTs_HandleValueIndication
398  *
399  * Description      This function sends a handle value indication to a client.
400  *
401  * Parameter        conn_id: connection identifier.
402  *                  attr_handle: Attribute handle of this handle value
403  *                               indication.
404  *                  val_len: Length of the indicated attribute value.
405  *                  p_val: Pointer to the indicated attribute value data.
406  *
407  * Returns          GATT_SUCCESS if sucessfully sent or queued; otherwise error
408  *                  code.
409  *
410  ******************************************************************************/
GATTS_HandleValueIndication(uint16_t conn_id,uint16_t attr_handle,uint16_t val_len,uint8_t * p_val)411 tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle,
412                                          uint16_t val_len, uint8_t* p_val) {
413   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
414   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
415   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
416   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
417 
418   VLOG(1) << __func__;
419   if ((p_reg == NULL) || (p_tcb == NULL)) {
420     LOG(ERROR) << __func__ << ": Unknown  conn_id=" << loghex(conn_id);
421     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
422   }
423 
424   if (!GATT_HANDLE_IS_VALID(attr_handle)) return GATT_ILLEGAL_PARAMETER;
425 
426   tGATT_VALUE indication;
427   indication.conn_id = conn_id;
428   indication.handle = attr_handle;
429   indication.len = val_len;
430   memcpy(indication.value, p_val, val_len);
431   indication.auth_req = GATT_AUTH_REQ_NONE;
432 
433   if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
434     VLOG(1) << "Add a pending indication";
435     gatt_add_pending_ind(p_tcb, &indication);
436     return GATT_SUCCESS;
437   }
438 
439   tGATT_SR_MSG gatt_sr_msg;
440   gatt_sr_msg.attr_value = indication;
441   BT_HDR* p_msg =
442       attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_IND, &gatt_sr_msg);
443   if (!p_msg) return GATT_NO_RESOURCES;
444 
445   tGATT_STATUS cmd_status = attp_send_sr_msg(*p_tcb, p_msg);
446   if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED) {
447     p_tcb->indicate_handle = indication.handle;
448     gatt_start_conf_timer(p_tcb);
449   }
450   return cmd_status;
451 }
452 
453 /*******************************************************************************
454  *
455  * Function         GATTS_HandleValueNotification
456  *
457  * Description      This function sends a handle value notification to a client.
458  *
459  * Parameter        conn_id: connection identifier.
460  *                  attr_handle: Attribute handle of this handle value
461  *                               indication.
462  *                  val_len: Length of the indicated attribute value.
463  *                  p_val: Pointer to the indicated attribute value data.
464  *
465  * Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
466  *
467  ******************************************************************************/
GATTS_HandleValueNotification(uint16_t conn_id,uint16_t attr_handle,uint16_t val_len,uint8_t * p_val)468 tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id,
469                                            uint16_t attr_handle,
470                                            uint16_t val_len, uint8_t* p_val) {
471   tGATT_VALUE notif;
472   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
473   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
474   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
475   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
476 
477   VLOG(1) << __func__;
478 
479   if ((p_reg == NULL) || (p_tcb == NULL)) {
480     LOG(ERROR) << __func__ << "Unknown  conn_id: " << conn_id;
481     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
482   }
483 
484   if (!GATT_HANDLE_IS_VALID(attr_handle)) {
485     return GATT_ILLEGAL_PARAMETER;
486   }
487 
488   notif.handle = attr_handle;
489   notif.len = val_len;
490   memcpy(notif.value, p_val, val_len);
491   notif.auth_req = GATT_AUTH_REQ_NONE;
492 
493   tGATT_STATUS cmd_sent;
494   tGATT_SR_MSG gatt_sr_msg;
495   gatt_sr_msg.attr_value = notif;
496   BT_HDR* p_buf =
497       attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_NOTIF, &gatt_sr_msg);
498   if (p_buf != NULL) {
499     cmd_sent = attp_send_sr_msg(*p_tcb, p_buf);
500   } else
501     cmd_sent = GATT_NO_RESOURCES;
502   return cmd_sent;
503 }
504 
505 /*******************************************************************************
506  *
507  * Function         GATTS_SendRsp
508  *
509  * Description      This function sends the server response to client.
510  *
511  * Parameter        conn_id: connection identifier.
512  *                  trans_id: transaction id
513  *                  status: response status
514  *                  p_msg: pointer to message parameters structure.
515  *
516  * Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
517  *
518  ******************************************************************************/
GATTS_SendRsp(uint16_t conn_id,uint32_t trans_id,tGATT_STATUS status,tGATTS_RSP * p_msg)519 tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id,
520                            tGATT_STATUS status, tGATTS_RSP* p_msg) {
521   tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER;
522   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
523   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
524   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
525   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
526 
527   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
528           << ", trans_id=" << loghex(trans_id) << ", status=" << loghex(status);
529 
530   if ((p_reg == NULL) || (p_tcb == NULL)) {
531     LOG(ERROR) << "Unknown  conn_id=" << loghex(conn_id);
532     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
533   }
534 
535   if (p_tcb->sr_cmd.trans_id != trans_id) {
536     LOG(ERROR) << "conn_id=" << loghex(conn_id)
537                << " waiting for op_code=" << loghex(p_tcb->sr_cmd.op_code);
538     return (GATT_WRONG_STATE);
539   }
540   /* Process App response */
541   cmd_sent = gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id,
542                                      p_tcb->sr_cmd.op_code, status, p_msg);
543 
544   return cmd_sent;
545 }
546 
547 /******************************************************************************/
548 /* GATT Profile Srvr Functions */
549 /******************************************************************************/
550 
551 /******************************************************************************/
552 /*                                                                            */
553 /*                  GATT CLIENT APIs                                          */
554 /*                                                                            */
555 /******************************************************************************/
556 
557 /*******************************************************************************
558  *
559  * Function         GATTC_ConfigureMTU
560  *
561  * Description      This function is called to configure the ATT MTU size.
562  *
563  * Parameters       conn_id: connection identifier.
564  *                  mtu    - attribute MTU size..
565  *
566  * Returns          GATT_SUCCESS if command started successfully.
567  *
568  ******************************************************************************/
GATTC_ConfigureMTU(uint16_t conn_id,uint16_t mtu)569 tGATT_STATUS GATTC_ConfigureMTU(uint16_t conn_id, uint16_t mtu) {
570   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
571   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
572   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
573   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
574 
575   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id) << ", mtu=" << +mtu;
576 
577   if ((p_tcb == NULL) || (p_reg == NULL) || (mtu < GATT_DEF_BLE_MTU_SIZE) ||
578       (mtu > GATT_MAX_MTU_SIZE)) {
579     return GATT_ILLEGAL_PARAMETER;
580   }
581 
582   /* Validate that the link is BLE, not BR/EDR */
583   if (p_tcb->transport != BT_TRANSPORT_LE) {
584     return GATT_ERROR;
585   }
586 
587   if (gatt_is_clcb_allocated(conn_id)) {
588     LOG(ERROR) << "GATT_BUSY conn_id = " << +conn_id;
589     return GATT_BUSY;
590   }
591 
592   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
593   if (!p_clcb) return GATT_NO_RESOURCES;
594 
595   p_clcb->p_tcb->payload_size = mtu;
596   p_clcb->operation = GATTC_OPTYPE_CONFIG;
597   tGATT_CL_MSG gatt_cl_msg;
598   gatt_cl_msg.mtu = mtu;
599   return attp_send_cl_msg(*p_clcb->p_tcb, p_clcb, GATT_REQ_MTU, &gatt_cl_msg);
600 }
601 
602 /*******************************************************************************
603  *
604  * Function         GATTC_Discover
605  *
606  * Description      This function is called to do a discovery procedure on ATT
607  *                  server.
608  *
609  * Parameters       conn_id: connection identifier.
610  *                  disc_type:discovery type.
611  *                  start_handle and end_handle: range of handles for discovery
612  *                  uuid: uuid to discovery. set to Uuid::kEmpty for requests
613  *                        that don't need it
614  *
615  * Returns          GATT_SUCCESS if command received/sent successfully.
616  *
617  ******************************************************************************/
GATTC_Discover(uint16_t conn_id,tGATT_DISC_TYPE disc_type,uint16_t start_handle,uint16_t end_handle,const Uuid & uuid)618 tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
619                             uint16_t start_handle, uint16_t end_handle,
620                             const Uuid& uuid) {
621   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
622   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
623   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
624   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
625 
626   if ((p_tcb == NULL) || (p_reg == NULL) || (disc_type >= GATT_DISC_MAX)) {
627     LOG(ERROR) << __func__ << " Illegal param: disc_type=" << +disc_type
628                << " conn_id=" << loghex(conn_id);
629     return GATT_ILLEGAL_PARAMETER;
630   }
631 
632   LOG(INFO) << __func__ << " conn_id=" << loghex(conn_id)
633             << ", disc_type=" << +disc_type
634             << ", s_handle=" << loghex(start_handle)
635             << ", e_handle=" << loghex(end_handle);
636 
637   if (!GATT_HANDLE_IS_VALID(start_handle) ||
638       !GATT_HANDLE_IS_VALID(end_handle) ||
639       /* search by type does not have a valid UUID param */
640       (disc_type == GATT_DISC_SRVC_BY_UUID && uuid.IsEmpty())) {
641     return GATT_ILLEGAL_PARAMETER;
642   }
643 
644   if (gatt_is_clcb_allocated(conn_id)) {
645     LOG(ERROR) << __func__ << "GATT_BUSY conn_id = " << +conn_id;
646     return GATT_BUSY;
647   }
648 
649   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
650   if (!p_clcb) return GATT_NO_RESOURCES;
651 
652   p_clcb->operation = GATTC_OPTYPE_DISCOVERY;
653   p_clcb->op_subtype = disc_type;
654   p_clcb->s_handle = start_handle;
655   p_clcb->e_handle = end_handle;
656   p_clcb->uuid = uuid;
657 
658   gatt_act_discovery(p_clcb);
659   return GATT_SUCCESS;
660 }
661 
GATTC_Discover(uint16_t conn_id,tGATT_DISC_TYPE disc_type,uint16_t start_handle,uint16_t end_handle)662 tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
663                             uint16_t start_handle, uint16_t end_handle) {
664   return GATTC_Discover(conn_id, disc_type, start_handle, end_handle,
665                         Uuid::kEmpty);
666 }
667 
668 /*******************************************************************************
669  *
670  * Function         GATTC_Read
671  *
672  * Description      This function is called to read the value of an attribute
673  *                  from the server.
674  *
675  * Parameters       conn_id: connection identifier.
676  *                  type    - attribute read type.
677  *                  p_read  - read operation parameters.
678  *
679  * Returns          GATT_SUCCESS if command started successfully.
680  *
681  ******************************************************************************/
GATTC_Read(uint16_t conn_id,tGATT_READ_TYPE type,tGATT_READ_PARAM * p_read)682 tGATT_STATUS GATTC_Read(uint16_t conn_id, tGATT_READ_TYPE type,
683                         tGATT_READ_PARAM* p_read) {
684   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
685   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
686   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
687   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
688 
689   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
690           << ", type=" << loghex(type);
691 
692   if ((p_tcb == NULL) || (p_reg == NULL) || (p_read == NULL) ||
693       ((type >= GATT_READ_MAX) || (type == 0))) {
694     LOG(ERROR) << ": illegal param: conn_id=" << loghex(conn_id)
695                << "type=" << loghex(type);
696     return GATT_ILLEGAL_PARAMETER;
697   }
698 
699   if (gatt_is_clcb_allocated(conn_id)) {
700     LOG(ERROR) << "GATT_BUSY conn_id=" << loghex(conn_id);
701     return GATT_BUSY;
702   }
703 
704   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
705   if (!p_clcb) return GATT_NO_RESOURCES;
706 
707   p_clcb->operation = GATTC_OPTYPE_READ;
708   p_clcb->op_subtype = type;
709   p_clcb->auth_req = p_read->by_handle.auth_req;
710   p_clcb->counter = 0;
711   p_clcb->read_req_current_mtu = p_tcb->payload_size;
712 
713   switch (type) {
714     case GATT_READ_BY_TYPE:
715     case GATT_READ_CHAR_VALUE:
716       p_clcb->s_handle = p_read->service.s_handle;
717       p_clcb->e_handle = p_read->service.e_handle;
718       p_clcb->uuid = p_read->service.uuid;
719       break;
720     case GATT_READ_MULTIPLE: {
721       p_clcb->s_handle = 0;
722       /* copy multiple handles in CB */
723       tGATT_READ_MULTI* p_read_multi =
724           (tGATT_READ_MULTI*)osi_malloc(sizeof(tGATT_READ_MULTI));
725       p_clcb->p_attr_buf = (uint8_t*)p_read_multi;
726       memcpy(p_read_multi, &p_read->read_multiple, sizeof(tGATT_READ_MULTI));
727       break;
728     }
729     case GATT_READ_BY_HANDLE:
730     case GATT_READ_PARTIAL:
731       p_clcb->uuid = Uuid::kEmpty;
732       p_clcb->s_handle = p_read->by_handle.handle;
733 
734       if (type == GATT_READ_PARTIAL) {
735         p_clcb->counter = p_read->partial.offset;
736       }
737 
738       break;
739     default:
740       break;
741   }
742 
743   /* start security check */
744   if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
745   return GATT_SUCCESS;
746 }
747 
748 /*******************************************************************************
749  *
750  * Function         GATTC_Write
751  *
752  * Description      This function is called to write the value of an attribute
753  *                  to the server.
754  *
755  * Parameters       conn_id: connection identifier.
756  *                  type    - attribute write type.
757  *                  p_write  - write operation parameters.
758  *
759  * Returns          GATT_SUCCESS if command started successfully.
760  *
761  ******************************************************************************/
GATTC_Write(uint16_t conn_id,tGATT_WRITE_TYPE type,tGATT_VALUE * p_write)762 tGATT_STATUS GATTC_Write(uint16_t conn_id, tGATT_WRITE_TYPE type,
763                          tGATT_VALUE* p_write) {
764   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
765   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
766   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
767   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
768 
769   if ((p_tcb == NULL) || (p_reg == NULL) || (p_write == NULL) ||
770       ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) &&
771        (type != GATT_WRITE_NO_RSP))) {
772     LOG(ERROR) << __func__ << " Illegal param: conn_id=" << loghex(conn_id)
773                << ", type=" << loghex(type);
774     return GATT_ILLEGAL_PARAMETER;
775   }
776 
777   if (gatt_is_clcb_allocated(conn_id)) {
778     LOG(ERROR) << "GATT_BUSY conn_id=" << loghex(conn_id);
779     return GATT_BUSY;
780   }
781 
782   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
783   if (!p_clcb) return GATT_NO_RESOURCES;
784 
785   p_clcb->operation = GATTC_OPTYPE_WRITE;
786   p_clcb->op_subtype = type;
787   p_clcb->auth_req = p_write->auth_req;
788 
789   p_clcb->p_attr_buf = (uint8_t*)osi_malloc(sizeof(tGATT_VALUE));
790   memcpy(p_clcb->p_attr_buf, (void*)p_write, sizeof(tGATT_VALUE));
791 
792   tGATT_VALUE* p = (tGATT_VALUE*)p_clcb->p_attr_buf;
793   if (type == GATT_WRITE_PREPARE) {
794     p_clcb->start_offset = p_write->offset;
795     p->offset = 0;
796   }
797 
798   if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
799   return GATT_SUCCESS;
800 }
801 
802 /*******************************************************************************
803  *
804  * Function         GATTC_ExecuteWrite
805  *
806  * Description      This function is called to send an Execute write request to
807  *                  the server.
808  *
809  * Parameters       conn_id: connection identifier.
810  *                  is_execute - to execute or cancel the prepared write
811  *                               request(s)
812  *
813  * Returns          GATT_SUCCESS if command started successfully.
814  *
815  ******************************************************************************/
GATTC_ExecuteWrite(uint16_t conn_id,bool is_execute)816 tGATT_STATUS GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute) {
817   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
818   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
819   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
820   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
821 
822   VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
823           << ", is_execute=" << +is_execute;
824 
825   if ((p_tcb == NULL) || (p_reg == NULL)) {
826     LOG(ERROR) << " Illegal param: conn_id=" << loghex(conn_id);
827     return GATT_ILLEGAL_PARAMETER;
828   }
829 
830   if (gatt_is_clcb_allocated(conn_id)) {
831     LOG(ERROR) << " GATT_BUSY conn_id=" << loghex(conn_id);
832     return GATT_BUSY;
833   }
834 
835   tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
836   if (!p_clcb) return GATT_NO_RESOURCES;
837 
838   p_clcb->operation = GATTC_OPTYPE_EXE_WRITE;
839   tGATT_EXEC_FLAG flag =
840       is_execute ? GATT_PREP_WRITE_EXEC : GATT_PREP_WRITE_CANCEL;
841   gatt_send_queue_write_cancel(*p_clcb->p_tcb, p_clcb, flag);
842   return GATT_SUCCESS;
843 }
844 
845 /*******************************************************************************
846  *
847  * Function         GATTC_SendHandleValueConfirm
848  *
849  * Description      This function is called to send a handle value confirmation
850  *                  as response to a handle value notification from server.
851  *
852  * Parameters       conn_id: connection identifier.
853  *                  handle: the handle of the attribute confirmation.
854  *
855  * Returns          GATT_SUCCESS if command started successfully.
856  *
857  ******************************************************************************/
GATTC_SendHandleValueConfirm(uint16_t conn_id,uint16_t handle)858 tGATT_STATUS GATTC_SendHandleValueConfirm(uint16_t conn_id, uint16_t handle) {
859   VLOG(1) << __func__ << " conn_id=" << loghex(conn_id)
860           << ", handle=" << loghex(handle);
861 
862   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id));
863   if (!p_tcb) {
864     LOG(ERROR) << "Unknown conn_id=" << loghex(conn_id);
865     return GATT_ILLEGAL_PARAMETER;
866   }
867 
868   if (p_tcb->ind_count == 0) {
869     VLOG(1) << " conn_id: " << loghex(conn_id)
870             << " ignored not waiting for indicaiton ack";
871     return GATT_SUCCESS;
872   }
873 
874   alarm_cancel(p_tcb->ind_ack_timer);
875 
876   VLOG(1) << "notif_count= " << p_tcb->ind_count;
877   /* send confirmation now */
878   tGATT_CL_MSG gatt_cl_msg;
879   gatt_cl_msg.handle = handle;
880   tGATT_STATUS ret =
881       attp_send_cl_msg(*p_tcb, nullptr, GATT_HANDLE_VALUE_CONF, &gatt_cl_msg);
882 
883   p_tcb->ind_count = 0;
884 
885   return ret;
886 }
887 
888 /******************************************************************************/
889 /*                                                                            */
890 /*                  GATT  APIs                                                */
891 /*                                                                            */
892 /******************************************************************************/
893 /*******************************************************************************
894  *
895  * Function         GATT_SetIdleTimeout
896  *
897  * Description      This function (common to both client and server) sets the
898  *                  idle timeout for a tansport connection
899  *
900  * Parameter        bd_addr:   target device bd address.
901  *                  idle_tout: timeout value in seconds.
902  *
903  * Returns          void
904  *
905  ******************************************************************************/
GATT_SetIdleTimeout(const RawAddress & bd_addr,uint16_t idle_tout,tBT_TRANSPORT transport)906 void GATT_SetIdleTimeout(const RawAddress& bd_addr, uint16_t idle_tout,
907                          tBT_TRANSPORT transport) {
908   bool status = false;
909 
910   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
911   if (p_tcb != NULL) {
912     if (p_tcb->att_lcid == L2CAP_ATT_CID) {
913       status = L2CA_SetFixedChannelTout(bd_addr, L2CAP_ATT_CID, idle_tout);
914 
915       if (idle_tout == GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP)
916         L2CA_SetIdleTimeoutByBdAddr(p_tcb->peer_bda,
917                                     GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP,
918                                     BT_TRANSPORT_LE);
919     } else {
920       status = L2CA_SetIdleTimeout(p_tcb->att_lcid, idle_tout, false);
921     }
922   }
923 
924   VLOG(1) << __func__ << " idle_tout=" << idle_tout << ", status=" << +status
925           << " (1-OK 0-not performed)";
926 }
927 
928 /*******************************************************************************
929  *
930  * Function         GATT_Register
931  *
932  * Description      This function is called to register an  application
933  *                  with GATT
934  *
935  * Parameter        p_app_uuid128: Application UUID
936  *                  p_cb_info: callback functions.
937  *
938  * Returns          0 for error, otherwise the index of the client registered
939  *                  with GATT
940  *
941  ******************************************************************************/
GATT_Register(const Uuid & app_uuid128,tGATT_CBACK * p_cb_info)942 tGATT_IF GATT_Register(const Uuid& app_uuid128, tGATT_CBACK* p_cb_info) {
943   tGATT_REG* p_reg;
944   uint8_t i_gatt_if = 0;
945   tGATT_IF gatt_if = 0;
946 
947   LOG(INFO) << __func__ << " " << app_uuid128;
948 
949   for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
950        i_gatt_if++, p_reg++) {
951     if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
952       LOG(ERROR) << "application already registered.";
953       return 0;
954     }
955   }
956 
957   for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
958        i_gatt_if++, p_reg++) {
959     if (!p_reg->in_use) {
960       memset(p_reg, 0, sizeof(tGATT_REG));
961       i_gatt_if++; /* one based number */
962       p_reg->app_uuid128 = app_uuid128;
963       gatt_if = p_reg->gatt_if = (tGATT_IF)i_gatt_if;
964       p_reg->app_cb = *p_cb_info;
965       p_reg->in_use = true;
966 
967       LOG(INFO) << "allocated gatt_if=" << +gatt_if;
968       return gatt_if;
969     }
970   }
971 
972   LOG(ERROR) << "can't Register GATT client, MAX client reached: "
973              << GATT_MAX_APPS;
974   return 0;
975 }
976 
977 /*******************************************************************************
978  *
979  * Function         GATT_Deregister
980  *
981  * Description      This function deregistered the application from GATT.
982  *
983  * Parameters       gatt_if: applicaiton interface.
984  *
985  * Returns          None.
986  *
987  ******************************************************************************/
GATT_Deregister(tGATT_IF gatt_if)988 void GATT_Deregister(tGATT_IF gatt_if) {
989   VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
990 
991   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
992   /* Index 0 is GAP and is never deregistered */
993   if ((gatt_if == 0) || (p_reg == NULL)) {
994     LOG(ERROR) << "invalid gatt_if=" << +gatt_if;
995     return;
996   }
997 
998   /* stop all services  */
999   /* todo an applcaiton can not be deregistered if its services is also used by
1000     other application
1001     deregisteration need to bed performed in an orderly fashion
1002     no check for now */
1003   for (auto it = gatt_cb.srv_list_info->begin();
1004        it != gatt_cb.srv_list_info->end();) {
1005     if (it->gatt_if == gatt_if) {
1006       GATTS_StopService(it++->s_hdl);
1007     } else {
1008       ++it;
1009     }
1010   }
1011 
1012   /* free all services db buffers if owned by this application */
1013   gatt_free_srvc_db_buffer_app_id(p_reg->app_uuid128);
1014 
1015   /* When an application deregisters, check remove the link associated with the
1016    * app */
1017   tGATT_TCB* p_tcb;
1018   int i, j;
1019   for (i = 0, p_tcb = gatt_cb.tcb; i < GATT_MAX_PHY_CHANNEL; i++, p_tcb++) {
1020     if (!p_tcb->in_use) continue;
1021 
1022     if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE) {
1023       gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1024     }
1025 
1026     tGATT_CLCB* p_clcb;
1027     for (j = 0, p_clcb = &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; j++, p_clcb++) {
1028       if (p_clcb->in_use && (p_clcb->p_reg->gatt_if == gatt_if) &&
1029           (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx)) {
1030         alarm_cancel(p_clcb->gatt_rsp_timer_ent);
1031         gatt_clcb_dealloc(p_clcb);
1032         break;
1033       }
1034     }
1035   }
1036 
1037   connection_manager::on_app_deregistered(gatt_if);
1038 
1039   memset(p_reg, 0, sizeof(tGATT_REG));
1040 }
1041 
1042 /*******************************************************************************
1043  *
1044  * Function         GATT_StartIf
1045  *
1046  * Description      This function is called after registration to start
1047  *                  receiving callbacks for registered interface.  Function may
1048  *                  call back with connection status and queued notifications
1049  *
1050  * Parameter        gatt_if: applicaiton interface.
1051  *
1052  * Returns          None.
1053  *
1054  ******************************************************************************/
GATT_StartIf(tGATT_IF gatt_if)1055 void GATT_StartIf(tGATT_IF gatt_if) {
1056   tGATT_REG* p_reg;
1057   tGATT_TCB* p_tcb;
1058   RawAddress bda;
1059   uint8_t start_idx, found_idx;
1060   uint16_t conn_id;
1061   tGATT_TRANSPORT transport;
1062 
1063   VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
1064   p_reg = gatt_get_regcb(gatt_if);
1065   if (p_reg != NULL) {
1066     start_idx = 0;
1067     while (
1068         gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
1069       p_tcb = gatt_find_tcb_by_addr(bda, transport);
1070       if (p_reg->app_cb.p_conn_cb && p_tcb) {
1071         conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1072         (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, true, 0, transport);
1073       }
1074       start_idx = ++found_idx;
1075     }
1076   }
1077 }
1078 
1079 /*******************************************************************************
1080  *
1081  * Function         GATT_Connect
1082  *
1083  * Description      This function initiate a connecttion to a remote device on
1084  *                  GATT channel.
1085  *
1086  * Parameters       gatt_if: applicaiton interface
1087  *                  bd_addr: peer device address.
1088  *                  is_direct: is a direct conenection or a background auto
1089  *                             connection
1090  *
1091  * Returns          true if connection started; false if connection start
1092  *                  failure.
1093  *
1094  ******************************************************************************/
GATT_Connect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct,tBT_TRANSPORT transport,bool opportunistic)1095 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1096                   tBT_TRANSPORT transport, bool opportunistic) {
1097   uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
1098   return GATT_Connect(gatt_if, bd_addr, is_direct, transport, opportunistic,
1099                       phy);
1100 }
1101 
GATT_Connect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct,tBT_TRANSPORT transport,bool opportunistic,uint8_t initiating_phys)1102 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
1103                   tBT_TRANSPORT transport, bool opportunistic,
1104                   uint8_t initiating_phys) {
1105   LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << ", address=" << bd_addr;
1106 
1107   /* Make sure app is registered */
1108   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1109   if (!p_reg) {
1110     LOG(ERROR) << "gatt_if = " << +gatt_if << " is not registered";
1111     return false;
1112   }
1113 
1114   if (!is_direct && transport != BT_TRANSPORT_LE) {
1115     LOG(ERROR) << "Unsupported transport for background connection";
1116     return false;
1117   }
1118 
1119   if (opportunistic) {
1120     LOG(INFO) << __func__ << " opportunistic connection";
1121     return true;
1122   }
1123 
1124   bool ret;
1125   if (is_direct) {
1126     ret = gatt_act_connect(p_reg, bd_addr, transport, initiating_phys);
1127   } else {
1128     if (!BTM_BackgroundConnectAddressKnown(bd_addr)) {
1129       //  RPA can rotate, causing address to "expire" in the background
1130       //  connection list. RPA is allowed for direct connect, as such request
1131       //  times out after 30 seconds
1132       LOG(INFO) << "Can't add RPA to background connection.";
1133       ret = true;
1134     } else {
1135       ret = connection_manager::background_connect_add(gatt_if, bd_addr);
1136     }
1137   }
1138 
1139   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1140   // background connections don't necessarily create tcb
1141   if (p_tcb && ret)
1142     gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, !is_direct);
1143 
1144   return ret;
1145 }
1146 
1147 /*******************************************************************************
1148  *
1149  * Function         GATT_CancelConnect
1150  *
1151  * Description      This function terminate the connection initaition to a
1152  *                  remote device on GATT channel.
1153  *
1154  * Parameters       gatt_if: client interface. If 0 used as unconditionally
1155  *                           disconnect, typically used for direct connection
1156  *                           cancellation.
1157  *                  bd_addr: peer device address.
1158  *
1159  * Returns          true if the connection started; false otherwise.
1160  *
1161  ******************************************************************************/
GATT_CancelConnect(tGATT_IF gatt_if,const RawAddress & bd_addr,bool is_direct)1162 bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr,
1163                         bool is_direct) {
1164   LOG(INFO) << __func__ << ": gatt_if:" << +gatt_if << ", address: " << bd_addr
1165             << ", direct:" << is_direct;
1166 
1167   tGATT_REG* p_reg;
1168   if (gatt_if) {
1169     p_reg = gatt_get_regcb(gatt_if);
1170     if (!p_reg) {
1171       LOG(ERROR) << "gatt_if=" << +gatt_if << " is not registered";
1172       return false;
1173     }
1174 
1175     if (is_direct)
1176       return gatt_cancel_open(gatt_if, bd_addr);
1177     else
1178       return gatt_auto_connect_dev_remove(p_reg->gatt_if, bd_addr);
1179   }
1180 
1181   VLOG(1) << " unconditional";
1182 
1183   /* only LE connection can be cancelled */
1184   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
1185   if (p_tcb && !p_tcb->app_hold_link.empty()) {
1186     for (auto it = p_tcb->app_hold_link.begin();
1187          it != p_tcb->app_hold_link.end();) {
1188       auto next = std::next(it);
1189       // gatt_cancel_open modifies the app_hold_link.
1190       gatt_cancel_open(*it, bd_addr);
1191 
1192       it = next;
1193     }
1194   }
1195 
1196   if (!connection_manager::remove_unconditional(bd_addr)) {
1197     LOG(ERROR)
1198         << __func__
1199         << ": no app associated with the bg device for unconditional removal";
1200     return false;
1201   }
1202 
1203   return true;
1204 }
1205 
1206 /*******************************************************************************
1207  *
1208  * Function         GATT_Disconnect
1209  *
1210  * Description      This function disconnects the GATT channel for this
1211  *                  registered application.
1212  *
1213  * Parameters       conn_id: connection identifier.
1214  *
1215  * Returns          GATT_SUCCESS if disconnected.
1216  *
1217  ******************************************************************************/
GATT_Disconnect(uint16_t conn_id)1218 tGATT_STATUS GATT_Disconnect(uint16_t conn_id) {
1219   LOG(INFO) << __func__ << " conn_id=" << loghex(conn_id);
1220 
1221   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1222   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1223   if (!p_tcb) return GATT_ILLEGAL_PARAMETER;
1224 
1225   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1226   gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1227   return GATT_SUCCESS;
1228 }
1229 
1230 /*******************************************************************************
1231  *
1232  * Function         GATT_GetConnectionInfor
1233  *
1234  * Description      This function uses conn_id to find its associated BD address
1235  *                  and application interface
1236  *
1237  * Parameters        conn_id: connection id  (input)
1238  *                   p_gatt_if: applicaiton interface (output)
1239  *                   bd_addr: peer device address. (output)
1240  *
1241  * Returns          true the ligical link information is found for conn_id
1242  *
1243  ******************************************************************************/
GATT_GetConnectionInfor(uint16_t conn_id,tGATT_IF * p_gatt_if,RawAddress & bd_addr,tBT_TRANSPORT * p_transport)1244 bool GATT_GetConnectionInfor(uint16_t conn_id, tGATT_IF* p_gatt_if,
1245                              RawAddress& bd_addr, tBT_TRANSPORT* p_transport) {
1246   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1247   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1248   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1249   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1250 
1251   VLOG(1) << __func__ << " conn_id=" << loghex(conn_id);
1252 
1253   if (!p_tcb || !p_reg) return false;
1254 
1255   bd_addr = p_tcb->peer_bda;
1256   *p_gatt_if = gatt_if;
1257   *p_transport = p_tcb->transport;
1258   return true;
1259 }
1260 
1261 /*******************************************************************************
1262  *
1263  * Function         GATT_GetConnIdIfConnected
1264  *
1265  * Description      This function find the conn_id if the logical link for BD
1266  *                  address and applciation interface is connected
1267  *
1268  * Parameters        gatt_if: applicaiton interface (input)
1269  *                   bd_addr: peer device address. (input)
1270  *                   p_conn_id: connection id  (output)
1271  *                   transport: transport option
1272  *
1273  * Returns          true the logical link is connected
1274  *
1275  ******************************************************************************/
GATT_GetConnIdIfConnected(tGATT_IF gatt_if,const RawAddress & bd_addr,uint16_t * p_conn_id,tBT_TRANSPORT transport)1276 bool GATT_GetConnIdIfConnected(tGATT_IF gatt_if, const RawAddress& bd_addr,
1277                                uint16_t* p_conn_id, tBT_TRANSPORT transport) {
1278   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1279   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1280   bool status = false;
1281 
1282   if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)) {
1283     *p_conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1284     status = true;
1285   }
1286 
1287   VLOG(1) << __func__ << " status= " << +status;
1288   return status;
1289 }
1290